diff --git a/docs/content/docs/features/local-install.mdx b/docs/content/docs/features/local-install.mdx index db3ecc5f..081e1ae8 100644 --- a/docs/content/docs/features/local-install.mdx +++ b/docs/content/docs/features/local-install.mdx @@ -118,6 +118,7 @@ installed component. findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/docs/content/docs/framework-guides/expo.mdx b/docs/content/docs/framework-guides/expo.mdx index cd712d69..446f2146 100644 --- a/docs/content/docs/framework-guides/expo.mdx +++ b/docs/content/docs/framework-guides/expo.mdx @@ -17,7 +17,7 @@ description: Install and configure Convex + Better Auth for Expo. ```npm npm install convex@latest @convex-dev/better-auth - npm install better-auth@~1.6.15 @better-auth/expo@~1.6.15 + npm install better-auth@~1.7.7 @better-auth/expo@~1.7.7 ``` diff --git a/docs/content/docs/framework-guides/next.mdx b/docs/content/docs/framework-guides/next.mdx index b2b2b626..c434d0fa 100644 --- a/docs/content/docs/framework-guides/next.mdx +++ b/docs/content/docs/framework-guides/next.mdx @@ -22,7 +22,7 @@ description: Install and configure Convex + Better Auth for Next.js. ```npm npm install convex@latest @convex-dev/better-auth - npm install better-auth@~1.6.15 + npm install better-auth@~1.7.7 ``` diff --git a/docs/content/docs/framework-guides/react.mdx b/docs/content/docs/framework-guides/react.mdx index 80528313..76908b30 100644 --- a/docs/content/docs/framework-guides/react.mdx +++ b/docs/content/docs/framework-guides/react.mdx @@ -22,7 +22,7 @@ description: Install and configure Convex + Better Auth for React. ```npm npm install convex@latest @convex-dev/better-auth - npm install better-auth@~1.6.15 + npm install better-auth@~1.7.7 ``` diff --git a/docs/content/docs/framework-guides/sveltekit.mdx b/docs/content/docs/framework-guides/sveltekit.mdx index 2702fec0..f1742d0e 100644 --- a/docs/content/docs/framework-guides/sveltekit.mdx +++ b/docs/content/docs/framework-guides/sveltekit.mdx @@ -99,7 +99,7 @@ npm install convex @mmailaender/convex-svelte ```npm npm install @convex-dev/better-auth @mmailaender/convex-better-auth-svelte - npm install better-auth@~1.6.15 + npm install better-auth@~1.7.7 ``` diff --git a/docs/content/docs/framework-guides/tanstack-start.mdx b/docs/content/docs/framework-guides/tanstack-start.mdx index 3d9196ba..782ec0e5 100644 --- a/docs/content/docs/framework-guides/tanstack-start.mdx +++ b/docs/content/docs/framework-guides/tanstack-start.mdx @@ -23,7 +23,7 @@ description: Install and configure Convex + Better Auth for TanStack Start. ```npm npm install convex@latest @convex-dev/better-auth - npm install better-auth@~1.6.15 + npm install better-auth@~1.7.7 npm install @types/node --save-dev ``` diff --git a/docs/content/docs/migrations/meta.json b/docs/content/docs/migrations/meta.json index c5bc92ec..0da75a15 100644 --- a/docs/content/docs/migrations/meta.json +++ b/docs/content/docs/migrations/meta.json @@ -1,5 +1,5 @@ { "title": "Migrations", - "pages": ["migrate-to-0-12", "migrate-to-0-11", "migrate-to-0-10", "migrate-to-0-9", "migrate-to-0-8"], + "pages": ["migrate-to-0-13", "migrate-to-0-12", "migrate-to-0-11", "migrate-to-0-10", "migrate-to-0-9", "migrate-to-0-8"], "defaultOpen": true } diff --git a/docs/content/docs/migrations/migrate-to-0-13.mdx b/docs/content/docs/migrations/migrate-to-0-13.mdx new file mode 100644 index 00000000..2dbe16b4 --- /dev/null +++ b/docs/content/docs/migrations/migrate-to-0-13.mdx @@ -0,0 +1,308 @@ +--- +title: Migrate to 0.13 +description: Migrate to @convex-dev/better-auth@0.13 +--- + +## Upgrade + +
+ +
+ +### Install dependencies + +Update Better Auth and the component. Better Auth must be on `1.7.7` or later in +the `1.7.x` line. Update any installed `@better-auth/*` packages together. + +```npm +npm install @convex-dev/better-auth@^0.13.0 +npm install better-auth@~1.7.7 +``` + + + Review the [Better Auth 1.7 upgrade + guide](https://www.better-auth.com/docs/guides/1-7-upgrade-guide) and [1.7.7 + release notes](https://github.com/better-auth/better-auth/releases/tag/v1.7.7) + for the features your app uses. + + +
+ +
+ +### Check existing accounts + +Accounts still use `(providerId, accountId)`, as in 1.6. **No issuer backfill is +needed.** Check for duplicate pairs before upgrading; Better Auth now rejects +ambiguous account lookups. Resolve duplicates using trusted provider data and +keep different users separate. Credential accounts should have `accountId` equal +to `userId`. + +If you tested 1.7.0–1.7.2, see [Early 1.7 deployments](#early-17-deployments) +below. Microsoft accounts have a separate migration described below. + +
+ +
+ +### Deploy and test + +Back up your data and test the upgrade on a development deployment first. +Regenerate Convex bindings, then deploy the component and application changes +together. Verify sign-in, existing sessions, account linking, token refresh, and +`/api/auth/convex/jwks` for the features you use. + +Upgrade servers sharing verification storage and OAuth Proxy participants +together. Request fresh Magic Links and restart pending OAuth/SAML sign-ins +after deploying, as required by the 1.7.7 security fixes. + +
+ +
+ +## Breaking changes + +### Account selectors + +Read the local account `id` from `listAccounts` and pass it as `accountId` to +`unlinkAccount`. For `getAccessToken`, `refreshToken`, and `accountInfo`, pass +exactly one of `{ accountId: account.id }` or `{ useAccountCookie: true }`. +Remove `providerId` from these selectors. Cookie selection requires +`account.storeAccountCookie` in your Better Auth configuration. + +### Generic OAuth + +Use the standard social client APIs: + +```ts +await authClient.signIn.social({ provider: "my-provider" }); +await authClient.linkSocial({ provider: "my-provider" }); +``` + +These replace `signIn.oauth2()` and `oauth2.link()`. Remove +`genericOAuthClient()` and change provider callback URLs from +`/api/auth/oauth2/callback/:id` to `/api/auth/callback/:id`. + +PKCE is enabled by default. Set `pkce: false` only for providers that reject it. +Remove `issuer` and `requireIssuerValidation`; issuer validation is automatic. + +Review custom provider identity mapping. Discovery providers use verified `sub`, +and plain OAuth providers use `id`. Set `accountSubject` if that default is not +the provider's immutable identifier. Keep the provider identifier in +`getUserInfo().data`; `getUserInfo().user` contains mutable user fields, and +`mapProfileToUser` can no longer return `id`. See the upstream +[account identity guidance](https://www.better-auth.com/docs/guides/1-7-upgrade-guide#account-identity-keeps-the-provider-key). + +### Microsoft accounts + +Microsoft accounts now use `oid` instead of `sub`, including the Generic OAuth +Microsoft Entra helper. Pause Microsoft sign-in and linking while updating +stored account IDs from verified ID tokens or a trusted Entra export. The old +account row alone cannot supply this mapping. + +The Generic OAuth `microsoftEntraId` helper requires a concrete tenant GUID and +an `id_token` from the token exchange. Use the built-in Microsoft provider for +`common`, `organizations`, or `consumers`. Follow the upstream guide's +[Microsoft migration steps](https://www.better-auth.com/docs/guides/1-7-upgrade-guide#migrate-microsoft-account-identifiers). + +### Database joins + +Move `experimental.joins` to `advanced.database.joins`. The Convex adapter +continues to disable native joins and use its existing relation queries. + +### Expo + +The `@better-auth/expo` client's `getCookie()` now returns a promise. Await it +and make callbacks that read cookies asynchronous. Passing `expo-secure-store` +directly still works; custom storage must implement `getItem`, `getItemAsync`, +`setItem`, and `setItemAsync`. See the upstream +[Expo migration guidance](https://www.better-auth.com/docs/guides/1-7-upgrade-guide#expo-and-react-native). + +### Two-factor authentication + +Check the returned `method` before reading `totpURI` or backup codes from +`enableTwoFactor`. Those fields are present only when `method === "totp"`. The +Next.js and TanStack examples include this check. + +## Early 1.7 deployments + +Better Auth 1.7.3 removed the required `issuer` field introduced in 1.7.0–1.7.2. +The bundled component keeps it optional to accept existing data, but no longer +includes issuer indexes or backfill functions. + +For Local Install, remove issuer-based constraints and indexes. Keep `issuer` +optional until stored values are removed. If different issuers shared one +provider ID and overlapping account IDs, assign distinct provider IDs and update +the matching account rows before resuming sign-in. + +## OAuth or OIDC provider + +The conversion below is for apps that used `oidcProvider` to act as an identity +provider. Apps that only sign in through an external provider can skip it. + +If you already use `@better-auth/oauth-provider` with Local Install, follow the +upstream +[OAuth client migration](https://www.better-auth.com/docs/guides/1-7-upgrade-guide#migrate-oauth-client-records) +before applying the generated schema. Existing clients need field backfills and +configuration changes; schema generation alone does not migrate their data. Skip +the legacy export and cleanup below. + +Use a temporary Convex schema that accepts both the existing and migrated client +records. Backfill the new fields and remove the legacy `type` and `public` +fields from existing `oauthClient` documents before deploying the final +generated schema. Remove those fields in a component mutation with +`ctx.db.patch(id, { type: undefined, public: undefined })`; setting them to +`null` still leaves fields that the final schema rejects. + +### Export and clear legacy records + +Back up your data and pause authentication writes and public HTTP routes during +the conversion. Keep the bundled component mounted until export and cleanup are +complete. Add these internal wrappers: + +```ts title="convex/migrations.ts" +import { v } from "convex/values"; +import { internalMutation, internalQuery } from "./_generated/server"; +import { components } from "./_generated/api"; + +export const listLegacyOAuthApplications = internalQuery({ + args: { cursor: v.union(v.string(), v.null()) }, + handler: async (ctx, { cursor }) => { + return await ctx.runQuery( + components.betterAuth.migrations.listLegacyOAuthApplications, + { paginationOpts: { cursor, numItems: 100 } } + ); + }, +}); + +export const clearLegacyOAuthProviderRecords = internalMutation({ + args: { + table: v.union( + v.literal("oauthApplication"), + v.literal("oauthAccessToken"), + v.literal("oauthConsent") + ), + cursor: v.union(v.string(), v.null()), + }, + handler: async (ctx, { table, cursor }) => { + return await ctx.runMutation( + components.betterAuth.migrations.clearLegacyOAuthProviderRecords, + { table, paginationOpts: { cursor, numItems: 100 } } + ); + }, +}); +``` + +Export every page of client registrations and save the results securely. The +export omits `clientSecret`; review custom `metadata` before reusing it. + +```bash +npx convex run migrations:listLegacyOAuthApplications '{"cursor":null}' +``` + +After verifying the export, clear the old tokens, consents, and applications in +that order. This invalidates existing provider tokens and removes client +secrets. + +```bash +npx convex run migrations:clearLegacyOAuthProviderRecords \ + '{"table":"oauthAccessToken","cursor":null}' +npx convex run migrations:clearLegacyOAuthProviderRecords \ + '{"table":"oauthConsent","cursor":null}' +npx convex run migrations:clearLegacyOAuthProviderRecords \ + '{"table":"oauthApplication","cursor":null}' +``` + +For each command, pass the returned `continueCursor` to the next call until +`isDone` is true. A completed cursor is terminal; use `null` only to start a new +pass. Add `--prod` when running against production. + +### Switch to Local Install + +1. Follow the [Local Install guide](/local-install). Keep the component mounted + as `betterAuth` so existing data stays under `components.betterAuth`. +2. Install `@better-auth/oauth-provider@~1.7.7` and replace `oidcProvider()` + with `jwt()` and `oauthProvider()` in your static Better Auth options. Follow + the upstream + [provider migration guide](https://www.better-auth.com/docs/guides/1-7-upgrade-guide#as-an-identity-provider). +3. Generate the new schema after adding the plugin and clearing all three legacy + tables. Retain optional `account.issuer` if existing records still contain + it. +4. Deploy while writes remain paused. Confirm that existing users, accounts, and + sessions remain under the same component mount before proceeding. +5. Re-register exported clients. Map `redirectUrls` to `redirectUris`, parse + legacy `metadata` as JSON, and review grant types and token authentication. + Distribute new client secrets and issue new provider tokens. +6. Test authorization, consent, token issuance, refresh, user info, and logout + before restoring traffic. Restore the backup with the old application version + if the conversion fails. + +### Configure provider signing keys + +Use database-backed signing keys for this provider setup. Static keys passed to +`convex({ jwks: ... })` are not supported: the JWT plugin signs provider tokens +with database keys, while Convex publishes the static keys. Clients would then +be unable to verify those provider tokens. + +In the runtime plugin array, place `jwt()` before `convex()` and +`oauthProvider()` after `convex()`. These plugins share endpoint keys, so order +matters. `registerRoutes` and `registerRoutesLazy` direct root OpenID discovery +to the OAuth provider when it is configured, so root discovery advertises the +provider issuer. Convex JWT verifiers should continue to use the Convex issuer +and `/api/auth/convex/jwks` directly. + +Configure the JWT plugin to use Convex's public signing-key URL: + +```ts +jwt({ + disableSettingJwtHeader: true, + jwks: { + remoteUrl: `${process.env.CONVEX_SITE_URL}/api/auth/convex/jwks`, + keyPairConfig: { alg: "RS256" }, + }, +}); +``` + +Replace `/api/auth` if you use a custom `basePath`. Use the same signing +algorithm as your Convex auth configuration (`RS256` by default). Disabling the +JWT header avoids generating an extra token when reading a session; Convex +clients use `/convex/token`. + +### Custom consent pages + +Before displaying consent details, verify the signed query on the server with +`verifyOAuthQueryParams` from `@better-auth/oauth-provider`. Use the provider's +resolved secret, `(await auth.$context).secret`, from your server-side auth +instance and keep it on the server. See the upstream +[consent screen example](https://www.better-auth.com/docs/plugins/oauth-provider#consent-screen). + +## Local Install additional steps + +Generate the 1.7.7 schema to a side file and compare it with your deployed +schema: + +```npm +cd convex/betterAuth +npx auth generate --output generatedSchema.next.ts +``` + +Preserve existing plugin tables, custom fields, and indexes. Include the +generated credential lookup index `userId_providerId_accountId` on +`["userId", "providerId", "accountId"]` and export `incrementOne` with your +other adapter functions. The adapter implements `consumeOne` using the +component's atomic `deleteOne`. + +If you already use Local Install with `oidcProvider`, copy +`src/component/migrations.ts` from the installed `@convex-dev/better-auth` +package to `convex/betterAuth/migrations.ts`. Install `convex-helpers` as a +direct dependency, choosing a version compatible with your installed Convex +version. The helpers use its `paginator`, since `ctx.db.query(...).paginate()` +is not supported inside components. Use the internal wrappers above to call +them. + +Before exporting, deploy a temporary schema that retains `oauthApplication` and +accepts both legacy and new `oauthAccessToken` and `oauthConsent` records. Keep +both sets of fields and indexes, make required new fields such as `clientId` and +`scopes` optional, and allow `scopes` to be either a string or an array of +strings. Clear legacy records before applying the final provider schema, and +remove the temporary migration helpers and wrappers in that same deployment. diff --git a/docs/content/docs/supported-plugins.mdx b/docs/content/docs/supported-plugins.mdx index f3df30ef..0c2bf46a 100644 --- a/docs/content/docs/supported-plugins.mdx +++ b/docs/content/docs/supported-plugins.mdx @@ -5,12 +5,12 @@ description: Supported plugins for Convex + Better Auth ## Supported plugins -Any Better Auth plugin may be used with Convex + Better Auth, but only a subset -are considered supported for the integration. Convex + Better Auth works out of -the box for these without any required schema changes. +Better Auth plugins may be used with Convex + Better Auth when their runtime and +adapter requirements are met, but only a subset are considered supported for the +integration. These work without any required schema changes. -For plugins that require schema changes and aren't in the list, check out [Local -Install](/local-install). +For plugins that require schema changes and aren't in the list, check out +[Local Install](/local-install). - [Anonymous](https://www.better-auth.com/docs/plugins/anonymous) - [Email OTP](https://www.better-auth.com/docs/plugins/email-otp) @@ -22,9 +22,23 @@ Install](/local-install). - [Two Factor](https://www.better-auth.com/docs/plugins/2fa) - [Username](https://www.better-auth.com/docs/plugins/username) +### Local Install plugins + +Schema-changing plugins that are not bundled with the component require +[Local Install](/local-install). This includes the +[`@better-auth/oauth-provider`](https://www.better-auth.com/docs/plugins/oauth-provider) +package used when your application acts as an OAuth or OIDC provider. + +Local Install allows schema changes but does not add adapter capabilities +required by a plugin. Check its requirements before using it. + ### Incompatible plugins Official Better Auth plugins that are incompatible with Convex + Better Auth (even when Local Install is used): -- [SSO](https://www.better-auth.com/docs/plugins/sso) - has direct dependencies on Node.js +- [SSO](https://www.better-auth.com/docs/plugins/sso) - has direct dependencies + on Node.js +- [SCIM](https://www.better-auth.com/docs/plugins/scim) - requires native + interactive adapter transactions in Better Auth 1.7, which the Convex adapter + does not provide. diff --git a/e2e/.gitignore b/e2e/.gitignore index 6aaf5b72..0288404e 100644 --- a/e2e/.gitignore +++ b/e2e/.gitignore @@ -7,3 +7,6 @@ convex-local-backend convex-local-backend.log convex_local_storage convex_local_backend.sqlite3 + +# Generated when the E2E fixture is deployed. +convex/**/_generated/ diff --git a/e2e/convex/auth.config.ts b/e2e/convex/auth.config.ts new file mode 100644 index 00000000..793ec105 --- /dev/null +++ b/e2e/convex/auth.config.ts @@ -0,0 +1,2 @@ +import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config"; +export default { providers: [getAuthConfigProvider()] }; diff --git a/e2e/convex/auth.ts b/e2e/convex/auth.ts new file mode 100644 index 00000000..b1a0c45a --- /dev/null +++ b/e2e/convex/auth.ts @@ -0,0 +1,40 @@ +import { createClient, type GenericCtx } from "@convex-dev/better-auth"; +import { convex } from "@convex-dev/better-auth/plugins"; +import { oauthProvider } from "@better-auth/oauth-provider"; +import { betterAuth, type BetterAuthOptions } from "better-auth/minimal"; +import { jwt } from "better-auth/plugins/jwt"; +import { components } from "./_generated/api"; +import type { DataModel } from "./_generated/dataModel"; +import schema from "./betterAuth/schema"; +import authConfig from "./auth.config"; + +export const authComponent = createClient( + components.oauthProvider, + { local: { schema } } +); +export const createAuthOptions = (ctx: GenericCtx) => + ({ + emailAndPassword: { enabled: true }, + baseURL: process.env.CONVEX_SITE_URL, + database: authComponent.adapter(ctx), + plugins: [ + jwt({ + disableSettingJwtHeader: true, + jwks: { + remoteUrl: `${process.env.CONVEX_SITE_URL}/api/auth/convex/jwks`, + keyPairConfig: { alg: "RS256" }, + }, + }), + convex({ authConfig }), + oauthProvider({ + loginPage: "/sign-in", + consentPage: "/consent", + scopes: ["openid", "profile", "email", "offline_access"], + grantTypes: ["authorization_code", "refresh_token"], + refreshTokenReuseInterval: 0, + }), + ], + }) satisfies BetterAuthOptions; + +export const createAuth = (ctx: GenericCtx) => + betterAuth(createAuthOptions(ctx)); diff --git a/e2e/convex/betterAuth/adapter.ts b/e2e/convex/betterAuth/adapter.ts new file mode 100644 index 00000000..69c8c7c1 --- /dev/null +++ b/e2e/convex/betterAuth/adapter.ts @@ -0,0 +1,14 @@ +import { createApi } from "@convex-dev/better-auth"; +import schema from "./schema"; +import { createAuthOptions } from "../auth"; + +export const { + create, + findOne, + findMany, + updateOne, + incrementOne, + updateMany, + deleteOne, + deleteMany, +} = createApi(schema, createAuthOptions); diff --git a/e2e/convex/betterAuth/auth.ts b/e2e/convex/betterAuth/auth.ts new file mode 100644 index 00000000..f572a538 --- /dev/null +++ b/e2e/convex/betterAuth/auth.ts @@ -0,0 +1,3 @@ +import { createAuth } from "../auth"; +// Only used by the Better Auth schema generator. +export const auth = createAuth({} as never); diff --git a/e2e/convex/betterAuth/convex.config.ts b/e2e/convex/betterAuth/convex.config.ts new file mode 100644 index 00000000..948c02a7 --- /dev/null +++ b/e2e/convex/betterAuth/convex.config.ts @@ -0,0 +1,2 @@ +import { defineComponent } from "convex/server"; +export default defineComponent("betterAuth"); diff --git a/e2e/convex/betterAuth/schema.ts b/e2e/convex/betterAuth/schema.ts new file mode 100644 index 00000000..61127971 --- /dev/null +++ b/e2e/convex/betterAuth/schema.ts @@ -0,0 +1,207 @@ +/** + * This file is auto-generated. Do not edit this file manually. + * To regenerate the schema, from your project root: + * + * cd convex/betterAuth + * npx auth generate --output schema.ts + * + * To customize the schema, generate to an alternate file and import + * the table definitions to your schema file. See + * https://labs.convex.dev/better-auth/features/local-install#adding-custom-indexes. + */ + +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_providerId_accountId", ["userId", "providerId", "accountId"]) + .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(), + expiresAt: v.optional(v.union(v.null(), v.number())), + alg: v.optional(v.union(v.null(), v.string())), + crv: v.optional(v.union(v.null(), v.string())), + }), + oauthClient: defineTable({ + clientId: v.string(), + clientSecret: v.optional(v.union(v.null(), v.string())), + clientDiscoveryId: v.optional(v.union(v.null(), v.string())), + disabled: v.optional(v.union(v.null(), v.boolean())), + skipConsent: v.optional(v.union(v.null(), v.boolean())), + enableEndSession: v.optional(v.union(v.null(), v.boolean())), + subjectType: v.optional(v.union(v.null(), v.string())), + scopes: v.optional(v.union(v.null(), v.array(v.string()))), + clientCredentialsScopes: v.optional(v.union(v.null(), v.array(v.string()))), + userId: v.optional(v.union(v.null(), v.string())), + createdAt: v.optional(v.union(v.null(), v.number())), + updatedAt: v.optional(v.union(v.null(), v.number())), + name: v.optional(v.union(v.null(), v.string())), + uri: v.optional(v.union(v.null(), v.string())), + icon: v.optional(v.union(v.null(), v.string())), + contacts: v.optional(v.union(v.null(), v.array(v.string()))), + tos: v.optional(v.union(v.null(), v.string())), + policy: v.optional(v.union(v.null(), v.string())), + softwareId: v.optional(v.union(v.null(), v.string())), + softwareVersion: v.optional(v.union(v.null(), v.string())), + softwareStatement: v.optional(v.union(v.null(), v.string())), + redirectUris: v.array(v.string()), + postLogoutRedirectUris: v.optional(v.union(v.null(), v.array(v.string()))), + backchannelLogoutUri: v.optional(v.union(v.null(), v.string())), + backchannelLogoutSessionRequired: v.optional( + v.union(v.null(), v.boolean()) + ), + tokenEndpointAuthMethod: v.optional(v.union(v.null(), v.string())), + applicationType: v.optional(v.union(v.null(), v.string())), + jwks: v.optional(v.union(v.null(), v.string())), + jwksUri: v.optional(v.union(v.null(), v.string())), + grantTypes: v.optional(v.union(v.null(), v.array(v.string()))), + responseTypes: v.optional(v.union(v.null(), v.array(v.string()))), + requirePKCE: v.optional(v.union(v.null(), v.boolean())), + dpopBoundAccessTokens: v.optional(v.union(v.null(), v.boolean())), + referenceId: v.optional(v.union(v.null(), v.string())), + metadata: v.optional(v.union(v.null(), v.string())), + }) + .index("clientId", ["clientId"]) + .index("userId", ["userId"]), + oauthResource: defineTable({ + identifier: v.string(), + name: v.string(), + accessTokenTtl: v.optional(v.union(v.null(), v.number())), + refreshTokenTtl: v.optional(v.union(v.null(), v.number())), + signingAlgorithm: v.optional(v.union(v.null(), v.string())), + signingKeyId: v.optional(v.union(v.null(), v.string())), + allowedScopes: v.optional(v.union(v.null(), v.array(v.string()))), + customClaims: v.optional(v.union(v.null(), v.string())), + dpopBoundAccessTokensRequired: v.optional(v.union(v.null(), v.boolean())), + disabled: v.optional(v.union(v.null(), v.boolean())), + createdAt: v.optional(v.union(v.null(), v.number())), + updatedAt: v.optional(v.union(v.null(), v.number())), + policyVersion: v.optional(v.union(v.null(), v.number())), + metadata: v.optional(v.union(v.null(), v.string())), + }).index("identifier", ["identifier"]), + oauthClientResource: defineTable({ + clientId: v.string(), + resourceId: v.string(), + metadata: v.optional(v.union(v.null(), v.string())), + createdAt: v.optional(v.union(v.null(), v.number())), + }) + .index("clientId_resourceId", ["clientId", "resourceId"]) + .index("clientId", ["clientId"]) + .index("resourceId", ["resourceId"]), + oauthRefreshToken: defineTable({ + token: v.string(), + clientId: v.string(), + sessionId: v.optional(v.union(v.null(), v.string())), + userId: v.string(), + referenceId: v.optional(v.union(v.null(), v.string())), + authorizationCodeId: v.optional(v.union(v.null(), v.string())), + resources: v.optional(v.union(v.null(), v.array(v.string()))), + requestedUserInfoClaims: v.optional(v.union(v.null(), v.array(v.string()))), + expiresAt: v.optional(v.union(v.null(), v.number())), + createdAt: v.optional(v.union(v.null(), v.number())), + revoked: v.optional(v.union(v.null(), v.number())), + rotatedAt: v.optional(v.union(v.null(), v.number())), + rotationReplayResponse: v.optional(v.union(v.null(), v.string())), + rotationReplayExpiresAt: v.optional(v.union(v.null(), v.number())), + authTime: v.optional(v.union(v.null(), v.number())), + confirmation: v.optional(v.union(v.null(), v.string())), + scopes: v.array(v.string()), + }) + .index("token", ["token"]) + .index("clientId", ["clientId"]) + .index("sessionId", ["sessionId"]) + .index("userId", ["userId"]), + oauthAccessToken: defineTable({ + token: v.optional(v.union(v.null(), v.string())), + clientId: v.string(), + sessionId: v.optional(v.union(v.null(), v.string())), + userId: v.optional(v.union(v.null(), v.string())), + referenceId: v.optional(v.union(v.null(), v.string())), + authorizationCodeId: v.optional(v.union(v.null(), v.string())), + resources: v.optional(v.union(v.null(), v.array(v.string()))), + requestedUserInfoClaims: v.optional(v.union(v.null(), v.array(v.string()))), + refreshId: v.optional(v.union(v.null(), v.string())), + expiresAt: v.optional(v.union(v.null(), v.number())), + createdAt: v.optional(v.union(v.null(), v.number())), + revoked: v.optional(v.union(v.null(), v.number())), + confirmation: v.optional(v.union(v.null(), v.string())), + scopes: v.array(v.string()), + }) + .index("token", ["token"]) + .index("clientId", ["clientId"]) + .index("sessionId", ["sessionId"]) + .index("userId", ["userId"]) + .index("refreshId", ["refreshId"]), + oauthConsent: defineTable({ + clientId: v.string(), + userId: v.optional(v.union(v.null(), v.string())), + referenceId: v.optional(v.union(v.null(), v.string())), + resources: v.optional(v.union(v.null(), v.array(v.string()))), + requestedUserInfoClaims: v.optional(v.union(v.null(), v.array(v.string()))), + scopes: v.array(v.string()), + createdAt: v.optional(v.union(v.null(), v.number())), + updatedAt: v.optional(v.union(v.null(), v.number())), + }) + .index("clientId_userId", ["clientId", "userId"]) + .index("userId", ["userId"]), + oauthClientAssertion: defineTable({ + expiresAt: v.number(), + }), +}; + +const schema = defineSchema(tables); + +export default schema; diff --git a/e2e/convex/convex.config.ts b/e2e/convex/convex.config.ts new file mode 100644 index 00000000..2f87f607 --- /dev/null +++ b/e2e/convex/convex.config.ts @@ -0,0 +1,6 @@ +import { defineApp } from "convex/server"; +import oauthProvider from "./betterAuth/convex.config"; + +const app = defineApp(); +app.use(oauthProvider, { name: "oauthProvider" }); +export default app; diff --git a/e2e/convex/http.ts b/e2e/convex/http.ts new file mode 100644 index 00000000..d6af2133 --- /dev/null +++ b/e2e/convex/http.ts @@ -0,0 +1,19 @@ +import { httpRouter, httpActionGeneric } from "convex/server"; +import { authComponent, createAuth } from "./auth"; + +const http = httpRouter(); +const registration = process.env.OAUTH_ROUTE_REGISTRATION; +if (registration !== "eager" && registration !== "lazy") { + throw new Error("OAUTH_ROUTE_REGISTRATION must be eager or lazy"); +} +http.route({ + path: "/registration-mode", + method: "GET", + handler: httpActionGeneric(async () => Response.json({ registration })), +}); +if (registration === "lazy") { + authComponent.registerRoutesLazy(http, createAuth); +} else { + authComponent.registerRoutes(http, createAuth); +} +export default http; diff --git a/e2e/convex/schema.ts b/e2e/convex/schema.ts new file mode 100644 index 00000000..8cc1e2ba --- /dev/null +++ b/e2e/convex/schema.ts @@ -0,0 +1,2 @@ +import { defineSchema } from "convex/server"; +export default defineSchema({}); diff --git a/e2e/convex/tsconfig.json b/e2e/convex/tsconfig.json new file mode 100644 index 00000000..42b170fb --- /dev/null +++ b/e2e/convex/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowJs": true, + "strict": true, + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "target": "ESNext", + "lib": ["ES2023", "dom"], + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "isolatedModules": true, + "noEmit": true + }, + "include": ["./**/*"], + "exclude": ["./_generated"] +} diff --git a/e2e/oauth-provider/provider.spec.ts b/e2e/oauth-provider/provider.spec.ts new file mode 100644 index 00000000..49ae9fe4 --- /dev/null +++ b/e2e/oauth-provider/provider.spec.ts @@ -0,0 +1,158 @@ +import { createHash, randomBytes, randomUUID } from "node:crypto"; +import { test, expect, type APIRequestContext } from "@playwright/test"; +import { createLocalJWKSet, jwtVerify } from "jose"; + +const site = "http://127.0.0.1:3211"; +const base = `${site}/api/auth`; +const redirectUri = "https://client.example.com/callback"; + +async function authorize(request: APIRequestContext) { + const signup = await request.post(`${base}/sign-up/email`, { + data: { + name: "OAuth test user", + email: `${randomUUID()}@example.com`, + password: "TestPassword123!", + }, + }); + expect(signup.status()).toBe(200); + const { user } = await signup.json(); + const registration = await request.post(`${base}/oauth2/create-client`, { + data: { + client_name: "E2E client", + redirect_uris: [redirectUri], + token_endpoint_auth_method: "client_secret_post", + grant_types: ["authorization_code", "refresh_token"], + response_types: ["code"], + scope: "openid profile email offline_access", + }, + }); + expect(registration.status()).toBe(201); + const { client_id, client_secret } = await registration.json(); + expect(client_id).toBeTruthy(); + expect(client_secret).toBeTruthy(); + const verifier = randomBytes(32).toString("base64url"); + const state = randomUUID(); + const nonce = randomUUID(); + const authorization = await request.get(`${base}/oauth2/authorize`, { + params: { + client_id, + redirect_uri: redirectUri, + response_type: "code", + scope: "openid profile email offline_access", + state, + nonce, + code_challenge: createHash("sha256").update(verifier).digest("base64url"), + code_challenge_method: "S256", + prompt: "consent", + }, + maxRedirects: 0, + }); + expect(authorization.status()).toBe(302); + const consentUrl = new URL(authorization.headers().location, site); + expect(consentUrl.pathname).toBe("/consent"); + const consent = await request.post(`${base}/oauth2/consent`, { + data: { accept: true, oauth_query: consentUrl.search.slice(1) }, + }); + expect(consent.status()).toBe(200); + const callback = new URL((await consent.json()).url); + expect(`${callback.origin}${callback.pathname}`).toBe(redirectUri); + expect(callback.searchParams.get("state")).toBe(state); + const code = callback.searchParams.get("code"); + expect(code).toBeTruthy(); + const credentials = { client_id, client_secret }; + const exchange = await request.post(`${base}/oauth2/token`, { + headers: { cookie: "" }, + form: { + ...credentials, + grant_type: "authorization_code", + code: code!, + code_verifier: verifier, + redirect_uri: redirectUri, + }, + }); + expect(exchange.status()).toBe(200); + const tokens = await exchange.json(); + expect(tokens.access_token).toBeTruthy(); + expect(tokens.refresh_token).toBeTruthy(); + expect(tokens.id_token).toBeTruthy(); + return { credentials, tokens, user, nonce }; +} + +test.describe(`${process.env.OAUTH_ROUTE_REGISTRATION} OAuth provider`, () => { + test.beforeEach(async ({ request }) => { + const mode = await request.get("/registration-mode"); + expect(mode.status()).toBe(200); + expect(await mode.json()).toEqual({ + registration: process.env.OAUTH_ROUTE_REGISTRATION, + }); + }); + test("discovery leads to provider metadata and keys that verify its ID token", async ({ + request, + }) => { + const root = await request.get(`${site}/.well-known/openid-configuration`, { + maxRedirects: 0, + }); + expect(root.status()).toBe(302); + expect(root.headers().location).toBe( + `${base}/.well-known/openid-configuration` + ); + const discovery = await request.get(root.headers().location); + expect(discovery.status()).toBe(200); + const metadata = await discovery.json(); + expect(metadata).toMatchObject({ + issuer: base, + authorization_endpoint: `${base}/oauth2/authorize`, + token_endpoint: `${base}/oauth2/token`, + jwks_uri: `${base}/convex/jwks`, + }); + const { credentials, tokens, user, nonce } = await authorize(request); + const keys = await request.get(metadata.jwks_uri); + expect(keys.status()).toBe(200); + const jwks = await keys.json(); + expect(jwks.keys.length).toBeGreaterThan(0); + for (const key of jwks.keys) expect(key).not.toHaveProperty("d"); + const { payload } = await jwtVerify( + tokens.id_token, + createLocalJWKSet(jwks), + { + issuer: metadata.issuer, + audience: credentials.client_id, + algorithms: ["RS256"], + } + ); + expect(payload).toMatchObject({ sub: user.id, nonce }); + }); + + test("refresh rotates the token and rejects reuse of the old token and its family", async ({ + request, + }) => { + const { credentials, tokens, user } = await authorize(request); + const refresh = (token: string) => + request.post(`${base}/oauth2/token`, { + headers: { cookie: "" }, + form: { + ...credentials, + grant_type: "refresh_token", + refresh_token: token, + }, + }); + const rotation = await refresh(tokens.refresh_token); + expect(rotation.status()).toBe(200); + const rotated = await rotation.json(); + expect(rotated.refresh_token).toBeTruthy(); + expect(rotated.refresh_token).not.toBe(tokens.refresh_token); + expect(rotated.access_token).toBeTruthy(); + const profile = await request.get(`${base}/oauth2/userinfo`, { + headers: { cookie: "", authorization: `Bearer ${rotated.access_token}` }, + }); + expect(profile.status()).toBe(200); + expect(await profile.json()).toMatchObject({ sub: user.id }); + + const replay = await refresh(tokens.refresh_token); + expect(replay.status()).toBe(400); + expect(await replay.json()).toMatchObject({ error: "invalid_grant" }); + const family = await refresh(rotated.refresh_token); + expect(family.status()).toBe(400); + expect(await family.json()).toMatchObject({ error: "invalid_grant" }); + }); +}); diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 576f4b09..2edf1c9d 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -6,9 +6,666 @@ "": { "name": "e2e-tests", "dependencies": { + "@better-auth/oauth-provider": "1.7.7", + "@convex-dev/better-auth": "file:..", "@playwright/test": "^1.60.0", "adm-zip": "^0.5.16", - "dotenv": "^17.0.0" + "better-auth": "1.7.7", + "convex": "1.41.0", + "dotenv": "^17.0.0", + "jose": "^6.1.0" + } + }, + "..": { + "name": "@convex-dev/better-auth", + "version": "0.12.5", + "license": "Apache-2.0", + "dependencies": { + "@better-fetch/fetch": "^1.3.2", + "common-tags": "^1.8.2", + "convex-helpers": "^0.1.95", + "jose": "^6.1.0", + "remeda": "^2.32.0", + "semver": "^7.7.3", + "type-fest": "^5.0.0", + "zod": "^4.0.0" + }, + "devDependencies": { + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", + "@convex-dev/eslint-plugin": "2.0.0", + "@edge-runtime/vm": "5.0.0", + "@eslint/eslintrc": "3.3.5", + "@eslint/js": "9.39.4", + "@tanstack/react-start": "1.167.65", + "@types/common-tags": "1.8.4", + "@types/node": "24.12.3", + "@types/react": "19.2.14", + "@types/react-dom": "19.2.3", + "@types/semver": "7.7.1", + "better-auth": "1.7.7", + "chokidar-cli": "3.0.0", + "concurrently": "10.0.3", + "convex": "1.41.0", + "convex-test": "0.0.51", + "eslint": "9.39.4", + "eslint-plugin-import": "2.32.0", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-react-refresh": "0.5.2", + "globals": "17.6.0", + "next": "16.2.6", + "pkg-pr-new": "0.0.71", + "prettier": "3.8.3", + "react": "19.2.6", + "react-dom": "19.2.6", + "typescript": "5.9.3", + "typescript-eslint": "8.59.2", + "vitest": "4.1.10" + }, + "peerDependencies": { + "better-auth": ">=1.7.7 <1.8.0", + "convex": "^1.25.0", + "react": "^18.3.1 || ^19.0.0" + } + }, + "node_modules/@better-auth/core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.7.7.tgz", + "integrity": "sha512-srgFzHEjB2WWlokFz1i4BfG41sNhsA105Pukgqu6RrEh5A+LSkzf1mCHydVipkjt9l5qswtBMi7IL6ouHbZL4Q==", + "license": "MIT", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.41.1", + "@standard-schema/spec": "^1.1.0", + "zod": "^4.5.4" + }, + "peerDependencies": { + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2", + "@opentelemetry/api": "^1.9.0", + "better-call": "1.4.0", + "jose": "^6.1.0", + "kysely": "^0.28.5 || ^0.29.0", + "nanostores": "^1.0.1" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } + } + }, + "node_modules/@better-auth/drizzle-adapter": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.7.7.tgz", + "integrity": "sha512-qon0U94PR5FQysuyGoAlGVQpIIiNg5dtDpwjE63sN/HjoRWZadZzHPcS9mn7JsJyQZK6iTNhd7LD0AaXt2f78w==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0" + }, + "peerDependenciesMeta": { + "drizzle-orm": { + "optional": true + } + } + }, + "node_modules/@better-auth/kysely-adapter": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.7.7.tgz", + "integrity": "sha512-9FONOCgOcrQI9wJ5v1oDGIg9sT7pa9RjZZQ4fsCTudo8R87SrIGNUvUxDFTJhZvUblvFfGaIBR9Vb8LA+8bqLQ==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "kysely": "^0.28.17 || ^0.29.0" + }, + "peerDependenciesMeta": { + "kysely": { + "optional": true + } + } + }, + "node_modules/@better-auth/memory-adapter": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/memory-adapter/-/memory-adapter-1.7.7.tgz", + "integrity": "sha512-FqKFEe+b5tXXV0gRbyirca+qXgMpLOeJ8Wk19yykb/scQKy0WJ4k22WzEV3TTPctQV9DZhwCXPlDtQhnlOv5Gg==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2" + } + }, + "node_modules/@better-auth/mongo-adapter": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/mongo-adapter/-/mongo-adapter-1.7.7.tgz", + "integrity": "sha512-ZnVDuRrXqbf0oHphrEN27oTImNH5NTO26dtWatq5cXyYAsH7goof9QIoTOmxTbBxUQahKBw9T6+9h6n+RtOE+g==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "mongodb": "^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "mongodb": { + "optional": true + } + } + }, + "node_modules/@better-auth/oauth-provider": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/oauth-provider/-/oauth-provider-1.7.7.tgz", + "integrity": "sha512-dc4C/ZF+8qc88ebcU8kaFp8yladCtfTkuUt2zBSmYw25YCNC5BoUP9rpAkIx4nemlZ11gLtSnkEPc0sA7MwVmw==", + "license": "MIT", + "dependencies": { + "jose": "^6.2.3", + "zod": "^4.5.4" + }, + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2", + "better-auth": "^1.7.7", + "better-call": "1.4.0" + } + }, + "node_modules/@better-auth/prisma-adapter": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/prisma-adapter/-/prisma-adapter-1.7.7.tgz", + "integrity": "sha512-4YcnrcVdvWiAZw0sZl63tWUClPXg5r3QsLn7C2sG7kKEBY06zOng0ibecyxRBixKq1zE1ceHuEUqez5Rhi+nQA==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", + "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@prisma/client": { + "optional": true + }, + "prisma": { + "optional": true + } + } + }, + "node_modules/@better-auth/telemetry": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.7.7.tgz", + "integrity": "sha512-PaRA6i+kAioVYmza2gHPcdrxP0hAotph4KV9hft2GeNJq+AZXDiBu3FuLM9HxvcmiZeUT74Vufqd9ypmB8veTA==", + "license": "MIT", + "peerDependencies": { + "@better-auth/core": "^1.7.7", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2" + } + }, + "node_modules/@better-auth/utils": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.4.2.tgz", + "integrity": "sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^2.0.1" + } + }, + "node_modules/@better-fetch/fetch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.3.2.tgz", + "integrity": "sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow==", + "license": "MIT" + }, + "node_modules/@convex-dev/better-auth": { + "resolved": "..", + "link": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@noble/ciphers": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.4.0.tgz", + "integrity": "sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", + "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" } }, "node_modules/@playwright/test": { @@ -26,6 +683,12 @@ "node": ">=18" } }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, "node_modules/adm-zip": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.17.tgz", @@ -35,6 +698,180 @@ "node": ">=12.0" } }, + "node_modules/better-auth": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.7.7.tgz", + "integrity": "sha512-Zhgxi/c5ylmfB/sX+nwnBbsFf/j6k0L8DvL6CJXZSrXgxc5pPMC/e7j812zNd4L4B4ELmdURCPw3X8nAOUdcjw==", + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.7", + "@better-auth/drizzle-adapter": "1.7.7", + "@better-auth/kysely-adapter": "1.7.7", + "@better-auth/memory-adapter": "1.7.7", + "@better-auth/mongo-adapter": "1.7.7", + "@better-auth/prisma-adapter": "1.7.7", + "@better-auth/telemetry": "1.7.7", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.0", + "defu": "^6.1.4", + "jose": "^6.2.3", + "kysely": "^0.28.17 || ^0.29.0", + "nanostores": "^1.3.0", + "zod": "^4.5.4" + }, + "peerDependencies": { + "@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", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.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 || ^5.0.0", + "vue": "^3.0.0" + }, + "peerDependenciesMeta": { + "@lynx-js/react": { + "optional": true + }, + "@prisma/client": { + "optional": true + }, + "@sveltejs/kit": { + "optional": true + }, + "@tanstack/react-start": { + "optional": true + }, + "@tanstack/solid-start": { + "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 + } + } + }, + "node_modules/better-call": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.4.0.tgz", + "integrity": "sha512-bBKOT4vv1kZLDgxVePdilk/Jwkn+dtRRsmi3DzHcDP+WnswyVl6dR59l2HEeP/0cB+bDoopASAesWDPIdd/zZA==", + "license": "MIT", + "dependencies": { + "@better-auth/utils": "^0.5.0", + "@better-fetch/fetch": "^1.3.1", + "rou3": "^0.9.1", + "set-cookie-parser": "^3.1.2" + }, + "peerDependencies": { + "zod": "^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/better-call/node_modules/@better-auth/utils": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.5.0.tgz", + "integrity": "sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^2.0.1" + } + }, + "node_modules/convex": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/convex/-/convex-1.41.0.tgz", + "integrity": "sha512-euxVf6yfpB7/VGKOobkLgjpbJidsUgW+b0ezonEyCUPqlpHFwR4/yIiI1hjjErzraiw91GxrtxpXQClMLNqU+w==", + "license": "Apache-2.0", + "dependencies": { + "esbuild": "0.27.0", + "prettier": "^3.0.0", + "ws": "8.20.1" + }, + "bin": { + "convex": "bin/main.js" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=7.0.0" + }, + "peerDependencies": { + "@auth0/auth0-react": "^2.0.1", + "@clerk/clerk-react": "^4.12.8 || ^5.0.0", + "@clerk/react": "^6.4.3", + "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@auth0/auth0-react": { + "optional": true + }, + "@clerk/clerk-react": { + "optional": true + }, + "@clerk/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, "node_modules/dotenv": { "version": "17.4.2", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", @@ -47,6 +884,47 @@ "url": "https://dotenvx.com" } }, + "node_modules/esbuild": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -61,6 +939,39 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/jose": { + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz", + "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/kysely": { + "version": "0.29.6", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.29.6.tgz", + "integrity": "sha512-hHaB8C/rfzDDtr/t8YZwxAuPJTT0zHyaPoVzcXwDYhYNAgH/4sIfVhi/XLLIY+bL/FqaIJnjATDbi8ObSELmxg==", + "license": "MIT", + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/nanostores": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.5.4.tgz", + "integrity": "sha512-4UXY7OAJEK0Y6V3SudBU7cXjAzTDc189R78dDOh0Xbm19gpKYto6WizSg58LJf12lTsRxKSLGyE117OiLpM4DQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": "^20.0.0 || >=22.0.0" + } + }, "node_modules/playwright": { "version": "1.60.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", @@ -90,6 +1001,63 @@ "engines": { "node": ">=18" } + }, + "node_modules/prettier": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.9.tgz", + "integrity": "sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/rou3": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.9.2.tgz", + "integrity": "sha512-3SOzvaAg8rkHrXtRjpCvCvbyO5to9oOO27Z/XqHEYXfMRVSw/qMIVdmaOk9W2lcRLtR6dlqTjo9hDeJk70QBYQ==", + "license": "MIT" + }, + "node_modules/set-cookie-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.2.tgz", + "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==", + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", + "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/e2e/package.json b/e2e/package.json index d6d9a9b9..3a6c5ee0 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -7,8 +7,13 @@ "testExistingBackend": "./run-e2e-tests.sh" }, "dependencies": { + "@better-auth/oauth-provider": "1.7.7", + "@convex-dev/better-auth": "file:..", "@playwright/test": "^1.60.0", "adm-zip": "^0.5.16", - "dotenv": "^17.0.0" + "better-auth": "1.7.7", + "convex": "1.41.0", + "dotenv": "^17.0.0", + "jose": "^6.1.0" } } diff --git a/e2e/playwright.oauth.config.ts b/e2e/playwright.oauth.config.ts new file mode 100644 index 00000000..7eced2d4 --- /dev/null +++ b/e2e/playwright.oauth.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "@playwright/test"; + +export default defineConfig({ + testDir: "./oauth-provider", + forbidOnly: !!process.env.CI, + workers: 1, + timeout: 60_000, + reporter: "list", + use: { + baseURL: "http://127.0.0.1:3211", + extraHTTPHeaders: { origin: "http://127.0.0.1:3211" }, + }, +}); diff --git a/e2e/run-e2e-tests.sh b/e2e/run-e2e-tests.sh index 0fc33dea..b425aa2d 100755 --- a/e2e/run-e2e-tests.sh +++ b/e2e/run-e2e-tests.sh @@ -27,3 +27,12 @@ popd > /dev/null echo "Running Playwright tests..." npx playwright test --config "$SCRIPT_DIR/playwright.config.ts" + +pushd "$SCRIPT_DIR" > /dev/null +for registration in eager lazy; do + echo "Running OAuth provider tests ($registration)..." + npx convex env set OAUTH_ROUTE_REGISTRATION "$registration" --url "$CONVEX_URL" --admin-key "$ADMIN_KEY" + npx convex deploy --url "$CONVEX_URL" --admin-key "$ADMIN_KEY" -y + OAUTH_ROUTE_REGISTRATION="$registration" npx playwright test --config "$SCRIPT_DIR/playwright.oauth.config.ts" +done +popd > /dev/null diff --git a/examples/next/app/(auth)/settings/EnableTwoFactor.tsx b/examples/next/app/(auth)/settings/EnableTwoFactor.tsx index e33859de..f7311e8a 100644 --- a/examples/next/app/(auth)/settings/EnableTwoFactor.tsx +++ b/examples/next/app/(auth)/settings/EnableTwoFactor.tsx @@ -53,7 +53,7 @@ export default function EnableTwoFactor() { const { data } = await authClient.twoFactor.enable({ password, }); - if (data?.totpURI) { + if (data?.method === "totp") { setTotpUri(data.totpURI); if (data.backupCodes) { setBackupCodes(data.backupCodes); diff --git a/examples/next/app/(unauth)/sign-in/SignIn.tsx b/examples/next/app/(unauth)/sign-in/SignIn.tsx index 9d5d4a8d..96e6c9bc 100644 --- a/examples/next/app/(unauth)/sign-in/SignIn.tsx +++ b/examples/next/app/(unauth)/sign-in/SignIn.tsx @@ -152,9 +152,9 @@ export default function SignIn() { }; const handleSlackSignIn = async () => { - await authClient.signIn.oauth2( + await authClient.signIn.social( { - providerId: "slack", + provider: "slack", }, { onRequest: () => { diff --git a/examples/next/convex/betterAuth/_generated/component.ts b/examples/next/convex/betterAuth/_generated/component.ts index 97ab5f56..6c60a754 100644 --- a/examples/next/convex/betterAuth/_generated/component.ts +++ b/examples/next/convex/betterAuth/_generated/component.ts @@ -88,6 +88,8 @@ export type ComponentApi = | { data: { backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret: string; userId: string; verified?: null | boolean; @@ -96,7 +98,9 @@ export type ComponentApi = } | { data: { + alg?: null | string; createdAt: number; + crv?: null | string; expiresAt?: null | number; privateKey: string; publicKey: string; @@ -271,6 +275,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -303,6 +309,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -501,6 +509,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -533,6 +543,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -654,6 +666,298 @@ export type ComponentApi = any, Name >; + incrementOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + increment: Record; + model: "user"; + set?: { + createdAt?: number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + foo?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "isAnonymous" + | "username" + | "displayUsername" + | "twoFactorEnabled" + | "userId" + | "foo" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "session"; + set?: { + 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "account"; + set?: { + 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "verification"; + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "twoFactor"; + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; updateMany: FunctionReference< "mutation", "internal", @@ -855,6 +1159,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -866,6 +1172,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -892,7 +1200,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -904,6 +1214,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1141,6 +1453,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -1152,6 +1466,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1178,7 +1494,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -1190,6 +1508,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: diff --git a/examples/next/convex/betterAuth/adapter.ts b/examples/next/convex/betterAuth/adapter.ts index 58547fd9..69c8c7c1 100644 --- a/examples/next/convex/betterAuth/adapter.ts +++ b/examples/next/convex/betterAuth/adapter.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/examples/next/convex/betterAuth/generatedSchema.ts b/examples/next/convex/betterAuth/generatedSchema.ts index c352749c..2e6af099 100644 --- a/examples/next/convex/betterAuth/generatedSchema.ts +++ b/examples/next/convex/betterAuth/generatedSchema.ts @@ -28,7 +28,7 @@ export const tables = { userId: v.optional(v.union(v.null(), v.string())), foo: v.optional(v.union(v.null(), v.string())), }) - .index("email_name", ["email","name"]) + .index("email_name", ["email", "name"]) .index("name", ["name"]) .index("userId", ["userId"]) .index("username", ["username"]), @@ -42,7 +42,7 @@ export const tables = { userId: v.string(), }) .index("expiresAt", ["expiresAt"]) - .index("expiresAt_userId", ["expiresAt","userId"]) + .index("expiresAt_userId", ["expiresAt", "userId"]) .index("token", ["token"]) .index("userId", ["userId"]), account: defineTable({ @@ -60,8 +60,13 @@ export const tables = { updatedAt: v.number(), }) .index("accountId", ["accountId"]) - .index("accountId_providerId", ["accountId","providerId"]) - .index("providerId_userId", ["providerId","userId"]) + .index("accountId_providerId", ["accountId", "providerId"]) + .index("providerId_userId", ["providerId", "userId"]) + .index("userId_providerId_accountId", [ + "userId", + "providerId", + "accountId", + ]) .index("userId", ["userId"]), verification: defineTable({ identifier: v.string(), @@ -77,13 +82,16 @@ export const tables = { backupCodes: v.string(), userId: v.string(), verified: v.optional(v.union(v.null(), v.boolean())), - }) - .index("userId", ["userId"]), + failedVerificationCount: v.optional(v.union(v.null(), v.number())), + lockedUntil: v.optional(v.union(v.null(), v.number())), + }).index("userId", ["userId"]), jwks: defineTable({ publicKey: v.string(), privateKey: v.string(), createdAt: v.number(), expiresAt: v.optional(v.union(v.null(), v.number())), + alg: v.optional(v.union(v.null(), v.string())), + crv: v.optional(v.union(v.null(), v.string())), }), }; diff --git a/examples/next/lib/auth-client.tsx b/examples/next/lib/auth-client.tsx index 6f5ca766..00128b37 100644 --- a/examples/next/lib/auth-client.tsx +++ b/examples/next/lib/auth-client.tsx @@ -4,7 +4,6 @@ import { twoFactorClient, magicLinkClient, emailOTPClient, - genericOAuthClient, anonymousClient, inferAdditionalFields, } from "better-auth/client/plugins"; @@ -24,7 +23,6 @@ export const authClient = createAuthClient({ magicLinkClient(), emailOTPClient(), twoFactorClient(), - genericOAuthClient(), convexClient(), ], }); diff --git a/examples/next/package-lock.json b/examples/next/package-lock.json index 40c7eae8..1732847a 100644 --- a/examples/next/package-lock.json +++ b/examples/next/package-lock.json @@ -52,7 +52,7 @@ "version": "0.12.5", "license": "Apache-2.0", "dependencies": { - "@better-fetch/fetch": "^1.1.18", + "@better-fetch/fetch": "^1.3.2", "common-tags": "^1.8.2", "convex-helpers": "^0.1.128", "jose": "^6.1.0", @@ -62,8 +62,8 @@ "zod": "^4.0.0" }, "devDependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/test-utils": "1.6.15", + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", "@convex-dev/eslint-plugin": "2.0.0", "@edge-runtime/vm": "5.0.0", "@eslint/eslintrc": "3.3.5", @@ -74,7 +74,7 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@types/semver": "7.7.1", - "better-auth": "1.6.15", + "better-auth": "1.7.7", "chokidar-cli": "3.0.0", "concurrently": "10.0.3", "convex": "1.46.0", @@ -92,34 +92,34 @@ "react-dom": "19.2.6", "typescript": "5.9.3", "typescript-eslint": "8.59.2", - "vitest": "4.1.5" + "vitest": "4.1.10" }, "peerDependencies": { - "better-auth": ">=1.6.11 <1.7.0", + "better-auth": ">=1.7.7 <1.8.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" } }, "../../node_modules/better-auth": { - "version": "1.6.15", - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/drizzle-adapter": "1.6.15", - "@better-auth/kysely-adapter": "1.6.15", - "@better-auth/memory-adapter": "1.6.15", - "@better-auth/mongo-adapter": "1.6.15", - "@better-auth/prisma-adapter": "1.6.15", - "@better-auth/telemetry": "1.6.15", - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", - "better-call": "1.3.5", + "version": "1.7.1", + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.1", + "@better-auth/drizzle-adapter": "1.7.1", + "@better-auth/kysely-adapter": "1.7.1", + "@better-auth/memory-adapter": "1.7.1", + "@better-auth/mongo-adapter": "1.7.1", + "@better-auth/prisma-adapter": "1.7.1", + "@better-auth/telemetry": "1.7.1", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.1", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.0", "defu": "^6.1.4", - "jose": "^6.1.3", + "jose": "^6.2.3", "kysely": "^0.28.17 || ^0.29.0", - "nanostores": "^1.1.1", + "nanostores": "^1.3.0", "zod": "^4.3.6" }, "peerDependencies": { @@ -129,8 +129,8 @@ "@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.45.2", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", diff --git a/examples/react/package-lock.json b/examples/react/package-lock.json index 249da82b..0f60d0dc 100644 --- a/examples/react/package-lock.json +++ b/examples/react/package-lock.json @@ -51,7 +51,7 @@ "version": "0.12.5", "license": "Apache-2.0", "dependencies": { - "@better-fetch/fetch": "^1.1.18", + "@better-fetch/fetch": "^1.3.2", "common-tags": "^1.8.2", "convex-helpers": "^0.1.128", "jose": "^6.1.0", @@ -61,8 +61,8 @@ "zod": "^4.0.0" }, "devDependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/test-utils": "1.6.15", + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", "@convex-dev/eslint-plugin": "2.0.0", "@edge-runtime/vm": "5.0.0", "@eslint/eslintrc": "3.3.5", @@ -73,7 +73,7 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@types/semver": "7.7.1", - "better-auth": "1.6.15", + "better-auth": "1.7.7", "chokidar-cli": "3.0.0", "concurrently": "10.0.3", "convex": "1.46.0", @@ -91,34 +91,34 @@ "react-dom": "19.2.6", "typescript": "5.9.3", "typescript-eslint": "8.59.2", - "vitest": "4.1.5" + "vitest": "4.1.10" }, "peerDependencies": { - "better-auth": ">=1.6.11 <1.7.0", + "better-auth": ">=1.7.7 <1.8.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" } }, "../../node_modules/better-auth": { - "version": "1.6.15", - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/drizzle-adapter": "1.6.15", - "@better-auth/kysely-adapter": "1.6.15", - "@better-auth/memory-adapter": "1.6.15", - "@better-auth/mongo-adapter": "1.6.15", - "@better-auth/prisma-adapter": "1.6.15", - "@better-auth/telemetry": "1.6.15", - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", - "better-call": "1.3.5", + "version": "1.7.1", + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.1", + "@better-auth/drizzle-adapter": "1.7.1", + "@better-auth/kysely-adapter": "1.7.1", + "@better-auth/memory-adapter": "1.7.1", + "@better-auth/mongo-adapter": "1.7.1", + "@better-auth/prisma-adapter": "1.7.1", + "@better-auth/telemetry": "1.7.1", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.1", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.0", "defu": "^6.1.4", - "jose": "^6.1.3", + "jose": "^6.2.3", "kysely": "^0.28.17 || ^0.29.0", - "nanostores": "^1.1.1", + "nanostores": "^1.3.0", "zod": "^4.3.6" }, "peerDependencies": { @@ -128,8 +128,8 @@ "@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.45.2", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", diff --git a/examples/tanstack/convex/betterAuth/_generated/component.ts b/examples/tanstack/convex/betterAuth/_generated/component.ts index 14a14be6..832040aa 100644 --- a/examples/tanstack/convex/betterAuth/_generated/component.ts +++ b/examples/tanstack/convex/betterAuth/_generated/component.ts @@ -8,7 +8,7 @@ * @module */ -import type { FunctionReference } from "convex/server"; +import type { FunctionReference } from 'convex/server' /** * A utility for referencing a Convex component's exposed API. @@ -25,1184 +25,1500 @@ export type ComponentApi = { adapter: { create: FunctionReference< - "mutation", - "internal", + 'mutation', + 'internal', { input: | { data: { - createdAt: number; - email: string; - emailVerified: boolean; - foo?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - }; - model: "user"; + createdAt: number + email: string + emailVerified: boolean + foo?: null | string + image?: null | string + isAnonymous?: null | boolean + name: string + twoFactorEnabled?: null | boolean + 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"; + 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"; + 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"; + createdAt: number + expiresAt: number + identifier: string + updatedAt: number + value: string + } + model: 'verification' } | { data: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; + backupCodes: string + failedVerificationCount?: null | number + lockedUntil?: null | number + secret: string + userId: string + verified?: null | boolean + } + model: 'twoFactor' } | { data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - }; - onCreateHandle?: string; - select?: Array; + alg?: null | string + createdAt: number + crv?: null | string + expiresAt?: null | number + privateKey: string + publicKey: string + } + model: 'jwks' + } + onCreateHandle?: string + select?: Array }, any, Name - >; + > deleteMany: FunctionReference< - "mutation", - "internal", + 'mutation', + 'internal', { input: | { - model: "user"; + model: 'user' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "name" - | "email" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "userId" - | "foo" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'name' + | 'email' + | 'emailVerified' + | 'image' + | 'createdAt' + | 'updatedAt' + | 'twoFactorEnabled' + | 'isAnonymous' + | 'userId' + | 'foo' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "session"; + model: 'session' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "expiresAt" - | "token" - | "createdAt" - | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'expiresAt' + | 'token' + | 'createdAt' + | 'updatedAt' + | 'ipAddress' + | 'userAgent' + | 'userId' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "account"; + model: 'account' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'accountId' + | 'providerId' + | 'userId' + | 'accessToken' + | 'refreshToken' + | 'idToken' + | 'accessTokenExpiresAt' + | 'refreshTokenExpiresAt' + | 'scope' + | 'password' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "verification"; + model: 'verification' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'identifier' + | 'value' + | 'expiresAt' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "twoFactor"; + model: 'twoFactor' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'secret' + | 'backupCodes' + | 'userId' + | 'verified' + | 'failedVerificationCount' + | 'lockedUntil' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "jwks"; + model: 'jwks' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'publicKey' + | 'privateKey' + | 'createdAt' + | 'expiresAt' + | 'alg' + | 'crv' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; - }; - onDeleteHandle?: string; + | null + }> + } + onDeleteHandle?: string paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; + cursor: string | null + endCursor?: string | null + id?: number + maximumBytesRead?: number + maximumRowsRead?: number + numItems: number + } }, any, Name - >; + > deleteOne: FunctionReference< - "mutation", - "internal", + 'mutation', + 'internal', { input: | { - model: "user"; + model: 'user' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "name" - | "email" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "userId" - | "foo" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'name' + | 'email' + | 'emailVerified' + | 'image' + | 'createdAt' + | 'updatedAt' + | 'twoFactorEnabled' + | 'isAnonymous' + | 'userId' + | 'foo' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "session"; + model: 'session' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "expiresAt" - | "token" - | "createdAt" - | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'expiresAt' + | 'token' + | 'createdAt' + | 'updatedAt' + | 'ipAddress' + | 'userAgent' + | 'userId' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "account"; + model: 'account' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'accountId' + | 'providerId' + | 'userId' + | 'accessToken' + | 'refreshToken' + | 'idToken' + | 'accessTokenExpiresAt' + | 'refreshTokenExpiresAt' + | 'scope' + | 'password' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "verification"; + model: 'verification' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'identifier' + | 'value' + | 'expiresAt' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "twoFactor"; + model: 'twoFactor' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'secret' + | 'backupCodes' + | 'userId' + | 'verified' + | 'failedVerificationCount' + | 'lockedUntil' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "jwks"; + model: 'jwks' where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'publicKey' + | 'privateKey' + | 'createdAt' + | 'expiresAt' + | 'alg' + | 'crv' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; - }; - onDeleteHandle?: string; + | null + }> + } + onDeleteHandle?: string }, any, Name - >; + > findMany: FunctionReference< - "query", - "internal", + 'query', + 'internal', { - join?: any; - limit?: number; + join?: any + limit?: number model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "jwks"; - offset?: number; + | 'user' + | 'session' + | 'account' + | 'verification' + | 'twoFactor' + | 'jwks' + offset?: number paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; + cursor: string | null + endCursor?: string | null + id?: number + maximumBytesRead?: number + maximumRowsRead?: number + numItems: number + } + select?: Array + sortBy?: { direction: 'asc' | 'desc'; field: string } where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; + connector?: 'AND' | 'OR' + field: string + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> }, any, Name - >; + > findOne: FunctionReference< - "query", - "internal", + 'query', + 'internal', { - join?: any; + join?: any model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "jwks"; - select?: Array; + | 'user' + | 'session' + | 'account' + | 'verification' + | 'twoFactor' + | 'jwks' + select?: Array where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; + connector?: 'AND' | 'OR' + field: string + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> + }, + any, + Name + > + incrementOne: FunctionReference< + 'mutation', + 'internal', + { + input: + | { + increment: Record + model: 'user' + set?: { + createdAt?: number + email?: string + emailVerified?: boolean + foo?: null | string + image?: null | string + isAnonymous?: null | boolean + name?: string + twoFactorEnabled?: null | boolean + updatedAt?: number + userId?: null | string + } + where: Array<{ + connector?: 'AND' | 'OR' + field: + | 'name' + | 'email' + | 'emailVerified' + | 'image' + | 'createdAt' + | 'updatedAt' + | 'twoFactorEnabled' + | 'isAnonymous' + | 'userId' + | 'foo' + | '_id' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + | { + increment: Record + model: 'session' + set?: { + 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' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + | { + increment: Record + model: 'account' + set?: { + 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' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + | { + increment: Record + model: 'verification' + set?: { + createdAt?: number + expiresAt?: number + identifier?: string + updatedAt?: number + value?: string + } + where: Array<{ + connector?: 'AND' | 'OR' + field: + | 'identifier' + | 'value' + | 'expiresAt' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + | { + increment: Record + model: 'twoFactor' + set?: { + backupCodes?: string + failedVerificationCount?: null | number + lockedUntil?: null | number + secret?: string + userId?: string + verified?: null | boolean + } + where: Array<{ + connector?: 'AND' | 'OR' + field: + | 'secret' + | 'backupCodes' + | 'userId' + | 'verified' + | 'failedVerificationCount' + | 'lockedUntil' + | '_id' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + | { + increment: Record + model: 'jwks' + set?: { + alg?: null | string + createdAt?: number + crv?: null | string + expiresAt?: null | number + privateKey?: string + publicKey?: string + } + where: Array<{ + connector?: 'AND' | 'OR' + field: + | 'publicKey' + | 'privateKey' + | 'createdAt' + | 'expiresAt' + | 'alg' + | 'crv' + | '_id' + mode?: 'sensitive' | 'insensitive' + operator?: + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' + value: + | string + | number + | boolean + | Array + | Array + | null + }> + } + onUpdateHandle?: string }, any, Name - >; + > updateMany: FunctionReference< - "mutation", - "internal", + 'mutation', + 'internal', { input: | { - model: "user"; + model: 'user' update: { - createdAt?: number; - email?: string; - emailVerified?: boolean; - foo?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - }; + createdAt?: number + email?: string + emailVerified?: boolean + foo?: null | string + image?: null | string + isAnonymous?: null | boolean + name?: string + twoFactorEnabled?: null | boolean + updatedAt?: number + userId?: null | string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "name" - | "email" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "userId" - | "foo" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'name' + | 'email' + | 'emailVerified' + | 'image' + | 'createdAt' + | 'updatedAt' + | 'twoFactorEnabled' + | 'isAnonymous' + | 'userId' + | 'foo' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "session"; + model: 'session' update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + createdAt?: number + expiresAt?: number + ipAddress?: null | string + token?: string + updatedAt?: number + userAgent?: null | string + userId?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "expiresAt" - | "token" - | "createdAt" - | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'expiresAt' + | 'token' + | 'createdAt' + | 'updatedAt' + | 'ipAddress' + | 'userAgent' + | 'userId' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "account"; + 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; - }; + 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"; + connector?: 'AND' | 'OR' field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'accountId' + | 'providerId' + | 'userId' + | 'accessToken' + | 'refreshToken' + | 'idToken' + | 'accessTokenExpiresAt' + | 'refreshTokenExpiresAt' + | 'scope' + | 'password' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "verification"; + model: 'verification' update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; + createdAt?: number + expiresAt?: number + identifier?: string + updatedAt?: number + value?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'identifier' + | 'value' + | 'expiresAt' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "twoFactor"; + model: 'twoFactor' update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; + backupCodes?: string + failedVerificationCount?: null | number + lockedUntil?: null | number + secret?: string + userId?: string + verified?: null | boolean + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'secret' + | 'backupCodes' + | 'userId' + | 'verified' + | 'failedVerificationCount' + | 'lockedUntil' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "jwks"; + model: 'jwks' update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; + alg?: null | string + createdAt?: number + crv?: null | string + expiresAt?: null | number + privateKey?: string + publicKey?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'publicKey' + | 'privateKey' + | 'createdAt' + | 'expiresAt' + | 'alg' + | 'crv' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; - }; - onUpdateHandle?: string; + | null + }> + } + onUpdateHandle?: string paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; + cursor: string | null + endCursor?: string | null + id?: number + maximumBytesRead?: number + maximumRowsRead?: number + numItems: number + } }, any, Name - >; + > updateOne: FunctionReference< - "mutation", - "internal", + 'mutation', + 'internal', { input: | { - model: "user"; + model: 'user' update: { - createdAt?: number; - email?: string; - emailVerified?: boolean; - foo?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - }; + createdAt?: number + email?: string + emailVerified?: boolean + foo?: null | string + image?: null | string + isAnonymous?: null | boolean + name?: string + twoFactorEnabled?: null | boolean + updatedAt?: number + userId?: null | string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "name" - | "email" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "userId" - | "foo" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'name' + | 'email' + | 'emailVerified' + | 'image' + | 'createdAt' + | 'updatedAt' + | 'twoFactorEnabled' + | 'isAnonymous' + | 'userId' + | 'foo' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "session"; + model: 'session' update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + createdAt?: number + expiresAt?: number + ipAddress?: null | string + token?: string + updatedAt?: number + userAgent?: null | string + userId?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "expiresAt" - | "token" - | "createdAt" - | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'expiresAt' + | 'token' + | 'createdAt' + | 'updatedAt' + | 'ipAddress' + | 'userAgent' + | 'userId' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "account"; + 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; - }; + 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"; + connector?: 'AND' | 'OR' field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'accountId' + | 'providerId' + | 'userId' + | 'accessToken' + | 'refreshToken' + | 'idToken' + | 'accessTokenExpiresAt' + | 'refreshTokenExpiresAt' + | 'scope' + | 'password' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "verification"; + model: 'verification' update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; + createdAt?: number + expiresAt?: number + identifier?: string + updatedAt?: number + value?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'identifier' + | 'value' + | 'expiresAt' + | 'createdAt' + | 'updatedAt' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "twoFactor"; + model: 'twoFactor' update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; + backupCodes?: string + failedVerificationCount?: null | number + lockedUntil?: null | number + secret?: string + userId?: string + verified?: null | boolean + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'secret' + | 'backupCodes' + | 'userId' + | 'verified' + | 'failedVerificationCount' + | 'lockedUntil' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; + | null + }> } | { - model: "jwks"; + model: 'jwks' update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; + alg?: null | string + createdAt?: number + crv?: null | string + expiresAt?: null | number + privateKey?: string + publicKey?: string + } where?: Array<{ - connector?: "AND" | "OR"; + connector?: 'AND' | 'OR' field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; + | 'publicKey' + | 'privateKey' + | 'createdAt' + | 'expiresAt' + | 'alg' + | 'crv' + | '_id' + mode?: 'sensitive' | 'insensitive' operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; + | 'lt' + | 'lte' + | 'gt' + | 'gte' + | 'eq' + | 'in' + | 'not_in' + | 'ne' + | 'contains' + | 'starts_with' + | 'ends_with' value: | string | number | boolean | Array | Array - | null; - }>; - }; - onUpdateHandle?: string; + | null + }> + } + onUpdateHandle?: string }, any, Name - >; - }; - }; + > + } + } diff --git a/examples/tanstack/convex/betterAuth/adapter.ts b/examples/tanstack/convex/betterAuth/adapter.ts index e8f90a76..301e9e9e 100644 --- a/examples/tanstack/convex/betterAuth/adapter.ts +++ b/examples/tanstack/convex/betterAuth/adapter.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/examples/tanstack/convex/betterAuth/schema.ts b/examples/tanstack/convex/betterAuth/schema.ts index 2fade4aa..67730355 100644 --- a/examples/tanstack/convex/betterAuth/schema.ts +++ b/examples/tanstack/convex/betterAuth/schema.ts @@ -3,15 +3,15 @@ * To regenerate the schema, from your project root: * * cd convex/betterAuth - * npx auth generate + * npx auth generate --output schema.ts * * To customize the schema, generate to an alternate file and import * the table definitions to your schema file. See * https://labs.convex.dev/better-auth/features/local-install#adding-custom-indexes. */ -import { defineSchema, defineTable } from "convex/server"; -import { v } from "convex/values"; +import { defineSchema, defineTable } from 'convex/server' +import { v } from 'convex/values' export const tables = { user: defineTable({ @@ -26,9 +26,9 @@ export const tables = { userId: v.optional(v.union(v.null(), v.string())), foo: v.optional(v.union(v.null(), v.string())), }) - .index("email_name", ["email","name"]) - .index("name", ["name"]) - .index("userId", ["userId"]), + .index('email_name', ['email', 'name']) + .index('name', ['name']) + .index('userId', ['userId']), session: defineTable({ expiresAt: v.number(), token: v.string(), @@ -38,10 +38,10 @@ export const tables = { 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"]), + .index('expiresAt', ['expiresAt']) + .index('expiresAt_userId', ['expiresAt', 'userId']) + .index('token', ['token']) + .index('userId', ['userId']), account: defineTable({ accountId: v.string(), providerId: v.string(), @@ -56,10 +56,15 @@ export const tables = { createdAt: v.number(), updatedAt: v.number(), }) - .index("accountId", ["accountId"]) - .index("accountId_providerId", ["accountId","providerId"]) - .index("providerId_userId", ["providerId","userId"]) - .index("userId", ["userId"]), + .index('accountId', ['accountId']) + .index('accountId_providerId', ['accountId', 'providerId']) + .index('providerId_userId', ['providerId', 'userId']) + .index('userId_providerId_accountId', [ + 'userId', + 'providerId', + 'accountId', + ]) + .index('userId', ['userId']), verification: defineTable({ identifier: v.string(), value: v.string(), @@ -67,23 +72,26 @@ export const tables = { createdAt: v.number(), updatedAt: v.number(), }) - .index("expiresAt", ["expiresAt"]) - .index("identifier", ["identifier"]), + .index('expiresAt', ['expiresAt']) + .index('identifier', ['identifier']), twoFactor: defineTable({ secret: v.string(), backupCodes: v.string(), userId: v.string(), verified: v.optional(v.union(v.null(), v.boolean())), - }) - .index("userId", ["userId"]), + failedVerificationCount: v.optional(v.union(v.null(), v.number())), + lockedUntil: v.optional(v.union(v.null(), v.number())), + }).index('userId', ['userId']), jwks: defineTable({ publicKey: v.string(), privateKey: v.string(), createdAt: v.number(), expiresAt: v.optional(v.union(v.null(), v.number())), + alg: v.optional(v.union(v.null(), v.string())), + crv: v.optional(v.union(v.null(), v.string())), }), -}; +} -const schema = defineSchema(tables); +const schema = defineSchema(tables) -export default schema; +export default schema diff --git a/examples/tanstack/package-lock.json b/examples/tanstack/package-lock.json index 388d7a6b..6d547b3c 100644 --- a/examples/tanstack/package-lock.json +++ b/examples/tanstack/package-lock.json @@ -60,7 +60,7 @@ "version": "0.12.5", "license": "Apache-2.0", "dependencies": { - "@better-fetch/fetch": "^1.1.18", + "@better-fetch/fetch": "^1.3.2", "common-tags": "^1.8.2", "convex-helpers": "^0.1.128", "jose": "^6.1.0", @@ -70,8 +70,8 @@ "zod": "^4.0.0" }, "devDependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/test-utils": "1.6.15", + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", "@convex-dev/eslint-plugin": "2.0.0", "@edge-runtime/vm": "5.0.0", "@eslint/eslintrc": "3.3.5", @@ -82,7 +82,7 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@types/semver": "7.7.1", - "better-auth": "1.6.15", + "better-auth": "1.7.7", "chokidar-cli": "3.0.0", "concurrently": "10.0.3", "convex": "1.46.0", @@ -100,34 +100,34 @@ "react-dom": "19.2.6", "typescript": "5.9.3", "typescript-eslint": "8.59.2", - "vitest": "4.1.5" + "vitest": "4.1.10" }, "peerDependencies": { - "better-auth": ">=1.6.11 <1.7.0", + "better-auth": ">=1.7.7 <1.8.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" } }, "../../node_modules/better-auth": { - "version": "1.6.15", - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/drizzle-adapter": "1.6.15", - "@better-auth/kysely-adapter": "1.6.15", - "@better-auth/memory-adapter": "1.6.15", - "@better-auth/mongo-adapter": "1.6.15", - "@better-auth/prisma-adapter": "1.6.15", - "@better-auth/telemetry": "1.6.15", - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", - "better-call": "1.3.5", + "version": "1.7.1", + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.1", + "@better-auth/drizzle-adapter": "1.7.1", + "@better-auth/kysely-adapter": "1.7.1", + "@better-auth/memory-adapter": "1.7.1", + "@better-auth/mongo-adapter": "1.7.1", + "@better-auth/prisma-adapter": "1.7.1", + "@better-auth/telemetry": "1.7.1", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.1", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.0", "defu": "^6.1.4", - "jose": "^6.1.3", + "jose": "^6.2.3", "kysely": "^0.28.17 || ^0.29.0", - "nanostores": "^1.1.1", + "nanostores": "^1.3.0", "zod": "^4.3.6" }, "peerDependencies": { @@ -137,8 +137,8 @@ "@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.45.2", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", diff --git a/examples/tanstack/src/components/EnableTwoFactor.tsx b/examples/tanstack/src/components/EnableTwoFactor.tsx index 5f837a5d..22a62cf0 100644 --- a/examples/tanstack/src/components/EnableTwoFactor.tsx +++ b/examples/tanstack/src/components/EnableTwoFactor.tsx @@ -46,7 +46,7 @@ export default function EnableTwoFactor({ onBack }: { onBack: () => void }) { const { data } = await authClient.twoFactor.enable({ password, }) - if (data?.totpURI) { + if (data?.method === 'totp') { setTotpUri(data.totpURI) if (data.backupCodes) { setBackupCodes(data.backupCodes) diff --git a/package-lock.json b/package-lock.json index 9d7f564d..b5a65cf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.12.5", "license": "Apache-2.0", "dependencies": { - "@better-fetch/fetch": "^1.1.18", + "@better-fetch/fetch": "^1.3.2", "common-tags": "^1.8.2", "convex-helpers": "^0.1.128", "jose": "^6.1.0", @@ -19,8 +19,8 @@ "zod": "^4.0.0" }, "devDependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/test-utils": "1.6.15", + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", "@convex-dev/eslint-plugin": "2.0.0", "@edge-runtime/vm": "5.0.0", "@eslint/eslintrc": "3.3.5", @@ -31,7 +31,7 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@types/semver": "7.7.1", - "better-auth": "1.6.15", + "better-auth": "1.7.7", "chokidar-cli": "3.0.0", "concurrently": "10.0.3", "convex": "1.46.0", @@ -52,7 +52,7 @@ "vitest": "4.1.5" }, "peerDependencies": { - "better-auth": ">=1.6.11 <1.7.0", + "better-auth": ">=1.7.7 <1.8.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" } @@ -318,45 +318,41 @@ } }, "node_modules/@better-auth/core": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.6.15.tgz", - "integrity": "sha512-gPgeEn+2t2cohSKj1CJFCJLo4jNqvtvhKP/y6Uwuurg4ReEf2Y9PUCYffvbp7DDc+GevWTuD0Cv9x0+e83+HpA==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.7.7.tgz", + "integrity": "sha512-srgFzHEjB2WWlokFz1i4BfG41sNhsA105Pukgqu6RrEh5A+LSkzf1mCHydVipkjt9l5qswtBMi7IL6ouHbZL4Q==", "dev": true, "license": "MIT", "dependencies": { - "@opentelemetry/semantic-conventions": "^1.39.0", + "@opentelemetry/semantic-conventions": "^1.41.1", "@standard-schema/spec": "^1.1.0", - "zod": "^4.3.6" + "zod": "^4.5.4" }, "peerDependencies": { - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21", - "@cloudflare/workers-types": ">=4", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2", "@opentelemetry/api": "^1.9.0", - "better-call": "1.3.5", + "better-call": "1.4.0", "jose": "^6.1.0", "kysely": "^0.28.5 || ^0.29.0", "nanostores": "^1.0.1" }, "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - }, "@opentelemetry/api": { "optional": true } } }, "node_modules/@better-auth/drizzle-adapter": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.6.15.tgz", - "integrity": "sha512-+ho2RozN6cZmCN+6XkZd/ec5iolVlefgInQ7znJ18qRPbgllHxdyu9tGrgKZyEsXSCyqAa6wi5Yb4hd3WZmTNQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/drizzle-adapter/-/drizzle-adapter-1.7.7.tgz", + "integrity": "sha512-qon0U94PR5FQysuyGoAlGVQpIIiNg5dtDpwjE63sN/HjoRWZadZzHPcS9mn7JsJyQZK6iTNhd7LD0AaXt2f78w==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1", - "drizzle-orm": "^0.45.2" + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0" }, "peerDependenciesMeta": { "drizzle-orm": { @@ -365,14 +361,14 @@ } }, "node_modules/@better-auth/kysely-adapter": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.6.15.tgz", - "integrity": "sha512-E29Sugm+DWRK4oQNBPrjPA4kBYiKy2bBtX1arIlkuyAB9A1BEb4Xn+8t7wlNIF5eFcxpkFZ3F80ceSpWDSYU0Q==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/kysely-adapter/-/kysely-adapter-1.7.7.tgz", + "integrity": "sha512-9FONOCgOcrQI9wJ5v1oDGIg9sT7pa9RjZZQ4fsCTudo8R87SrIGNUvUxDFTJhZvUblvFfGaIBR9Vb8LA+8bqLQ==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1", + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2", "kysely": "^0.28.17 || ^0.29.0" }, "peerDependenciesMeta": { @@ -382,25 +378,25 @@ } }, "node_modules/@better-auth/memory-adapter": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/memory-adapter/-/memory-adapter-1.6.15.tgz", - "integrity": "sha512-BRE5Ft0Tn5thOPjCmyXHge7kOI/paLybaKDU+Hzg24DZMU6JvWooYWzvf52r1viDbxq5tz0G97iyaH4bouDyug==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/memory-adapter/-/memory-adapter-1.7.7.tgz", + "integrity": "sha512-FqKFEe+b5tXXV0gRbyirca+qXgMpLOeJ8Wk19yykb/scQKy0WJ4k22WzEV3TTPctQV9DZhwCXPlDtQhnlOv5Gg==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1" + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2" } }, "node_modules/@better-auth/mongo-adapter": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/mongo-adapter/-/mongo-adapter-1.6.15.tgz", - "integrity": "sha512-r0X9AtFhwDeOU1KMP9kZ5NeV0O3TSFzn8+uidaH+aicy2e1dNUsd9nPYrozEloSxdA2ZOnv5gD4jzH7HPeKkUQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/mongo-adapter/-/mongo-adapter-1.7.7.tgz", + "integrity": "sha512-ZnVDuRrXqbf0oHphrEN27oTImNH5NTO26dtWatq5cXyYAsH7goof9QIoTOmxTbBxUQahKBw9T6+9h6n+RtOE+g==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1", + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2", "mongodb": "^6.0.0 || ^7.0.0" }, "peerDependenciesMeta": { @@ -410,14 +406,14 @@ } }, "node_modules/@better-auth/prisma-adapter": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/prisma-adapter/-/prisma-adapter-1.6.15.tgz", - "integrity": "sha512-pUOlIUnpMu2l8C2ytgu46+OoOr3LZ+aLpJMFRGIPdnWl1BF2co2YaoZPT3+ZBu1Lzm0FrBN1ZRCAzZbkFoeIAQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/prisma-adapter/-/prisma-adapter-1.7.7.tgz", + "integrity": "sha512-4YcnrcVdvWiAZw0sZl63tWUClPXg5r3QsLn7C2sG7kKEBY06zOng0ibecyxRBixKq1zE1ceHuEUqez5Rhi+nQA==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1", + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, @@ -431,33 +427,33 @@ } }, "node_modules/@better-auth/telemetry": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.6.15.tgz", - "integrity": "sha512-eoFlUPVrVXLML9saHD11OSKKSRCAYETgRgBW4vQF3Y6pCgmThKD9oehYk3kkb/FsRgfqmsocmvAFqsiyjPIygg==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/telemetry/-/telemetry-1.7.7.tgz", + "integrity": "sha512-PaRA6i+kAioVYmza2gHPcdrxP0hAotph4KV9hft2GeNJq+AZXDiBu3FuLM9HxvcmiZeUT74Vufqd9ypmB8veTA==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21" + "@better-auth/core": "1.7.7", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2" } }, "node_modules/@better-auth/test-utils": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@better-auth/test-utils/-/test-utils-1.6.15.tgz", - "integrity": "sha512-q5rvEsAhBHAXniwMlZpE1GiRSBPu/3rZM4iA5yOJ5uDw7fZjvWuufsJUc8raQuripXquLQZBYlGtVInHBadMyw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/@better-auth/test-utils/-/test-utils-1.7.7.tgz", + "integrity": "sha512-110vhQ9r/va7h/4ABIcejoy+p/lwBgoyEI8d4N1RRZ8Zh4T8IiDnGsOCj/VUVP3WBAy2vIZcd3rajZtjkg9yAw==", "dev": true, "license": "MIT", "peerDependencies": { - "@better-auth/core": "^1.6.15", - "better-auth": "^1.6.15", - "vitest": "^4.1.5" + "@better-auth/core": "1.7.7", + "better-auth": "1.7.7", + "vitest": "^4.0.0 || ^5.0.0" } }, "node_modules/@better-auth/utils": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.4.1.tgz", - "integrity": "sha512-SZBPRPF3z0nBvE5ygOkxae35wnnXPRShmqFo78S+qslLeFoPu/pMgnXAuNKFMMybac3tiLaVg1e3MQW5MC+1iA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.4.2.tgz", + "integrity": "sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==", "dev": true, "license": "MIT", "dependencies": { @@ -465,9 +461,10 @@ } }, "node_modules/@better-fetch/fetch": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.21.tgz", - "integrity": "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==" + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.3.2.tgz", + "integrity": "sha512-Gs7n99b5tqUC6cQAPbV0uED3IraHB6xQbHLQ/C3l7ZFafHScOx9pQ+DYmP5blbLFShVWLqxNUlI9wi4xU/X+ow==", + "license": "MIT" }, "node_modules/@convex-dev/eslint-plugin": { "version": "2.0.0", @@ -2062,9 +2059,9 @@ } }, "node_modules/@noble/ciphers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.2.0.tgz", - "integrity": "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.4.0.tgz", + "integrity": "sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==", "dev": true, "license": "MIT", "engines": { @@ -2075,9 +2072,9 @@ } }, "node_modules/@noble/hashes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", - "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.3.0.tgz", + "integrity": "sha512-oN+QwyX7VSHotibwubG3kpzbwKrfnyR6OOO+3Nk/53ADL7FmgHHz4TgrbaYKvvOw09u6QTx0oiH1cNCIOuN0CQ==", "dev": true, "license": "MIT", "engines": { @@ -2140,9 +2137,9 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz", - "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3826,29 +3823,29 @@ } }, "node_modules/better-auth": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.6.15.tgz", - "integrity": "sha512-0nuQuEru3ZrLF+9xFUuN3llAmR+6gHLtLunoXaZxB9lXGjSmfBcc6SZUgYq4DfzugPnLvdnzYazsyprZFSFC4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/drizzle-adapter": "1.6.15", - "@better-auth/kysely-adapter": "1.6.15", - "@better-auth/memory-adapter": "1.6.15", - "@better-auth/mongo-adapter": "1.6.15", - "@better-auth/prisma-adapter": "1.6.15", - "@better-auth/telemetry": "1.6.15", - "@better-auth/utils": "0.4.1", - "@better-fetch/fetch": "1.1.21", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", - "better-call": "1.3.5", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.7.7.tgz", + "integrity": "sha512-Zhgxi/c5ylmfB/sX+nwnBbsFf/j6k0L8DvL6CJXZSrXgxc5pPMC/e7j812zNd4L4B4ELmdURCPw3X8nAOUdcjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@better-auth/core": "1.7.7", + "@better-auth/drizzle-adapter": "1.7.7", + "@better-auth/kysely-adapter": "1.7.7", + "@better-auth/memory-adapter": "1.7.7", + "@better-auth/mongo-adapter": "1.7.7", + "@better-auth/prisma-adapter": "1.7.7", + "@better-auth/telemetry": "1.7.7", + "@better-auth/utils": "0.4.2", + "@better-fetch/fetch": "1.3.2", + "@noble/ciphers": "^2.2.0", + "@noble/hashes": "^2.2.0", + "better-call": "1.4.0", "defu": "^6.1.4", - "jose": "^6.1.3", + "jose": "^6.2.3", "kysely": "^0.28.17 || ^0.29.0", - "nanostores": "^1.1.1", - "zod": "^4.3.6" + "nanostores": "^1.3.0", + "zod": "^4.5.4" }, "peerDependencies": { "@lynx-js/react": "*", @@ -3856,9 +3853,8 @@ "@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.45.2", + "drizzle-kit": ">=0.31.4 || >=1.0.0-beta.1", + "drizzle-orm": "^0.45.2 || >=1.0.0-rc.1 <2.0.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", @@ -3868,7 +3864,7 @@ "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", + "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "vue": "^3.0.0" }, "peerDependenciesMeta": { @@ -3887,9 +3883,6 @@ "@tanstack/solid-start": { "optional": true }, - "better-sqlite3": { - "optional": true - }, "drizzle-kit": { "optional": true }, @@ -3932,16 +3925,16 @@ } }, "node_modules/better-call": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.3.5.tgz", - "integrity": "sha512-kOFJkBP7utAQLEYrobZm3vkTH8mXq5GNgvjc5/XEST1ilVHaxXUXfeDeFlqoETMtyqS4+3/h4ONX2i++ebZrvA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.4.0.tgz", + "integrity": "sha512-bBKOT4vv1kZLDgxVePdilk/Jwkn+dtRRsmi3DzHcDP+WnswyVl6dR59l2HEeP/0cB+bDoopASAesWDPIdd/zZA==", "dev": true, "license": "MIT", "dependencies": { - "@better-auth/utils": "^0.4.0", - "@better-fetch/fetch": "^1.1.21", - "rou3": "^0.7.12", - "set-cookie-parser": "^3.0.1" + "@better-auth/utils": "^0.5.0", + "@better-fetch/fetch": "^1.3.1", + "rou3": "^0.9.1", + "set-cookie-parser": "^3.1.2" }, "peerDependencies": { "zod": "^4.0.0" @@ -3952,6 +3945,16 @@ } } }, + "node_modules/better-call/node_modules/@better-auth/utils": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.5.0.tgz", + "integrity": "sha512-BL8W4EfIZFwlu0r54m3v1ztjDhu6dDe/amLTm0xybmbZaNgYUqhD3SjpAsnq0q8YD6/ki4iwIgxJNLP/N3TxiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^2.0.1" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -6890,9 +6893,9 @@ } }, "node_modules/nanostores": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.2.0.tgz", - "integrity": "sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.5.2.tgz", + "integrity": "sha512-B0UbxzK1s0CN8Xht6r+7iT5+xV8PTaRERR1nATeplRv1Rw5YLWfVAid0hkqY3EceqpG4RjTk8GAwIxQY39Rnwg==", "dev": true, "funding": [ { @@ -7592,9 +7595,9 @@ "license": "MIT" }, "node_modules/rou3": { - "version": "0.7.12", - "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.7.12.tgz", - "integrity": "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.9.2.tgz", + "integrity": "sha512-3SOzvaAg8rkHrXtRjpCvCvbyO5to9oOO27Z/XqHEYXfMRVSw/qMIVdmaOk9W2lcRLtR6dlqTjo9hDeJk70QBYQ==", "dev": true, "license": "MIT" }, @@ -7713,9 +7716,9 @@ "license": "ISC" }, "node_modules/set-cookie-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz", - "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.2.tgz", + "integrity": "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw==", "dev": true, "license": "MIT" }, @@ -8240,9 +8243,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", - "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 17366e76..f9b5a9d9 100644 --- a/package.json +++ b/package.json @@ -101,13 +101,13 @@ } }, "peerDependencies": { - "better-auth": ">=1.6.11 <1.7.0", + "better-auth": ">=1.7.7 <1.8.0", "convex": "^1.25.0", "react": "^18.3.1 || ^19.0.0" }, "devDependencies": { - "@better-auth/core": "1.6.15", - "@better-auth/test-utils": "1.6.15", + "@better-auth/core": "1.7.7", + "@better-auth/test-utils": "1.7.7", "@convex-dev/eslint-plugin": "2.0.0", "@edge-runtime/vm": "5.0.0", "@eslint/eslintrc": "3.3.5", @@ -118,7 +118,7 @@ "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@types/semver": "7.7.1", - "better-auth": "1.6.15", + "better-auth": "1.7.7", "chokidar-cli": "3.0.0", "concurrently": "10.0.3", "convex": "1.46.0", @@ -141,7 +141,7 @@ "types": "./dist/client/index.d.ts", "module": "./dist/client/index.js", "dependencies": { - "@better-fetch/fetch": "^1.1.18", + "@better-fetch/fetch": "^1.3.2", "common-tags": "^1.8.2", "convex-helpers": "^0.1.128", "jose": "^6.1.0", diff --git a/src/auth-config.test.ts b/src/auth-config.test.ts new file mode 100644 index 00000000..a7725bc5 --- /dev/null +++ b/src/auth-config.test.ts @@ -0,0 +1,66 @@ +import { afterEach, beforeEach, describe, expect, it } from "vitest"; +import { getAuthConfigProvider } from "./auth-config.js"; + +describe("getAuthConfigProvider", () => { + const originalConvexSiteUrl = process.env.CONVEX_SITE_URL; + + beforeEach(() => { + process.env.CONVEX_SITE_URL = "https://deployment.convex.site/"; + }); + + afterEach(() => { + if (originalConvexSiteUrl === undefined) { + delete process.env.CONVEX_SITE_URL; + } else { + process.env.CONVEX_SITE_URL = originalConvexSiteUrl; + } + }); + + it.each([ + [undefined, "https://deployment.convex.site/api/auth/convex/jwks"], + ["/", "https://deployment.convex.site/convex/jwks"], + ["/custom/auth/", "https://deployment.convex.site/custom/auth/convex/jwks"], + ["custom/auth", "https://deployment.convex.site/custom/auth/convex/jwks"], + ])("normalizes the %s base path", (basePath, expected) => { + expect(getAuthConfigProvider({ basePath }).jwks).toBe(expected); + }); + + it("reports a missing Convex site URL", () => { + delete process.env.CONVEX_SITE_URL; + + expect(() => getAuthConfigProvider()).toThrow("CONVEX_SITE_URL is not set"); + }); + + it.each(["deployment.convex.site", "ftp://deployment.convex.site"])( + "rejects the invalid Convex site URL %s", + (siteUrl) => { + process.env.CONVEX_SITE_URL = siteUrl; + + expect(() => getAuthConfigProvider()).toThrow( + "CONVEX_SITE_URL must be a valid HTTP or HTTPS URL" + ); + expect(() => getAuthConfigProvider({ jwks: "[]" })).toThrow( + "CONVEX_SITE_URL must be a valid HTTP or HTTPS URL" + ); + } + ); + + it.each([ + "https://deployment.convex.site?region=us", + "https://deployment.convex.site#fragment", + ])("rejects URL components in the Convex site URL %s", (siteUrl) => { + process.env.CONVEX_SITE_URL = siteUrl; + + expect(() => getAuthConfigProvider()).toThrow( + "CONVEX_SITE_URL must not include a query string or fragment" + ); + }); + + it("accepts an HTTP URL for a local Convex deployment", () => { + process.env.CONVEX_SITE_URL = "http://127.0.0.1:3211"; + + expect(getAuthConfigProvider().jwks).toBe( + "http://127.0.0.1:3211/api/auth/convex/jwks" + ); + }); +}); diff --git a/src/auth-config.ts b/src/auth-config.ts index 246974fc..b7ecae36 100644 --- a/src/auth-config.ts +++ b/src/auth-config.ts @@ -1,6 +1,7 @@ import type { JwtOptions } from "better-auth/plugins/jwt"; import type { AuthProvider } from "convex/server"; import type { JSONWebKeySet } from "jose"; +import { getJwksUrl, validateConvexSiteUrl } from "./jwks-url.js"; type JwksDoc = { id: string; @@ -69,14 +70,19 @@ export const getAuthConfigProvider = (opts?: { */ jwks?: string; }) => { + const siteUrl = process.env.CONVEX_SITE_URL; + if (!siteUrl) { + throw new Error("CONVEX_SITE_URL is not set"); + } + validateConvexSiteUrl(siteUrl); const parsedJwks = opts?.jwks ? JSON.parse(opts.jwks) : undefined; return { type: "customJwt", - issuer: `${process.env.CONVEX_SITE_URL}`, + issuer: siteUrl, applicationID: "convex", algorithm: "RS256", jwks: parsedJwks ? `data:text/plain;charset=utf-8;base64,${btoa(JSON.stringify(createPublicJwks(parsedJwks)))}` - : `${process.env.CONVEX_SITE_URL}${opts?.basePath ?? "/api/auth"}/convex/jwks`, + : getJwksUrl(siteUrl, opts?.basePath), } satisfies AuthProvider; }; diff --git a/src/auth-options.ts b/src/auth-options.ts index 6281482f..eda273f4 100644 --- a/src/auth-options.ts +++ b/src/auth-options.ts @@ -5,7 +5,6 @@ import { emailOTP } from "better-auth/plugins/email-otp"; import { genericOAuth } from "better-auth/plugins/generic-oauth"; import { jwt } from "better-auth/plugins/jwt"; import { magicLink } from "better-auth/plugins/magic-link"; -import { oidcProvider } from "better-auth/plugins/oidc-provider"; import { oneTimeToken } from "better-auth/plugins/one-time-token"; import { phoneNumber } from "better-auth/plugins/phone-number"; import { twoFactor } from "better-auth/plugins/two-factor"; @@ -35,10 +34,6 @@ export const options = { }, ], }), - oidcProvider({ - loginPage: "/login", - __skipDeprecationWarning: true, - }), bearer(), oneTimeToken(), jwt(), diff --git a/src/client/adapter-compatibility.test.ts b/src/client/adapter-compatibility.test.ts new file mode 100644 index 00000000..d552c9d7 --- /dev/null +++ b/src/client/adapter-compatibility.test.ts @@ -0,0 +1,200 @@ +/// + +import { describe, expect, it } from "vitest"; +import { convexTest } from "convex-test"; +import { api } from "../component/_generated/api.js"; +import schema from "../component/schema.js"; +import { convexAdapter } from "./adapter.js"; + +const setup = () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + const adapter = convexAdapter( + { + runQuery: t.query.bind(t), + runMutation: t.mutation.bind(t), + } as any, + { adapter: api.adapter } as any + )({}); + return { t, adapter }; +}; + +describe("Better Auth 1.7.7 compatibility", () => { + it.each([false, true])( + "keeps modelKey out of component calls (OR: %s)", + async (or) => { + const { adapter } = setup(); + await adapter.create({ + model: "user", + data: { name: "Alice", email: "alice@example.com" }, + }); + const where = or + ? [ + { field: "name", value: "Alice", connector: "OR" as const }, + { + field: "email", + value: "alice@example.com", + connector: "OR" as const, + }, + ] + : [{ field: "name", value: "Alice" }]; + expect(await adapter.findOne({ model: "user", where })).toMatchObject({ + name: "Alice", + }); + expect(await adapter.findMany({ model: "user", where })).toHaveLength(1); + expect(await adapter.count({ model: "user", where })).toBe(1); + expect( + await adapter.updateMany({ + model: "user", + where, + update: { emailVerified: true }, + }) + ).toBe(1); + expect(await adapter.findOne({ model: "user", where })).toMatchObject({ + emailVerified: true, + }); + expect(await adapter.deleteMany({ model: "user", where })).toBe(1); + expect(await adapter.count({ model: "user", where })).toBe(0); + } + ); + + it("does not revisit rows when filtered pagination splits a page", async () => { + const { t, adapter } = setup(); + await t.run(async (ctx) => { + // Rejected rows force the scan budget to split before 200 matches. + for (let i = 0; i < 4; i++) { + await ctx.db.insert("user", { + name: `Other ${i}`, + email: `other-${i}@example.com`, + emailVerified: false, + createdAt: 1, + updatedAt: 1, + }); + } + for (let i = 0; i < 205; i++) { + await ctx.db.insert("user", { + name: `Fixture ${i}`, + email: `fixture-${i}@example.com`, + emailVerified: false, + createdAt: 1, + updatedAt: 1, + }); + } + }); + const where = [ + { field: "email", operator: "starts_with" as const, value: "fixture-" }, + ]; + expect(await adapter.count({ model: "user", where })).toBe(205); + const users = await adapter.findMany<{ id: string }>({ + model: "user", + where, + limit: 1000, + }); + expect(users).toHaveLength(205); + expect(new Set(users.map((user) => user.id)).size).toBe(205); + const limited = await adapter.findMany<{ id: string }>({ + model: "user", + where, + limit: 200, + }); + expect(limited).toHaveLength(200); + expect(new Set(limited.map((user) => user.id)).size).toBe(200); + expect( + await adapter.updateMany({ + model: "user", + where, + update: { name: "Updated" }, + }) + ).toBe(205); + expect(await adapter.deleteMany({ model: "user", where })).toBe(205); + expect(await adapter.count({ model: "user", where })).toBe(0); + }); + + it.each([undefined, null, "already-set"])( + "guards atomic updates against a null optional field (stored: %s)", + async (image) => { + const { adapter } = setup(); + const user = await adapter.create<{ id: string }>({ + model: "user", + data: { + name: "Alice", + email: "alice@example.com", + ...(image !== undefined ? { image } : {}), + }, + }); + const where = [ + { field: "id", value: user.id }, + { field: "image", operator: "eq" as const, value: null }, + ]; + const expectedMatch = image == null; + expect(Boolean(await adapter.findOne({ model: "user", where }))).toBe( + expectedMatch + ); + expect(await adapter.findMany({ model: "user", where })).toHaveLength( + expectedMatch ? 1 : 0 + ); + expect( + Boolean( + await adapter.findOne({ + model: "user", + where: [ + { field: "id", value: user.id }, + { field: "image", operator: "ne", value: null }, + ], + }) + ) + ).toBe(!expectedMatch); + // OAuth refresh rotation uses this shape: an empty increment with a + // guarded set, where the revocation field may never have been written. + const claimed = await adapter.incrementOne<{ image: string }>({ + model: "user", + where, + increment: {}, + set: { image: "claimed" }, + }); + expect(claimed?.image ?? null).toBe(expectedMatch ? "claimed" : null); + expect( + await adapter.incrementOne({ + model: "user", + where, + increment: {}, + set: { image: "claimed-again" }, + }) + ).toBeNull(); + } + ); + + it("creates and updates core accounts without an issuer backfill", async () => { + const { t, adapter } = setup(); + const account = await adapter.create({ + model: "account", + data: { + accountId: "subject", + providerId: "provider-a", + userId: "user-a", + createdAt: new Date(), + updatedAt: new Date(), + }, + }); + await adapter.create({ + model: "account", + data: { + accountId: "subject", + providerId: "provider-b", + userId: "user-b", + createdAt: new Date(), + updatedAt: new Date(), + }, + }); + await adapter.update({ + model: "account", + where: [{ field: "id", value: account.id }], + update: { scope: "openid" }, + }); + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(2); + expect(accounts.every((row) => row.issuer === undefined)).toBe(true); + expect(accounts.find((row) => row.providerId === "provider-a")?.scope).toBe( + "openid" + ); + }); +}); diff --git a/src/client/adapter-utils.test.ts b/src/client/adapter-utils.test.ts new file mode 100644 index 00000000..1e0680f1 --- /dev/null +++ b/src/client/adapter-utils.test.ts @@ -0,0 +1,131 @@ +/// + +import { describe, expect, it, vi } from "vitest"; +import { convexTest } from "convex-test"; +import { defineSchema, defineTable } from "convex/server"; +import { v } from "convex/values"; +import type { BetterAuthDBSchema } from "better-auth/db"; +import { checkUniqueFields, paginate } from "./adapter-utils.js"; + +const schema = defineSchema({ + account: defineTable({ + issuer: v.string(), + accountId: v.string(), + }).index("issuer_accountId", ["issuer", "accountId"]), +}); + +const betterAuthSchema = { + account: { + modelName: "account", + fields: { + issuer: { type: "string", required: true }, + accountId: { type: "string", required: true }, + }, + indexes: [{ fields: ["issuer", "accountId"], unique: true }], + }, +} satisfies BetterAuthDBSchema; + +const credentialSchema = defineSchema({ + account: defineTable({ + userId: v.string(), + providerId: v.string(), + issuer: v.string(), + accountId: v.string(), + }).index("userId_providerId_issuer_accountId", [ + "userId", + "providerId", + "issuer", + "accountId", + ]), +}); + +const credentialBetterAuthSchema = { + account: { + modelName: "account", + fields: { + userId: { type: "string", required: true }, + providerId: { type: "string", required: true }, + issuer: { type: "string", required: true }, + accountId: { type: "string", required: true }, + }, + }, +} satisfies BetterAuthDBSchema; + +const modules = import.meta.glob("../component/**/*.*s"); + +describe("ordered compound indexes", () => { + it("uses an index for Better Auth's credential account lookup", async () => { + const t = convexTest(credentialSchema, modules); + const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined); + + try { + await t.run((ctx) => + paginate(ctx, credentialSchema, credentialBetterAuthSchema, { + model: "account", + where: [ + { field: "userId", value: "user-1" }, + { field: "providerId", value: "credential" }, + { field: "issuer", value: "local:credential" }, + { field: "accountId", value: "user-1" }, + ], + paginationOpts: { cursor: null, numItems: 1 }, + }) + ); + expect(warn).not.toHaveBeenCalled(); + } finally { + warn.mockRestore(); + } + }); + + it("pairs equality values with fields in the selected index order", async () => { + const t = convexTest(schema, modules); + await t.run(async (ctx) => { + await ctx.db.insert("account", { + issuer: "issuer-value", + accountId: "account-value", + }); + await ctx.db.insert("account", { + issuer: "account-value", + accountId: "issuer-value", + }); + }); + + const result = await t.run((ctx) => + paginate(ctx, schema, betterAuthSchema, { + model: "account", + where: [ + { field: "accountId", value: "account-value" }, + { field: "issuer", value: "issuer-value" }, + ], + paginationOpts: { cursor: null, numItems: 10 }, + }) + ); + + expect(result.page).toHaveLength(1); + expect(result.page[0]).toMatchObject({ + issuer: "issuer-value", + accountId: "account-value", + }); + }); + + it("checks compound uniqueness against the declared index order", async () => { + const t = convexTest(schema, modules); + await t.run((ctx) => + ctx.db.insert("account", { + issuer: "issuer-value", + accountId: "account-value", + }) + ); + + await expect( + t.run((ctx) => + checkUniqueFields(ctx, schema, betterAuthSchema, "account", { + issuer: "issuer-value", + accountId: "account-value", + }) + ) + ).rejects.toThrow( + "account unique constraint issuer+accountId already exists" + ); + }); +}); diff --git a/src/client/adapter-utils.ts b/src/client/adapter-utils.ts index 7e04ffdf..66eafe76 100644 --- a/src/client/adapter-utils.ts +++ b/src/client/adapter-utils.ts @@ -58,33 +58,54 @@ export const adapterArgsValidator = v.object({ offset: v.optional(v.number()), }); -const isUniqueField = ( +const getUniqueConstraints = ( betterAuthSchema: BetterAuthDBSchema, - model: string, - field: string + model: string ) => { - const fields = Object.values(betterAuthSchema).find( + const table = Object.values(betterAuthSchema).find( (value) => value.modelName === model - )?.fields; - if (!fields) { - return false; + ); + if (!table) { + return []; } - return Object.entries(fields) + const singleFieldConstraints = Object.entries(table.fields) .filter(([, value]) => value.unique) - .map(([key]) => key) - .includes(field); + .map(([key, value]) => [value.fieldName ?? key]); + const tableConstraints = + table.indexes + ?.filter((index) => index.unique) + .map((index) => + index.fields.map((field) => table.fields[field]?.fieldName ?? field) + ) ?? []; + return [...singleFieldConstraints, ...tableConstraints]; }; +const isUniqueField = ( + betterAuthSchema: BetterAuthDBSchema, + model: string, + field: string +) => + getUniqueConstraints(betterAuthSchema, model).some( + (constraint) => constraint.length === 1 && constraint[0] === field + ); export const hasUniqueFields = ( betterAuthSchema: BetterAuthDBSchema, model: string, input: Record ) => { - for (const field of Object.keys(input)) { - if (isUniqueField(betterAuthSchema, model, field)) { - return true; - } - } - return false; + const inputFields = new Set(Object.keys(input)); + return getUniqueConstraints(betterAuthSchema, model).some((constraint) => + constraint.every((field) => inputFields.has(field)) + ); +}; +export const touchesUniqueFields = ( + betterAuthSchema: BetterAuthDBSchema, + model: string, + input: Record +) => { + const inputFields = new Set(Object.keys(input)); + return getUniqueConstraints(betterAuthSchema, model).some((constraint) => + constraint.some((field) => inputFields.has(field)) + ); }; const findIndex = ( @@ -170,10 +191,7 @@ const findIndex = ( const indexEqFields = where ?.filter((w) => !w.operator || w.operator === "eq") - .sort((a, b) => { - return a.field.localeCompare(b.field); - }) - .map((w) => [w.field, w.value]) ?? []; + .map((w) => [w.field, w.value] as const) ?? []; if (!indexEqFields?.length && !boundField && !args.sortBy) { return; } @@ -185,8 +203,16 @@ const findIndex = ( const sortField = args.sortBy?.field; // We internally use _creationTime in place of Better Auth's createdAt - const indexFields = indexEqFields - .map(([field]) => field) + const eqFields = indexEqFields.map(([field]) => field); + const eqValues = new Map(indexEqFields); + const suffixFields = [ + boundField && boundField !== "createdAt" ? boundField : "", + sortField && sortField !== "createdAt" && boundField !== sortField + ? sortField + : "", + ].filter(Boolean); + const indexFields = [...eqFields] + .sort((a, b) => a.localeCompare(b)) .concat(boundField && boundField !== "createdAt" ? boundField : "") .concat( sortField && sortField !== "createdAt" && boundField !== sortField @@ -204,18 +230,35 @@ const findIndex = ( indexDescriptor: "by_creation_time", fields: [], } - : indexes.find(({ fields }: { fields: string[] }) => { - const fieldsMatch = indexFields.every( - (field, idx) => field === fields[idx] - ); - // If sorting by createdAt, no intermediate fields can be on the index - // as they may override the createdAt sort order. - const boundFieldMatch = - boundField === "createdAt" || sortField === "createdAt" - ? indexFields.length === fields.length - : true; - return fieldsMatch && boundFieldMatch; - }); + : (indexes.find(({ fields }: { fields: string[] }) => + matchesIndex(fields, true) + ) ?? + indexes.find(({ fields }: { fields: string[] }) => + matchesIndex(fields, false) + )); + + function matchesIndex(fields: string[], requireExactEqOrder: boolean) { + if ( + eqValues.size !== eqFields.length || + fields.length < eqFields.length + suffixFields.length + ) { + return false; + } + const eqPrefix = fields.slice(0, eqFields.length); + const eqFieldsMatch = requireExactEqOrder + ? eqPrefix.every((field, index) => field === eqFields[index]) + : eqPrefix.every((field) => eqValues.has(field)); + const suffixFieldsMatch = suffixFields.every( + (field, index) => field === fields[eqFields.length + index] + ); + // If sorting by createdAt, no intermediate fields can be on the index + // as they may override the createdAt sort order. + const createdAtFieldMatch = + boundField === "createdAt" || sortField === "createdAt" + ? eqFields.length + suffixFields.length === fields.length + : true; + return eqFieldsMatch && suffixFieldsMatch && createdAtFieldMatch; + } if (!index) { return { indexFields }; } @@ -227,7 +270,9 @@ const findIndex = ( boundField, sortField, values: { - eq: indexEqFields.map(([, value]) => value), + eq: index.fields + .slice(0, eqFields.length) + .map((field: string) => [field, eqValues.get(field)!] as const), lt: lowerBound?.operator === "lt" ? lowerBound.value : undefined, lte: lowerBound?.operator === "lte" ? lowerBound.value : undefined, gt: upperBound?.operator === "gt" ? upperBound.value : undefined, @@ -246,31 +291,51 @@ export const checkUniqueFields = async < input: Record, doc?: Record ) => { - if (!hasUniqueFields(betterAuthSchema, table, input)) { - return; - } - for (const field of Object.keys(input)) { - if (!isUniqueField(betterAuthSchema, table, field)) { + const mergedDoc = { ...doc, ...input }; + for (const constraint of getUniqueConstraints(betterAuthSchema, table)) { + if ( + !constraint.some((field) => field in input) || + !constraint.every((field) => mergedDoc[field] !== undefined) + ) { continue; } - const { index } = - findIndex(schema, { - model: table, - where: [ - { field, operator: "eq", value: input[field as keyof typeof input] }, - ], - }) || {}; + const { index } = findIndex(schema, { + model: table, + where: constraint.map((field) => ({ + field, + operator: "eq" as const, + value: mergedDoc[field], + })), + }) || { index: undefined }; if (!index) { - throw new Error(`No index found for ${table}${field}`); + throw new Error( + `No index found for unique constraint ${table}.${constraint.join("+")}` + ); } - const existingDoc = await ctx.db + const indexConstraintFields = index.fields.slice(0, constraint.length); + if ( + indexConstraintFields.length !== constraint.length || + !indexConstraintFields.every((field) => constraint.includes(field)) + ) { + throw new Error( + `Index ${index.indexDescriptor} does not match unique constraint ${table}.${constraint.join("+")}` + ); + } + const existingDocs = await ctx.db .query(table as any) .withIndex(index.indexDescriptor, (q) => - q.eq(field, input[field as keyof typeof input]) + indexConstraintFields.reduce( + (query: any, field: string) => query.eq(field, mergedDoc[field]), + q + ) ) - .unique(); - if (existingDoc && existingDoc._id !== doc?._id) { - throw new Error(`${table} ${field} already exists`); + .take(2); + if (existingDocs.some((existingDoc) => existingDoc._id !== doc?._id)) { + const constraintName = + constraint.length === 1 + ? constraint[0] + : `unique constraint ${constraint.join("+")}`; + throw new Error(`${table} ${constraintName} already exists`); } } }; @@ -343,7 +408,9 @@ const filterByWhere = < switch (w.operator) { case undefined: case "eq": { - return value === w.value; + // Convex omits unset optional fields; Better Auth's null guards must + // also match those fields (for example, unrevoked refresh tokens). + return w.value === null ? value == null : value === w.value; } case "in": { return Array.isArray(w.value) && (w.value as any[]).includes(value); @@ -366,7 +433,7 @@ const filterByWhere = < return value === w.value || isGreaterThan(value, w.value); } case "ne": { - return value !== w.value; + return w.value === null ? value != null : value !== w.value; } case "contains": { return typeof value === "string" && value.includes(w.value as string); @@ -409,8 +476,8 @@ const generateQuery = ( usableIndex.indexDescriptor, hasValues ? (q: any) => { - for (const [idx, value] of (values?.eq ?? []).entries()) { - q = q.eq(usableIndex.fields[idx], value); + for (const [field, value] of values?.eq ?? []) { + q = q.eq(field, value); } if (values?.lt !== undefined) { q = q.lt(boundField, values.lt); @@ -518,9 +585,7 @@ export const paginate = async < where: [uniqueWhere], }) || {}; if (uniqueWhere.field !== "_id" && !index) { - throw new Error( - `No index found for ${args.model}.${uniqueWhere.field}` - ); + throw new Error(`No index found for ${args.model}.${uniqueWhere.field}`); } const doc = uniqueWhere.field === "_id" @@ -530,7 +595,7 @@ export const paginate = async < : await ctx.db .query(args.model as any) .withIndex(index?.indexDescriptor as any, (q) => - q.eq(index?.fields[0], uniqueWhere.value) + q.eq(uniqueWhere.field, uniqueWhere.value) ) .unique(); diff --git a/src/client/adapter.test.ts b/src/client/adapter.test.ts index c5fe58ee..f6139834 100644 --- a/src/client/adapter.test.ts +++ b/src/client/adapter.test.ts @@ -25,6 +25,8 @@ import { renameModelUserTableTestSuite, } from "../test/adapter-factory/index.js"; +import { constraintsProfileOptions } from "../component/testProfiles/auth-options.constraints.js"; + const MIN_NODE_MAJOR = 24; const currentNodeMajor = Number.parseInt( process.versions.node.split(".")[0] ?? "0", @@ -91,6 +93,7 @@ const getOverrideBetterAuthOptions = ( type AdapterModule = ComponentApi["adapter"]; type TestProfileName = + | "adapterConstraints" | "adapterAdditionalFields" | "adapterPluginTable" | "adapterRenameField" @@ -169,10 +172,28 @@ if (currentNodeMajor < MIN_NODE_MAJOR) { }), transactionsTestSuite({ disableTests: { ALL: true } }), coreAuthFlowTestSuite(), - convexCustomTestSuite(), ], }); + const constraintsProfileClient = createClient( + profileApi("adapterConstraints"), + { verbose: false } + ); + const { execute: executeConstraintsProfile } = await testAdapter({ + adapter: () => constraintsProfileClient.adapter(wrappedCtx), + runMigrations: noMigrations, + overrideBetterAuthOptions: (opts) => + getOverrideBetterAuthOptions({ + ...opts, + plugins: [ + ...(opts.plugins ?? []), + ...constraintsProfileOptions.plugins, + ], + }), + prefixTests: "profile:custom-constraints", + tests: [convexCustomTestSuite()], + }); + const { execute: executeAdditionalFieldsProfile } = await testAdapter({ adapter: () => additionalFieldsProfileClient.adapter(wrappedCtx), runMigrations: noMigrations, @@ -225,6 +246,7 @@ if (currentNodeMajor < MIN_NODE_MAJOR) { }); executeBaseProfile(); + executeConstraintsProfile(); executeAdditionalFieldsProfile(); executePluginTableProfile(); executeRenameFieldProfile(); diff --git a/src/client/adapter.ts b/src/client/adapter.ts index c40b60ac..ad73e3fd 100644 --- a/src/client/adapter.ts +++ b/src/client/adapter.ts @@ -3,6 +3,7 @@ import type { DBAdapterDebugLogOption } from "better-auth/adapters"; import { createFunctionHandle } from "convex/server"; import type { FunctionHandle, + FunctionReference, GenericActionCtx, GenericDataModel, PaginationOptions, @@ -17,10 +18,9 @@ import { asyncMap } from "convex-helpers"; import { prop, sortBy } from "remeda"; import { isRunMutationCtx } from "../utils/index.js"; import type { Doc, TableNames } from "../component/_generated/dataModel.js"; -import type { ComponentApi } from "../component/_generated/component.js"; import type { AuthFunctions, GenericCtx, Triggers } from "./index.js"; -let didWarnExperimentalJoinsUnsupported = false; +let didWarnJoinsUnsupported = false; const handlePagination = async ( next: ({ @@ -46,11 +46,9 @@ const handlePagination = async ( const onResult = ( result: SetOptional, "page"> & { count?: number } ) => { - state.cursor = - result.pageStatus === "SplitRecommended" || - result.pageStatus === "SplitRequired" - ? (result.splitCursor ?? result.continueCursor) - : result.continueCursor; + // splitCursor divides the page we already received. Continuing there would + // revisit its second half and double-count reads and mutations. + state.cursor = result.continueCursor; if (result.page) { state.docs.push(...result.page); state.isDone = (limit && state.docs.length >= limit) || result.isDone; @@ -84,8 +82,7 @@ const handlePagination = async ( // A page that returns nothing and doesn't advance the cursor while !isDone // can never terminate; fail loudly instead of looping forever. const advanced = state.cursor !== cursorBeforePage; - const produced = - (result.page?.length ?? 0) > 0 || (result.count ?? 0) > 0; + const produced = (result.page?.length ?? 0) > 0 || (result.count ?? 0) > 0; if (!state.isDone && !advanced && !produced) { throw new Error( "handlePagination made no forward progress; aborting to avoid an infinite pagination loop" @@ -184,7 +181,16 @@ export const convexAdapter = < >( ctx: Ctx, api: { - adapter: ComponentApi["adapter"]; + adapter: { + create: FunctionReference<"mutation", "internal">; + findOne: FunctionReference<"query", "internal">; + findMany: FunctionReference<"query", "internal">; + updateOne: FunctionReference<"mutation", "internal">; + incrementOne: FunctionReference<"mutation", "internal">; + updateMany: FunctionReference<"mutation", "internal">; + deleteOne: FunctionReference<"mutation", "internal">; + deleteMany: FunctionReference<"mutation", "internal">; + }; }, config: { debugLogs?: DBAdapterDebugLogOption; @@ -228,16 +234,19 @@ export const convexAdapter = < adapter: ({ options }) => { // Disable telemetry in all cases because it requires Node options.telemetry = { enabled: false }; - if (options.experimental?.joins) { - options.experimental = { - ...options.experimental, - joins: false, + if (options.advanced?.database?.joins) { + options.advanced = { + ...options.advanced, + database: { + ...options.advanced.database, + joins: false, + }, }; - if (!didWarnExperimentalJoinsUnsupported) { - didWarnExperimentalJoinsUnsupported = true; + if (!didWarnJoinsUnsupported) { + didWarnJoinsUnsupported = true; // eslint-disable-next-line no-console console.warn( - "[convex-better-auth] Better Auth experimental.joins is not supported by the Convex adapter yet. Forcing experimental.joins = false." + "[convex-better-auth] Better Auth advanced.database.joins is not supported by the Convex adapter yet. Forcing advanced.database.joins = false." ); } } @@ -247,15 +256,13 @@ export const convexAdapter = < where: (Where & { join?: undefined })[]; }) => { const results = await asyncMap(data.where, async (w) => - handlePagination( - async ({ paginationOpts }) => { - return await ctx.runQuery(api.adapter.findMany, { - model: data.model as TableNames, - where: parseWhere(w), - paginationOpts, - }); - } - ) + handlePagination(async ({ paginationOpts }) => { + return await ctx.runQuery(api.adapter.findMany, { + model: data.model as TableNames, + where: parseWhere(w), + paginationOpts, + }); + }) ); const ids = dedupeDocsById(results.flatMap((r) => r.docs)) .map((doc) => getDocId(doc)) @@ -288,7 +295,8 @@ export const convexAdapter = < onCreateHandle: onCreateHandle, }); }, - findOne: async (data): Promise => { + // modelKey is Better Auth metadata, not a Convex component argument. + findOne: async ({ modelKey: _modelKey, ...data }): Promise => { if (data.where?.every((w) => w.connector === "OR")) { for (const w of data.where) { const result = await ctx.runQuery(api.adapter.findOne, { @@ -307,7 +315,7 @@ export const convexAdapter = < where: parseWhere(data.where), }); }, - findMany: async (data): Promise => { + findMany: async ({ modelKey: _modelKey, ...data }): Promise => { if (data.offset) { throw new Error("offset not supported"); } @@ -355,7 +363,7 @@ export const convexAdapter = < ); return result.docs; }, - count: async (data) => { + count: async ({ modelKey: _modelKey, ...data }) => { // Yes, count is just findMany returning a number. if (data.where?.some((w) => w.connector === "OR")) { const results = await asyncMap(data.where, async (w) => @@ -410,6 +418,52 @@ export const convexAdapter = < onUpdateHandle: onUpdateHandle, }); }, + consumeOne: async (data): Promise => { + if (!("runMutation" in ctx)) { + throw new Error("ctx is not a mutation ctx"); + } + if (!data.where.length) { + return null; + } + const onDeleteHandle = + config.authFunctions?.onDelete && + config.triggers?.[data.model]?.onDelete + ? ((await createFunctionHandle( + config.authFunctions.onDelete + )) as FunctionHandle<"mutation">) + : undefined; + return ctx.runMutation(api.adapter.deleteOne, { + input: { + model: data.model as TableNames, + where: parseWhere(data.where), + }, + onDeleteHandle, + }); + }, + incrementOne: async (data): Promise => { + if (!("runMutation" in ctx)) { + throw new Error("ctx is not a mutation ctx"); + } + if (!data.where.length) { + return null; + } + const onUpdateHandle = + config.authFunctions?.onUpdate && + config.triggers?.[data.model]?.onUpdate + ? ((await createFunctionHandle( + config.authFunctions.onUpdate + )) as FunctionHandle<"mutation">) + : undefined; + return ctx.runMutation(api.adapter.incrementOne, { + input: { + model: data.model as TableNames, + where: parseWhere(data.where), + increment: data.increment, + set: data.set as any, + }, + onUpdateHandle, + }); + }, delete: async (data) => { if (!("runMutation" in ctx)) { throw new Error("ctx is not a mutation ctx"); @@ -429,7 +483,7 @@ export const convexAdapter = < onDeleteHandle: onDeleteHandle, }); }, - deleteMany: async (data) => { + deleteMany: async ({ modelKey: _modelKey, ...data }) => { if (!("runMutation" in ctx)) { throw new Error("ctx is not a mutation ctx"); } @@ -469,7 +523,7 @@ export const convexAdapter = < }); return result.count; }, - updateMany: async (data) => { + updateMany: async ({ modelKey: _modelKey, ...data }) => { if (!("runMutation" in ctx)) { throw new Error("ctx is not a mutation ctx"); } diff --git a/src/client/create-api.test.ts b/src/client/create-api.test.ts new file mode 100644 index 00000000..e03370c8 --- /dev/null +++ b/src/client/create-api.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; +import type { BetterAuthDBSchema } from "better-auth/db"; +import { assertRequiredFields } from "./create-api.js"; + +describe("assertRequiredFields", () => { + it("resolves renamed models and stored field names", () => { + const schema = { + account: { + modelName: "customAccount", + fields: { + issuer: { + type: "string", + required: true, + fieldName: "customIssuer", + }, + }, + }, + } satisfies BetterAuthDBSchema; + + expect(() => assertRequiredFields(schema, "customAccount", {})).toThrow( + "Missing required field customAccount.customIssuer" + ); + expect(() => + assertRequiredFields(schema, "customAccount", { + customIssuer: "https://issuer.example.com", + }) + ).not.toThrow(); + }); +}); diff --git a/src/client/create-api.ts b/src/client/create-api.ts index 97679db6..a1083dd6 100644 --- a/src/client/create-api.ts +++ b/src/client/create-api.ts @@ -3,7 +3,12 @@ import { paginationOptsValidator, queryGeneric, } from "convex/server"; -import type { FunctionHandle, SchemaDefinition } from "convex/server"; +import type { + FunctionHandle, + GenericDataModel, + GenericMutationCtx, + SchemaDefinition, +} from "convex/server"; import { v } from "convex/values"; import type { GenericId } from "convex/values"; import { asyncMap } from "convex-helpers"; @@ -15,8 +20,10 @@ import { listOne, paginate, selectFields, + touchesUniqueFields, } from "./adapter-utils.js"; import { getAuthTables } from "better-auth/db"; +import type { BetterAuthDBSchema } from "better-auth/db"; import type { TableNames } from "../component/_generated/dataModel.js"; import type { BetterAuthOptions } from "better-auth/minimal"; @@ -58,11 +65,122 @@ const whereValidator = ( mode: v.optional(v.union(v.literal("sensitive"), v.literal("insensitive"))), }); +const requiredFieldNames = ( + betterAuthSchema: BetterAuthDBSchema, + model: string +) => { + const table = Object.values(betterAuthSchema).find( + (value) => value.modelName === model + ); + if (!table) { + return []; + } + return Object.entries(table.fields) + .filter(([, field]) => field.required) + .map(([fieldName, field]) => field.fieldName ?? fieldName); +}; + +export const assertRequiredFields = ( + betterAuthSchema: BetterAuthDBSchema, + model: string, + data: Record +) => { + for (const fieldName of requiredFieldNames(betterAuthSchema, model)) { + if (data[fieldName] == null) { + throw new Error(`Missing required field ${model}.${fieldName}`); + } + } +}; + +const assertRequiredUpdateFields = ( + betterAuthSchema: BetterAuthDBSchema, + model: string, + update: Record +) => { + for (const fieldName of requiredFieldNames(betterAuthSchema, model)) { + if ( + Object.prototype.hasOwnProperty.call(update, fieldName) && + update[fieldName] == null + ) { + throw new Error(`Cannot clear required field ${model}.${fieldName}`); + } + } +}; + +const assertRequiredFieldTransitions = ( + betterAuthSchema: BetterAuthDBSchema, + model: string, + before: Record, + after: Record +) => { + for (const fieldName of requiredFieldNames(betterAuthSchema, model)) { + if ( + after[fieldName] == null && + (before[fieldName] != null || + (!Object.prototype.hasOwnProperty.call(before, fieldName) && + Object.prototype.hasOwnProperty.call(after, fieldName))) + ) { + throw new Error(`Trigger cleared required field ${model}.${fieldName}`); + } + } +}; + export const createApi = >( schema: Schema, createAuthOptions: (ctx: any) => BetterAuthOptions ) => { const betterAuthSchema = getAuthTables(createAuthOptions({} as any)); + const checkPersistedUniqueFields = async ( + ctx: GenericMutationCtx, + model: string, + doc: Record + ) => { + await checkUniqueFields(ctx, schema, betterAuthSchema, model, doc, doc); + }; + const applySingleUpdate = async >( + ctx: GenericMutationCtx, + model: TableNames, + doc: Doc, + update: Record, + onUpdateHandle?: string + ): Promise => { + assertRequiredUpdateFields(betterAuthSchema, model, update); + await checkUniqueFields(ctx, schema, betterAuthSchema, model, update, doc); + await ctx.db.patch(model, doc._id as GenericId, update as any); + const updatedDoc = await ctx.db.get( + model, + doc._id as GenericId + ); + if (!updatedDoc) { + throw new Error(`Failed to update ${model}`); + } + if (!onUpdateHandle) { + return updatedDoc as Doc; + } + await ctx.runMutation(onUpdateHandle as FunctionHandle<"mutation">, { + model, + newDoc: updatedDoc, + oldDoc: doc, + }); + const triggeredDoc = await ctx.db.get( + model, + doc._id as GenericId + ); + if (!triggeredDoc) { + throw new Error( + `Failed to update ${model} (deleted by onUpdate trigger?)` + ); + } + assertRequiredFieldTransitions( + betterAuthSchema, + model, + updatedDoc, + triggeredDoc + ); + await checkPersistedUniqueFields(ctx, model, triggeredDoc); + return triggeredDoc as Doc; + }; + return { create: mutationGeneric({ args: { @@ -78,6 +196,11 @@ export const createApi = >( onCreateHandle: v.optional(v.string()), }, handler: async (ctx, args) => { + assertRequiredFields( + betterAuthSchema, + args.input.model, + args.input.data + ); await checkUniqueFields( ctx, schema, @@ -108,6 +231,8 @@ export const createApi = >( `Failed to create ${args.input.model} (deleted by onCreate trigger?)` ); } + assertRequiredFields(betterAuthSchema, args.input.model, updatedDoc); + await checkPersistedUniqueFields(ctx, args.input.model, updatedDoc); return selectFields(updatedDoc, args.select); } return result; @@ -168,49 +293,64 @@ export const createApi = >( handler: async (ctx, args) => { const doc = await listOne(ctx, schema, betterAuthSchema, args.input); if (!doc) { - throw new Error(`Failed to update ${args.input.model}`); + return null; } - await checkUniqueFields( + return await applySingleUpdate( ctx, - schema, - betterAuthSchema, args.input.model, + doc, args.input.update, - doc - ); - await ctx.db.patch( - args.input.model, - doc._id as GenericId, - args.input.update as any - ); - const updatedDoc = await ctx.db.get( - args.input.model, - doc._id as GenericId + args.onUpdateHandle ); - if (!updatedDoc) { - throw new Error(`Failed to update ${args.input.model}`); - } - if (args.onUpdateHandle) { - await ctx.runMutation( - args.onUpdateHandle as FunctionHandle<"mutation">, - { - model: args.input.model, - newDoc: updatedDoc, - oldDoc: doc, + }, + }), + incrementOne: mutationGeneric({ + args: { + input: v.union( + ...Object.entries(schema.tables).map( + ([name, table]: [string, Schema["tables"][string]]) => { + const tableName = name as TableNames; + return v.object({ + model: v.literal(tableName), + where: v.array(whereValidator(schema, tableName)), + increment: v.record(v.string(), v.number()), + set: v.optional(v.object(partial(table.validator.fields))), + }); } - ); - const innerUpdatedDoc = await ctx.db.get( - args.input.model, - doc._id as GenericId - ); - if (!innerUpdatedDoc) { + ) + ), + onUpdateHandle: v.optional(v.string()), + }, + handler: async (ctx, args) => { + if (!args.input.where.length) { + return null; + } + const doc = await listOne(ctx, schema, betterAuthSchema, args.input); + if (!doc) { + return null; + } + + const update: Record = { ...args.input.set }; + for (const [field, delta] of Object.entries(args.input.increment)) { + const current = doc[field]; + if ( + current !== undefined && + current !== null && + typeof current !== "number" + ) { throw new Error( - `Failed to update ${args.input.model} (deleted by onUpdate trigger?)` + `Cannot increment non-numeric field ${args.input.model}.${field}` ); } - return innerUpdatedDoc; + update[field] = (current ?? 0) + delta; } - return updatedDoc; + return await applySingleUpdate( + ctx, + args.input.model, + doc, + update, + args.onUpdateHandle + ); }, }), updateMany: mutationGeneric({ @@ -232,16 +372,40 @@ export const createApi = >( onUpdateHandle: v.optional(v.string()), }, handler: async (ctx, args) => { + const uniqueFieldsTouched = touchesUniqueFields( + betterAuthSchema, + args.input.model, + args.input.update ?? {} + ); + const firstInWhere = args.input.where?.find( + (where) => where.operator === "in" + ); + const usesAtomicIdSet = firstInWhere?.field === "_id"; + const requestedPageSize = args.paginationOpts.numItems; const { page, ...result } = await paginate( ctx, schema, betterAuthSchema, { ...args.input, - paginationOpts: args.paginationOpts, + paginationOpts: uniqueFieldsTouched + ? { + ...args.paginationOpts, + numItems: requestedPageSize + 1, + } + : args.paginationOpts, } ); if (args.input.update) { + if ( + uniqueFieldsTouched && + !usesAtomicIdSet && + (page.length > requestedPageSize || !result.isDone) + ) { + throw new Error( + `Cannot update unique fields across multiple pages in ${args.input.model}` + ); + } if ( hasUniqueFields( betterAuthSchema, @@ -254,7 +418,12 @@ export const createApi = >( `Attempted to set unique fields in multiple documents in ${args.input.model} with the same value. Fields: ${Object.keys(args.input.update ?? {}).join(", ")}` ); } - await asyncMap(page, async (doc) => { + const updateDoc = async (doc: (typeof page)[number]) => { + assertRequiredUpdateFields( + betterAuthSchema, + args.input.model, + args.input.update ?? {} + ); await checkUniqueFields( ctx, schema, @@ -270,19 +439,50 @@ export const createApi = >( ); if (args.onUpdateHandle) { + const updatedDoc = await ctx.db.get( + args.input.model, + doc._id as GenericId + ); + if (!updatedDoc) { + throw new Error(`Failed to update ${args.input.model}`); + } await ctx.runMutation( args.onUpdateHandle as FunctionHandle<"mutation">, { model: args.input.model, - newDoc: await ctx.db.get( - args.input.model, - doc._id as GenericId - ), + newDoc: updatedDoc, oldDoc: doc, } ); + const triggeredDoc = await ctx.db.get( + args.input.model, + doc._id as GenericId + ); + if (!triggeredDoc) { + throw new Error( + `Failed to update ${args.input.model} (deleted by onUpdate trigger?)` + ); + } + assertRequiredFieldTransitions( + betterAuthSchema, + args.input.model, + updatedDoc, + triggeredDoc + ); + await checkPersistedUniqueFields( + ctx, + args.input.model, + triggeredDoc + ); } - }); + }; + if (uniqueFieldsTouched) { + for (const doc of page) { + await updateDoc(doc); + } + } else { + await asyncMap(page, updateDoc); + } } return { ...result, diff --git a/src/client/create-client.test.ts b/src/client/create-client.test.ts index 548bdf43..6d2bbc9c 100644 --- a/src/client/create-client.test.ts +++ b/src/client/create-client.test.ts @@ -1,5 +1,5 @@ -import { describe, expect, it, vi } from "vitest"; -import { httpRouter } from "convex/server"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { httpActionGeneric, httpRouter } from "convex/server"; import { createClient } from "./create-client.js"; const component = { @@ -29,6 +29,92 @@ const getRouteHandler = ( }; describe("createClient route registration", () => { + afterEach(() => vi.unstubAllEnvs()); + + describe.each(["registerRoutes", "registerRoutesLazy"] as const)( + "%s discovery", + (register) => { + it.each([ + [undefined, false, "/api/auth/convex/.well-known/openid-configuration"], + [undefined, true, "/api/auth/.well-known/openid-configuration"], + ["/custom/auth", true, "/custom/auth/.well-known/openid-configuration"], + [ + "/custom/auth", + false, + "/custom/auth/convex/.well-known/openid-configuration", + ], + ])( + "redirects basePath=%s provider=%s", + async (basePath, provider, target) => { + vi.stubEnv("CONVEX_SITE_URL", "https://deployment.convex.site"); + const client = createClient(component); + const http = httpRouter(); + const createAuth = vi.fn(() => ({ + handler: async (request: Request) => + new URL(request.url).pathname === target + ? Response.json({ issuer: "https://deployment.convex.site" }) + : new Response(null, { status: 404 }), + options: { + basePath, + plugins: provider ? [{ id: "oauth-provider" }] : [], + }, + $context: Promise.resolve({ options: {} }), + })); + if (register === "registerRoutesLazy") { + client.registerRoutesLazy(http, createAuth, { basePath }); + expect(createAuth).not.toHaveBeenCalled(); + } else { + client.registerRoutes(http, createAuth); + } + const root = + "https://deployment.convex.site/.well-known/openid-configuration"; + const redirect = await getRouteHandler( + http, + new URL(root).pathname, + "GET" + )!._handler({}, new Request(root)); + expect(redirect.status).toBe(302); + const location = redirect.headers.get("location")!; + expect(location).toBe(`https://deployment.convex.site${target}`); + const response = await getRouteHandler( + http, + new URL(location).pathname, + "GET" + )!._handler({}, new Request(location)); + expect(response.status).toBe(200); + } + ); + + it("preserves an application-defined discovery route", async () => { + const client = createClient(component); + const http = httpRouter(); + http.route({ + path: "/.well-known/openid-configuration", + method: "GET", + handler: httpActionGeneric(async () => + Response.json({ custom: true }) + ), + }); + const createAuth = vi.fn(() => ({ + handler: async () => new Response(null, { status: 404 }), + options: { plugins: [{ id: "oauth-provider" }] }, + $context: Promise.resolve({ options: {} }), + })); + client[register](http, createAuth); + const response = await getRouteHandler( + http, + "/.well-known/openid-configuration", + "GET" + )!._handler( + {}, + new Request( + "https://deployment.convex.site/.well-known/openid-configuration" + ) + ); + expect(await response.json()).toEqual({ custom: true }); + }); + } + ); it("registerRoutes eagerly initializes auth and infers basePath", () => { const client = createClient(component); const http = httpRouter(); @@ -145,7 +231,9 @@ describe("createClient route registration", () => { const forwardedRequest = handler.mock.calls[0]?.[0]; expect(forwardedRequest).toBeInstanceOf(Request); - expect(forwardedRequest.headers.get("x-forwarded-host")).toBe("app.example.com"); + expect(forwardedRequest.headers.get("x-forwarded-host")).toBe( + "app.example.com" + ); expect(forwardedRequest.headers.get("x-forwarded-proto")).toBe("https"); }); diff --git a/src/client/create-client.ts b/src/client/create-client.ts index 9b4c3f77..561b3a86 100644 --- a/src/client/create-client.ts +++ b/src/client/create-client.ts @@ -20,6 +20,12 @@ import type defaultSchema from "../component/schema.js"; import type { CreateAuth, GenericCtx } from "./index.js"; import type { TrustedOriginsOption } from "../utils/index.js"; +const getOpenIdConfigPath = (plugins: unknown) => + Array.isArray(plugins) && + plugins.some((plugin) => plugin?.id === "oauth-provider") + ? "/.well-known/openid-configuration" + : "/convex/.well-known/openid-configuration"; + export type AuthFunctions = { onCreate?: FunctionReference<"mutation", "internal", { [key: string]: any }>; onUpdate?: FunctionReference<"mutation", "internal", { [key: string]: any }>; @@ -65,6 +71,7 @@ type SlimComponentApi = { findOne: FunctionReference<"query", "internal">; findMany: FunctionReference<"query", "internal">; updateOne: FunctionReference<"mutation", "internal">; + incrementOne: FunctionReference<"mutation", "internal">; updateMany: FunctionReference<"mutation", "internal">; deleteOne: FunctionReference<"mutation", "internal">; deleteMany: FunctionReference<"mutation", "internal">; @@ -411,7 +418,7 @@ export const createClient = < path: "/.well-known/openid-configuration", method: "GET", handler: httpActionGeneric(async () => { - const url = `${process.env.CONVEX_SITE_URL}${path}/convex/.well-known/openid-configuration`; + const url = `${process.env.CONVEX_SITE_URL}${path}${getOpenIdConfigPath(staticAuth.options.plugins)}`; return Response.redirect(url); }), }); @@ -530,8 +537,9 @@ export const createClient = < http.route({ path: "/.well-known/openid-configuration", method: "GET", - handler: httpActionGeneric(async () => { - const url = `${process.env.CONVEX_SITE_URL}${path}/convex/.well-known/openid-configuration`; + handler: httpActionGeneric(async (ctx) => { + const auth = createAuth(ctx as any); + const url = `${process.env.CONVEX_SITE_URL}${path}${getOpenIdConfigPath(auth.options.plugins)}`; return Response.redirect(url); }), }); diff --git a/src/client/create-schema.test.ts b/src/client/create-schema.test.ts new file mode 100644 index 00000000..8c7e9027 --- /dev/null +++ b/src/client/create-schema.test.ts @@ -0,0 +1,92 @@ +import { describe, expect, it } from "vitest"; +import type { BetterAuthDBSchema } from "better-auth/db"; +import { createSchema } from "./create-schema.js"; + +describe("createSchema", () => { + it("generates the Better Auth credential account lookup index", async () => { + const tables = { + account: { + modelName: "account", + fields: { + userId: { + type: "string", + required: true, + references: { field: "id", model: "user" }, + }, + providerId: { type: "string", required: true }, + accountId: { type: "string", required: true }, + }, + }, + } satisfies BetterAuthDBSchema; + + const { code } = await createSchema({ tables }); + + expect(code).toContain( + '.index("userId_providerId_accountId", ["userId","providerId","accountId"])' + ); + expect(code).toContain('.index("userId", ["userId"])'); + }); + + it("generates table-level compound indexes without mutating their order", async () => { + const indexFields = ["issuer", "accountId"] as [string, ...string[]]; + const tables = { + account: { + modelName: "account", + fields: { + issuer: { type: "string", required: true }, + accountId: { type: "string", required: true }, + }, + indexes: [{ fields: indexFields, unique: true }], + }, + } satisfies BetterAuthDBSchema; + + const { code } = await createSchema({ tables }); + + expect(code).toContain( + '.index("issuer_accountId", ["issuer","accountId"])' + ); + expect(indexFields).toEqual(["issuer", "accountId"]); + }); + + it("does not add a standalone index covered by a compound prefix", async () => { + const tables = { + user: { + modelName: "user", + fields: { + email: { type: "string", required: true, unique: true }, + name: { type: "string", required: true }, + }, + }, + } satisfies BetterAuthDBSchema; + + const { code } = await createSchema({ tables }); + + expect(code).toContain('.index("email_name", ["email","name"])'); + expect(code).not.toContain('.index("email", ["email"])'); + }); + + it("keeps reversed compound indexes distinct", async () => { + const tables = { + account: { + modelName: "account", + fields: { + issuer: { type: "string", required: true }, + accountId: { type: "string", required: true }, + }, + indexes: [ + { fields: ["issuer", "accountId"], unique: true }, + { fields: ["accountId", "issuer"], unique: false }, + ], + }, + } satisfies BetterAuthDBSchema; + + const { code } = await createSchema({ tables }); + + expect(code).toContain( + '.index("issuer_accountId", ["issuer","accountId"])' + ); + expect(code).toContain( + '.index("accountId_issuer", ["accountId","issuer"])' + ); + }); +}); diff --git a/src/client/create-schema.ts b/src/client/create-schema.ts index 464274c0..2fcf2fee 100644 --- a/src/client/create-schema.ts +++ b/src/client/create-schema.ts @@ -16,7 +16,13 @@ const resolveCdTarget = ( // Manually add fields to index on for schema generation, // all fields in the schema specialFields are automatically indexed export const indexFields = { - account: ["accountId", ["accountId", "providerId"], ["providerId", "userId"]], + account: [ + "accountId", + ["accountId", "providerId"], + ["providerId", "userId"], + ["userId", "providerId", "accountId"], + "userId", + ], rateLimit: ["key"], session: ["expiresAt", ["expiresAt", "userId"]], verification: ["expiresAt", "identifier"], @@ -53,10 +59,14 @@ const specialFields = (tables: BetterAuthDBSchema) => const mergedIndexFields = (tables: BetterAuthDBSchema) => Object.fromEntries( Object.entries(tables).map(([key, table]) => { - const manualIndexes = + const schemaIndexes = + table.indexes?.map((index) => + index.fields.map((field) => table.fields[field]?.fieldName ?? field) + ) ?? []; + const manualIndexes: string[][] = indexFields[key as keyof typeof indexFields]?.map((index) => { return typeof index === "string" - ? (table.fields[index]?.fieldName ?? index) + ? [table.fields[index]?.fieldName ?? index] : index.map((i) => table.fields[i]?.fieldName ?? i); }) || []; const specialFieldIndexes = Object.keys( @@ -64,11 +74,25 @@ const mergedIndexFields = (tables: BetterAuthDBSchema) => {} ).filter( (index) => - !manualIndexes.some((m) => - Array.isArray(m) ? m[0] === index : m === index - ) + !manualIndexes.some((manualIndex) => manualIndex[0] === index) ); - return [key, manualIndexes.concat(specialFieldIndexes)]; + const indexes = schemaIndexes.concat( + manualIndexes, + specialFieldIndexes.map((field) => [field]) + ); + const deduplicated = indexes.filter((index, indexPosition) => { + return ( + indexes.findIndex((candidate) => { + return ( + candidate.length === index.length && + candidate.every( + (field, fieldPosition) => field === index[fieldPosition] + ) + ); + }) === indexPosition + ); + }); + return [key, deduplicated]; }) ); @@ -110,7 +134,10 @@ export const createSchema = async ({ projectRoot !== null ? path.relative(projectRoot, cwd).split(path.sep).join("/") : null; - const generateCommand = `npx auth generate${file ? ` --output ${file}` : ""}`; + const outputPath = file ? path.relative(cwd, file) : file; + const generateCommand = `npx auth generate${ + outputPath ? ` --output ${outputPath}` : "" + }`; const cdTarget = resolveCdTarget(relativeDir, path.basename(cwd)); const commandBlock = cdTarget ? ` * cd ${cdTarget}\n * ${generateCommand}` @@ -167,7 +194,7 @@ export const tables = { mergedIndexFields(tables)[ tableKey as keyof typeof mergedIndexFields ]?.map((index) => { - const indexArray = Array.isArray(index) ? index.sort() : [index]; + const indexArray = Array.isArray(index) ? index : [index]; const indexName = indexArray.join("_"); return `.index("${indexName}", ${JSON.stringify(indexArray)})`; }) || []; diff --git a/src/client/required-fields.test.ts b/src/client/required-fields.test.ts new file mode 100644 index 00000000..be2f8ebf --- /dev/null +++ b/src/client/required-fields.test.ts @@ -0,0 +1,293 @@ +/// + +import { describe, expect, it } from "vitest"; +import { convexTest } from "convex-test"; +import { createFunctionHandle } from "convex/server"; +import { constraintsProfileOptions } from "../component/testProfiles/auth-options.constraints.js"; +import schema from "../component/testProfiles/schema.constraints.js"; +import { api, internal } from "../component/_generated/api.js"; +import type { DataModel } from "../component/_generated/dataModel.js"; +import { createClient } from "./index.js"; + +const accountData = () => ({ + issuer: "local:credential", + accountId: "user-1", + providerId: "credential", + userId: "user-1", + password: "password-hash", + createdAt: Date.now(), + updatedAt: Date.now(), +}); + +const createAccount = async ( + t: ReturnType, + onCreateHandle?: string +) => + await t.run(async (ctx) => + ctx.runMutation(api.testProfiles.adapterConstraints.create, { + input: { model: "account", data: accountData() }, + onCreateHandle, + }) + ); + +const insertLegacyAccount = async ( + t: ReturnType, + suffix: string +) => + await t.run((ctx) => + ctx.db.insert("account", { + accountId: `legacy-account-${suffix}`, + providerId: "credential", + userId: `legacy-user-${suffix}`, + password: "password-hash", + createdAt: Date.now(), + updatedAt: 100, + }) + ); + +describe("required fields", () => { + it.each(["updateOne", "incrementOne", "updateMany"] as const)( + "rejects null issuer through %s", + async (operation) => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await createAccount(t); + + const mutation = t.run(async (ctx) => { + if (operation === "updateOne") { + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateOne, + { + input: { + model: "account", + update: { issuer: null }, + where: [ + { field: "accountId", operator: "eq", value: "user-1" }, + ], + }, + } + ); + } + if (operation === "incrementOne") { + return await ctx.runMutation( + api.testProfiles.adapterConstraints.incrementOne, + { + input: { + model: "account", + increment: { updatedAt: 1 }, + set: { issuer: null }, + where: [ + { field: "accountId", operator: "eq", value: "user-1" }, + ], + }, + } + ); + } + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateMany, + { + input: { + model: "account", + update: { issuer: null }, + where: [{ field: "accountId", operator: "eq", value: "user-1" }], + }, + paginationOpts: { cursor: null, numItems: 10 }, + } + ); + }); + + await expect(mutation).rejects.toThrow( + "Cannot clear required field account.issuer" + ); + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(1); + expect(accounts[0]?.issuer).toBe("local:credential"); + } + ); + + it.each(["updateOne", "incrementOne", "updateMany"] as const)( + "allows an unrelated %s on a legacy account", + async (operation) => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await insertLegacyAccount(t, operation); + + await t.run(async (ctx) => { + const where = [ + { + field: "accountId", + operator: "eq" as const, + value: `legacy-account-${operation}`, + }, + ]; + if (operation === "updateOne") { + await ctx.runMutation(api.testProfiles.adapterConstraints.updateOne, { + input: { + model: "account", + update: { accessToken: "updated-token" }, + where, + }, + }); + return; + } + if (operation === "incrementOne") { + await ctx.runMutation( + api.testProfiles.adapterConstraints.incrementOne, + { + input: { + model: "account", + increment: { updatedAt: 1 }, + where, + }, + } + ); + return; + } + await ctx.runMutation(api.testProfiles.adapterConstraints.updateMany, { + input: { + model: "account", + update: { scope: "updated-scope" }, + where, + }, + paginationOpts: { cursor: null, numItems: 10 }, + }); + }); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(1); + expect(accounts[0]?.issuer).toBeUndefined(); + if (operation === "updateOne") { + expect(accounts[0]?.accessToken).toBe("updated-token"); + } else if (operation === "incrementOne") { + expect(accounts[0]?.updatedAt).toBe(101); + } else { + expect(accounts[0]?.scope).toBe("updated-scope"); + } + } + ); + + it("updates multiple pages containing a legacy account", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await t.run(async (ctx) => { + for (let i = 0; i < 401; i += 1) { + await ctx.db.insert("account", { + ...(i === 250 ? {} : { issuer: `local:legacy-${i}` }), + accountId: `legacy-bulk-account-${i}`, + providerId: "legacy-bulk-provider", + userId: `legacy-bulk-user-${i.toString().padStart(3, "0")}`, + createdAt: Date.now(), + updatedAt: Date.now(), + }); + } + }); + const adapter = createClient( + { adapter: api.testProfiles.adapterConstraints } as any, + { + verbose: false, + } + ).adapter({ + runMutation: t.mutation.bind(t), + runQuery: t.query.bind(t), + } as any)(constraintsProfileOptions); + + await expect( + adapter.updateMany({ + model: "account", + where: [{ field: "providerId", value: "legacy-bulk-provider" }], + update: { scope: "updated-scope" }, + }) + ).resolves.toBe(401); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(401); + expect(accounts.every(({ scope }) => scope === "updated-scope")).toBe(true); + expect(accounts.filter(({ issuer }) => issuer === undefined)).toHaveLength( + 1 + ); + }); + + it("rolls back an onCreate trigger that clears a required field", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + + await expect( + t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnCreateIssuerClearer + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.create, + { + input: { model: "account", data: accountData() }, + onCreateHandle: handle, + } + ); + }) + ).rejects.toThrow("Missing required field account.issuer"); + expect(await t.run((ctx) => ctx.db.query("account").collect())).toEqual([]); + }); + + it("rolls back an onUpdate trigger that clears a required field", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await createAccount(t); + + await expect( + t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnUpdateIssuerClearer + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateOne, + { + input: { + model: "account", + update: { updatedAt: Date.now() + 1 }, + where: [{ field: "accountId", operator: "eq", value: "user-1" }], + }, + onUpdateHandle: handle, + } + ); + }) + ).rejects.toThrow("Trigger cleared required field account.issuer"); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(1); + expect(accounts[0]?.issuer).toBe("local:credential"); + }); + + it("allows a no-op trigger on a legacy account with a null issuer", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await t.run((ctx) => + ctx.db.insert("account", { + issuer: null, + accountId: "legacy-null-account", + providerId: "credential", + userId: "legacy-null-user", + createdAt: Date.now(), + updatedAt: Date.now(), + }) + ); + + await t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnUpdateNoop + ); + await ctx.runMutation(api.testProfiles.adapterConstraints.updateOne, { + input: { + model: "account", + update: { scope: "updated-scope" }, + where: [ + { + field: "accountId", + operator: "eq", + value: "legacy-null-account", + }, + ], + }, + onUpdateHandle: handle, + }); + }); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(1); + expect(accounts[0]?.issuer).toBeNull(); + expect(accounts[0]?.scope).toBe("updated-scope"); + }); +}); diff --git a/src/client/triggers.test.ts b/src/client/triggers.test.ts index 73ab6e68..6b668e0f 100644 --- a/src/client/triggers.test.ts +++ b/src/client/triggers.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest"; import { convexTest } from "convex-test"; import { createFunctionHandle } from "convex/server"; -import schema from "../component/schema.js"; +import schema from "../component/testProfiles/schema.constraints.js"; import { api, internal } from "../component/_generated/api.js"; const baseSessionData = () => ({ @@ -14,14 +14,33 @@ const baseSessionData = () => ({ userAgent: "original", }); +const accountData = ({ + issuer, + accountId, + providerId, + userId, +}: { + issuer: string; + accountId: string; + providerId: string; + userId: string; +}) => ({ + issuer, + accountId, + providerId, + userId, + createdAt: Date.now(), + updatedAt: Date.now(), +}); + describe("trigger result propagation", () => { - it("api.adapter.create returns the doc reflecting onCreateHandle writes", async () => { + it("api.testProfiles.adapterConstraints.create returns the doc reflecting onCreateHandle writes", async () => { const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); const result = await t.run(async (ctx) => { const handle = await createFunctionHandle( internal.testTriggerHandlers.sessionOnCreateUpdater ); - return await ctx.runMutation(api.adapter.create, { + return await ctx.runMutation(api.testProfiles.adapterConstraints.create, { input: { model: "session", data: { ...baseSessionData(), token: "create-token-1" }, @@ -32,10 +51,10 @@ describe("trigger result propagation", () => { expect(result.userAgent).toBe("trigger-ran-on-create"); }); - it("api.adapter.updateOne returns the doc reflecting onUpdateHandle writes", async () => { + it("api.testProfiles.adapterConstraints.updateOne returns the doc reflecting onUpdateHandle writes", async () => { const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); const result = await t.run(async (ctx) => { - await ctx.runMutation(api.adapter.create, { + await ctx.runMutation(api.testProfiles.adapterConstraints.create, { input: { model: "session", data: { ...baseSessionData(), token: "update-token-1" }, @@ -44,15 +63,278 @@ describe("trigger result propagation", () => { const handle = await createFunctionHandle( internal.testTriggerHandlers.sessionOnUpdateUpdater ); - return await ctx.runMutation(api.adapter.updateOne, { + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateOne, + { + input: { + model: "session", + update: { userAgent: "set-by-update" }, + where: [ + { field: "token", operator: "eq", value: "update-token-1" }, + ], + }, + onUpdateHandle: handle, + } + ); + }); + expect(result).toMatchObject({ userAgent: "trigger-ran-on-update" }); + }); + + it("api.testProfiles.adapterConstraints.incrementOne returns the doc reflecting onUpdateHandle writes", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + const result = await t.run(async (ctx) => { + await ctx.runMutation(api.testProfiles.adapterConstraints.create, { input: { model: "session", - update: { userAgent: "set-by-update" }, - where: [{ field: "token", operator: "eq", value: "update-token-1" }], + data: { + ...baseSessionData(), + expiresAt: 100, + token: "increment-token-1", + }, }, - onUpdateHandle: handle, }); + const handle = await createFunctionHandle( + internal.testTriggerHandlers.sessionOnUpdateUpdater + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.incrementOne, + { + input: { + model: "session", + increment: { expiresAt: 1 }, + where: [ + { + field: "token", + operator: "eq", + value: "increment-token-1", + }, + ], + }, + onUpdateHandle: handle, + } + ); + }); + expect(result).toMatchObject({ + expiresAt: 101, + userAgent: "trigger-ran-on-update", + }); + }); + + it("api.testProfiles.adapterConstraints.updateMany runs onUpdateHandle for every updated doc", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + const result = await t.run(async (ctx) => { + for (const token of ["bulk-update-token-1", "bulk-update-token-2"]) { + await ctx.runMutation(api.testProfiles.adapterConstraints.create, { + input: { + model: "session", + data: { ...baseSessionData(), token }, + }, + }); + } + const handle = await createFunctionHandle( + internal.testTriggerHandlers.sessionOnUpdateUpdater + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateMany, + { + input: { + model: "session", + update: { userAgent: "set-by-update" }, + where: [{ field: "userId", operator: "eq", value: "user-1" }], + }, + paginationOpts: { cursor: null, numItems: 10 }, + onUpdateHandle: handle, + } + ); + }); + expect(result.count).toBe(2); + + const sessions = await t.run((ctx) => ctx.db.query("session").collect()); + expect(sessions).toHaveLength(2); + expect( + sessions.every(({ userAgent }) => userAgent === "trigger-ran-on-update") + ).toBe(true); + }); +}); + +describe("trigger unique constraint enforcement", () => { + it("rolls back an onCreate trigger that creates an account identity collision", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await t.run((ctx) => + ctx.runMutation(api.testProfiles.adapterConstraints.create, { + input: { + model: "account", + data: accountData({ + issuer: "collision-issuer", + accountId: "collision-account", + providerId: "existing-provider", + userId: "existing-user", + }), + }, + }) + ); + + await expect( + t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnCreateIssuerCollider + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.create, + { + input: { + model: "account", + data: accountData({ + issuer: "safe-issuer", + accountId: "collision-account", + providerId: "candidate-provider", + userId: "candidate-user", + }), + }, + onCreateHandle: handle, + } + ); + }) + ).rejects.toThrow( + "account unique constraint issuer+accountId already exists" + ); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(1); + expect(accounts[0]).toMatchObject({ + issuer: "collision-issuer", + accountId: "collision-account", + providerId: "existing-provider", + }); + }); + + it("rolls back an onUpdate trigger that creates an account identity collision", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await t.run(async (ctx) => { + for (const data of [ + accountData({ + issuer: "collision-issuer", + accountId: "collision-account", + providerId: "existing-provider", + userId: "existing-user", + }), + accountData({ + issuer: "collision-issuer", + accountId: "safe-account", + providerId: "candidate-provider", + userId: "candidate-user", + }), + ]) { + await ctx.runMutation(api.testProfiles.adapterConstraints.create, { + input: { model: "account", data }, + }); + } + }); + + await expect( + t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnUpdateAccountIdCollider + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateOne, + { + input: { + model: "account", + update: { scope: "updated-scope" }, + where: [ + { + field: "providerId", + operator: "eq", + value: "candidate-provider", + }, + ], + }, + onUpdateHandle: handle, + } + ); + }) + ).rejects.toThrow( + "account unique constraint issuer+accountId already exists" + ); + + const candidate = await t.run((ctx) => + ctx.db + .query("account") + .withIndex("providerId_userId", (q) => + q + .eq("providerId", "candidate-provider") + .eq("userId", "candidate-user") + ) + .unique() + ); + expect(candidate).toMatchObject({ + accountId: "safe-account", + issuer: "collision-issuer", + }); + expect(candidate?.scope).toBeUndefined(); + }); + + it("rolls back updateMany when a trigger creates an account identity collision", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + await t.run(async (ctx) => { + for (const data of [ + accountData({ + issuer: "collision-issuer", + accountId: "collision-account", + providerId: "existing-provider", + userId: "existing-user", + }), + accountData({ + issuer: "collision-issuer", + accountId: "safe-account", + providerId: "candidate-provider", + userId: "candidate-user", + }), + ]) { + await ctx.runMutation(api.testProfiles.adapterConstraints.create, { + input: { model: "account", data }, + }); + } + }); + + await expect( + t.run(async (ctx) => { + const handle = await createFunctionHandle( + internal.testTriggerHandlers.accountOnUpdateAccountIdCollider + ); + return await ctx.runMutation( + api.testProfiles.adapterConstraints.updateMany, + { + input: { + model: "account", + update: { scope: "updated-scope" }, + where: [ + { + field: "providerId", + operator: "eq", + value: "candidate-provider", + }, + ], + }, + paginationOpts: { cursor: null, numItems: 10 }, + onUpdateHandle: handle, + } + ); + }) + ).rejects.toThrow( + "account unique constraint issuer+accountId already exists" + ); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(2); + const candidate = accounts.find( + ({ providerId }) => providerId === "candidate-provider" + ); + expect(candidate).toMatchObject({ + accountId: "safe-account", + issuer: "collision-issuer", }); - expect(result.userAgent).toBe("trigger-ran-on-update"); + expect(candidate?.scope).toBeUndefined(); }); }); diff --git a/src/client/update-many-pagination.test.ts b/src/client/update-many-pagination.test.ts new file mode 100644 index 00000000..0dc58231 --- /dev/null +++ b/src/client/update-many-pagination.test.ts @@ -0,0 +1,55 @@ +/// + +import { describe, expect, it } from "vitest"; +import { convexTest } from "convex-test"; +import schema from "../component/testProfiles/schema.constraints.js"; +import { api } from "../component/_generated/api.js"; + +describe("updateMany pagination", () => { + it("does not treat a later ID filter as the atomic ID-set path", async () => { + const t = convexTest(schema, import.meta.glob("../component/**/*.*s")); + const ids = await t.run(async (ctx) => { + const insertedIds = []; + for (let i = 0; i < 300; i += 1) { + insertedIds.push( + await ctx.db.insert("account", { + issuer: `original-${i}`, + accountId: `mixed-filter-account-${i}`, + providerId: "mixed-filter-provider", + userId: `mixed-filter-user-${i}`, + scope: "mixed-filter-scope", + createdAt: Date.now(), + updatedAt: Date.now(), + }) + ); + } + return insertedIds; + }); + + await expect( + t.mutation(api.testProfiles.adapterConstraints.updateMany, { + input: { + model: "account", + update: { issuer: "updated-issuer" }, + where: [ + { + field: "scope", + operator: "in", + value: ["mixed-filter-scope"], + }, + { field: "_id", operator: "in", value: ids }, + ], + }, + paginationOpts: { cursor: null, numItems: 200 }, + }) + ).rejects.toThrow( + "Cannot update unique fields across multiple pages in account" + ); + + const accounts = await t.run((ctx) => ctx.db.query("account").collect()); + expect(accounts).toHaveLength(300); + expect( + accounts.every(({ issuer }) => issuer?.startsWith("original-") === true) + ).toBe(true); + }); +}); diff --git a/src/component/_generated/api.ts b/src/component/_generated/api.ts index 72723865..c0e1b2fc 100644 --- a/src/component/_generated/api.ts +++ b/src/component/_generated/api.ts @@ -9,7 +9,9 @@ */ import type * as adapter from "../adapter.js"; +import type * as migrations from "../migrations.js"; import type * as testProfiles_adapterAdditionalFields from "../testProfiles/adapterAdditionalFields.js"; +import type * as testProfiles_adapterConstraints from "../testProfiles/adapterConstraints.js"; import type * as testProfiles_adapterOrganizationJoins from "../testProfiles/adapterOrganizationJoins.js"; import type * as testProfiles_adapterPluginTable from "../testProfiles/adapterPluginTable.js"; import type * as testProfiles_adapterRenameField from "../testProfiles/adapterRenameField.js"; @@ -26,7 +28,9 @@ import { anyApi, componentsGeneric } from "convex/server"; const fullApi: ApiFromModules<{ adapter: typeof adapter; + migrations: typeof migrations; "testProfiles/adapterAdditionalFields": typeof testProfiles_adapterAdditionalFields; + "testProfiles/adapterConstraints": typeof testProfiles_adapterConstraints; "testProfiles/adapterOrganizationJoins": typeof testProfiles_adapterOrganizationJoins; "testProfiles/adapterPluginTable": typeof testProfiles_adapterPluginTable; "testProfiles/adapterRenameField": typeof testProfiles_adapterRenameField; diff --git a/src/component/_generated/component.ts b/src/component/_generated/component.ts index b7e27676..e4dd6382 100644 --- a/src/component/_generated/component.ts +++ b/src/component/_generated/component.ts @@ -66,6 +66,7 @@ export type ComponentApi = accountId: string; createdAt: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId: string; refreshToken?: null | string; @@ -89,6 +90,8 @@ export type ComponentApi = | { data: { backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret: string; userId: string; verified?: null | boolean; @@ -138,7 +141,9 @@ export type ComponentApi = } | { data: { + alg?: null | string; createdAt: number; + crv?: null | string; expiresAt?: null | number; privateKey: string; publicKey: string; @@ -241,6 +246,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -318,6 +324,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -460,6 +468,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -609,6 +619,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -686,6 +697,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -828,6 +841,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -984,14 +999,15 @@ export type ComponentApi = any, Name >; - updateMany: FunctionReference< + incrementOne: FunctionReference< "mutation", "internal", { input: | { + increment: Record; model: "user"; - update: { + set?: { createdAt?: number; displayUsername?: null | string; email?: string; @@ -1006,7 +1022,7 @@ export type ComponentApi = userId?: null | string; username?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -1046,8 +1062,9 @@ export type ComponentApi = }>; } | { + increment: Record; model: "session"; - update: { + set?: { createdAt?: number; expiresAt?: number; ipAddress?: null | string; @@ -1056,7 +1073,7 @@ export type ComponentApi = userAgent?: null | string; userId?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "expiresAt" @@ -1090,13 +1107,15 @@ export type ComponentApi = }>; } | { + increment: Record; model: "account"; - update: { + set?: { accessToken?: null | string; accessTokenExpiresAt?: null | number; accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -1105,9 +1124,10 @@ export type ComponentApi = updatedAt?: number; userId?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -1144,15 +1164,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "verification"; - update: { + set?: { createdAt?: number; expiresAt?: number; identifier?: string; updatedAt?: number; value?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "identifier" @@ -1184,20 +1205,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "twoFactor"; - update: { + set?: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "secret" | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1222,8 +1248,9 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthApplication"; - update: { + set?: { clientId?: null | string; clientSecret?: null | string; createdAt?: null | number; @@ -1236,7 +1263,7 @@ export type ComponentApi = updatedAt?: null | number; userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -1274,8 +1301,9 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthAccessToken"; - update: { + set?: { accessToken?: null | string; accessTokenExpiresAt?: null | number; clientId?: null | string; @@ -1286,7 +1314,7 @@ export type ComponentApi = updatedAt?: null | number; userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "accessToken" @@ -1322,8 +1350,9 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthConsent"; - update: { + set?: { clientId?: null | string; consentGiven?: null | boolean; createdAt?: null | number; @@ -1331,7 +1360,7 @@ export type ComponentApi = updatedAt?: null | number; userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "clientId" @@ -1364,20 +1393,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "jwks"; - update: { + set?: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "publicKey" | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1402,9 +1436,10 @@ export type ComponentApi = }>; } | { + increment: Record; model: "rateLimit"; - update: { count?: number; key?: string; lastRequest?: number }; - where?: Array<{ + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; @@ -1430,19 +1465,11 @@ export type ComponentApi = }>; }; onUpdateHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; }, any, Name >; - updateOne: FunctionReference< + updateMany: FunctionReference< "mutation", "internal", { @@ -1555,6 +1582,7 @@ export type ComponentApi = accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -1566,6 +1594,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -1645,6 +1674,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -1656,6 +1687,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1824,7 +1857,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -1836,6 +1871,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -1888,212 +1925,6730 @@ export type ComponentApi = }>; }; onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; }, any, Name >; - }; - testProfiles: { - adapterAdditionalFields: { - create: FunctionReference< - "mutation", - "internal", - { - input: - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email: string; - emailVerified: boolean; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; + updateOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + update: { + createdAt?: number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; }; - onCreateHandle?: string; - select?: Array; - }, - any, - Name - >; - deleteMany: FunctionReference< - "mutation", - "internal", - { - input: - | { - model: "user"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "name" - | "email" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "customField" - | "numericField" - | "testField" - | "cbDefaultValueField" - | "dateField" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - } - | { - model: "session"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "expiresAt" - | "token" + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + update: { count?: number; key?: string; lastRequest?: number }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + migrations: { + clearLegacyOAuthProviderRecords: FunctionReference< + "mutation", + "internal", + { + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + table: "oauthApplication" | "oauthAccessToken" | "oauthConsent"; + }, + { continueCursor: string; deleted: number; isDone: boolean }, + Name + >; + listLegacyOAuthApplications: FunctionReference< + "query", + "internal", + { + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + { + continueCursor: string; + isDone: boolean; + page: Array<{ + _creationTime: number; + _id: string; + clientId?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + hadClientSecret: boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }>; + pageStatus?: "SplitRecommended" | "SplitRequired" | null; + splitCursor?: string | null; + }, + Name + >; + }; + testProfiles: { + adapterAdditionalFields: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email: string; + emailVerified: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "customField" + | "numericField" + | "testField" + | "cbDefaultValueField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + deleteOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "customField" + | "numericField" + | "testField" + | "cbDefaultValueField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit"; + offset?: number; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + increment: Record; + model: "user"; + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "customField" + | "numericField" + | "testField" + | "cbDefaultValueField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "session"; + set?: { + 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "account"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "verification"; + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "twoFactor"; + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthApplication"; + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthAccessToken"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthConsent"; + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "rateLimit"; + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + updateMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "customField" + | "numericField" + | "testField" + | "cbDefaultValueField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + updateOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "customField" + | "numericField" + | "testField" + | "cbDefaultValueField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterConstraints: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + createdAt: number; + displayUsername?: null | string; + email: string; + emailVerified: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + deleteOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit"; + offset?: number; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + increment: Record; + model: "user"; + set?: { + createdAt?: number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "session"; + set?: { + 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "account"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "verification"; + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "twoFactor"; + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthApplication"; + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthAccessToken"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "oauthConsent"; + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "rateLimit"; + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + updateMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + update: { + createdAt?: number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + updateOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + update: { + createdAt?: number; + displayUsername?: null | string; + email?: string; + emailVerified?: boolean; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | 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"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterOrganizationJoins: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_custom"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_table"; + } + | { data: { oneToOne: string }; model: "oneToOneTable" } + | { + data: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + model: "one_to_one_table"; + } + | { + data: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + model: "testModel"; + } + | { + data: { + createdAt: number; + logo?: null | string; + metadata?: null | string; + name: string; + slug: string; + updatedAt?: null | number; + }; + model: "organization"; + } + | { + data: { + createdAt: number; + organizationId: string; + role: string; + updatedAt?: null | number; + userId: string; + }; + model: "member"; + } + | { + data: { + createdAt: number; + memberCount: number; + name: string; + organizationId: string; + updatedAt?: null | number; + }; + model: "team"; + } + | { + data: { + createdAt?: null | number; + membershipKey?: null | string; + teamId: string; + userId: string; + }; + model: "teamMember"; + } + | { + data: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + model: "invitation"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "user_custom"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "user_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oneToOneTable"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "one_to_one_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "testModel"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "organization"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "member"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "team"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "memberCount" + | "organizationId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "teamMember"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "invitation"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + deleteOne: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "session"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "account"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "verification"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "identifier" + | "value" + | "expiresAt" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "twoFactor"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthAccessToken"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "user_custom"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2118,22 +8673,29 @@ export type ComponentApi = }>; } | { - model: "account"; + model: "user_table"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2158,16 +8720,10 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "oneToOneTable"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -2191,14 +8747,43 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "one_to_one_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "testModel"; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2223,19 +8808,14 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "organization"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -2262,17 +8842,13 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; + model: "member"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -2299,16 +8875,15 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; + model: "team"; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2333,14 +8908,14 @@ export type ComponentApi = }>; } | { - model: "jwks"; + model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2365,10 +8940,20 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; + model: "invitation"; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -2392,6 +8977,38 @@ export type ComponentApi = }>; }; onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + offset?: number; paginationOpts: { cursor: string | null; endCursor?: string | null; @@ -2400,22 +9017,126 @@ export type ComponentApi = maximumRowsRead?: number; numItems: number; }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; }, any, Name >; - deleteOne: FunctionReference< + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< "mutation", "internal", { input: | { + increment: Record; model: "user"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" | "email" + | "email_address" | "emailVerified" | "image" | "createdAt" @@ -2427,10 +9148,10 @@ export type ComponentApi = | "phoneNumber" | "phoneNumberVerified" | "userId" - | "customField" - | "numericField" | "testField" | "cbDefaultValueField" + | "customField" + | "numericField" | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; @@ -2456,8 +9177,18 @@ export type ComponentApi = }>; } | { + increment: Record; model: "session"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + ipAddress?: null | string; + token?: string; + updatedAt?: number; + userAgent?: null | string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "expiresAt" @@ -2491,10 +9222,27 @@ export type ComponentApi = }>; } | { + increment: Record; model: "account"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -2531,8 +9279,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "verification"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "identifier" @@ -2564,14 +9320,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "twoFactor"; - where?: Array<{ + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "secret" | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2596,8 +9363,22 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthApplication"; - where?: Array<{ + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -2635,8 +9416,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthAccessToken"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "accessToken" @@ -2672,8 +9465,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthConsent"; - where?: Array<{ + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "clientId" @@ -2703,188 +9505,92 @@ export type ComponentApi = | Array | Array | null; - }>; - } - | { - model: "jwks"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - } - | { - model: "rateLimit"; - where?: Array<{ - connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit"; - select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - updateMany: FunctionReference< - "mutation", - "internal", - { - input: + }>; + } | { - model: "user"; - update: { + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "rateLimit"; + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "user_custom"; + set?: { cbDefaultValueField?: null | string; createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; - email?: string; + email?: null | string; emailVerified?: boolean; + email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; name?: string; @@ -2897,11 +9603,12 @@ export type ComponentApi = userId?: null | string; username?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" | "email" + | "email_address" | "emailVerified" | "image" | "createdAt" @@ -2913,10 +9620,10 @@ export type ComponentApi = | "phoneNumber" | "phoneNumberVerified" | "userId" - | "customField" - | "numericField" | "testField" | "cbDefaultValueField" + | "customField" + | "numericField" | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; @@ -2942,26 +9649,51 @@ export type ComponentApi = }>; } | { - model: "session"; - update: { + increment: Record; + model: "user_table"; + set?: { + cbDefaultValueField?: null | string; createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; updatedAt?: number; - userAgent?: null | string; - userId?: string; + userId?: null | string; + username?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -2986,37 +9718,12 @@ export type ComponentApi = }>; } | { - 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<{ + increment: Record; + model: "oneToOneTable"; + set?: { oneToOne?: string }; + where: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -3040,23 +9747,15 @@ export type ComponentApi = }>; } | { - model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; + increment: Record; + model: "one_to_one_table"; + set?: { + oneToOne?: null | string; + one_to_one?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -3080,20 +9779,25 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; + increment: Record; + model: "testModel"; + set?: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -3118,32 +9822,23 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; + increment: Record; + model: "organization"; + set?: { + createdAt?: number; + logo?: null | string; metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; + name?: string; + slug?: string; updatedAt?: null | number; - userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -3170,28 +9865,21 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; + increment: Record; + model: "member"; + set?: { + createdAt?: number; + organizationId?: string; + role?: string; updatedAt?: null | number; - userId?: null | string; + userId?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -3215,27 +9903,26 @@ export type ComponentApi = | Array | Array | null; - }>; - } - | { - model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; + }>; + } + | { + increment: Record; + model: "team"; + set?: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; updatedAt?: null | number; - userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -3260,20 +9947,21 @@ export type ComponentApi = }>; } | { - model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; + increment: Record; + model: "teamMember"; + set?: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -3298,15 +9986,32 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; + increment: Record; + model: "invitation"; + set?: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -3330,19 +10035,11 @@ export type ComponentApi = }>; }; onUpdateHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; }, any, Name >; - updateOne: FunctionReference< + updateMany: FunctionReference< "mutation", "internal", { @@ -3355,8 +10052,9 @@ export type ComponentApi = customField?: null | string; dateField?: null | number; displayUsername?: null | string; - email?: string; + email?: null | string; emailVerified?: boolean; + email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; name?: string; @@ -3374,6 +10072,7 @@ export type ComponentApi = field: | "name" | "email" + | "email_address" | "emailVerified" | "image" | "createdAt" @@ -3385,10 +10084,10 @@ export type ComponentApi = | "phoneNumber" | "phoneNumberVerified" | "userId" - | "customField" - | "numericField" | "testField" | "cbDefaultValueField" + | "customField" + | "numericField" | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; @@ -3465,6 +10164,7 @@ export type ComponentApi = accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -3476,6 +10176,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -3555,6 +10256,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -3566,6 +10269,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -3734,7 +10439,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -3746,6 +10453,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -3800,277 +10509,98 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - }, - any, - Name - >; - }; - adapterOrganizationJoins: { - create: FunctionReference< - "mutation", - "internal", - { - input: - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; } | { - data: { + model: "user_custom"; + update: { cbDefaultValueField?: null | string; - createdAt: number; + createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified: boolean; + emailVerified?: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name: string; + name?: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt: number; + updatedAt?: number; userId?: null | string; username?: null | string; }; - model: "user_custom"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { + model: "user_table"; + update: { cbDefaultValueField?: null | string; - createdAt: number; + createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified: boolean; + emailVerified?: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name: string; + name?: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt: number; + updatedAt?: number; userId?: null | string; username?: null | string; }; - model: "user_table"; - } - | { data: { oneToOne: string }; model: "oneToOneTable" } - | { - data: { - oneToOne?: null | string; - one_to_one?: null | string; - }; - model: "one_to_one_table"; - } - | { - data: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; - model: "testModel"; - } - | { - data: { - createdAt: number; - logo?: null | string; - metadata?: null | string; - name: string; - slug: string; - updatedAt?: null | number; - }; - model: "organization"; - } - | { - data: { - createdAt: number; - organizationId: string; - role: string; - updatedAt?: null | number; - userId: string; - }; - model: "member"; - } - | { - data: { - createdAt: number; - name: string; - organizationId: string; - updatedAt?: null | number; - }; - model: "team"; - } - | { - data: { - createdAt?: null | number; - teamId: string; - userId: string; - }; - model: "teamMember"; - } - | { - data: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; - model: "invitation"; - }; - onCreateHandle?: string; - select?: Array; - }, - any, - Name - >; - deleteMany: FunctionReference< - "mutation", - "internal", - { - input: - | { - model: "user"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -4117,17 +10647,125 @@ export type ComponentApi = }>; } | { - model: "session"; + model: "oneToOneTable"; + update: { oneToOne?: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4152,20 +10790,20 @@ export type ComponentApi = }>; } | { - model: "account"; + model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "accountId" - | "providerId" + | "organizationId" | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -4192,13 +10830,20 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "identifier" - | "value" - | "expiresAt" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" | "_id"; @@ -4225,14 +10870,20 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" + | "teamId" | "userId" - | "verified" + | "membershipKey" + | "createdAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4257,19 +10908,28 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "invitation"; + update: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "icon" - | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" | "createdAt" | "updatedAt" | "_id"; @@ -4294,21 +10954,70 @@ export type ComponentApi = | Array | null; }>; - } + }; + onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + updateOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "oauthAccessToken"; + model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" - | "userId" - | "scopes" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4333,16 +11042,26 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; + 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: - | "clientId" - | "userId" - | "scopes" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "consentGiven" + | "ipAddress" + | "userAgent" + | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4367,14 +11086,38 @@ export type ComponentApi = }>; } | { - model: "jwks"; + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: - | "publicKey" - | "privateKey" + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" | "createdAt" - | "expiresAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4399,10 +11142,23 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; + model: "verification"; + update: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4426,29 +11182,24 @@ export type ComponentApi = }>; } | { - model: "user_custom"; + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "secret" + | "backupCodes" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4473,29 +11224,34 @@ export type ComponentApi = }>; } | { - model: "user_table"; + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4520,10 +11276,31 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; + field: + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4547,10 +11324,25 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4574,16 +11366,24 @@ export type ComponentApi = }>; } | { - model: "testModel"; + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4608,17 +11408,15 @@ export type ComponentApi = }>; } | { - model: "organization"; + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "name" - | "slug" - | "logo" - | "metadata" - | "createdAt" - | "updatedAt" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4642,15 +11440,50 @@ export type ComponentApi = }>; } | { - model: "member"; + model: "user_custom"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" - | "userId" - | "role" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4675,14 +11508,50 @@ export type ComponentApi = }>; } | { - model: "team"; + model: "user_table"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "organizationId" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4707,10 +11576,11 @@ export type ComponentApi = }>; } | { - model: "teamMember"; + model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4734,20 +11604,14 @@ export type ComponentApi = }>; } | { - model: "invitation"; + model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -4769,49 +11633,26 @@ export type ComponentApi = | Array | null; }>; - }; - onDeleteHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - }, - any, - Name - >; - deleteOne: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; + model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" + | "nullableReference" | "testField" | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4836,17 +11677,24 @@ export type ComponentApi = }>; } | { - model: "session"; + model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "slug" + | "logo" + | "metadata" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4871,20 +11719,20 @@ export type ComponentApi = }>; } | { - model: "account"; + model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "accountId" - | "providerId" + | "organizationId" | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -4911,13 +11759,20 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "identifier" - | "value" - | "expiresAt" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" | "_id"; @@ -4944,14 +11799,20 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" + | "teamId" | "userId" - | "verified" + | "membershipKey" + | "createdAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -4976,19 +11837,28 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "invitation"; + update: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "icon" - | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" | "createdAt" | "updatedAt" | "_id"; @@ -5013,139 +11883,284 @@ export type ComponentApi = | Array | null; }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterPluginTable: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_custom"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_table"; + } + | { data: { oneToOne: string }; model: "oneToOneTable" } + | { + data: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + model: "one_to_one_table"; } | { - model: "oauthAccessToken"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" - | "userId" - | "scopes" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + data: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + model: "testModel"; } | { - model: "oauthConsent"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "clientId" - | "userId" - | "scopes" - | "createdAt" - | "updatedAt" - | "consentGiven" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + data: { + createdAt: number; + logo?: null | string; + metadata?: null | string; + name: string; + slug: string; + updatedAt?: null | number; + }; + model: "organization"; } | { - model: "jwks"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "publicKey" - | "privateKey" - | "createdAt" - | "expiresAt" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + data: { + createdAt: number; + organizationId: string; + role: string; + updatedAt?: null | number; + userId: string; + }; + model: "member"; } | { - model: "rateLimit"; - where?: Array<{ - connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + data: { + createdAt: number; + memberCount: number; + name: string; + organizationId: string; + updatedAt?: null | number; + }; + model: "team"; } | { - model: "user_custom"; + data: { + createdAt?: null | number; + membershipKey?: null | string; + teamId: string; + userId: string; + }; + model: "teamMember"; + } + | { + data: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + model: "invitation"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -5192,29 +12207,17 @@ export type ComponentApi = }>; } | { - model: "user_table"; + model: "session"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5239,37 +12242,24 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - where?: Array<{ - connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - } - | { - model: "one_to_one_table"; + model: "account"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -5293,16 +12283,15 @@ export type ComponentApi = }>; } | { - model: "testModel"; + model: "verification"; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5327,16 +12316,16 @@ export type ComponentApi = }>; } | { - model: "organization"; + model: "twoFactor"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "slug" - | "logo" - | "metadata" - | "createdAt" - | "updatedAt" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5361,13 +12350,19 @@ export type ComponentApi = }>; } | { - model: "member"; + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" | "userId" - | "role" | "createdAt" | "updatedAt" | "_id"; @@ -5394,12 +12389,17 @@ export type ComponentApi = }>; } | { - model: "team"; + model: "oauthAccessToken"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -5426,10 +12426,17 @@ export type ComponentApi = }>; } | { - model: "teamMember"; + model: "oauthConsent"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -5453,19 +12460,16 @@ export type ComponentApi = }>; } | { - model: "invitation"; + model: "jwks"; where?: Array<{ connector?: "AND" | "OR"; field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" + | "publicKey" + | "privateKey" | "createdAt" - | "updatedAt" + | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5486,186 +12490,14 @@ export type ComponentApi = | boolean | Array | Array - | null; - }>; - }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - updateMany: FunctionReference< - "mutation", - "internal", - { - input: - | { - model: "user"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" - | "_id"; + | null; + }>; + } + | { + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -5689,26 +12521,29 @@ export type ComponentApi = }>; } | { - model: "session"; - update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + model: "user_custom"; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5733,36 +12568,29 @@ export type ComponentApi = }>; } | { - 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; - }; + model: "user_table"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5787,23 +12615,10 @@ export type ComponentApi = }>; } | { - model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; + model: "oneToOneTable"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -5827,21 +12642,10 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; + model: "one_to_one_table"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -5865,34 +12669,16 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "testModel"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "icon" - | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" - | "createdAt" - | "updatedAt" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -5917,28 +12703,14 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "organization"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" - | "userId" - | "scopes" + | "name" + | "slug" + | "logo" + | "metadata" | "createdAt" | "updatedAt" | "_id"; @@ -5965,24 +12737,15 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "member"; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6007,20 +12770,15 @@ export type ComponentApi = }>; } | { - model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; + model: "team"; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "name" + | "memberCount" + | "organizationId" | "createdAt" - | "expiresAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6045,15 +12803,15 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; - }; + model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6077,50 +12835,19 @@ export type ComponentApi = }>; } | { - model: "user_custom"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "invitation"; where?: Array<{ - connector?: "AND" | "OR"; - field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" + connector?: "AND" | "OR"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6143,30 +12870,27 @@ export type ComponentApi = | Array | null; }>; - } + }; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + deleteOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "user_table"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "user"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -6213,11 +12937,18 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; + model: "session"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; + field: + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6241,14 +12972,24 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; - }; + model: "account"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6272,24 +13013,15 @@ export type ComponentApi = }>; } | { - model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; + model: "verification"; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6314,24 +13046,16 @@ export type ComponentApi = }>; } | { - model: "organization"; - update: { - createdAt?: number; - logo?: null | string; - metadata?: null | string; - name?: string; - slug?: string; - updatedAt?: null | number; - }; + model: "twoFactor"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "slug" - | "logo" - | "metadata" - | "createdAt" - | "updatedAt" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6356,20 +13080,19 @@ export type ComponentApi = }>; } | { - model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" | "userId" - | "role" | "createdAt" | "updatedAt" | "_id"; @@ -6396,18 +13119,17 @@ export type ComponentApi = }>; } | { - model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; + model: "oauthAccessToken"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -6434,15 +13156,17 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; + model: "oauthConsent"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6466,30 +13190,16 @@ export type ComponentApi = }>; } | { - model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; + model: "jwks"; where?: Array<{ connector?: "AND" | "OR"; field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" + | "publicKey" + | "privateKey" | "createdAt" - | "updatedAt" + | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6512,48 +13222,36 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - }, - any, - Name - >; - updateOne: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "user_custom"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -6600,26 +13298,29 @@ export type ComponentApi = }>; } | { - model: "session"; - update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + model: "user_table"; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6644,37 +13345,10 @@ export type ComponentApi = }>; } | { - 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; - }; + model: "oneToOneTable"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6698,23 +13372,10 @@ export type ComponentApi = }>; } | { - model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; + model: "one_to_one_table"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6738,20 +13399,16 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; + model: "testModel"; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6776,32 +13433,14 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "organization"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -6828,28 +13467,13 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "member"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -6876,24 +13500,15 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "team"; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6918,20 +13533,14 @@ export type ComponentApi = }>; } | { - model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; + model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -6956,15 +13565,20 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; - }; + model: "invitation"; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -6986,10 +13600,142 @@ export type ComponentApi = | Array | null; }>; - } + }; + onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + offset?: number; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "user_custom"; - update: { + increment: Record; + model: "user"; + set?: { cbDefaultValueField?: null | string; createdAt?: number; customField?: null | string; @@ -7010,7 +13756,7 @@ export type ComponentApi = userId?: null | string; username?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -7056,50 +13802,27 @@ export type ComponentApi = }>; } | { - model: "user_table"; - update: { - cbDefaultValueField?: null | string; + increment: Record; + model: "session"; + set?: { createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; + expiresAt?: number; + ipAddress?: null | string; + token?: string; updatedAt?: number; - userId?: null | string; - username?: null | string; + userAgent?: null | string; + userId?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -7124,11 +13847,40 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; - where?: Array<{ + increment: Record; + model: "account"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: "oneToOne" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -7152,14 +13904,24 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; + increment: Record; + model: "verification"; + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -7183,24 +13945,25 @@ export type ComponentApi = }>; } | { - model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; + increment: Record; + model: "twoFactor"; + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -7225,22 +13988,33 @@ export type ComponentApi = }>; } | { - model: "organization"; - update: { - createdAt?: number; - logo?: null | string; + increment: Record; + model: "oauthApplication"; + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; metadata?: null | string; - name?: string; - slug?: string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; updatedAt?: null | number; + userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" + | "icon" | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -7267,20 +14041,29 @@ export type ComponentApi = }>; } | { - model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; + increment: Record; + model: "oauthAccessToken"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; updatedAt?: null | number; - userId?: string; + userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" | "userId" - | "role" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -7307,20 +14090,25 @@ export type ComponentApi = }>; } | { - model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; + increment: Record; + model: "oauthConsent"; + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; updatedAt?: null | number; + userId?: null | string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -7345,15 +14133,26 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; }; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -7377,31 +14176,12 @@ export type ComponentApi = }>; } | { - model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; - where?: Array<{ + increment: Record; + model: "rateLimit"; + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -7423,203 +14203,210 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - }, - any, - Name - >; - }; - adapterPluginTable: { - create: FunctionReference< - "mutation", - "internal", - { - input: - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; } | { - data: { + increment: Record; + model: "user_custom"; + set?: { cbDefaultValueField?: null | string; - createdAt: number; + createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified: boolean; + emailVerified?: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name: string; + name?: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt: number; + updatedAt?: number; userId?: null | string; username?: null | string; }; - model: "user_custom"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { + increment: Record; + model: "user_table"; + set?: { cbDefaultValueField?: null | string; - createdAt: number; + createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified: boolean; + emailVerified?: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name: string; + name?: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt: number; + updatedAt?: number; userId?: null | string; username?: null | string; }; - model: "user_table"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } - | { data: { oneToOne: string }; model: "oneToOneTable" } | { - data: { + increment: Record; + model: "oneToOneTable"; + set?: { oneToOne?: string }; + where: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + increment: Record; + model: "one_to_one_table"; + set?: { oneToOne?: null | string; one_to_one?: null | string; }; - model: "one_to_one_table"; + where: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { + increment: Record; + model: "testModel"; + set?: { cbDefaultValueField?: null | string; json?: any; nullableReference?: null | string; @@ -7627,48 +14414,206 @@ export type ComponentApi = stringArray?: null | Array; testField?: null | string; }; - model: "testModel"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; + increment: Record; + model: "organization"; + set?: { + createdAt?: number; logo?: null | string; metadata?: null | string; - name: string; - slug: string; + name?: string; + slug?: string; updatedAt?: null | number; }; - model: "organization"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - organizationId: string; - role: string; + increment: Record; + model: "member"; + set?: { + createdAt?: number; + organizationId?: string; + role?: string; updatedAt?: null | number; - userId: string; + userId?: string; }; - model: "member"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - name: string; - organizationId: string; + increment: Record; + model: "team"; + set?: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; updatedAt?: null | number; }; - model: "team"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "memberCount" + | "organizationId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { + increment: Record; + model: "teamMember"; + set?: { createdAt?: null | number; - teamId: string; - userId: string; + membershipKey?: null | string; + teamId?: string; + userId?: string; }; - model: "teamMember"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { + increment: Record; + model: "invitation"; + set?: { createdAt?: null | number; email?: null | string; expiresAt?: null | number; @@ -7679,21 +14624,74 @@ export type ComponentApi = teamId?: null | string; updatedAt?: null | number; }; - model: "invitation"; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; }; - onCreateHandle?: string; - select?: Array; + onUpdateHandle?: string; }, any, Name >; - deleteMany: FunctionReference< + updateMany: FunctionReference< "mutation", "internal", { input: | { model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7741,6 +14739,15 @@ export type ComponentApi = } | { 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: @@ -7776,9 +14783,25 @@ export type ComponentApi = } | { model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -7816,6 +14839,13 @@ export type ComponentApi = } | { model: "verification"; + update: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7849,6 +14879,14 @@ export type ComponentApi = } | { model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7856,6 +14894,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -7881,6 +14921,19 @@ export type ComponentApi = } | { model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7920,6 +14973,17 @@ export type ComponentApi = } | { model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7957,6 +15021,14 @@ export type ComponentApi = } | { model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7991,6 +15063,14 @@ export type ComponentApi = } | { model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -7998,6 +15078,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -8023,6 +15105,11 @@ export type ComponentApi = } | { model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; where?: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; @@ -8050,6 +15137,27 @@ export type ComponentApi = } | { model: "user_custom"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8097,6 +15205,27 @@ export type ComponentApi = } | { model: "user_table"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8144,6 +15273,7 @@ export type ComponentApi = } | { model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; @@ -8171,6 +15301,10 @@ export type ComponentApi = } | { model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; @@ -8198,6 +15332,14 @@ export type ComponentApi = } | { model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8232,6 +15374,14 @@ export type ComponentApi = } | { model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8266,6 +15416,13 @@ export type ComponentApi = } | { model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8299,10 +15456,18 @@ export type ComponentApi = } | { model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -8331,9 +15496,20 @@ export type ComponentApi = } | { model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -8358,6 +15534,17 @@ export type ComponentApi = } | { model: "invitation"; + update: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8393,7 +15580,7 @@ export type ComponentApi = | null; }>; }; - onDeleteHandle?: string; + onUpdateHandle?: string; paginationOpts: { cursor: string | null; endCursor?: string | null; @@ -8406,13 +15593,34 @@ export type ComponentApi = any, Name >; - deleteOne: FunctionReference< + updateOne: FunctionReference< "mutation", "internal", { input: | { model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8460,6 +15668,15 @@ export type ComponentApi = } | { 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: @@ -8495,9 +15712,25 @@ export type ComponentApi = } | { model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -8535,6 +15768,13 @@ export type ComponentApi = } | { model: "verification"; + update: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8568,6 +15808,14 @@ export type ComponentApi = } | { model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8575,6 +15823,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -8600,6 +15850,19 @@ export type ComponentApi = } | { model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8639,6 +15902,17 @@ export type ComponentApi = } | { model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8676,6 +15950,14 @@ export type ComponentApi = } | { model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8710,6 +15992,14 @@ export type ComponentApi = } | { model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8717,6 +16007,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -8742,6 +16034,11 @@ export type ComponentApi = } | { model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; where?: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; @@ -8769,6 +16066,27 @@ export type ComponentApi = } | { model: "user_custom"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8816,6 +16134,27 @@ export type ComponentApi = } | { model: "user_table"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8863,6 +16202,7 @@ export type ComponentApi = } | { model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; @@ -8890,6 +16230,10 @@ export type ComponentApi = } | { model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; @@ -8917,6 +16261,14 @@ export type ComponentApi = } | { model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -8950,14 +16302,102 @@ export type ComponentApi = }>; } | { - model: "organization"; + model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" - | "metadata" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" | "_id"; @@ -8984,15 +16424,20 @@ export type ComponentApi = }>; } | { - model: "member"; + model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "teamId" | "userId" - | "role" + | "membershipKey" | "createdAt" - | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -9017,12 +16462,28 @@ export type ComponentApi = }>; } | { - model: "team"; + model: "invitation"; + update: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" + | "email" + | "role" + | "status" | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" | "createdAt" | "updatedAt" | "_id"; @@ -9047,225 +16508,284 @@ export type ComponentApi = | Array | null; }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterRenameField: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_custom"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_table"; + } + | { data: { oneToOne: string }; model: "oneToOneTable" } + | { + data: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + model: "one_to_one_table"; + } + | { + data: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + model: "testModel"; + } + | { + data: { + createdAt: number; + logo?: null | string; + metadata?: null | string; + name: string; + slug: string; + updatedAt?: null | number; + }; + model: "organization"; + } + | { + data: { + createdAt: number; + organizationId: string; + role: string; + updatedAt?: null | number; + userId: string; + }; + model: "member"; + } + | { + data: { + createdAt: number; + memberCount: number; + name: string; + organizationId: string; + updatedAt?: null | number; + }; + model: "team"; } | { + data: { + createdAt?: null | number; + membershipKey?: null | string; + teamId: string; + userId: string; + }; model: "teamMember"; - where?: Array<{ - connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; } | { + data: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; model: "invitation"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; + onCreateHandle?: string; select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; }, any, Name >; - updateMany: FunctionReference< + deleteMany: FunctionReference< "mutation", "internal", { input: | { model: "user"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9307,21 +16827,12 @@ export type ComponentApi = | number | boolean | Array - | Array - | null; - }>; - } - | { - model: "session"; - update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + | Array + | null; + }>; + } + | { + model: "session"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9357,23 +16868,10 @@ export type ComponentApi = } | { 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -9411,13 +16909,6 @@ export type ComponentApi = } | { model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9451,12 +16942,6 @@ export type ComponentApi = } | { model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9464,6 +16949,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -9489,19 +16976,6 @@ export type ComponentApi = } | { model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9541,17 +17015,6 @@ export type ComponentApi = } | { model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9589,14 +17052,6 @@ export type ComponentApi = } | { model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9631,12 +17086,6 @@ export type ComponentApi = } | { model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9644,6 +17093,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -9669,11 +17120,6 @@ export type ComponentApi = } | { model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; - }; where?: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; @@ -9701,27 +17147,6 @@ export type ComponentApi = } | { model: "user_custom"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9769,27 +17194,6 @@ export type ComponentApi = } | { model: "user_table"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9837,7 +17241,6 @@ export type ComponentApi = } | { model: "oneToOneTable"; - update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; @@ -9865,10 +17268,6 @@ export type ComponentApi = } | { model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; @@ -9896,14 +17295,6 @@ export type ComponentApi = } | { model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9938,14 +17329,6 @@ export type ComponentApi = } | { model: "organization"; - update: { - createdAt?: number; - logo?: null | string; - metadata?: null | string; - name?: string; - slug?: string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -9980,13 +17363,6 @@ export type ComponentApi = } | { model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10020,16 +17396,11 @@ export type ComponentApi = } | { model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -10058,14 +17429,14 @@ export type ComponentApi = } | { model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -10090,17 +17461,6 @@ export type ComponentApi = } | { model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10136,7 +17496,7 @@ export type ComponentApi = | null; }>; }; - onUpdateHandle?: string; + onDeleteHandle?: string; paginationOpts: { cursor: string | null; endCursor?: string | null; @@ -10149,34 +17509,13 @@ export type ComponentApi = any, Name >; - updateOne: FunctionReference< + deleteOne: FunctionReference< "mutation", "internal", { input: | { model: "user"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10224,15 +17563,6 @@ export type ComponentApi = } | { 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: @@ -10268,23 +17598,10 @@ export type ComponentApi = } | { 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -10322,13 +17639,6 @@ export type ComponentApi = } | { model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10362,12 +17672,6 @@ export type ComponentApi = } | { model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10375,6 +17679,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -10391,28 +17697,15 @@ export type ComponentApi = | "ends_with"; value: | string - | number - | boolean - | Array - | Array - | null; - }>; - } - | { - model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10452,17 +17745,6 @@ export type ComponentApi = } | { model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10500,14 +17782,6 @@ export type ComponentApi = } | { model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10542,12 +17816,6 @@ export type ComponentApi = } | { model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10555,6 +17823,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -10580,11 +17850,6 @@ export type ComponentApi = } | { model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; - }; where?: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; @@ -10612,27 +17877,6 @@ export type ComponentApi = } | { model: "user_custom"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10680,27 +17924,6 @@ export type ComponentApi = } | { model: "user_table"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10748,7 +17971,6 @@ export type ComponentApi = } | { model: "oneToOneTable"; - update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; @@ -10776,10 +17998,6 @@ export type ComponentApi = } | { model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; @@ -10807,14 +18025,6 @@ export type ComponentApi = } | { model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10849,14 +18059,6 @@ export type ComponentApi = } | { model: "organization"; - update: { - createdAt?: number; - logo?: null | string; - metadata?: null | string; - name?: string; - slug?: string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10891,13 +18093,6 @@ export type ComponentApi = } | { model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -10931,16 +18126,11 @@ export type ComponentApi = } | { model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -10969,14 +18159,14 @@ export type ComponentApi = } | { model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -11001,17 +18191,6 @@ export type ComponentApi = } | { model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -11047,277 +18226,162 @@ export type ComponentApi = | null; }>; }; - onUpdateHandle?: string; + onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + offset?: number; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; }, any, Name >; - }; - adapterRenameField: { - create: FunctionReference< + incrementOne: FunctionReference< "mutation", "internal", { input: | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; + increment: Record; 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; - } - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; - model: "user_custom"; - } - | { - data: { + set?: { cbDefaultValueField?: null | string; - createdAt: number; + createdAt?: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified: boolean; + emailVerified?: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name: string; + name?: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt: number; + updatedAt?: number; userId?: null | string; username?: null | string; }; - model: "user_table"; - } - | { data: { oneToOne: string }; model: "oneToOneTable" } - | { - data: { - oneToOne?: null | string; - one_to_one?: null | string; - }; - model: "one_to_one_table"; - } - | { - data: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; - model: "testModel"; - } - | { - data: { - createdAt: number; - logo?: null | string; - metadata?: null | string; - name: string; - slug: string; - updatedAt?: null | number; - }; - model: "organization"; - } - | { - data: { - createdAt: number; - organizationId: string; - role: string; - updatedAt?: null | number; - userId: string; - }; - model: "member"; - } - | { - data: { - createdAt: number; - name: string; - organizationId: string; - updatedAt?: null | number; - }; - model: "team"; - } - | { - data: { - createdAt?: null | number; - teamId: string; - userId: string; - }; - model: "teamMember"; - } - | { - data: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; - model: "invitation"; - }; - onCreateHandle?: string; - select?: Array; - }, - any, - Name - >; - deleteMany: FunctionReference< - "mutation", - "internal", - { - input: - | { - model: "user"; - where?: Array<{ + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -11363,8 +18427,18 @@ export type ComponentApi = }>; } | { + increment: Record; model: "session"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + ipAddress?: null | string; + token?: string; + updatedAt?: number; + userAgent?: null | string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "expiresAt" @@ -11398,10 +18472,27 @@ export type ComponentApi = }>; } | { + increment: Record; model: "account"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -11438,8 +18529,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "verification"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "identifier" @@ -11471,14 +18570,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "twoFactor"; - where?: Array<{ + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "secret" | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -11503,8 +18613,22 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthApplication"; - where?: Array<{ + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -11542,8 +18666,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthAccessToken"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "accessToken" @@ -11579,8 +18715,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthConsent"; - where?: Array<{ + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "clientId" @@ -11613,14 +18758,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "jwks"; - where?: Array<{ + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "publicKey" | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -11645,8 +18801,10 @@ export type ComponentApi = }>; } | { + increment: Record; model: "rateLimit"; - where?: Array<{ + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; @@ -11672,8 +18830,30 @@ export type ComponentApi = }>; } | { + increment: Record; model: "user_custom"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -11719,8 +18899,30 @@ export type ComponentApi = }>; } | { + increment: Record; model: "user_table"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -11766,8 +18968,10 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oneToOneTable"; - where?: Array<{ + set?: { oneToOne?: string }; + where: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; @@ -11793,8 +18997,13 @@ export type ComponentApi = }>; } | { + increment: Record; model: "one_to_one_table"; - where?: Array<{ + set?: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; @@ -11820,8 +19029,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "testModel"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "nullableReference" @@ -11854,8 +19072,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "organization"; - where?: Array<{ + set?: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -11888,8 +19115,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "member"; - where?: Array<{ + set?: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "organizationId" @@ -11921,11 +19156,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "team"; - where?: Array<{ + set?: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -11953,10 +19197,22 @@ export type ComponentApi = }>; } | { + increment: Record; model: "teamMember"; - where?: Array<{ + set?: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -11980,8 +19236,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "invitation"; - where?: Array<{ + set?: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "email" @@ -12016,26 +19284,39 @@ export type ComponentApi = | null; }>; }; - onDeleteHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; + onUpdateHandle?: string; }, any, Name >; - deleteOne: FunctionReference< + updateMany: FunctionReference< "mutation", "internal", { input: | { model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12083,6 +19364,15 @@ export type ComponentApi = } | { 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: @@ -12118,9 +19408,25 @@ export type ComponentApi = } | { model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -12158,6 +19464,13 @@ export type ComponentApi = } | { model: "verification"; + update: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12191,6 +19504,14 @@ export type ComponentApi = } | { model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12198,6 +19519,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -12223,6 +19546,19 @@ export type ComponentApi = } | { model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12262,6 +19598,17 @@ export type ComponentApi = } | { model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12299,6 +19646,14 @@ export type ComponentApi = } | { model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12333,6 +19688,14 @@ export type ComponentApi = } | { model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12340,6 +19703,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -12365,6 +19730,11 @@ export type ComponentApi = } | { model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; where?: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; @@ -12392,6 +19762,27 @@ export type ComponentApi = } | { model: "user_custom"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12439,6 +19830,27 @@ export type ComponentApi = } | { model: "user_table"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12486,6 +19898,7 @@ export type ComponentApi = } | { model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; @@ -12513,6 +19926,10 @@ export type ComponentApi = } | { model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; @@ -12540,6 +19957,14 @@ export type ComponentApi = } | { model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12574,6 +19999,14 @@ export type ComponentApi = } | { model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12608,6 +20041,13 @@ export type ComponentApi = } | { model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12641,10 +20081,18 @@ export type ComponentApi = } | { model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -12673,9 +20121,20 @@ export type ComponentApi = } | { model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -12700,6 +20159,17 @@ export type ComponentApi = } | { model: "invitation"; + update: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -12721,147 +20191,34 @@ export type ComponentApi = | "gte" | "eq" | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }; + onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; }, any, Name >; - updateMany: FunctionReference< + updateOne: FunctionReference< "mutation", "internal", { @@ -12986,6 +20343,7 @@ export type ComponentApi = accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -12997,6 +20355,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -13076,6 +20435,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -13087,6 +20448,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13255,7 +20618,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -13267,6 +20632,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13417,24 +20784,247 @@ export type ComponentApi = connector?: "AND" | "OR"; field: | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oneToOneTable"; + update: { oneToOne?: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "one_to_one_table"; + update: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "testModel"; + update: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "organization"; + update: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "member"; + update: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "team"; + update: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13459,11 +21049,21 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; + model: "teamMember"; + update: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -13487,14 +21087,31 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; + model: "invitation"; update: { - oneToOne?: null | string; - one_to_one?: null | string; + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -13516,10 +21133,208 @@ export type ComponentApi = | Array | null; }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterRenameUserCustom: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user"; } | { - model: "testModel"; - update: { + 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; + } + | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_custom"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; + model: "user_table"; + } + | { data: { oneToOne: string }; model: "oneToOneTable" } + | { + data: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + model: "one_to_one_table"; + } + | { + data: { cbDefaultValueField?: null | string; json?: any; nullableReference?: null | string; @@ -13527,57 +21342,97 @@ export type ComponentApi = stringArray?: null | Array; testField?: null | string; }; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" - | "_id"; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + model: "testModel"; } | { - model: "organization"; - update: { - createdAt?: number; + data: { + createdAt: number; logo?: null | string; metadata?: null | string; - name?: string; - slug?: string; + name: string; + slug: string; + updatedAt?: null | number; + }; + model: "organization"; + } + | { + data: { + createdAt: number; + organizationId: string; + role: string; + updatedAt?: null | number; + userId: string; + }; + model: "member"; + } + | { + data: { + createdAt: number; + memberCount: number; + name: string; + organizationId: string; + updatedAt?: null | number; + }; + model: "team"; + } + | { + data: { + createdAt?: null | number; + membershipKey?: null | string; + teamId: string; + userId: string; + }; + model: "teamMember"; + } + | { + data: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; updatedAt?: null | number; }; + model: "invitation"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" - | "metadata" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13602,22 +21457,17 @@ export type ComponentApi = }>; } | { - model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; + model: "session"; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" - | "userId" - | "role" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13642,18 +21492,21 @@ export type ComponentApi = }>; } | { - model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; + model: "account"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" | "createdAt" | "updatedAt" | "_id"; @@ -13680,15 +21533,16 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; + model: "verification"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -13712,30 +21566,16 @@ export type ComponentApi = }>; } | { - model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; + model: "twoFactor"; where?: Array<{ connector?: "AND" | "OR"; field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13758,70 +21598,23 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - }, - any, - Name - >; - updateOne: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" + | "createdAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13846,26 +21639,19 @@ export type ComponentApi = }>; } | { - model: "session"; - update: { - createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; - updatedAt?: number; - userAgent?: null | string; - userId?: string; - }; + model: "oauthAccessToken"; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" - | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13890,36 +21676,16 @@ export type ComponentApi = }>; } | { - 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; - }; + model: "oauthConsent"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accountId" - | "providerId" + | "clientId" | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13944,22 +21710,16 @@ export type ComponentApi = }>; } | { - model: "verification"; - update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; - }; + model: "jwks"; where?: Array<{ connector?: "AND" | "OR"; field: - | "identifier" - | "value" - | "expiresAt" + | "publicKey" + | "privateKey" | "createdAt" - | "updatedAt" + | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -13984,21 +21744,10 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; - update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; - }; + model: "rateLimit"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "secret" - | "backupCodes" - | "userId" - | "verified" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -14022,34 +21771,29 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; - update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "user_custom"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" - | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14074,30 +21818,29 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; - update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "user_table"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" - | "userId" - | "scopes" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14122,24 +21865,70 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; - update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; + model: "oneToOneTable"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "one_to_one_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "testModel"; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" - | "createdAt" - | "updatedAt" - | "consentGiven" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14164,20 +21953,16 @@ export type ComponentApi = }>; } | { - model: "jwks"; - update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; - }; + model: "organization"; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "name" + | "slug" + | "logo" + | "metadata" | "createdAt" - | "expiresAt" + | "updatedAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14202,15 +21987,16 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; - update: { - count?: number; - key?: string; - lastRequest?: number; - }; + model: "member"; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -14234,50 +22020,15 @@ export type ComponentApi = }>; } | { - model: "user_custom"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "team"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" - | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14302,50 +22053,14 @@ export type ComponentApi = }>; } | { - model: "user_table"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" - | "createdAt" - | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "teamId" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" + | "membershipKey" + | "createdAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14370,11 +22085,20 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; + model: "invitation"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -14396,16 +22120,50 @@ export type ComponentApi = | Array | null; }>; - } + }; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + deleteOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; - }; + model: "user"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -14429,24 +22187,17 @@ export type ComponentApi = }>; } | { - model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; + model: "session"; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "expiresAt" + | "token" + | "createdAt" + | "updatedAt" + | "ipAddress" + | "userAgent" + | "userId" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14471,22 +22222,21 @@ export type ComponentApi = }>; } | { - model: "organization"; - update: { - createdAt?: number; - logo?: null | string; - metadata?: null | string; - name?: string; - slug?: string; - updatedAt?: null | number; - }; + model: "account"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "slug" - | "logo" - | "metadata" + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" | "createdAt" | "updatedAt" | "_id"; @@ -14513,20 +22263,13 @@ export type ComponentApi = }>; } | { - model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; + model: "verification"; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" - | "userId" - | "role" + | "identifier" + | "value" + | "expiresAt" | "createdAt" | "updatedAt" | "_id"; @@ -14553,20 +22296,16 @@ export type ComponentApi = }>; } | { - model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; + model: "twoFactor"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" - | "createdAt" - | "updatedAt" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -14591,15 +22330,22 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "name" + | "icon" + | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -14623,28 +22369,17 @@ export type ComponentApi = }>; } | { - model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; + model: "oauthAccessToken"; where?: Array<{ connector?: "AND" | "OR"; field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -14661,285 +22396,112 @@ export type ComponentApi = | "contains" | "starts_with" | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }; - onUpdateHandle?: string; - }, - any, - Name - >; - }; - adapterRenameUserCustom: { - create: FunctionReference< - "mutation", - "internal", - { - input: - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; - } - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; - model: "user_custom"; - } - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; - model: "user_table"; - } - | { data: { oneToOne: string }; model: "oneToOneTable" } - | { - data: { - oneToOne?: null | string; - one_to_one?: null | string; - }; - model: "one_to_one_table"; - } - | { - data: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; - model: "testModel"; - } - | { - data: { - createdAt: number; - logo?: null | string; - metadata?: null | string; - name: string; - slug: string; - updatedAt?: null | number; - }; - model: "organization"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - organizationId: string; - role: string; - updatedAt?: null | number; - userId: string; - }; - model: "member"; + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" + | "createdAt" + | "updatedAt" + | "consentGiven" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - name: string; - organizationId: string; - updatedAt?: null | number; - }; - model: "team"; + model: "jwks"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt?: null | number; - teamId: string; - userId: string; - }; - model: "teamMember"; + model: "rateLimit"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "key" | "count" | "lastRequest" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; - model: "invitation"; - }; - onCreateHandle?: string; - select?: Array; - }, - any, - Name - >; - deleteMany: FunctionReference< - "mutation", - "internal", - { - input: - | { - model: "user"; + model: "user_custom"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -14986,17 +22548,29 @@ export type ComponentApi = }>; } | { - model: "session"; + model: "user_table"; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15021,23 +22595,10 @@ export type ComponentApi = }>; } | { - model: "account"; + model: "oneToOneTable"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15061,16 +22622,10 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "one_to_one_table"; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15094,14 +22649,16 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "testModel"; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15126,19 +22683,14 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "organization"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -15165,17 +22717,13 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; + model: "member"; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -15202,16 +22750,15 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; + model: "team"; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15236,14 +22783,14 @@ export type ComponentApi = }>; } | { - model: "jwks"; + model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15268,10 +22815,20 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; + model: "invitation"; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15293,10 +22850,163 @@ export type ComponentApi = | Array | null; }>; - } + }; + onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + offset?: number; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "user_custom"; - where?: Array<{ + increment: Record; + model: "user"; + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -15342,29 +23052,27 @@ export type ComponentApi = }>; } | { - model: "user_table"; - where?: Array<{ + increment: Record; + model: "session"; + set?: { + createdAt?: number; + expiresAt?: number; + ipAddress?: null | string; + token?: string; + updatedAt?: number; + userAgent?: null | string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15389,10 +23097,40 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - where?: Array<{ + increment: Record; + model: "account"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: "oneToOne" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15416,10 +23154,24 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; - where?: Array<{ + increment: Record; + model: "verification"; + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15443,16 +23195,25 @@ export type ComponentApi = }>; } | { - model: "testModel"; - where?: Array<{ + increment: Record; + model: "twoFactor"; + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15477,14 +23238,33 @@ export type ComponentApi = }>; } | { - model: "organization"; - where?: Array<{ + increment: Record; + model: "oauthApplication"; + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" + | "icon" | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -15511,13 +23291,29 @@ export type ComponentApi = }>; } | { - model: "member"; - where?: Array<{ + increment: Record; + model: "oauthAccessToken"; + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" | "userId" - | "role" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -15544,14 +23340,25 @@ export type ComponentApi = }>; } | { - model: "team"; - where?: Array<{ + increment: Record; + model: "oauthConsent"; + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15576,10 +23383,26 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - where?: Array<{ + increment: Record; + model: "jwks"; + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15603,20 +23426,12 @@ export type ComponentApi = }>; } | { - model: "invitation"; - where?: Array<{ + increment: Record; + model: "rateLimit"; + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15638,28 +23453,32 @@ export type ComponentApi = | Array | null; }>; - }; - onDeleteHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - }, - any, - Name - >; - deleteOne: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; - where?: Array<{ + increment: Record; + model: "user_custom"; + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -15705,17 +23524,51 @@ export type ComponentApi = }>; } | { - model: "session"; - where?: Array<{ + increment: Record; + model: "user_table"; + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15740,23 +23593,12 @@ export type ComponentApi = }>; } | { - model: "account"; - where?: Array<{ + increment: Record; + model: "oneToOneTable"; + set?: { oneToOne?: string }; + where: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15780,16 +23622,15 @@ export type ComponentApi = }>; } | { - model: "verification"; - where?: Array<{ + increment: Record; + model: "one_to_one_table"; + set?: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -15813,14 +23654,25 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; - where?: Array<{ + increment: Record; + model: "testModel"; + set?: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15845,19 +23697,23 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; - where?: Array<{ + increment: Record; + model: "organization"; + set?: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -15884,17 +23740,21 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; - where?: Array<{ - connector?: "AND" | "OR"; - field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + increment: Record; + model: "member"; + set?: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; + where: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -15921,16 +23781,23 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; - where?: Array<{ + increment: Record; + model: "team"; + set?: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15955,14 +23822,21 @@ export type ComponentApi = }>; } | { - model: "jwks"; - where?: Array<{ + increment: Record; + model: "teamMember"; + set?: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -15987,10 +23861,32 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; - where?: Array<{ + increment: Record; + model: "invitation"; + set?: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16012,9 +23908,40 @@ export type ComponentApi = | Array | null; }>; - } + }; + onUpdateHandle?: string; + }, + any, + Name + >; + updateMany: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "user_custom"; + model: "user"; + update: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: @@ -16061,29 +23988,26 @@ export type ComponentApi = }>; } | { - model: "user_table"; + 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: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16108,10 +24032,39 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: "oneToOne" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16135,10 +24088,23 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; + model: "verification"; + update: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16162,16 +24128,24 @@ export type ComponentApi = }>; } | { - model: "testModel"; + model: "twoFactor"; + update: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16196,14 +24170,32 @@ export type ComponentApi = }>; } | { - model: "organization"; + model: "oauthApplication"; + update: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" + | "icon" | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -16230,13 +24222,28 @@ export type ComponentApi = }>; } | { - model: "member"; + model: "oauthAccessToken"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" | "userId" - | "role" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -16263,14 +24270,24 @@ export type ComponentApi = }>; } | { - model: "team"; + model: "oauthConsent"; + update: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16295,10 +24312,25 @@ export type ComponentApi = }>; } | { - model: "teamMember"; + model: "jwks"; + update: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16322,20 +24354,15 @@ export type ComponentApi = }>; } | { - model: "invitation"; + model: "rateLimit"; + update: { + count?: number; + key?: string; + lastRequest?: number; + }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16357,140 +24384,9 @@ export type ComponentApi = | Array | null; }>; - }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - updateMany: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; + model: "user_custom"; update: { cbDefaultValueField?: null | string; createdAt?: number; @@ -16558,26 +24454,50 @@ export type ComponentApi = }>; } | { - model: "session"; + model: "user_table"; update: { + cbDefaultValueField?: null | string; createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; updatedAt?: number; - userAgent?: null | string; - userId?: string; + userId?: null | string; + username?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16602,37 +24522,11 @@ export type ComponentApi = }>; } | { - 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; - }; + model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16656,23 +24550,14 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "one_to_one_table"; update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; + oneToOne?: null | string; + one_to_one?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16696,20 +24581,24 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "testModel"; update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16734,32 +24623,22 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "organization"; update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; + createdAt?: number; + logo?: null | string; metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; + name?: string; + slug?: string; updatedAt?: null | number; - userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -16786,28 +24665,20 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; + model: "member"; update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; + createdAt?: number; + organizationId?: string; + role?: string; updatedAt?: null | number; - userId?: null | string; + userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -16834,24 +24705,22 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; + model: "team"; update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; updatedAt?: null | number; - userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16876,20 +24745,20 @@ export type ComponentApi = }>; } | { - model: "jwks"; + model: "teamMember"; update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -16914,15 +24783,31 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; + model: "invitation"; update: { - count?: number; - key?: string; - lastRequest?: number; + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; }; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -16944,9 +24829,27 @@ export type ComponentApi = | Array | null; }>; - } + }; + onUpdateHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; + }, + any, + Name + >; + updateOne: FunctionReference< + "mutation", + "internal", + { + input: | { - model: "user_custom"; + model: "user"; update: { cbDefaultValueField?: null | string; createdAt?: number; @@ -17014,50 +24917,26 @@ export type ComponentApi = }>; } | { - model: "user_table"; + model: "session"; update: { - cbDefaultValueField?: null | string; createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; + expiresAt?: number; + ipAddress?: null | string; + token?: string; updatedAt?: number; - userId?: null | string; - username?: null | string; + userAgent?: null | string; + userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17082,11 +24961,39 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; + model: "account"; + update: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: "oneToOne" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17110,14 +25017,23 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; + model: "verification"; update: { - oneToOne?: null | string; - one_to_one?: null | string; + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; }; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17141,24 +25057,24 @@ export type ComponentApi = }>; } | { - model: "testModel"; + model: "twoFactor"; update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17183,22 +25099,32 @@ export type ComponentApi = }>; } | { - model: "organization"; + model: "oauthApplication"; update: { - createdAt?: number; - logo?: null | string; + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; metadata?: null | string; - name?: string; - slug?: string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; updatedAt?: null | number; + userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" + | "icon" | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -17225,20 +25151,28 @@ export type ComponentApi = }>; } | { - model: "member"; + model: "oauthAccessToken"; update: { - createdAt?: number; - organizationId?: string; - role?: string; + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; updatedAt?: null | number; - userId?: string; + userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" | "userId" - | "role" + | "scopes" | "createdAt" | "updatedAt" | "_id"; @@ -17265,20 +25199,24 @@ export type ComponentApi = }>; } | { - model: "team"; + model: "oauthConsent"; update: { - createdAt?: number; - name?: string; - organizationId?: string; + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; updatedAt?: null | number; + userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17303,15 +25241,25 @@ export type ComponentApi = }>; } | { - model: "teamMember"; + model: "jwks"; update: { - createdAt?: null | number; - teamId?: string; - userId?: string; + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "publicKey" + | "privateKey" + | "createdAt" + | "expiresAt" + | "alg" + | "crv" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17335,31 +25283,15 @@ export type ComponentApi = }>; } | { - model: "invitation"; + model: "rateLimit"; update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; + count?: number; + key?: string; + lastRequest?: number; }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17381,27 +25313,9 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - }, - any, - Name - >; - updateOne: FunctionReference< - "mutation", - "internal", - { - input: + } | { - model: "user"; + model: "user_custom"; update: { cbDefaultValueField?: null | string; createdAt?: number; @@ -17469,26 +25383,50 @@ export type ComponentApi = }>; } | { - model: "session"; + model: "user_table"; update: { + cbDefaultValueField?: null | string; createdAt?: number; - expiresAt?: number; - ipAddress?: null | string; - token?: string; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; updatedAt?: number; - userAgent?: null | string; - userId?: string; + userId?: null | string; + username?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "expiresAt" - | "token" + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" - | "ipAddress" - | "userAgent" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17513,37 +25451,11 @@ export type ComponentApi = }>; } | { - 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; - }; + model: "oneToOneTable"; + update: { oneToOne?: string }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "accountId" - | "providerId" - | "userId" - | "accessToken" - | "refreshToken" - | "idToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "scope" - | "password" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17567,23 +25479,14 @@ export type ComponentApi = }>; } | { - model: "verification"; + model: "one_to_one_table"; update: { - createdAt?: number; - expiresAt?: number; - identifier?: string; - updatedAt?: number; - value?: string; + oneToOne?: null | string; + one_to_one?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; - field: - | "identifier" - | "value" - | "expiresAt" - | "createdAt" - | "updatedAt" - | "_id"; + field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17607,20 +25510,24 @@ export type ComponentApi = }>; } | { - model: "twoFactor"; + model: "testModel"; update: { - backupCodes?: string; - secret?: string; - userId?: string; - verified?: null | boolean; + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "secret" - | "backupCodes" - | "userId" - | "verified" + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17645,32 +25552,22 @@ export type ComponentApi = }>; } | { - model: "oauthApplication"; + model: "organization"; update: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; + createdAt?: number; + logo?: null | string; metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; + name?: string; + slug?: string; updatedAt?: null | number; - userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "icon" + | "slug" + | "logo" | "metadata" - | "clientId" - | "clientSecret" - | "redirectUrls" - | "type" - | "disabled" - | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -17697,28 +25594,20 @@ export type ComponentApi = }>; } | { - model: "oauthAccessToken"; + model: "member"; update: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; + createdAt?: number; + organizationId?: string; + role?: string; updatedAt?: null | number; - userId?: null | string; + userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "accessToken" - | "refreshToken" - | "accessTokenExpiresAt" - | "refreshTokenExpiresAt" - | "clientId" + | "organizationId" | "userId" - | "scopes" + | "role" | "createdAt" | "updatedAt" | "_id"; @@ -17745,24 +25634,22 @@ export type ComponentApi = }>; } | { - model: "oauthConsent"; + model: "team"; update: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; updatedAt?: null | number; - userId?: null | string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "clientId" - | "userId" - | "scopes" + | "name" + | "memberCount" + | "organizationId" | "createdAt" | "updatedAt" - | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17787,20 +25674,20 @@ export type ComponentApi = }>; } | { - model: "jwks"; + model: "teamMember"; update: { - createdAt?: number; - expiresAt?: null | number; - privateKey?: string; - publicKey?: string; + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; field: - | "publicKey" - | "privateKey" + | "teamId" + | "userId" + | "membershipKey" | "createdAt" - | "expiresAt" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17825,15 +25712,31 @@ export type ComponentApi = }>; } | { - model: "rateLimit"; + model: "invitation"; update: { - count?: number; - key?: string; - lastRequest?: number; + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; }; where?: Array<{ connector?: "AND" | "OR"; - field: "key" | "count" | "lastRequest" | "_id"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -17855,30 +25758,284 @@ export type ComponentApi = | Array | null; }>; + }; + onUpdateHandle?: string; + }, + any, + Name + >; + }; + adapterRenameUserTable: { + create: FunctionReference< + "mutation", + "internal", + { + input: + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: 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; + issuer?: 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: { + backupCodes: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret: string; + userId: string; + verified?: null | boolean; + }; + model: "twoFactor"; + } + | { + data: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthApplication"; + } + | { + data: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthAccessToken"; + } + | { + data: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + model: "oauthConsent"; + } + | { + data: { + alg?: null | string; + createdAt: number; + crv?: null | string; + expiresAt?: null | number; + privateKey: string; + publicKey: string; + }; + model: "jwks"; } | { + data: { count: number; key: string; lastRequest: number }; + model: "rateLimit"; + } + | { + data: { + cbDefaultValueField?: null | string; + createdAt: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt: number; + userId?: null | string; + username?: null | string; + }; model: "user_custom"; - update: { + } + | { + data: { cbDefaultValueField?: null | string; - createdAt?: number; + createdAt: number; customField?: null | string; dateField?: null | number; displayUsername?: null | string; email?: null | string; - emailVerified?: boolean; + emailVerified: boolean; email_address?: null | string; image?: null | string; isAnonymous?: null | boolean; - name?: string; + name: string; numericField?: null | number; phoneNumber?: null | string; phoneNumberVerified?: null | boolean; testField?: null | string; twoFactorEnabled?: null | boolean; - updatedAt?: number; + updatedAt: number; userId?: null | string; username?: null | string; }; + model: "user_table"; + } + | { data: { oneToOne: string }; model: "oneToOneTable" } + | { + data: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + model: "one_to_one_table"; + } + | { + data: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + model: "testModel"; + } + | { + data: { + createdAt: number; + logo?: null | string; + metadata?: null | string; + name: string; + slug: string; + updatedAt?: null | number; + }; + model: "organization"; + } + | { + data: { + createdAt: number; + organizationId: string; + role: string; + updatedAt?: null | number; + userId: string; + }; + model: "member"; + } + | { + data: { + createdAt: number; + memberCount: number; + name: string; + organizationId: string; + updatedAt?: null | number; + }; + model: "team"; + } + | { + data: { + createdAt?: null | number; + membershipKey?: null | string; + teamId: string; + userId: string; + }; + model: "teamMember"; + } + | { + data: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + model: "invitation"; + }; + onCreateHandle?: string; + select?: Array; + }, + any, + Name + >; + deleteMany: FunctionReference< + "mutation", + "internal", + { + input: + | { + model: "user"; where?: Array<{ connector?: "AND" | "OR"; field: @@ -17925,50 +26082,17 @@ export type ComponentApi = }>; } | { - model: "user_table"; - update: { - cbDefaultValueField?: null | string; - createdAt?: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified?: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name?: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt?: number; - userId?: null | string; - username?: null | string; - }; + model: "session"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "email" - | "email_address" - | "emailVerified" - | "image" + | "expiresAt" + | "token" | "createdAt" | "updatedAt" - | "twoFactorEnabled" - | "isAnonymous" - | "username" - | "displayUsername" - | "phoneNumber" - | "phoneNumberVerified" + | "ipAddress" + | "userAgent" | "userId" - | "testField" - | "cbDefaultValueField" - | "customField" - | "numericField" - | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -17993,11 +26117,24 @@ export type ComponentApi = }>; } | { - model: "oneToOneTable"; - update: { oneToOne?: string }; + model: "account"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "_id"; + field: + | "issuer" + | "accountId" + | "providerId" + | "userId" + | "accessToken" + | "refreshToken" + | "idToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "scope" + | "password" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -18021,14 +26158,16 @@ export type ComponentApi = }>; } | { - model: "one_to_one_table"; - update: { - oneToOne?: null | string; - one_to_one?: null | string; - }; + model: "verification"; where?: Array<{ connector?: "AND" | "OR"; - field: "oneToOne" | "one_to_one" | "_id"; + field: + | "identifier" + | "value" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -18052,24 +26191,16 @@ export type ComponentApi = }>; } | { - model: "testModel"; - update: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; + model: "twoFactor"; where?: Array<{ connector?: "AND" | "OR"; field: - | "nullableReference" - | "testField" - | "cbDefaultValueField" - | "stringArray" - | "numberArray" - | "json" + | "secret" + | "backupCodes" + | "userId" + | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -18094,22 +26225,19 @@ export type ComponentApi = }>; } | { - model: "organization"; - update: { - createdAt?: number; - logo?: null | string; - metadata?: null | string; - name?: string; - slug?: string; - updatedAt?: null | number; - }; + model: "oauthApplication"; where?: Array<{ connector?: "AND" | "OR"; field: | "name" - | "slug" - | "logo" + | "icon" | "metadata" + | "clientId" + | "clientSecret" + | "redirectUrls" + | "type" + | "disabled" + | "userId" | "createdAt" | "updatedAt" | "_id"; @@ -18136,22 +26264,53 @@ export type ComponentApi = }>; } | { - model: "member"; - update: { - createdAt?: number; - organizationId?: string; - role?: string; - updatedAt?: null | number; - userId?: string; - }; + model: "oauthAccessToken"; where?: Array<{ connector?: "AND" | "OR"; field: - | "organizationId" + | "accessToken" + | "refreshToken" + | "accessTokenExpiresAt" + | "refreshTokenExpiresAt" + | "clientId" | "userId" - | "role" + | "scopes" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + } + | { + model: "oauthConsent"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "clientId" + | "userId" + | "scopes" | "createdAt" | "updatedAt" + | "consentGiven" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -18176,20 +26335,16 @@ export type ComponentApi = }>; } | { - model: "team"; - update: { - createdAt?: number; - name?: string; - organizationId?: string; - updatedAt?: null | number; - }; + model: "jwks"; where?: Array<{ connector?: "AND" | "OR"; field: - | "name" - | "organizationId" + | "publicKey" + | "privateKey" | "createdAt" - | "updatedAt" + | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -18214,15 +26369,10 @@ export type ComponentApi = }>; } | { - model: "teamMember"; - update: { - createdAt?: null | number; - teamId?: string; - userId?: string; - }; + model: "rateLimit"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -18246,30 +26396,29 @@ export type ComponentApi = }>; } | { - model: "invitation"; - update: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; + model: "user_custom"; where?: Array<{ connector?: "AND" | "OR"; field: + | "name" | "email" - | "role" - | "status" - | "organizationId" - | "teamId" - | "inviterId" - | "expiresAt" + | "email_address" + | "emailVerified" + | "image" | "createdAt" | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -18292,271 +26441,325 @@ export type ComponentApi = | Array | null; }>; - }; - onUpdateHandle?: string; - }, - any, - Name - >; - }; - adapterRenameUserTable: { - create: FunctionReference< - "mutation", - "internal", - { - input: - | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: 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: { - backupCodes: string; - secret: string; - userId: string; - verified?: null | boolean; - }; - model: "twoFactor"; - } - | { - data: { - clientId?: null | string; - clientSecret?: null | string; - createdAt?: null | number; - disabled?: null | boolean; - icon?: null | string; - metadata?: null | string; - name?: null | string; - redirectUrls?: null | string; - type?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthApplication"; - } - | { - data: { - accessToken?: null | string; - accessTokenExpiresAt?: null | number; - clientId?: null | string; - createdAt?: null | number; - refreshToken?: null | string; - refreshTokenExpiresAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthAccessToken"; - } - | { - data: { - clientId?: null | string; - consentGiven?: null | boolean; - createdAt?: null | number; - scopes?: null | string; - updatedAt?: null | number; - userId?: null | string; - }; - model: "oauthConsent"; - } - | { - data: { - createdAt: number; - expiresAt?: null | number; - privateKey: string; - publicKey: string; - }; - model: "jwks"; - } - | { - data: { count: number; key: string; lastRequest: number }; - model: "rateLimit"; } | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; - model: "user_custom"; + model: "user_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "email" + | "email_address" + | "emailVerified" + | "image" + | "createdAt" + | "updatedAt" + | "twoFactorEnabled" + | "isAnonymous" + | "username" + | "displayUsername" + | "phoneNumber" + | "phoneNumberVerified" + | "userId" + | "testField" + | "cbDefaultValueField" + | "customField" + | "numericField" + | "dateField" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - cbDefaultValueField?: null | string; - createdAt: number; - customField?: null | string; - dateField?: null | number; - displayUsername?: null | string; - email?: null | string; - emailVerified: boolean; - email_address?: null | string; - image?: null | string; - isAnonymous?: null | boolean; - name: string; - numericField?: null | number; - phoneNumber?: null | string; - phoneNumberVerified?: null | boolean; - testField?: null | string; - twoFactorEnabled?: null | boolean; - updatedAt: number; - userId?: null | string; - username?: null | string; - }; - model: "user_table"; + model: "oneToOneTable"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } - | { data: { oneToOne: string }; model: "oneToOneTable" } | { - data: { - oneToOne?: null | string; - one_to_one?: null | string; - }; model: "one_to_one_table"; + where?: Array<{ + connector?: "AND" | "OR"; + field: "oneToOne" | "one_to_one" | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - cbDefaultValueField?: null | string; - json?: any; - nullableReference?: null | string; - numberArray?: null | Array; - stringArray?: null | Array; - testField?: null | string; - }; model: "testModel"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "nullableReference" + | "testField" + | "cbDefaultValueField" + | "stringArray" + | "numberArray" + | "json" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - logo?: null | string; - metadata?: null | string; - name: string; - slug: string; - updatedAt?: null | number; - }; model: "organization"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "slug" + | "logo" + | "metadata" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - organizationId: string; - role: string; - updatedAt?: null | number; - userId: string; - }; model: "member"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "organizationId" + | "userId" + | "role" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt: number; - name: string; - organizationId: string; - updatedAt?: null | number; - }; model: "team"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "name" + | "memberCount" + | "organizationId" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt?: null | number; - teamId: string; - userId: string; - }; model: "teamMember"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; } | { - data: { - createdAt?: null | number; - email?: null | string; - expiresAt?: null | number; - inviterId?: null | string; - organizationId?: null | string; - role?: null | string; - status?: null | string; - teamId?: null | string; - updatedAt?: null | number; - }; model: "invitation"; + where?: Array<{ + connector?: "AND" | "OR"; + field: + | "email" + | "role" + | "status" + | "organizationId" + | "teamId" + | "inviterId" + | "expiresAt" + | "createdAt" + | "updatedAt" + | "_id"; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; }; - onCreateHandle?: string; - select?: Array; + onDeleteHandle?: string; + paginationOpts: { + cursor: string | null; + endCursor?: string | null; + id?: number; + maximumBytesRead?: number; + maximumRowsRead?: number; + numItems: number; + }; }, any, Name >; - deleteMany: FunctionReference< + deleteOne: FunctionReference< "mutation", "internal", { @@ -18648,6 +26851,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -18725,6 +26929,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -18867,6 +27073,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -19172,6 +27380,7 @@ export type ComponentApi = connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -19202,7 +27411,12 @@ export type ComponentApi = model: "teamMember"; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -19263,6 +27477,38 @@ export type ComponentApi = }>; }; onDeleteHandle?: string; + }, + any, + Name + >; + findMany: FunctionReference< + "query", + "internal", + { + join?: any; + limit?: number; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + offset?: number; paginationOpts: { cursor: string | null; endCursor?: string | null; @@ -19271,18 +27517,121 @@ export type ComponentApi = maximumRowsRead?: number; numItems: number; }; + select?: Array; + sortBy?: { direction: "asc" | "desc"; field: string }; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; }, any, Name >; - deleteOne: FunctionReference< + findOne: FunctionReference< + "query", + "internal", + { + join?: any; + model: + | "user" + | "session" + | "account" + | "verification" + | "twoFactor" + | "oauthApplication" + | "oauthAccessToken" + | "oauthConsent" + | "jwks" + | "rateLimit" + | "user_custom" + | "user_table" + | "oneToOneTable" + | "one_to_one_table" + | "testModel" + | "organization" + | "member" + | "team" + | "teamMember" + | "invitation"; + select?: Array; + where?: Array<{ + connector?: "AND" | "OR"; + field: string; + mode?: "sensitive" | "insensitive"; + operator?: + | "lt" + | "lte" + | "gt" + | "gte" + | "eq" + | "in" + | "not_in" + | "ne" + | "contains" + | "starts_with" + | "ends_with"; + value: + | string + | number + | boolean + | Array + | Array + | null; + }>; + }, + any, + Name + >; + incrementOne: FunctionReference< "mutation", "internal", { input: | { + increment: Record; model: "user"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -19328,8 +27677,18 @@ export type ComponentApi = }>; } | { + increment: Record; model: "session"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + ipAddress?: null | string; + token?: string; + updatedAt?: number; + userAgent?: null | string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "expiresAt" @@ -19363,10 +27722,27 @@ export type ComponentApi = }>; } | { + increment: Record; model: "account"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + accountId?: string; + createdAt?: number; + idToken?: null | string; + issuer?: 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: + | "issuer" | "accountId" | "providerId" | "userId" @@ -19403,8 +27779,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "verification"; - where?: Array<{ + set?: { + createdAt?: number; + expiresAt?: number; + identifier?: string; + updatedAt?: number; + value?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "identifier" @@ -19436,14 +27820,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "twoFactor"; - where?: Array<{ + set?: { + backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; + secret?: string; + userId?: string; + verified?: null | boolean; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "secret" | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -19468,8 +27863,22 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthApplication"; - where?: Array<{ + set?: { + clientId?: null | string; + clientSecret?: null | string; + createdAt?: null | number; + disabled?: null | boolean; + icon?: null | string; + metadata?: null | string; + name?: null | string; + redirectUrls?: null | string; + type?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -19507,8 +27916,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthAccessToken"; - where?: Array<{ + set?: { + accessToken?: null | string; + accessTokenExpiresAt?: null | number; + clientId?: null | string; + createdAt?: null | number; + refreshToken?: null | string; + refreshTokenExpiresAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "accessToken" @@ -19544,8 +27965,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oauthConsent"; - where?: Array<{ + set?: { + clientId?: null | string; + consentGiven?: null | boolean; + createdAt?: null | number; + scopes?: null | string; + updatedAt?: null | number; + userId?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "clientId" @@ -19578,14 +28008,25 @@ export type ComponentApi = }>; } | { + increment: Record; model: "jwks"; - where?: Array<{ + set?: { + alg?: null | string; + createdAt?: number; + crv?: null | string; + expiresAt?: null | number; + privateKey?: string; + publicKey?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "publicKey" | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -19610,8 +28051,10 @@ export type ComponentApi = }>; } | { + increment: Record; model: "rateLimit"; - where?: Array<{ + set?: { count?: number; key?: string; lastRequest?: number }; + where: Array<{ connector?: "AND" | "OR"; field: "key" | "count" | "lastRequest" | "_id"; mode?: "sensitive" | "insensitive"; @@ -19637,8 +28080,30 @@ export type ComponentApi = }>; } | { + increment: Record; model: "user_custom"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -19684,8 +28149,30 @@ export type ComponentApi = }>; } | { + increment: Record; model: "user_table"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + createdAt?: number; + customField?: null | string; + dateField?: null | number; + displayUsername?: null | string; + email?: null | string; + emailVerified?: boolean; + email_address?: null | string; + image?: null | string; + isAnonymous?: null | boolean; + name?: string; + numericField?: null | number; + phoneNumber?: null | string; + phoneNumberVerified?: null | boolean; + testField?: null | string; + twoFactorEnabled?: null | boolean; + updatedAt?: number; + userId?: null | string; + username?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -19731,8 +28218,10 @@ export type ComponentApi = }>; } | { + increment: Record; model: "oneToOneTable"; - where?: Array<{ + set?: { oneToOne?: string }; + where: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "_id"; mode?: "sensitive" | "insensitive"; @@ -19758,8 +28247,13 @@ export type ComponentApi = }>; } | { + increment: Record; model: "one_to_one_table"; - where?: Array<{ + set?: { + oneToOne?: null | string; + one_to_one?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: "oneToOne" | "one_to_one" | "_id"; mode?: "sensitive" | "insensitive"; @@ -19785,8 +28279,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "testModel"; - where?: Array<{ + set?: { + cbDefaultValueField?: null | string; + json?: any; + nullableReference?: null | string; + numberArray?: null | Array; + stringArray?: null | Array; + testField?: null | string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "nullableReference" @@ -19819,8 +28322,17 @@ export type ComponentApi = }>; } | { + increment: Record; model: "organization"; - where?: Array<{ + set?: { + createdAt?: number; + logo?: null | string; + metadata?: null | string; + name?: string; + slug?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" @@ -19853,8 +28365,16 @@ export type ComponentApi = }>; } | { + increment: Record; model: "member"; - where?: Array<{ + set?: { + createdAt?: number; + organizationId?: string; + role?: string; + updatedAt?: null | number; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "organizationId" @@ -19886,11 +28406,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "team"; - where?: Array<{ + set?: { + createdAt?: number; + memberCount?: number; + name?: string; + organizationId?: string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -19918,10 +28447,22 @@ export type ComponentApi = }>; } | { + increment: Record; model: "teamMember"; - where?: Array<{ + set?: { + createdAt?: null | number; + membershipKey?: null | string; + teamId?: string; + userId?: string; + }; + where: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -19945,8 +28486,20 @@ export type ComponentApi = }>; } | { + increment: Record; model: "invitation"; - where?: Array<{ + set?: { + createdAt?: null | number; + email?: null | string; + expiresAt?: null | number; + inviterId?: null | string; + organizationId?: null | string; + role?: null | string; + status?: null | string; + teamId?: null | string; + updatedAt?: null | number; + }; + where: Array<{ connector?: "AND" | "OR"; field: | "email" @@ -19981,128 +28534,7 @@ export type ComponentApi = | null; }>; }; - onDeleteHandle?: string; - }, - any, - Name - >; - findMany: FunctionReference< - "query", - "internal", - { - join?: any; - limit?: number; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - offset?: number; - paginationOpts: { - cursor: string | null; - endCursor?: string | null; - id?: number; - maximumBytesRead?: number; - maximumRowsRead?: number; - numItems: number; - }; - select?: Array; - sortBy?: { direction: "asc" | "desc"; field: string }; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; - }, - any, - Name - >; - findOne: FunctionReference< - "query", - "internal", - { - join?: any; - model: - | "user" - | "session" - | "account" - | "verification" - | "twoFactor" - | "oauthApplication" - | "oauthAccessToken" - | "oauthConsent" - | "jwks" - | "rateLimit" - | "user_custom" - | "user_table" - | "oneToOneTable" - | "one_to_one_table" - | "testModel" - | "organization" - | "member" - | "team" - | "teamMember" - | "invitation"; - select?: Array; - where?: Array<{ - connector?: "AND" | "OR"; - field: string; - mode?: "sensitive" | "insensitive"; - operator?: - | "lt" - | "lte" - | "gt" - | "gte" - | "eq" - | "in" - | "not_in" - | "ne" - | "contains" - | "starts_with" - | "ends_with"; - value: - | string - | number - | boolean - | Array - | Array - | null; - }>; + onUpdateHandle?: string; }, any, Name @@ -20232,6 +28664,7 @@ export type ComponentApi = accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -20243,6 +28676,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -20322,6 +28756,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -20333,6 +28769,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -20501,7 +28939,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -20513,6 +28953,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -20891,6 +29333,7 @@ export type ComponentApi = model: "team"; update: { createdAt?: number; + memberCount?: number; name?: string; organizationId?: string; updatedAt?: null | number; @@ -20899,6 +29342,7 @@ export type ComponentApi = connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -20929,12 +29373,18 @@ export type ComponentApi = model: "teamMember"; update: { createdAt?: null | number; + membershipKey?: null | string; teamId?: string; userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" @@ -21143,6 +29593,7 @@ export type ComponentApi = accountId?: string; createdAt?: number; idToken?: null | string; + issuer?: null | string; password?: null | string; providerId?: string; refreshToken?: null | string; @@ -21154,6 +29605,7 @@ export type ComponentApi = where?: Array<{ connector?: "AND" | "OR"; field: + | "issuer" | "accountId" | "providerId" | "userId" @@ -21233,6 +29685,8 @@ export type ComponentApi = model: "twoFactor"; update: { backupCodes?: string; + failedVerificationCount?: null | number; + lockedUntil?: null | number; secret?: string; userId?: string; verified?: null | boolean; @@ -21244,6 +29698,8 @@ export type ComponentApi = | "backupCodes" | "userId" | "verified" + | "failedVerificationCount" + | "lockedUntil" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -21412,7 +29868,9 @@ export type ComponentApi = | { model: "jwks"; update: { + alg?: null | string; createdAt?: number; + crv?: null | string; expiresAt?: null | number; privateKey?: string; publicKey?: string; @@ -21424,6 +29882,8 @@ export type ComponentApi = | "privateKey" | "createdAt" | "expiresAt" + | "alg" + | "crv" | "_id"; mode?: "sensitive" | "insensitive"; operator?: @@ -21802,6 +30262,7 @@ export type ComponentApi = model: "team"; update: { createdAt?: number; + memberCount?: number; name?: string; organizationId?: string; updatedAt?: null | number; @@ -21810,6 +30271,7 @@ export type ComponentApi = connector?: "AND" | "OR"; field: | "name" + | "memberCount" | "organizationId" | "createdAt" | "updatedAt" @@ -21840,12 +30302,18 @@ export type ComponentApi = model: "teamMember"; update: { createdAt?: null | number; + membershipKey?: null | string; teamId?: string; userId?: string; }; where?: Array<{ connector?: "AND" | "OR"; - field: "teamId" | "userId" | "createdAt" | "_id"; + field: + | "teamId" + | "userId" + | "membershipKey" + | "createdAt" + | "_id"; mode?: "sensitive" | "insensitive"; operator?: | "lt" diff --git a/src/component/adapter.ts b/src/component/adapter.ts index 41ee5cbc..4d4c86b9 100644 --- a/src/component/adapter.ts +++ b/src/component/adapter.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/migrations.test.ts b/src/component/migrations.test.ts new file mode 100644 index 00000000..ac65696e --- /dev/null +++ b/src/component/migrations.test.ts @@ -0,0 +1,174 @@ +/// + +import { describe, expect, it } from "vitest"; +import { convexTest } from "convex-test"; +import { api } from "./_generated/api.js"; +import schema from "./schema.js"; + +const modules = import.meta.glob("./**/*.*s"); +const listLegacyOAuthApplications = api.migrations.listLegacyOAuthApplications; +const clearLegacyOAuthProviderRecords = + api.migrations.clearLegacyOAuthProviderRecords; + +describe("legacy OAuth provider migrations", () => { + it("treats completed cursors as terminal instead of restarting", async () => { + const t = convexTest(schema, modules); + await t.run(async (ctx) => { + await ctx.db.insert("account", { + accountId: "github-subject", + providerId: "github", + userId: "user-1", + createdAt: 1, + updatedAt: 1, + }); + await ctx.db.insert("oauthApplication", { + clientId: "legacy-client", + clientSecret: "legacy-secret", + }); + }); + const initialPage = { cursor: null, numItems: 10 }; + + const exported = await t.query(listLegacyOAuthApplications, { + paginationOpts: initialPage, + }); + expect(exported.isDone).toBe(true); + await expect( + t.query(listLegacyOAuthApplications, { + paginationOpts: { cursor: exported.continueCursor, numItems: 10 }, + }) + ).resolves.toMatchObject({ isDone: true, page: [] }); + + const cleared = await t.mutation(clearLegacyOAuthProviderRecords, { + table: "oauthApplication", + paginationOpts: initialPage, + }); + expect(cleared.isDone).toBe(true); + await expect( + t.mutation(clearLegacyOAuthProviderRecords, { + table: "oauthApplication", + paginationOpts: { cursor: cleared.continueCursor, numItems: 10 }, + }) + ).resolves.toMatchObject({ isDone: true, deleted: 0 }); + }); + + it("rejects terminal cursors from other migrations and tables", async () => { + const t = convexTest(schema, modules); + await t.run(async (ctx) => { + await ctx.db.insert("account", { + accountId: "github-subject", + providerId: "github", + userId: "user-1", + createdAt: 1, + updatedAt: 1, + }); + await ctx.db.insert("oauthConsent", { + clientId: "legacy-client", + userId: "user-1", + scopes: "openid", + consentGiven: true, + }); + }); + const paginationOpts = { cursor: null, numItems: 10 }; + + const clearedApplications = await t.mutation( + clearLegacyOAuthProviderRecords, + { + table: "oauthApplication", + paginationOpts, + } + ); + await expect( + t.mutation(clearLegacyOAuthProviderRecords, { + table: "oauthConsent", + paginationOpts: { + cursor: clearedApplications.continueCursor, + numItems: 10, + }, + }) + ).rejects.toThrow( + "Migration cursor is not valid for clearLegacyOAuthProviderRecords:oauthConsent" + ); + + const [account] = await t.run((ctx) => ctx.db.query("account").collect()); + const consents = await t.run((ctx) => + ctx.db.query("oauthConsent").collect() + ); + expect(account?.issuer).toBeUndefined(); + expect(consents).toHaveLength(1); + }); + + it("accepts, exports, and clears legacy OAuth provider records", async () => { + const t = convexTest(schema, modules); + await t.run(async (ctx) => { + await ctx.db.insert("oauthApplication", { + clientId: "legacy-client", + clientSecret: "legacy-secret", + redirectUrls: "https://example.com/callback", + }); + await ctx.db.insert("oauthAccessToken", { + accessToken: "legacy-access-token", + refreshToken: "legacy-refresh-token", + clientId: "legacy-client", + scopes: "openid profile", + }); + await ctx.db.insert("oauthAccessToken", { + accessToken: "second-legacy-access-token", + clientId: "legacy-client", + scopes: "openid", + }); + await ctx.db.insert("oauthConsent", { + clientId: "legacy-client", + userId: "user-1", + scopes: "openid profile", + consentGiven: true, + }); + await ctx.db.insert("oauthConsent", { + clientId: "legacy-client", + userId: "user-2", + scopes: "openid", + consentGiven: true, + }); + }); + + const clients = await t.query(listLegacyOAuthApplications, { + paginationOpts: { cursor: null, numItems: 10 }, + }); + expect(clients.page).toEqual([ + expect.objectContaining({ + clientId: "legacy-client", + redirectUrls: "https://example.com/callback", + hadClientSecret: true, + }), + ]); + expect(clients.page[0]).not.toHaveProperty("clientSecret"); + + for (const table of [ + "oauthApplication", + "oauthAccessToken", + "oauthConsent", + ] as const) { + let cursor: string | null = null; + let deleted = 0; + do { + const result: { + deleted: number; + isDone: boolean; + continueCursor: string; + } = await t.mutation(clearLegacyOAuthProviderRecords, { + table, + paginationOpts: { cursor, numItems: 1 }, + }); + deleted += result.deleted; + cursor = result.isDone ? null : result.continueCursor; + if (result.isDone) break; + } while (cursor); + expect(deleted).toBe(table === "oauthApplication" ? 1 : 2); + } + const remaining = await t.run(async (ctx) => ({ + applications: await ctx.db.query("oauthApplication").collect(), + tokens: await ctx.db.query("oauthAccessToken").collect(), + consents: await ctx.db.query("oauthConsent").collect(), + })); + expect(remaining).toEqual({ applications: [], tokens: [], consents: [] }); + }); +}); diff --git a/src/component/migrations.ts b/src/component/migrations.ts new file mode 100644 index 00000000..618abc9f --- /dev/null +++ b/src/component/migrations.ts @@ -0,0 +1,125 @@ +import { + paginationOptsValidator, + paginationResultValidator, +} from "convex/server"; +import { v } from "convex/values"; +import { omit } from "convex-helpers"; +import { paginator } from "convex-helpers/server/pagination"; +import { mutation, query } from "./_generated/server.js"; +import schema from "./schema.js"; + +const migrationCompleteCursorPrefix = "convex-better-auth:migration-complete:"; + +const migrationCompleteCursorFor = (operation: string) => + `${migrationCompleteCursorPrefix}${operation}`; + +const isMigrationCompleteCursor = ( + cursor: string | null, + operation: string +) => { + const expected = migrationCompleteCursorFor(operation); + if (cursor === expected) { + return true; + } + if (cursor?.startsWith(migrationCompleteCursorPrefix)) { + throw new Error(`Migration cursor is not valid for ${operation}`); + } + return false; +}; + +const assertValidPaginationOpts = (paginationOpts: { + cursor: string | null; + numItems: number; +}) => { + if ( + !Number.isInteger(paginationOpts.numItems) || + paginationOpts.numItems <= 0 + ) { + throw new Error("paginationOpts.numItems must be a positive integer"); + } +}; + +const legacyOAuthApplicationExportValidator = v.object({ + ...omit(schema.tables.oauthApplication.validator.fields, ["clientSecret"]), + _id: v.id("oauthApplication"), + _creationTime: v.number(), + hadClientSecret: v.boolean(), +}); + +const clearedLegacyRecordsValidator = v.object({ + continueCursor: v.string(), + isDone: v.boolean(), + deleted: v.number(), +}); + +export const listLegacyOAuthApplications = query({ + args: { paginationOpts: paginationOptsValidator }, + returns: paginationResultValidator(legacyOAuthApplicationExportValidator), + handler: async (ctx, args) => { + const operation = "listLegacyOAuthApplications"; + const completeCursor = migrationCompleteCursorFor(operation); + assertValidPaginationOpts(args.paginationOpts); + if (isMigrationCompleteCursor(args.paginationOpts.cursor, operation)) { + return { + page: [], + continueCursor: completeCursor, + isDone: true, + }; + } + const result = await paginator(ctx.db, schema) + .query("oauthApplication") + .paginate(args.paginationOpts); + return { + ...result, + continueCursor: result.isDone ? completeCursor : result.continueCursor, + page: result.page.map(({ clientSecret, ...application }) => ({ + ...application, + hadClientSecret: Boolean(clientSecret), + })), + }; + }, +}); + +export const clearLegacyOAuthProviderRecords = mutation({ + args: { + table: v.union( + v.literal("oauthApplication"), + v.literal("oauthAccessToken"), + v.literal("oauthConsent") + ), + paginationOpts: paginationOptsValidator, + }, + returns: clearedLegacyRecordsValidator, + handler: async (ctx, args) => { + const operation = `clearLegacyOAuthProviderRecords:${args.table}`; + const completeCursor = migrationCompleteCursorFor(operation); + assertValidPaginationOpts(args.paginationOpts); + if (isMigrationCompleteCursor(args.paginationOpts.cursor, operation)) { + return { + continueCursor: completeCursor, + isDone: true, + deleted: 0, + }; + } + const result = + args.table === "oauthApplication" + ? await paginator(ctx.db, schema) + .query("oauthApplication") + .paginate(args.paginationOpts) + : args.table === "oauthAccessToken" + ? await paginator(ctx.db, schema) + .query("oauthAccessToken") + .paginate(args.paginationOpts) + : await paginator(ctx.db, schema) + .query("oauthConsent") + .paginate(args.paginationOpts); + for (const record of result.page) { + await ctx.db.delete(args.table, record._id); + } + return { + continueCursor: result.isDone ? completeCursor : result.continueCursor, + isDone: result.isDone, + deleted: result.page.length, + }; + }, +}); diff --git a/src/component/schema.test.ts b/src/component/schema.test.ts new file mode 100644 index 00000000..34a6010d --- /dev/null +++ b/src/component/schema.test.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from "vitest"; +import schema from "./schema.js"; + +describe("account schema", () => { + it("uses the current credential lookup fields without issuer indexes", () => { + const indexes = schema.tables.account[" indexes"](); + expect(indexes).toContainEqual({ + indexDescriptor: "userId_providerId_accountId", + fields: ["userId", "providerId", "accountId"], + }); + expect(indexes.every(({ fields }) => !fields.includes("issuer"))).toBe( + true + ); + }); +}); diff --git a/src/component/schema.ts b/src/component/schema.ts index 8b5ecc1c..373e23ba 100644 --- a/src/component/schema.ts +++ b/src/component/schema.ts @@ -1,5 +1,8 @@ /** - * This file is auto-generated. Do not edit this file manually. + * Generated from Better Auth 1.7.7, then intentionally staged for the 0.13 + * migration. Do not regenerate it without preserving the documented migration + * exceptions: optional legacy account.issuer and the three legacy OAuth provider + * tables retained below. * To regenerate the schema, from your project root: * * npx auth generate --output src/component/schema.ts @@ -28,7 +31,7 @@ export const tables = { phoneNumberVerified: v.optional(v.union(v.null(), v.boolean())), userId: v.optional(v.union(v.null(), v.string())), }) - .index("email_name", ["email","name"]) + .index("email_name", ["email", "name"]) .index("name", ["name"]) .index("userId", ["userId"]) .index("username", ["username"]) @@ -43,10 +46,13 @@ export const tables = { userId: v.string(), }) .index("expiresAt", ["expiresAt"]) - .index("expiresAt_userId", ["expiresAt","userId"]) + .index("expiresAt_userId", ["expiresAt", "userId"]) .index("token", ["token"]) .index("userId", ["userId"]), account: defineTable({ + // Retained only for data written by Better Auth 1.7.0–1.7.2. + // Better Auth 1.7.7 neither requires nor writes issuer. + issuer: v.optional(v.union(v.null(), v.string())), accountId: v.string(), providerId: v.string(), userId: v.string(), @@ -61,8 +67,13 @@ export const tables = { updatedAt: v.number(), }) .index("accountId", ["accountId"]) - .index("accountId_providerId", ["accountId","providerId"]) - .index("providerId_userId", ["providerId","userId"]) + .index("accountId_providerId", ["accountId", "providerId"]) + .index("providerId_userId", ["providerId", "userId"]) + .index("userId_providerId_accountId", [ + "userId", + "providerId", + "accountId", + ]) .index("userId", ["userId"]), verification: defineTable({ identifier: v.string(), @@ -78,8 +89,11 @@ export const tables = { backupCodes: v.string(), userId: v.string(), verified: v.optional(v.union(v.null(), v.boolean())), - }) - .index("userId", ["userId"]), + failedVerificationCount: v.optional(v.union(v.null(), v.number())), + lockedUntil: v.optional(v.union(v.null(), v.number())), + }).index("userId", ["userId"]), + // Kept during the 0.13 migration so existing OIDC provider clients can be + // exported before moving provider support to a Local Install. oauthApplication: defineTable({ name: v.optional(v.union(v.null(), v.string())), icon: v.optional(v.union(v.null(), v.string())), @@ -118,20 +132,21 @@ export const tables = { updatedAt: v.optional(v.union(v.null(), v.number())), consentGiven: v.optional(v.union(v.null(), v.boolean())), }) - .index("clientId_userId", ["clientId","userId"]) + .index("clientId_userId", ["clientId", "userId"]) .index("userId", ["userId"]), jwks: defineTable({ publicKey: v.string(), privateKey: v.string(), createdAt: v.number(), expiresAt: v.optional(v.union(v.null(), v.number())), + alg: v.optional(v.union(v.null(), v.string())), + crv: v.optional(v.union(v.null(), v.string())), }), rateLimit: defineTable({ key: v.string(), count: v.number(), lastRequest: v.number(), - }) - .index("key", ["key"]), + }).index("key", ["key"]), }; const schema = defineSchema(tables); diff --git a/src/component/testProfiles/adapterAdditionalFields.ts b/src/component/testProfiles/adapterAdditionalFields.ts index 9df286c5..638fcae6 100644 --- a/src/component/testProfiles/adapterAdditionalFields.ts +++ b/src/component/testProfiles/adapterAdditionalFields.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/adapterConstraints.ts b/src/component/testProfiles/adapterConstraints.ts new file mode 100644 index 00000000..7782ae34 --- /dev/null +++ b/src/component/testProfiles/adapterConstraints.ts @@ -0,0 +1,14 @@ +import { createApi } from "../../client/index.js"; +import { constraintsProfileOptions } from "./auth-options.constraints.js"; +import schema from "./schema.constraints.js"; + +export const { + create, + findOne, + findMany, + updateOne, + incrementOne, + updateMany, + deleteOne, + deleteMany, +} = createApi(schema, () => constraintsProfileOptions); diff --git a/src/component/testProfiles/adapterOrganizationJoins.ts b/src/component/testProfiles/adapterOrganizationJoins.ts index 526670be..cb6cb296 100644 --- a/src/component/testProfiles/adapterOrganizationJoins.ts +++ b/src/component/testProfiles/adapterOrganizationJoins.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/adapterPluginTable.ts b/src/component/testProfiles/adapterPluginTable.ts index 1c1d2435..577996f4 100644 --- a/src/component/testProfiles/adapterPluginTable.ts +++ b/src/component/testProfiles/adapterPluginTable.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/adapterRenameField.ts b/src/component/testProfiles/adapterRenameField.ts index bb79625b..cd2d85f6 100644 --- a/src/component/testProfiles/adapterRenameField.ts +++ b/src/component/testProfiles/adapterRenameField.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/adapterRenameUserCustom.ts b/src/component/testProfiles/adapterRenameUserCustom.ts index 45071851..f36daebd 100644 --- a/src/component/testProfiles/adapterRenameUserCustom.ts +++ b/src/component/testProfiles/adapterRenameUserCustom.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/adapterRenameUserTable.ts b/src/component/testProfiles/adapterRenameUserTable.ts index 84731f68..da6f2741 100644 --- a/src/component/testProfiles/adapterRenameUserTable.ts +++ b/src/component/testProfiles/adapterRenameUserTable.ts @@ -7,6 +7,7 @@ export const { findOne, findMany, updateOne, + incrementOne, updateMany, deleteOne, deleteMany, diff --git a/src/component/testProfiles/auth-options.constraints.ts b/src/component/testProfiles/auth-options.constraints.ts new file mode 100644 index 00000000..23ee99f1 --- /dev/null +++ b/src/component/testProfiles/auth-options.constraints.ts @@ -0,0 +1,19 @@ +import type { BetterAuthOptions } from "better-auth/minimal"; +import { options } from "../../auth-options.js"; + +// Test-only constraints; production accounts do not require issuer. +export const constraintsProfileOptions = { + ...options, + plugins: [ + ...(options.plugins ?? []), + { + id: "test-account-constraints", + schema: { + account: { + fields: { issuer: { type: "string", required: true } }, + indexes: [{ fields: ["issuer", "accountId"], unique: true }], + }, + }, + }, + ], +} satisfies BetterAuthOptions; diff --git a/src/component/testProfiles/schema.constraints.ts b/src/component/testProfiles/schema.constraints.ts new file mode 100644 index 00000000..757c0c92 --- /dev/null +++ b/src/component/testProfiles/schema.constraints.ts @@ -0,0 +1,12 @@ +import { defineSchema, defineTable } from "convex/server"; +import { tables } from "../schema.js"; + +const account = defineTable(tables.account.validator) + .index("issuer_accountId", ["issuer", "accountId"]) + .index("accountId", ["accountId"]) + .index("accountId_providerId", ["accountId", "providerId"]) + .index("providerId_userId", ["providerId", "userId"]) + .index("userId_providerId_accountId", ["userId", "providerId", "accountId"]) + .index("userId", ["userId"]); + +export default defineSchema({ ...tables, account }); diff --git a/src/component/testProfiles/schema.profile-plugin-table.ts b/src/component/testProfiles/schema.profile-plugin-table.ts index cf0d790f..657211af 100644 --- a/src/component/testProfiles/schema.profile-plugin-table.ts +++ b/src/component/testProfiles/schema.profile-plugin-table.ts @@ -1,6 +1,7 @@ import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; -import { tables as baseTables } from "../schema.js"; +import constraintsSchema from "./schema.constraints.js"; +const baseTables = constraintsSchema.tables; const makeUserTable = () => defineTable({ @@ -83,6 +84,7 @@ const memberTable = defineTable({ const teamTable = defineTable({ name: v.string(), + memberCount: v.number(), organizationId: v.string(), createdAt: v.number(), updatedAt: v.optional(v.union(v.null(), v.number())), @@ -93,9 +95,11 @@ const teamTable = defineTable({ const teamMemberTable = defineTable({ teamId: v.string(), userId: v.string(), + membershipKey: v.optional(v.union(v.null(), v.string())), createdAt: v.optional(v.union(v.null(), v.number())), }) .index("teamId", ["teamId"]) + .index("membershipKey", ["membershipKey"]) .index("userId", ["userId"]); const invitationTable = defineTable({ diff --git a/src/component/testTriggerHandlers.ts b/src/component/testTriggerHandlers.ts index 4fba0136..b6ab9147 100644 --- a/src/component/testTriggerHandlers.ts +++ b/src/component/testTriggerHandlers.ts @@ -25,3 +25,48 @@ export const sessionOnUpdateUpdater = internalMutationGeneric({ } }, }); + +export const accountOnCreateIssuerClearer = internalMutationGeneric({ + args: { doc: v.any(), model: v.string() }, + handler: async (ctx, args) => { + if (args.model === "account") { + await ctx.db.patch("account", args.doc._id, { issuer: null }); + } + }, +}); + +export const accountOnUpdateIssuerClearer = internalMutationGeneric({ + args: { newDoc: v.any(), oldDoc: v.any(), model: v.string() }, + handler: async (ctx, args) => { + if (args.model === "account") { + await ctx.db.patch("account", args.newDoc._id, { issuer: null }); + } + }, +}); + +export const accountOnUpdateNoop = internalMutationGeneric({ + args: { newDoc: v.any(), oldDoc: v.any(), model: v.string() }, + handler: async () => {}, +}); + +export const accountOnCreateIssuerCollider = internalMutationGeneric({ + args: { doc: v.any(), model: v.string() }, + handler: async (ctx, args) => { + if (args.model === "account") { + await ctx.db.patch("account", args.doc._id, { + issuer: "collision-issuer", + }); + } + }, +}); + +export const accountOnUpdateAccountIdCollider = internalMutationGeneric({ + args: { newDoc: v.any(), oldDoc: v.any(), model: v.string() }, + handler: async (ctx, args) => { + if (args.model === "account") { + await ctx.db.patch("account", args.newDoc._id, { + accountId: "collision-account", + }); + } + }, +}); diff --git a/src/jwks-url.ts b/src/jwks-url.ts new file mode 100644 index 00000000..fd080f99 --- /dev/null +++ b/src/jwks-url.ts @@ -0,0 +1,31 @@ +export const validateConvexSiteUrl = (siteUrl: string) => { + let parsedSiteUrl: URL; + try { + parsedSiteUrl = new URL(siteUrl); + } catch { + throw new Error("CONVEX_SITE_URL must be a valid HTTP or HTTPS URL"); + } + + if ( + parsedSiteUrl.protocol !== "http:" && + parsedSiteUrl.protocol !== "https:" + ) { + throw new Error("CONVEX_SITE_URL must be a valid HTTP or HTTPS URL"); + } + if (parsedSiteUrl.search || parsedSiteUrl.hash) { + throw new Error( + "CONVEX_SITE_URL must not include a query string or fragment" + ); + } + + return siteUrl; +}; + +export const getJwksUrl = (siteUrl: string, basePath: string | undefined) => { + validateConvexSiteUrl(siteUrl); + const normalizedSiteUrl = siteUrl.replace(/\/+$/, ""); + const configuredBasePath = basePath ?? "/api/auth"; + const trimmedBasePath = configuredBasePath.replace(/^\/+|\/+$/g, ""); + const normalizedBasePath = trimmedBasePath ? `/${trimmedBasePath}` : ""; + return `${normalizedSiteUrl}${normalizedBasePath}/convex/jwks`; +}; diff --git a/src/plugins/convex/index.test.ts b/src/plugins/convex/index.test.ts index 8c7cb984..802cb18a 100644 --- a/src/plugins/convex/index.test.ts +++ b/src/plugins/convex/index.test.ts @@ -53,3 +53,72 @@ describe("convex plugin JWT cookie refresh matcher", () => { expect(matcher(withoutSessionCtx as unknown as MatcherContext)).toBe(false); }); }); + +describe("convex plugin OpenID configuration", () => { + it("publishes only the Convex JWT metadata", async () => { + const originalConvexSiteUrl = process.env.CONVEX_SITE_URL; + process.env.CONVEX_SITE_URL = "https://deployment.convex.site"; + try { + const plugin = convex({ + authConfig: { + providers: [ + { + type: "customJwt", + applicationID: "convex", + issuer: "https://deployment.convex.site", + algorithm: "RS256", + jwks: "https://deployment.convex.site/custom/auth/convex/jwks", + }, + ], + }, + options: { basePath: "/custom/auth" }, + }); + + const response = await plugin.endpoints!.getOpenIdConfig!({ + context: {}, + asResponse: false, + returnHeaders: false, + returnStatus: false, + }); + + expect(response).toMatchObject({ + issuer: "https://deployment.convex.site", + jwks_uri: "https://deployment.convex.site/custom/auth/convex/jwks", + id_token_signing_alg_values_supported: ["RS256"], + }); + expect(response).not.toHaveProperty("authorization_endpoint"); + expect(response).not.toHaveProperty("token_endpoint"); + } finally { + if (originalConvexSiteUrl === undefined) { + delete process.env.CONVEX_SITE_URL; + } else { + process.env.CONVEX_SITE_URL = originalConvexSiteUrl; + } + } + }); + + it.each([ + ["/", "https://deployment.convex.site/convex/jwks"], + ["/custom/auth/", "https://deployment.convex.site/custom/auth/convex/jwks"], + ])("normalizes the %s base path", async (basePath, expected) => { + const originalConvexSiteUrl = process.env.CONVEX_SITE_URL; + process.env.CONVEX_SITE_URL = "https://deployment.convex.site"; + try { + const plugin = convex({ authConfig, options: { basePath } }); + const response = await plugin.endpoints!.getOpenIdConfig!({ + context: {}, + asResponse: false, + returnHeaders: false, + returnStatus: false, + }); + + expect(response).toMatchObject({ jwks_uri: expected }); + } finally { + if (originalConvexSiteUrl === undefined) { + delete process.env.CONVEX_SITE_URL; + } else { + process.env.CONVEX_SITE_URL = originalConvexSiteUrl; + } + } + }); +}); diff --git a/src/plugins/convex/index.ts b/src/plugins/convex/index.ts index db4cce2c..1769d650 100644 --- a/src/plugins/convex/index.ts +++ b/src/plugins/convex/index.ts @@ -8,28 +8,13 @@ import { import { bearer as bearerPlugin } from "better-auth/plugins/bearer"; import { jwt as jwtPlugin } from "better-auth/plugins/jwt"; import type { JwtOptions, Jwk } from "better-auth/plugins/jwt"; -import { oidcProvider as oidcProviderPlugin } from "better-auth/plugins/oidc-provider"; import { omit } from "convex-helpers"; import type { AuthConfig, AuthProvider } from "convex/server"; import { VERSION } from "../../version.js"; +import { getJwksUrl } from "../../jwks-url.js"; export const JWT_COOKIE_NAME = "convex_jwt"; -type BetterAuthAfterHooks = NonNullable< - NonNullable["after"] ->; -type BetterAuthAfterHook = BetterAuthAfterHooks[number]; -type BetterAuthHookContext = Parameters[0]; - -const normalizeAfterHooks = ( - hooks: THook[] -): BetterAuthAfterHooks => { - return hooks.map((hook) => ({ - ...hook, - matcher: (ctx: BetterAuthHookContext) => Boolean(hook.matcher(ctx)), - })); -}; - const getJwksAlg = (authProvider: AuthProvider) => { const isCustomJwt = "type" in authProvider && authProvider.type === "customJwt"; @@ -170,20 +155,12 @@ export const convex = (opts: { jwksRotateOnTokenGenerationError?: boolean; /** * @param {BetterAuthOptions} options - Better Auth options. Not required, - * currently used to pass the basePath to the oidcProvider plugin. + * currently used to keep discovery metadata aligned with the basePath. */ options?: BetterAuthOptions; }) => { const jwtExpirationSeconds = opts.jwt?.expirationSeconds ?? opts.jwtExpirationSeconds ?? 60 * 15; - const oidcProvider = oidcProviderPlugin({ - loginPage: "/not-used", - metadata: { - issuer: `${process.env.CONVEX_SITE_URL}`, - jwks_uri: `${process.env.CONVEX_SITE_URL}${opts.options?.basePath ?? "/api/auth"}/convex/jwks`, - }, - __skipDeprecationWarning: true, - }); const providerConfig = parseAuthConfig(opts.authConfig, opts); const jwtOptions = { @@ -304,24 +281,31 @@ export const convex = (opts: { return 0; }; }; + const noopAtomicWrite = (method: string) => { + const warn = noopWrite(method); + return async (...args: any[]) => { + await warn(...args); + return null; + }; + }; ctx.context.adapter.create = noopWrite("create") as any; ctx.context.adapter.update = noopWrite("update") as any; ctx.context.adapter.updateMany = noopWrite("updateMany") as any; ctx.context.adapter.delete = noopWrite("delete") as any; ctx.context.adapter.deleteMany = noopWrite("deleteMany") as any; + ctx.context.adapter.consumeOne = noopAtomicWrite("consumeOne"); + ctx.context.adapter.incrementOne = noopAtomicWrite("incrementOne"); return { context: ctx }; }), }, ], after: [ - ...normalizeAfterHooks(oidcProvider.hooks.after), { matcher: (ctx) => { return Boolean( ctx.path?.startsWith("/sign-in") || ctx.path?.startsWith("/sign-up") || ctx.path?.startsWith("/callback") || - ctx.path?.startsWith("/oauth2/callback") || ctx.path?.startsWith("/magic-link/verify") || ctx.path?.startsWith("/email-otp/verify-email") || ctx.path?.startsWith("/phone-number/verify") || @@ -383,14 +367,27 @@ export const convex = (opts: { }, // TODO: properly type this }, - async (ctx) => { - const response = await oidcProvider.endpoints.getOpenIdConfig({ - ...ctx, - asResponse: false, - returnHeaders: false, - returnStatus: false, - }); - return response; + async (_ctx) => { + const issuer = process.env.CONVEX_SITE_URL; + if (!issuer) { + throw new Error("CONVEX_SITE_URL is not set"); + } + return { + issuer, + jwks_uri: getJwksUrl(issuer, opts.options?.basePath), + id_token_signing_alg_values_supported: [getJwksAlg(providerConfig)], + claims_supported: [ + "sub", + "iss", + "aud", + "exp", + "iat", + "email", + "email_verified", + "name", + "picture", + ], + }; } ), getJwks: createAuthEndpoint( diff --git a/src/plugins/cross-domain/client.test.ts b/src/plugins/cross-domain/client.test.ts index 56dc9261..a0135a5c 100644 --- a/src/plugins/cross-domain/client.test.ts +++ b/src/plugins/cross-domain/client.test.ts @@ -1,5 +1,10 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { crossDomainClient, getCookie, getSetCookie } from "./client.js"; +import { + crossDomainCapability, + crossDomainClient, + getCookie, + getSetCookie, +} from "./client.js"; describe("getSetCookie", () => { it("stores cookies from RFC-1123 Expires headers without splitting the date", () => { @@ -158,6 +163,10 @@ describe("crossDomainClient", () => { return { onSuccess: plugin.fetchPlugins![0].hooks!.onSuccess!, notify }; } + it("exposes an explicit cross-domain capability marker", () => { + expect(getActions().crossDomainCapability).toBe(crossDomainCapability); + }); + describe("getSessionData", () => { it("returns null when storage is empty", () => { const actions = getActions(); diff --git a/src/plugins/cross-domain/client.ts b/src/plugins/cross-domain/client.ts index 381c0783..afe594c4 100644 --- a/src/plugins/cross-domain/client.ts +++ b/src/plugins/cross-domain/client.ts @@ -10,11 +10,14 @@ interface StoredCookie { } type CrossDomainActions = { + crossDomainCapability: typeof crossDomainCapability; getCookie: () => string; updateSession: () => void; getSessionData: () => Record | null; }; +export const crossDomainCapability = () => true; + type CrossDomainClientPlugin = Omit< BetterAuthClientPlugin, "$InferServerPlugin" | "getActions" @@ -93,6 +96,7 @@ export const crossDomainClient = ( getActions(_, $store) { store = $store; return { + crossDomainCapability, /** * Get the stored cookie. * diff --git a/src/plugins/cross-domain/index.test.ts b/src/plugins/cross-domain/index.test.ts index 1527b542..8e3f0874 100644 --- a/src/plugins/cross-domain/index.test.ts +++ b/src/plugins/cross-domain/index.test.ts @@ -100,31 +100,31 @@ describe("crossDomain plugin", async () => { }); }); - describe("callbackURL defaulting for oauth2", () => { + describe("callbackURL defaulting for generic OAuth", () => { it("injects siteUrl when callbackURL is absent", async () => { - const response = await post("/sign-in/oauth2", { - providerId: "example-oauth", + const response = await post("/sign-in/social", { + provider: "example-oauth", disableRedirect: true, }); const { url } = (await response.json()) as { url: string }; const state = new URL(url).searchParams.get("state"); const verification = db.verification.find( - (entry) => entry.identifier === state + (entry) => entry.identifier === `auth-state:${state}` ); expect(verification).toBeDefined(); expect(JSON.parse(verification!.value).callbackURL).toBe(SITE_URL); }); it("rewrites relative callbackURL to absolute using siteUrl", async () => { - const response = await post("/sign-in/oauth2", { - providerId: "example-oauth", + const response = await post("/sign-in/social", { + provider: "example-oauth", callbackURL: "/dashboard", disableRedirect: true, }); const { url } = (await response.json()) as { url: string }; const state = new URL(url).searchParams.get("state"); const verification = db.verification.find( - (entry) => entry.identifier === state + (entry) => entry.identifier === `auth-state:${state}` ); expect(verification).toBeDefined(); expect(JSON.parse(verification!.value).callbackURL).toBe( diff --git a/src/plugins/cross-domain/index.ts b/src/plugins/cross-domain/index.ts index be57aabf..13470312 100644 --- a/src/plugins/cross-domain/index.ts +++ b/src/plugins/cross-domain/index.ts @@ -108,7 +108,6 @@ export const crossDomain = ({ siteUrl }: { siteUrl: string }) => { ctx.body && !ctx.body.callbackURL && (ctx.path?.startsWith("/sign-in/social") || - ctx.path?.startsWith("/sign-in/oauth2") || ctx.path?.startsWith("/sign-in/magic-link") || ctx.path?.startsWith("/send-verification-email")) ) { @@ -154,7 +153,6 @@ export const crossDomain = ({ siteUrl }: { siteUrl: string }) => { matcher: (ctx) => { return Boolean( (ctx.path?.startsWith("/callback") || - ctx.path?.startsWith("/oauth2/callback") || ctx.path?.startsWith("/magic-link/verify")) && !isExpoNative(ctx) ); diff --git a/src/react/cross-domain.test.ts b/src/react/cross-domain.test.ts new file mode 100644 index 00000000..2ae9ac09 --- /dev/null +++ b/src/react/cross-domain.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, it, vi } from "vitest"; +import { createAuthClient } from "better-auth/react"; +import { + crossDomainCapability, + crossDomainClient, +} from "../plugins/cross-domain/client.js"; +import { handleCrossDomainCallback } from "./cross-domain.js"; +import type { RequiredAuthClient } from "./cross-domain.js"; + +const coreClient = (): RequiredAuthClient => ({ + useSession: () => ({ data: null, isPending: false }), + getSession: vi.fn(), + convex: { + token: vi.fn(), + }, +}); + +describe("handleCrossDomainCallback", () => { + it("preserves the token when the client lacks cross-domain support", async () => { + const authClient = createAuthClient({ + baseURL: "https://example.com", + }) as unknown as RequiredAuthClient; + const replaceUrl = vi.fn(); + + await handleCrossDomainCallback( + authClient, + "https://example.com/callback?ott=one-time-token&next=%2Fsettings", + replaceUrl + ); + + expect(replaceUrl).not.toHaveBeenCalled(); + }); + + it("marks real clients only when the cross-domain plugin is installed", () => { + const stored = new Map(); + const core = createAuthClient({ baseURL: "https://example.com" }); + const crossDomain = createAuthClient({ + baseURL: "https://example.com", + plugins: [ + crossDomainClient({ + storage: { + getItem: (key) => stored.get(key) ?? null, + setItem: (key, value) => stored.set(key, value), + }, + }), + ], + }); + + expect( + (core as unknown as { crossDomainCapability?: unknown }) + .crossDomainCapability === crossDomainCapability + ).toBe(false); + expect(crossDomain.crossDomainCapability === crossDomainCapability).toBe( + true + ); + }); + + it("verifies supported callbacks and refreshes the session", async () => { + const authClient = { + ...coreClient(), + crossDomainCapability, + crossDomain: { + oneTimeToken: { + verify: vi.fn().mockResolvedValue({ + data: { session: { token: "session-token" } }, + }), + }, + }, + updateSession: vi.fn(), + }; + const replaceUrl = vi.fn(); + + await handleCrossDomainCallback( + authClient, + "https://example.com/callback?ott=one-time-token&next=%2Fsettings", + replaceUrl + ); + + expect(authClient.crossDomain.oneTimeToken.verify).toHaveBeenCalledWith({ + token: "one-time-token", + }); + expect(replaceUrl).toHaveBeenCalledOnce(); + const replacedUrl = replaceUrl.mock.calls[0]?.[0] as URL; + expect(replacedUrl.searchParams.has("ott")).toBe(false); + expect(replacedUrl.searchParams.get("next")).toBe("/settings"); + expect(authClient.getSession).toHaveBeenCalledWith({ + fetchOptions: { + headers: { Authorization: "Bearer session-token" }, + }, + }); + expect(authClient.updateSession).toHaveBeenCalledOnce(); + }); +}); diff --git a/src/react/cross-domain.ts b/src/react/cross-domain.ts new file mode 100644 index 00000000..eae3d6da --- /dev/null +++ b/src/react/cross-domain.ts @@ -0,0 +1,67 @@ +import { crossDomainCapability } from "../plugins/cross-domain/client.js"; + +export type RequiredAuthClient = { + useSession: () => { + data: { session?: { id: string } } | null; + isPending: boolean; + }; + getSession: (args?: { + fetchOptions: { headers: Record }; + }) => Promise; + convex: { + token: (args: { + fetchOptions: { throw: boolean }; + }) => Promise<{ data?: { token?: string } | null }>; + }; +}; + +type AuthClientWithCrossDomain = RequiredAuthClient & { + crossDomainCapability: typeof crossDomainCapability; + crossDomain: { + oneTimeToken: { + verify: (args: { token: string }) => Promise<{ + data?: { session?: { token: string } } | null; + }>; + }; + }; + updateSession: () => void; +}; + +const hasCrossDomain = ( + authClient: RequiredAuthClient +): authClient is AuthClientWithCrossDomain => { + const candidate = authClient as Partial; + return ( + candidate.crossDomainCapability === crossDomainCapability && + typeof candidate.crossDomain?.oneTimeToken?.verify === "function" && + typeof candidate.updateSession === "function" + ); +}; + +export const handleCrossDomainCallback = async ( + authClient: RequiredAuthClient, + href: string, + replaceUrl: (url: URL) => void +) => { + const url = new URL(href); + const token = url.searchParams.get("ott"); + if (!token || !hasCrossDomain(authClient)) { + return; + } + + url.searchParams.delete("ott"); + replaceUrl(url); + const result = await authClient.crossDomain.oneTimeToken.verify({ token }); + const session = result.data?.session; + if (!session) { + return; + } + await authClient.getSession({ + fetchOptions: { + headers: { + Authorization: `Bearer ${session.token}`, + }, + }, + }); + authClient.updateSession(); +}; diff --git a/src/react/index.tsx b/src/react/index.tsx index dc10909a..7865bab4 100644 --- a/src/react/index.tsx +++ b/src/react/index.tsx @@ -1,5 +1,12 @@ import type { PropsWithChildren, ReactNode } from "react"; -import { Component, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + Component, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import type { AuthTokenFetcher } from "convex/browser"; import { Authenticated, @@ -8,34 +15,16 @@ import { useQuery, } from "convex/react"; import type { FunctionReference } from "convex/server"; -import type { BetterAuthClientPlugin } from "better-auth"; -import type { createAuthClient } from "better-auth/react"; -import type { - convexClient, - crossDomainClient, -} from "../client/plugins/index.js"; import type { EmptyObject } from "convex-helpers"; +import type { BetterAuthClientOptions } from "better-auth"; +import type { ReactAuthClient } from "better-auth/react"; +import { handleCrossDomainCallback } from "./cross-domain.js"; +import type { RequiredAuthClient } from "./cross-domain.js"; -type CrossDomainClient = ReturnType; -type ConvexClient = ReturnType; -type PluginsWithCrossDomain = ( - | CrossDomainClient - | ConvexClient - | BetterAuthClientPlugin -)[]; -type PluginsWithoutCrossDomain = (ConvexClient | BetterAuthClientPlugin)[]; -type AuthClientWithPlugins< - Plugins extends PluginsWithCrossDomain | PluginsWithoutCrossDomain, -> = ReturnType< - typeof createAuthClient< - BetterAuthClientPlugin & { - plugins: Plugins; - } - > ->; -export type AuthClient = - | AuthClientWithPlugins - | AuthClientWithPlugins; +export type AuthClient< + Client extends RequiredAuthClient = ReactAuthClient & + RequiredAuthClient, +> = Client & RequiredAuthClient; // Until we can import from our own entry points (requires TypeScript 4.7), // just describe the interface enough to help users pass the right type. @@ -50,7 +39,7 @@ type IConvexReactClient = { * * @public */ -export function ConvexBetterAuthProvider({ +export function ConvexBetterAuthProvider({ children, client, authClient, @@ -58,7 +47,7 @@ export function ConvexBetterAuthProvider({ }: { children: ReactNode; client: IConvexReactClient; - authClient: AuthClient; + authClient: Client; initialToken?: string | null; }) { const useBetterAuth = useUseAuthFromBetterAuth(authClient, initialToken); @@ -67,29 +56,9 @@ export function ConvexBetterAuthProvider({ if (typeof window === "undefined" || !window.location?.href) { return; } - const url = new URL(window.location.href); - const token = url.searchParams.get("ott"); - if (token) { - const authClientWithCrossDomain = - authClient as AuthClientWithPlugins; - url.searchParams.delete("ott"); - window.history.replaceState({}, "", url); - const result = - await authClientWithCrossDomain.crossDomain.oneTimeToken.verify({ - token, - }); - const session = result.data?.session; - if (session) { - await authClient.getSession({ - fetchOptions: { - headers: { - Authorization: `Bearer ${session.token}`, - }, - }, - }); - authClientWithCrossDomain.updateSession(); - } - } + await handleCrossDomainCallback(authClient, window.location.href, (url) => + window.history.replaceState({}, "", url) + ); })(); }, [authClient]); return ( @@ -101,8 +70,8 @@ export function ConvexBetterAuthProvider({ let initialTokenUsed = false; -function useUseAuthFromBetterAuth( - authClient: AuthClient, +function useUseAuthFromBetterAuth( + authClient: Client, initialToken?: string | null ) { const [cachedToken, setCachedToken] = useState( @@ -256,7 +225,7 @@ const UserSubscription = ({ * The component provides a query for this via `export const { getAuthUser } = authComponent.clientApi()`. * @param props.isAuthError - Function to check if the error is auth related. */ -export const AuthBoundary = ({ +export const AuthBoundary = ({ children, /** * The function to call when the user is unauthenticated. Typically a redirect @@ -282,7 +251,7 @@ export const AuthBoundary = ({ isAuthError, }: PropsWithChildren<{ onUnauth: () => void | Promise; - authClient: AuthClient; + authClient: Client; renderFallback?: () => React.ReactNode; getAuthUserFn: FunctionReference<"query", "public", EmptyObject>; isAuthError: (error: unknown) => boolean; diff --git a/src/react/index.types.test.ts b/src/react/index.types.test.ts new file mode 100644 index 00000000..6095ddb6 --- /dev/null +++ b/src/react/index.types.test.ts @@ -0,0 +1,9 @@ +import { expectTypeOf, it } from "vitest"; +import type { AuthClient } from "./index.js"; + +it("preserves the core Better Auth client API", () => { + expectTypeOf().not.toBeNever(); + expectTypeOf().toBeFunction(); + expectTypeOf().toBeFunction(); + expectTypeOf().toBeFunction(); +}); diff --git a/src/test/adapter-factory/convex-custom.ts b/src/test/adapter-factory/convex-custom.ts index 06bb5e7d..b8a7a60d 100644 --- a/src/test/adapter-factory/convex-custom.ts +++ b/src/test/adapter-factory/convex-custom.ts @@ -1,10 +1,30 @@ import { createTestSuite } from "@better-auth/test-utils/adapter"; +import type { BetterAuthOptions } from "better-auth"; +import { twoFactor } from "better-auth/plugins/two-factor"; import { expect } from "vitest"; +import { constraintsProfileOptions } from "../../component/testProfiles/auth-options.constraints.js"; + +const withBetterAuthOptions = ( + modifyBetterAuthOptions: ( + options: BetterAuthOptions, + shouldRunMigrations: boolean, + ) => Promise, + options: BetterAuthOptions, + test: () => Promise, +) => + async () => { + await modifyBetterAuthOptions(options, true); + try { + await test(); + } finally { + await modifyBetterAuthOptions({}, true); + } + }; export const convexCustomTestSuite = createTestSuite( "convex-custom", {}, - ({ adapter }) => ({ + ({ adapter, getBetterAuthOptions, modifyBetterAuthOptions }) => ({ "should handle lone range operators": async () => { const user = await adapter.create({ model: "user", @@ -495,6 +515,170 @@ export const convexCustomTestSuite = createTestSuite( ).toMatchObject({ emailVerified: true }); }, + "should roll back single-page bulk updates that collide on a compound unique constraint": + async () => { + await adapter.create({ + model: "account", + data: { + issuer: "issuer-a", + accountId: "shared-account", + providerId: "provider-a", + userId: "user-a", + createdAt: Date.now(), + updatedAt: Date.now(), + }, + }); + await adapter.create({ + model: "account", + data: { + issuer: "issuer-b", + accountId: "shared-account", + providerId: "provider-b", + userId: "user-b", + createdAt: Date.now(), + updatedAt: Date.now(), + }, + }); + + await expect( + adapter.updateMany({ + model: "account", + where: [{ field: "accountId", value: "shared-account" }], + update: { issuer: "issuer-c" }, + }), + ).rejects.toThrow( + "account unique constraint issuer+accountId already exists", + ); + + const accounts = await adapter.findMany({ + model: "account", + where: [{ field: "accountId", value: "shared-account" }], + }); + expect(accounts).toHaveLength(2); + expect(accounts).toEqual( + expect.arrayContaining([ + expect.objectContaining({ issuer: "issuer-a" }), + expect.objectContaining({ issuer: "issuer-b" }), + ]), + ); + }, + + "should allow a full-page unique update and reject larger updates": async () => { + for (let i = 0; i < 200; i += 1) { + await adapter.create({ + model: "account", + data: { + issuer: `original-${i}`, + accountId: `bulk-account-${i}`, + providerId: "bulk-provider", + userId: `bulk-user-${i}`, + createdAt: Date.now(), + updatedAt: Date.now(), + }, + }); + } + + await expect( + adapter.updateMany({ + model: "account", + where: [{ field: "providerId", value: "bulk-provider" }], + update: { issuer: "full-page-issuer" }, + }), + ).resolves.toBe(200); + await expect( + adapter.findOne({ + model: "account", + where: [{ field: "accountId", value: "bulk-account-0" }], + }), + ).resolves.toMatchObject({ issuer: "full-page-issuer" }); + + await adapter.create({ + model: "account", + data: { + issuer: "overflow-issuer", + accountId: "bulk-overflow", + providerId: "bulk-provider", + userId: "bulk-user-overflow", + createdAt: Date.now(), + updatedAt: Date.now(), + }, + }); + + await expect( + adapter.updateMany({ + model: "account", + where: [{ field: "providerId", value: "bulk-provider" }], + update: { issuer: "updated-issuer" }, + }), + ).rejects.toThrow( + "Cannot update unique fields across multiple pages in account", + ); + + await expect( + adapter.findOne({ + model: "account", + where: [{ field: "accountId", value: "bulk-account-0" }], + }), + ).resolves.toMatchObject({ issuer: "full-page-issuer" }); + }, + + "should allow atomic ID-set unique updates larger than one page": async () => { + for (let i = 0; i < 201; i += 1) { + await adapter.create({ + model: "account", + data: { + issuer: `original-${i}`, + accountId: `or-bulk-account-${i}`, + providerId: i % 2 === 0 ? "or-bulk-a" : "or-bulk-b", + userId: `or-bulk-user-${i}`, + createdAt: Date.now(), + updatedAt: Date.now(), + }, + }); + } + + await expect( + adapter.updateMany({ + model: "account", + where: [ + { field: "providerId", value: "or-bulk-a", connector: "OR" }, + { field: "providerId", value: "or-bulk-b", connector: "OR" }, + ], + update: { issuer: "atomic-id-set-issuer" }, + }), + ).resolves.toBe(201); + + await expect( + adapter.findOne({ + model: "account", + where: [{ field: "accountId", value: "or-bulk-account-0" }], + }), + ).resolves.toMatchObject({ issuer: "atomic-id-set-issuer" }); + }, + + "should reject new accounts without the required issuer": async () => { + const account = { + accountId: "subject", + providerId: "custom-provider", + userId: "user-without-issuer", + createdAt: Date.now(), + updatedAt: Date.now(), + }; + + await expect( + adapter.create({ + model: "account", + data: account as any, + }), + ).rejects.toThrow("Missing required field account.issuer"); + await expect( + adapter.create({ + model: "account", + data: { ...account, issuer: null } as any, + }), + ).rejects.toThrow("Missing required field account.issuer"); + }, + "should delete and count each match only once for overlapping OR clauses": async () => { await adapter.create({ @@ -589,6 +773,7 @@ export const convexCustomTestSuite = createTestSuite( await adapter.create({ model: "account", data: { + issuer: "local:oauth:bar", accountId: "foo", providerId: "bar", userId: "baz", @@ -626,6 +811,7 @@ export const convexCustomTestSuite = createTestSuite( const nullRangeAccount = await adapter.create({ model: "account", data: { + issuer: "local:oauth:null-range-provider", accountId: nullRangeAccountId, providerId: "null-range-provider", userId: `null-range-user-${now}`, @@ -638,6 +824,7 @@ export const convexCustomTestSuite = createTestSuite( const nonNullRangeAccount = await adapter.create({ model: "account", data: { + issuer: "local:oauth:non-null-range-provider", accountId: nonNullRangeAccountId, providerId: "non-null-range-provider", userId: `non-null-range-user-${now}`, @@ -737,11 +924,98 @@ export const convexCustomTestSuite = createTestSuite( await expect( adapter.create({ model: "user", - data: { name: "foo", email: "foo@bar.com" }, + data: { name: "different name", email: "foo@bar.com" }, }), ).rejects.toThrow("user email already exists"); }, + "should consume a matching record only once": async () => { + const user = await adapter.create({ + model: "user", + data: { name: "consume", email: "consume@example.com" }, + }); + const where = [{ field: "id", value: user.id }]; + + const consumed = await Promise.all([ + adapter.consumeOne({ model: "user", where }), + adapter.consumeOne({ model: "user", where }), + ]); + expect(consumed.filter(Boolean)).toEqual([user]); + await expect( + adapter.consumeOne({ model: "user", where }), + ).resolves.toBeNull(); + }, + + "should apply a guarded increment only once": withBetterAuthOptions( + modifyBetterAuthOptions, + { rateLimit: { enabled: true, storage: "database" } }, + async () => { + const rateLimit = await adapter.create({ + model: "rateLimit", + data: { key: "guarded-counter", count: 0, lastRequest: 0 }, + }); + const where = [ + { field: "id", value: rateLimit.id }, + { field: "count", operator: "lt" as const, value: 1 }, + ]; + + const increments = await Promise.all([ + adapter.incrementOne({ + model: "rateLimit", + where, + increment: { count: 1 }, + set: { lastRequest: 42 }, + }), + adapter.incrementOne({ + model: "rateLimit", + where, + increment: { count: 1 }, + set: { lastRequest: 42 }, + }), + ]); + expect(increments.filter(Boolean)).toEqual([ + expect.objectContaining({ count: 1, lastRequest: 42 }), + ]); + await expect( + adapter.incrementOne({ + model: "rateLimit", + where, + increment: { count: 1 }, + }), + ).resolves.toBeNull(); + }, + ), + + "should increment a nullable legacy counter from zero": + withBetterAuthOptions( + modifyBetterAuthOptions, + { plugins: [twoFactor()] }, + async () => { + const factor = await adapter.create({ + model: "twoFactor", + data: { + secret: "secret", + backupCodes: "[]", + userId: "legacy-counter-user", + failedVerificationCount: null, + }, + }); + + await expect( + adapter.incrementOne({ + model: "twoFactor", + where: [{ field: "id", value: factor.id }], + increment: { failedVerificationCount: 1 }, + }), + ).resolves.toMatchObject({ failedVerificationCount: 1 }); + }, + ), + + "should restore Better Auth options after a custom test": async () => { + expect(getBetterAuthOptions().plugins).toEqual(constraintsProfileOptions.plugins); + expect(getBetterAuthOptions().rateLimit).toBeUndefined(); + }, + "should be able to compare against a date": async () => { const now = new Date().toISOString(); const user = await adapter.create({