@convex-dev/better-auth 0.10.12 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-options.d.ts.map +1 -1
- package/dist/auth-options.js +0 -2
- package/dist/auth-options.js.map +1 -1
- package/dist/client/adapter-utils.d.ts +10 -10
- package/dist/client/adapter-utils.d.ts.map +1 -1
- package/dist/client/adapter-utils.js +41 -32
- package/dist/client/adapter-utils.js.map +1 -1
- package/dist/client/adapter.d.ts +1 -1
- package/dist/client/adapter.d.ts.map +1 -1
- package/dist/client/adapter.js +113 -7
- package/dist/client/adapter.js.map +1 -1
- package/dist/client/create-api.d.ts +8 -7
- package/dist/client/create-api.d.ts.map +1 -1
- package/dist/client/create-api.js +1 -0
- package/dist/client/create-api.js.map +1 -1
- package/dist/client/create-client.d.ts +1 -1
- package/dist/client/create-client.d.ts.map +1 -1
- package/dist/client/create-client.js +8 -7
- package/dist/client/create-client.js.map +1 -1
- package/dist/client/create-schema.d.ts +0 -1
- package/dist/client/create-schema.d.ts.map +1 -1
- package/dist/client/create-schema.js +0 -1
- package/dist/client/create-schema.js.map +1 -1
- package/dist/component/_generated/api.d.ts +12 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +7407 -92
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/adapter.d.ts +8 -7
- package/dist/component/adapter.d.ts.map +1 -1
- package/dist/component/adapterTest.d.ts +1 -7
- package/dist/component/adapterTest.d.ts.map +1 -1
- package/dist/component/adapterTest.js +193 -390
- package/dist/component/adapterTest.js.map +1 -1
- package/dist/component/schema.d.ts +35 -74
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +16 -21
- package/dist/component/schema.js.map +1 -1
- package/dist/component/testProfiles/adapterAdditionalFields.d.ts +131 -0
- package/dist/component/testProfiles/adapterAdditionalFields.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterAdditionalFields.js +5 -0
- package/dist/component/testProfiles/adapterAdditionalFields.js.map +1 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.d.ts +131 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.js +5 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.js.map +1 -0
- package/dist/component/testProfiles/adapterPluginTable.d.ts +131 -0
- package/dist/component/testProfiles/adapterPluginTable.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterPluginTable.js +5 -0
- package/dist/component/testProfiles/adapterPluginTable.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameField.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameField.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameField.js +5 -0
- package/dist/component/testProfiles/adapterRenameField.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.js +5 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserTable.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameUserTable.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserTable.js +5 -0
- package/dist/component/testProfiles/adapterRenameUserTable.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts +3 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.js +38 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts +3 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.js +92 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts +6 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.js +49 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.js.map +1 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.d.ts +227 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.d.ts.map +1 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.js +37 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.js.map +1 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.d.ts +450 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.d.ts.map +1 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.js +116 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.js.map +1 -0
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/index.js +1 -0
- package/dist/nextjs/index.js.map +1 -1
- package/dist/plugins/convex/index.d.ts +131 -12
- package/dist/plugins/convex/index.d.ts.map +1 -1
- package/dist/plugins/convex/index.js +12 -5
- package/dist/plugins/convex/index.js.map +1 -1
- package/dist/plugins/cross-domain/client.d.ts +1 -1
- package/dist/plugins/cross-domain/index.d.ts +126 -1
- package/dist/plugins/cross-domain/index.d.ts.map +1 -1
- package/dist/plugins/cross-domain/index.js +11 -16
- package/dist/plugins/cross-domain/index.js.map +1 -1
- package/dist/react-start/index.d.ts.map +1 -1
- package/dist/react-start/index.js +1 -0
- package/dist/react-start/index.js.map +1 -1
- package/dist/test/adapter-factory/auth-flow.d.ts +42 -0
- package/dist/test/adapter-factory/auth-flow.d.ts.map +1 -0
- package/dist/test/adapter-factory/auth-flow.js +145 -0
- package/dist/test/adapter-factory/auth-flow.js.map +1 -0
- package/dist/test/adapter-factory/basic.d.ts +190 -0
- package/dist/test/adapter-factory/basic.d.ts.map +1 -0
- package/dist/test/adapter-factory/basic.js +2713 -0
- package/dist/test/adapter-factory/basic.js.map +1 -0
- package/dist/test/adapter-factory/convex-custom.d.ts +18 -0
- package/dist/test/adapter-factory/convex-custom.d.ts.map +1 -0
- package/dist/test/adapter-factory/convex-custom.js +610 -0
- package/dist/test/adapter-factory/convex-custom.js.map +1 -0
- package/dist/test/adapter-factory/index.d.ts +11 -0
- package/dist/test/adapter-factory/index.d.ts.map +1 -0
- package/dist/test/adapter-factory/index.js +11 -0
- package/dist/test/adapter-factory/index.js.map +1 -0
- package/dist/test/adapter-factory/joins.d.ts +18 -0
- package/dist/test/adapter-factory/joins.d.ts.map +1 -0
- package/dist/test/adapter-factory/joins.js +22 -0
- package/dist/test/adapter-factory/joins.js.map +1 -0
- package/dist/test/adapter-factory/number-id.d.ts +18 -0
- package/dist/test/adapter-factory/number-id.d.ts.map +1 -0
- package/dist/test/adapter-factory/number-id.js +36 -0
- package/dist/test/adapter-factory/number-id.js.map +1 -0
- package/dist/test/adapter-factory/profile-additional-fields.d.ts +71 -0
- package/dist/test/adapter-factory/profile-additional-fields.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-additional-fields.js +44 -0
- package/dist/test/adapter-factory/profile-additional-fields.js.map +1 -0
- package/dist/test/adapter-factory/profile-plugin-table.d.ts +19 -0
- package/dist/test/adapter-factory/profile-plugin-table.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-plugin-table.js +25 -0
- package/dist/test/adapter-factory/profile-plugin-table.js.map +1 -0
- package/dist/test/adapter-factory/profile-rename-joins.d.ts +73 -0
- package/dist/test/adapter-factory/profile-rename-joins.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-rename-joins.js +34 -0
- package/dist/test/adapter-factory/profile-rename-joins.js.map +1 -0
- package/dist/test/adapter-factory/transactions.d.ts +21 -0
- package/dist/test/adapter-factory/transactions.d.ts.map +1 -0
- package/dist/test/adapter-factory/transactions.js +28 -0
- package/dist/test/adapter-factory/transactions.js.map +1 -0
- package/dist/test/adapter-factory/uuid.d.ts +18 -0
- package/dist/test/adapter-factory/uuid.d.ts.map +1 -0
- package/dist/test/adapter-factory/uuid.js +58 -0
- package/dist/test/adapter-factory/uuid.js.map +1 -0
- package/dist/utils/index.d.ts +18 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +9 -6
- package/src/auth-options.ts +0 -2
- package/src/client/adapter-utils.ts +80 -73
- package/src/client/adapter.test.ts +2 -74
- package/src/client/adapter.ts +142 -7
- package/src/client/create-api.ts +1 -0
- package/src/client/create-client.ts +14 -6
- package/src/client/create-schema.ts +0 -1
- package/src/component/_generated/api.ts +12 -0
- package/src/component/_generated/component.ts +19454 -215
- package/src/component/adapterTest.ts +250 -466
- package/src/component/schema.ts +21 -26
- package/src/component/testProfiles/adapterAdditionalFields.ts +13 -0
- package/src/component/testProfiles/adapterOrganizationJoins.ts +13 -0
- package/src/component/testProfiles/adapterPluginTable.ts +13 -0
- package/src/component/testProfiles/adapterRenameField.ts +13 -0
- package/src/component/testProfiles/adapterRenameUserCustom.ts +13 -0
- package/src/component/testProfiles/adapterRenameUserTable.ts +13 -0
- package/src/component/testProfiles/auth-options.profile-additional-fields.ts +39 -0
- package/src/component/testProfiles/auth-options.profile-plugin-table.ts +93 -0
- package/src/component/testProfiles/auth-options.profile-rename-joins.ts +54 -0
- package/src/component/testProfiles/schema.profile-additional-fields.ts +39 -0
- package/src/component/testProfiles/schema.profile-plugin-table.ts +130 -0
- package/src/nextjs/index.ts +1 -0
- package/src/plugins/convex/index.test.ts +55 -0
- package/src/plugins/convex/index.ts +26 -11
- package/src/plugins/cross-domain/index.test.ts +67 -0
- package/src/plugins/cross-domain/index.ts +11 -22
- package/src/react-start/index.ts +1 -0
- package/src/test/adapter-factory/auth-flow.ts +170 -0
- package/src/test/adapter-factory/basic.ts +3190 -0
- package/src/test/adapter-factory/convex-custom.ts +706 -0
- package/src/test/adapter-factory/index.ts +10 -0
- package/src/test/adapter-factory/joins.ts +28 -0
- package/src/test/adapter-factory/number-id.ts +45 -0
- package/src/test/adapter-factory/profile-additional-fields.ts +84 -0
- package/src/test/adapter-factory/profile-plugin-table.ts +37 -0
- package/src/test/adapter-factory/profile-rename-joins.ts +67 -0
- package/src/test/adapter-factory/transactions.ts +38 -0
- package/src/test/adapter-factory/uuid.ts +67 -0
- package/src/utils/index.ts +25 -3
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import type { Auth } from "better-auth";
|
|
2
|
-
import type { betterAuth } from "better-auth/minimal";
|
|
3
1
|
import type { AuthProvider, DefaultFunctionArgs, FunctionReference, GenericActionCtx, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server";
|
|
4
2
|
import type { Jwk } from "better-auth/plugins/jwt";
|
|
5
|
-
|
|
3
|
+
type TrustedOriginsOption = (string | null | undefined)[] | ((request?: Request) => (string | null | undefined)[] | Promise<(string | null | undefined)[]>);
|
|
4
|
+
type RegisterableAuth = {
|
|
5
|
+
handler: (request: Request) => Promise<Response>;
|
|
6
|
+
options: {
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
basePath?: string;
|
|
9
|
+
trustedOrigins?: TrustedOriginsOption;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
$context: Promise<{
|
|
13
|
+
options: {
|
|
14
|
+
trustedOrigins?: TrustedOriginsOption;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
};
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
export type CreateAuth<DataModel extends GenericDataModel, A extends RegisterableAuth = RegisterableAuth> = (ctx: GenericCtx<DataModel>) => A;
|
|
6
20
|
export type EventFunction<T extends DefaultFunctionArgs> = FunctionReference<"mutation", "internal" | "public", T>;
|
|
7
21
|
export type GenericCtx<DataModel extends GenericDataModel = GenericDataModel> = GenericQueryCtx<DataModel> | GenericMutationCtx<DataModel> | GenericActionCtx<DataModel>;
|
|
8
22
|
export type RunMutationCtx<DataModel extends GenericDataModel> = (GenericMutationCtx<DataModel> | GenericActionCtx<DataModel>) & {
|
|
@@ -30,4 +44,5 @@ export declare const getToken: (siteUrl: string, headers: Headers, opts?: GetTok
|
|
|
30
44
|
token: string | undefined;
|
|
31
45
|
}>;
|
|
32
46
|
export declare const parseJwks: (providerConfig: AuthProvider) => Jwk | undefined;
|
|
47
|
+
export {};
|
|
33
48
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/get-convex/better-auth/issues"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.11.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"keywords": [
|
|
12
12
|
"convex",
|
|
@@ -30,8 +30,10 @@
|
|
|
30
30
|
"test:debug": "vitest --inspect-brk --no-file-parallelism",
|
|
31
31
|
"test:e2e": "npm run build && cd e2e && npm run test",
|
|
32
32
|
"test:coverage": "vitest run --coverage --coverage.reporter=text",
|
|
33
|
+
"test:adapter-policy": "node test/adapter-policy/validate.mjs",
|
|
34
|
+
"test:adapter-drift": "node test/adapter-policy/check-upstream-drift.mjs",
|
|
33
35
|
"preversion": "npm ci && npm run build:clean && run-p test lint typecheck",
|
|
34
|
-
"prepublishOnly": "npm whoami || npm login",
|
|
36
|
+
"prepublishOnly": "npm whoami || npm login && sleep 1",
|
|
35
37
|
"alpha": "npm version prerelease --preid alpha && npm publish --tag alpha && git push --follow-tags",
|
|
36
38
|
"release": "npm version patch && npm publish && git push --follow-tags",
|
|
37
39
|
"version": "vim -c 'normal o' -c 'normal o## '$npm_package_version CHANGELOG.md && prettier -w CHANGELOG.md && git add CHANGELOG.md"
|
|
@@ -103,12 +105,13 @@
|
|
|
103
105
|
}
|
|
104
106
|
},
|
|
105
107
|
"peerDependencies": {
|
|
106
|
-
"better-auth": ">=1.
|
|
108
|
+
"better-auth": ">=1.5.0 <1.6.0",
|
|
107
109
|
"convex": "^1.25.0",
|
|
108
|
-
"react": "^18.3.1 || ^19.0.0"
|
|
109
|
-
"react-dom": "^18.3.1 || ^19.0.0"
|
|
110
|
+
"react": "^18.3.1 || ^19.0.0"
|
|
110
111
|
},
|
|
111
112
|
"devDependencies": {
|
|
113
|
+
"@better-auth/core": "^1.5.3",
|
|
114
|
+
"@better-auth/test-utils": "^1.5.3",
|
|
112
115
|
"@edge-runtime/vm": "5.0.0",
|
|
113
116
|
"@eslint/eslintrc": "3.3.1",
|
|
114
117
|
"@eslint/js": "9.39.1",
|
|
@@ -118,6 +121,7 @@
|
|
|
118
121
|
"@types/react": "18.3.26",
|
|
119
122
|
"@types/react-dom": "18.3.7",
|
|
120
123
|
"@types/semver": "^7.7.0",
|
|
124
|
+
"better-auth": "^1.5.3",
|
|
121
125
|
"chokidar-cli": "3.0.0",
|
|
122
126
|
"concurrently": "^9.2.0",
|
|
123
127
|
"convex": "^1.31.2",
|
|
@@ -142,7 +146,6 @@
|
|
|
142
146
|
"types": "./dist/client/index.d.ts",
|
|
143
147
|
"module": "./dist/client/index.js",
|
|
144
148
|
"dependencies": {
|
|
145
|
-
"@better-auth/passkey": "1.4.9",
|
|
146
149
|
"@better-fetch/fetch": "^1.1.18",
|
|
147
150
|
"common-tags": "^1.8.2",
|
|
148
151
|
"convex-helpers": "^0.1.95",
|
package/src/auth-options.ts
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
twoFactor,
|
|
14
14
|
username,
|
|
15
15
|
} from "better-auth/plugins";
|
|
16
|
-
import { passkey } from "@better-auth/passkey";
|
|
17
16
|
import { convex } from "./plugins/convex/index.js";
|
|
18
17
|
import { convexAdapter } from "./client/adapter.js";
|
|
19
18
|
|
|
@@ -30,7 +29,6 @@ export const options = {
|
|
|
30
29
|
phoneNumber(),
|
|
31
30
|
magicLink({ sendMagicLink: async () => {} }),
|
|
32
31
|
emailOTP({ sendVerificationOTP: async () => {} }),
|
|
33
|
-
passkey(),
|
|
34
32
|
genericOAuth({
|
|
35
33
|
config: [
|
|
36
34
|
{
|
|
@@ -279,7 +279,7 @@ export const checkUniqueFields = async <
|
|
|
279
279
|
|
|
280
280
|
// This handles basic select (stripping out the other fields if there
|
|
281
281
|
// is a select arg).
|
|
282
|
-
export const selectFields =
|
|
282
|
+
export const selectFields = <
|
|
283
283
|
T extends TableNamesInDataModel<GenericDataModel>,
|
|
284
284
|
D extends DocumentByName<GenericDataModel, T>,
|
|
285
285
|
>(
|
|
@@ -293,7 +293,10 @@ export const selectFields = async <
|
|
|
293
293
|
return doc;
|
|
294
294
|
}
|
|
295
295
|
return select.reduce((acc, field) => {
|
|
296
|
-
|
|
296
|
+
// Better Auth may request "id" while Convex stores it as "_id".
|
|
297
|
+
// Keep the raw field key here and let Better Auth map "_id" -> "id".
|
|
298
|
+
const sourceField = field === "id" && "_id" in doc ? "_id" : field;
|
|
299
|
+
(acc as any)[sourceField] = doc[sourceField as keyof typeof doc];
|
|
297
300
|
return acc;
|
|
298
301
|
}, {} as D);
|
|
299
302
|
};
|
|
@@ -321,19 +324,19 @@ const filterByWhere = <
|
|
|
321
324
|
typeof adapterWhereValidator
|
|
322
325
|
>["value"];
|
|
323
326
|
const isLessThan = (val: typeof value, wVal: typeof w.value) => {
|
|
324
|
-
if (
|
|
327
|
+
if (wVal === undefined || wVal === null) {
|
|
325
328
|
return false;
|
|
326
329
|
}
|
|
327
|
-
if (
|
|
330
|
+
if (val === undefined || val === null) {
|
|
328
331
|
return true;
|
|
329
332
|
}
|
|
330
333
|
return val < wVal;
|
|
331
334
|
};
|
|
332
335
|
const isGreaterThan = (val: typeof value, wVal: typeof w.value) => {
|
|
333
|
-
if (
|
|
336
|
+
if (val === undefined || val === null) {
|
|
334
337
|
return false;
|
|
335
338
|
}
|
|
336
|
-
if (
|
|
339
|
+
if (wVal === undefined || wVal === null) {
|
|
337
340
|
return true;
|
|
338
341
|
}
|
|
339
342
|
return val > wVal;
|
|
@@ -394,54 +397,57 @@ const generateQuery = (
|
|
|
394
397
|
) => {
|
|
395
398
|
const { index, values, boundField, indexFields } =
|
|
396
399
|
findIndex(schema, args) ?? {};
|
|
400
|
+
const usableIndex =
|
|
401
|
+
index?.indexDescriptor === "by_creation_time" ? undefined : index;
|
|
397
402
|
const query = stream(ctx.db as any, schema).query(args.model as any);
|
|
398
403
|
const hasValues =
|
|
399
|
-
values?.eq?.length ||
|
|
400
|
-
values?.lt ||
|
|
401
|
-
values?.lte ||
|
|
402
|
-
values?.gt ||
|
|
403
|
-
values?.gte;
|
|
404
|
-
const indexedQuery =
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
q = q.eq(index.fields[idx], value);
|
|
412
|
-
}
|
|
413
|
-
if (values?.lt) {
|
|
414
|
-
q = q.lt(boundField, values.lt);
|
|
415
|
-
}
|
|
416
|
-
if (values?.lte) {
|
|
417
|
-
q = q.lte(boundField, values.lte);
|
|
418
|
-
}
|
|
419
|
-
if (values?.gt) {
|
|
420
|
-
q = q.gt(boundField, values.gt);
|
|
421
|
-
}
|
|
422
|
-
if (values?.gte) {
|
|
423
|
-
q = q.gte(boundField, values.gte);
|
|
424
|
-
}
|
|
425
|
-
return q;
|
|
404
|
+
(values?.eq?.length ?? 0) > 0 ||
|
|
405
|
+
values?.lt !== undefined ||
|
|
406
|
+
values?.lte !== undefined ||
|
|
407
|
+
values?.gt !== undefined ||
|
|
408
|
+
values?.gte !== undefined;
|
|
409
|
+
const indexedQuery = usableIndex
|
|
410
|
+
? query.withIndex(
|
|
411
|
+
usableIndex.indexDescriptor,
|
|
412
|
+
hasValues
|
|
413
|
+
? (q: any) => {
|
|
414
|
+
for (const [idx, value] of (values?.eq ?? []).entries()) {
|
|
415
|
+
q = q.eq(usableIndex.fields[idx], value);
|
|
426
416
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
417
|
+
if (values?.lt !== undefined) {
|
|
418
|
+
q = q.lt(boundField, values.lt);
|
|
419
|
+
}
|
|
420
|
+
if (values?.lte !== undefined) {
|
|
421
|
+
q = q.lte(boundField, values.lte);
|
|
422
|
+
}
|
|
423
|
+
if (values?.gt !== undefined) {
|
|
424
|
+
q = q.gt(boundField, values.gt);
|
|
425
|
+
}
|
|
426
|
+
if (values?.gte !== undefined) {
|
|
427
|
+
q = q.gte(boundField, values.gte);
|
|
428
|
+
}
|
|
429
|
+
return q;
|
|
430
|
+
}
|
|
431
|
+
: undefined
|
|
432
|
+
)
|
|
433
|
+
: query;
|
|
430
434
|
const orderedQuery = args.sortBy
|
|
431
435
|
? indexedQuery.order(args.sortBy.direction === "desc" ? "desc" : "asc")
|
|
432
436
|
: indexedQuery;
|
|
437
|
+
if (!usableIndex && indexFields?.length) {
|
|
438
|
+
// eslint-disable-next-line no-console
|
|
439
|
+
console.warn(
|
|
440
|
+
stripIndent`
|
|
441
|
+
Querying without an index on table "${args.model}".
|
|
442
|
+
This can cause performance issues, and may hit the document read limit.
|
|
443
|
+
To fix, add an index that begins with the following fields in order:
|
|
444
|
+
[${indexFields.join(", ")}]
|
|
445
|
+
`
|
|
446
|
+
);
|
|
447
|
+
}
|
|
433
448
|
const filteredQuery = orderedQuery.filterWith(async (doc) => {
|
|
434
|
-
if (!
|
|
435
|
-
//
|
|
436
|
-
console.warn(
|
|
437
|
-
stripIndent`
|
|
438
|
-
Querying without an index on table "${args.model}".
|
|
439
|
-
This can cause performance issues, and may hit the document read limit.
|
|
440
|
-
To fix, add an index that begins with the following fields in order:
|
|
441
|
-
[${indexFields.join(", ")}]
|
|
442
|
-
`
|
|
443
|
-
);
|
|
444
|
-
// No index, handle all where clauses statically.
|
|
449
|
+
if (!usableIndex) {
|
|
450
|
+
// No usable index, handle all where clauses statically.
|
|
445
451
|
return filterByWhere(doc, args.where);
|
|
446
452
|
}
|
|
447
453
|
return filterByWhere(
|
|
@@ -521,7 +527,7 @@ export const paginate = async <
|
|
|
521
527
|
// Apply all other clauses as static filters to our 0 or 1 result.
|
|
522
528
|
if (filterByWhere(doc, args.where, (w) => w !== uniqueWhere)) {
|
|
523
529
|
return {
|
|
524
|
-
page: [
|
|
530
|
+
page: [selectFields(doc, args.select)].filter(Boolean) as Doc[],
|
|
525
531
|
isDone: true,
|
|
526
532
|
continueCursor: "",
|
|
527
533
|
};
|
|
@@ -559,28 +565,31 @@ export const paginate = async <
|
|
|
559
565
|
.filter((doc) => filterByWhere(doc, args.where, (w) => w !== inWhere));
|
|
560
566
|
|
|
561
567
|
return {
|
|
562
|
-
page: filteredDocs
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
if (args.sortBy) {
|
|
569
|
-
const aValue = a[args.sortBy.field as keyof typeof a];
|
|
570
|
-
const bValue = b[args.sortBy.field as keyof typeof b];
|
|
571
|
-
if (aValue === bValue) {
|
|
572
|
-
return 0;
|
|
568
|
+
page: filteredDocs
|
|
569
|
+
.sort((a, b) => {
|
|
570
|
+
if (args.sortBy?.field === "createdAt") {
|
|
571
|
+
return args.sortBy.direction === "asc"
|
|
572
|
+
? (a._creationTime as number) - (b._creationTime as number)
|
|
573
|
+
: (b._creationTime as number) - (a._creationTime as number);
|
|
573
574
|
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
575
|
+
if (args.sortBy) {
|
|
576
|
+
const aValue = a[args.sortBy.field as keyof typeof a];
|
|
577
|
+
const bValue = b[args.sortBy.field as keyof typeof b];
|
|
578
|
+
if (aValue === bValue) {
|
|
579
|
+
return 0;
|
|
580
|
+
}
|
|
581
|
+
return args.sortBy.direction === "asc"
|
|
582
|
+
? aValue! > bValue!
|
|
583
|
+
? 1
|
|
584
|
+
: -1
|
|
585
|
+
: aValue! > bValue!
|
|
586
|
+
? -1
|
|
587
|
+
: 1;
|
|
588
|
+
}
|
|
589
|
+
return 0;
|
|
590
|
+
})
|
|
591
|
+
.map((doc) => selectFields(doc, args.select))
|
|
592
|
+
.flatMap((doc) => (doc ? [doc] : [])) as Doc[],
|
|
584
593
|
isDone: true,
|
|
585
594
|
continueCursor: "",
|
|
586
595
|
};
|
|
@@ -605,9 +614,7 @@ export const paginate = async <
|
|
|
605
614
|
).paginate(paginationOpts);
|
|
606
615
|
return {
|
|
607
616
|
...result,
|
|
608
|
-
page:
|
|
609
|
-
selectFields(doc, args.select)
|
|
610
|
-
),
|
|
617
|
+
page: result.page.map((doc) => selectFields(doc, args.select)),
|
|
611
618
|
};
|
|
612
619
|
}
|
|
613
620
|
|
|
@@ -615,7 +622,7 @@ export const paginate = async <
|
|
|
615
622
|
const result = await query.paginate(paginationOpts);
|
|
616
623
|
return {
|
|
617
624
|
...result,
|
|
618
|
-
page:
|
|
625
|
+
page: result.page.map((doc) => selectFields(doc, args.select)),
|
|
619
626
|
};
|
|
620
627
|
};
|
|
621
628
|
|
|
@@ -1,83 +1,11 @@
|
|
|
1
1
|
/// <reference types="vite/client" />
|
|
2
2
|
|
|
3
3
|
import { describe } from "vitest";
|
|
4
|
-
import type { runAdapterTest } from "better-auth/adapters/test";
|
|
5
4
|
import { convexTest } from "convex-test";
|
|
6
5
|
import { api } from "../component/_generated/api.js";
|
|
7
|
-
import schema from "../component/schema.js";
|
|
8
|
-
import { createClient } from "./create-client.js";
|
|
9
|
-
import type { DataModel } from "../component/_generated/dataModel.js";
|
|
10
|
-
import type { BetterAuthOptions } from "better-auth/types";
|
|
11
|
-
import type { GenericCtx } from "./index.js";
|
|
12
|
-
|
|
13
|
-
export const getAdapter: (
|
|
14
|
-
ctx: GenericCtx<DataModel>
|
|
15
|
-
) => Parameters<typeof runAdapterTest>[0]["getAdapter"] =
|
|
16
|
-
(ctx: GenericCtx<DataModel>) =>
|
|
17
|
-
async (opts?: Omit<BetterAuthOptions, "database">) => {
|
|
18
|
-
const authComponent = createClient<DataModel>(api as any, {
|
|
19
|
-
verbose: false,
|
|
20
|
-
});
|
|
21
|
-
const adapterFactory = authComponent.adapter(ctx);
|
|
22
|
-
return adapterFactory(opts ?? {});
|
|
23
|
-
};
|
|
6
|
+
import schema from "../component/testProfiles/schema.profile-plugin-table.js";
|
|
24
7
|
|
|
25
8
|
describe("Better Auth Adapter Tests", async () => {
|
|
26
|
-
const status = {
|
|
27
|
-
active: "active",
|
|
28
|
-
only: "only",
|
|
29
|
-
notSupported: "not supported",
|
|
30
|
-
} as const;
|
|
31
|
-
const tests: Record<string, (typeof status)[keyof typeof status]> = {
|
|
32
|
-
CREATE_MODEL: status.active,
|
|
33
|
-
CREATE_MODEL_SHOULD_ALWAYS_RETURN_AN_ID: status.active,
|
|
34
|
-
FIND_MODEL: status.active,
|
|
35
|
-
FIND_MODEL_WITHOUT_ID: status.active,
|
|
36
|
-
FIND_MODEL_WITH_SELECT: status.active,
|
|
37
|
-
// Requires a custom schema - we fake success by overriding custom user
|
|
38
|
-
// schema in the test adapter because this test creates a user that other
|
|
39
|
-
// tests rely on.
|
|
40
|
-
FIND_MODEL_WITH_MODIFIED_FIELD_NAME: status.active,
|
|
41
|
-
UPDATE_MODEL: status.active,
|
|
42
|
-
SHOULD_FIND_MANY: status.active,
|
|
43
|
-
SHOULD_FIND_MANY_WITH_WHERE: status.active,
|
|
44
|
-
SHOULD_FIND_MANY_WITH_OPERATORS: status.active,
|
|
45
|
-
SHOULD_WORK_WITH_REFERENCE_FIELDS: status.active,
|
|
46
|
-
SHOULD_FIND_MANY_WITH_NOT_IN_OPERATOR: status.active,
|
|
47
|
-
SHOULD_FIND_MANY_WITH_SORT_BY: status.active,
|
|
48
|
-
SHOULD_FIND_MANY_WITH_LIMIT: status.active,
|
|
49
|
-
SHOULD_UPDATE_WITH_MULTIPLE_WHERE: status.active,
|
|
50
|
-
DELETE_MODEL: status.active,
|
|
51
|
-
SHOULD_DELETE_MANY: status.active,
|
|
52
|
-
SHOULD_NOT_THROW_ON_DELETE_RECORD_NOT_FOUND: status.active,
|
|
53
|
-
SHOULD_NOT_THROW_ON_RECORD_NOT_FOUND: status.active,
|
|
54
|
-
SHOULD_FIND_MANY_WITH_CONTAINS_OPERATOR: status.active,
|
|
55
|
-
SHOULD_SEARCH_USERS_WITH_STARTS_WITH: status.active,
|
|
56
|
-
SHOULD_SEARCH_USERS_WITH_ENDS_WITH: status.active,
|
|
57
|
-
// Use local install and Convex paginated queries
|
|
58
|
-
SHOULD_FIND_MANY_WITH_OFFSET: status.notSupported,
|
|
59
|
-
// Convex generates ids on insert
|
|
60
|
-
SHOULD_PREFER_GENERATE_ID_IF_PROVIDED: status.notSupported,
|
|
61
|
-
// Transactions are inherent for auth.api and not possible for authClient
|
|
62
|
-
SHOULD_ROLLBACK_FAILING_TRANSACTION: status.notSupported,
|
|
63
|
-
SHOULD_RETURN_TRANSACTION_RESULT: status.notSupported,
|
|
64
|
-
SHOULD_FIND_MANY_WITH_CONNECTORS: status.active,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const disableTests = Object.fromEntries(
|
|
68
|
-
Object.entries(tests).map((entry, idx, arr) => {
|
|
69
|
-
if (arr.some((e) => e[1] === status.only)) {
|
|
70
|
-
return [entry[0], !(entry[1] === status.only)];
|
|
71
|
-
}
|
|
72
|
-
return [entry[0], !(entry[1] === status.active)];
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const t = convexTest(schema, import.meta.glob("../component/**/*.*s"));
|
|
77
|
-
await t.action(api.adapterTest.runTests, { disableTests });
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe("Convex Adapter Tests", async () => {
|
|
81
9
|
const t = convexTest(schema, import.meta.glob("../component/**/*.*s"));
|
|
82
|
-
await t.action(api.adapterTest.
|
|
10
|
+
await t.action(api.adapterTest.runTests, {});
|
|
83
11
|
});
|
package/src/client/adapter.ts
CHANGED
|
@@ -14,12 +14,14 @@ import type { SetOptional } from "type-fest";
|
|
|
14
14
|
import type defaultSchema from "../component/schema.js";
|
|
15
15
|
import type { Where } from "better-auth/types";
|
|
16
16
|
import { asyncMap } from "convex-helpers";
|
|
17
|
-
import { prop, sortBy
|
|
17
|
+
import { prop, sortBy } from "remeda";
|
|
18
18
|
import { isRunMutationCtx } from "../utils/index.js";
|
|
19
19
|
import type { Doc, TableNames } from "../component/_generated/dataModel.js";
|
|
20
20
|
import type { ComponentApi } from "../component/_generated/component.js";
|
|
21
21
|
import type { AuthFunctions, GenericCtx, Triggers } from "./index.js";
|
|
22
22
|
|
|
23
|
+
let didWarnExperimentalJoinsUnsupported = false;
|
|
24
|
+
|
|
23
25
|
const handlePagination = async (
|
|
24
26
|
next: ({
|
|
25
27
|
paginationOpts,
|
|
@@ -102,6 +104,58 @@ const parseWhere = (
|
|
|
102
104
|
}) as ConvexCleanedWhere[];
|
|
103
105
|
};
|
|
104
106
|
|
|
107
|
+
type DocWithFlexibleId = {
|
|
108
|
+
_id?: string | null;
|
|
109
|
+
id?: string | null;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const getDocId = (doc: DocWithFlexibleId) => {
|
|
113
|
+
if (doc?._id !== undefined && doc?._id !== null) {
|
|
114
|
+
return String(doc._id);
|
|
115
|
+
}
|
|
116
|
+
if (doc?.id !== undefined && doc?.id !== null) {
|
|
117
|
+
return String(doc.id);
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const dedupeDocsById = <T extends DocWithFlexibleId>(docs: T[]) => {
|
|
123
|
+
const seen = new Set<string>();
|
|
124
|
+
const deduped: T[] = [];
|
|
125
|
+
for (const doc of docs) {
|
|
126
|
+
const id = getDocId(doc);
|
|
127
|
+
if (!id) {
|
|
128
|
+
deduped.push(doc);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (seen.has(id)) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
seen.add(id);
|
|
135
|
+
deduped.push(doc);
|
|
136
|
+
}
|
|
137
|
+
return deduped;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const selectDocFields = (
|
|
141
|
+
doc: DocWithFlexibleId & Record<string, unknown>,
|
|
142
|
+
select?: string[]
|
|
143
|
+
) => {
|
|
144
|
+
if (!select?.length) {
|
|
145
|
+
return doc;
|
|
146
|
+
}
|
|
147
|
+
return select.reduce(
|
|
148
|
+
(acc, field) => {
|
|
149
|
+
// Better Auth may request "id" while Convex stores it as "_id".
|
|
150
|
+
// Keep "_id" so Better Auth output mapping can translate to "id".
|
|
151
|
+
const sourceField = field === "id" && "_id" in doc ? "_id" : field;
|
|
152
|
+
acc[sourceField] = doc[sourceField];
|
|
153
|
+
return acc;
|
|
154
|
+
},
|
|
155
|
+
{} as Record<string, unknown>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
105
159
|
export const convexAdapter = <
|
|
106
160
|
DataModel extends GenericDataModel,
|
|
107
161
|
Ctx extends GenericCtx<DataModel> = GenericActionCtx<DataModel>,
|
|
@@ -154,6 +208,41 @@ export const convexAdapter = <
|
|
|
154
208
|
adapter: ({ options }) => {
|
|
155
209
|
// Disable telemetry in all cases because it requires Node
|
|
156
210
|
options.telemetry = { enabled: false };
|
|
211
|
+
if (options.experimental?.joins) {
|
|
212
|
+
options.experimental = {
|
|
213
|
+
...options.experimental,
|
|
214
|
+
joins: false,
|
|
215
|
+
};
|
|
216
|
+
if (!didWarnExperimentalJoinsUnsupported) {
|
|
217
|
+
didWarnExperimentalJoinsUnsupported = true;
|
|
218
|
+
// eslint-disable-next-line no-console
|
|
219
|
+
console.warn(
|
|
220
|
+
"[convex-better-auth] Better Auth experimental.joins is not supported by the Convex adapter yet. Forcing experimental.joins = false."
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const collectIdsForOrWhere = async (data: {
|
|
226
|
+
model: string;
|
|
227
|
+
where: (Where & { join?: undefined })[];
|
|
228
|
+
}) => {
|
|
229
|
+
const results = await asyncMap(data.where, async (w) =>
|
|
230
|
+
handlePagination(
|
|
231
|
+
async ({ paginationOpts }) => {
|
|
232
|
+
return await ctx.runQuery(api.adapter.findMany, {
|
|
233
|
+
model: data.model as TableNames,
|
|
234
|
+
where: parseWhere(w),
|
|
235
|
+
paginationOpts,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
);
|
|
240
|
+
const ids = dedupeDocsById(results.flatMap((r) => r.docs))
|
|
241
|
+
.map((doc) => getDocId(doc))
|
|
242
|
+
.flatMap((id) => (id ? [id] : []));
|
|
243
|
+
return ids;
|
|
244
|
+
};
|
|
245
|
+
|
|
157
246
|
return {
|
|
158
247
|
id: "convex",
|
|
159
248
|
options: {
|
|
@@ -204,11 +293,14 @@ export const convexAdapter = <
|
|
|
204
293
|
}
|
|
205
294
|
|
|
206
295
|
if (data.where?.some((w) => w.connector === "OR")) {
|
|
296
|
+
// Always fetch full docs for OR unions so we can dedupe
|
|
297
|
+
// by id and sort/limit before trimming selected fields.
|
|
298
|
+
const { select: _ignoredSelect, ...queryData } = data;
|
|
207
299
|
const results = await asyncMap(data.where, async (w) =>
|
|
208
300
|
handlePagination(
|
|
209
301
|
async ({ paginationOpts }) => {
|
|
210
302
|
return await ctx.runQuery(api.adapter.findMany, {
|
|
211
|
-
...
|
|
303
|
+
...queryData,
|
|
212
304
|
model: data.model as TableNames,
|
|
213
305
|
where: parseWhere(w),
|
|
214
306
|
paginationOpts,
|
|
@@ -217,14 +309,17 @@ export const convexAdapter = <
|
|
|
217
309
|
{ limit: data.limit }
|
|
218
310
|
)
|
|
219
311
|
);
|
|
220
|
-
|
|
312
|
+
let docs = dedupeDocsById(results.flatMap((r) => r.docs));
|
|
221
313
|
if (data.sortBy) {
|
|
222
|
-
|
|
314
|
+
docs = sortBy(docs, [
|
|
223
315
|
prop(data.sortBy.field),
|
|
224
316
|
data.sortBy.direction,
|
|
225
317
|
]);
|
|
226
318
|
}
|
|
227
|
-
|
|
319
|
+
if (data.limit !== undefined) {
|
|
320
|
+
docs = docs.slice(0, data.limit);
|
|
321
|
+
}
|
|
322
|
+
return docs.map((doc) => selectDocFields(doc, data.select));
|
|
228
323
|
}
|
|
229
324
|
|
|
230
325
|
const result = await handlePagination(
|
|
@@ -253,7 +348,7 @@ export const convexAdapter = <
|
|
|
253
348
|
});
|
|
254
349
|
})
|
|
255
350
|
);
|
|
256
|
-
const docs =
|
|
351
|
+
const docs = dedupeDocsById(results.flatMap((r) => r.docs));
|
|
257
352
|
return docs.length;
|
|
258
353
|
}
|
|
259
354
|
|
|
@@ -271,7 +366,7 @@ export const convexAdapter = <
|
|
|
271
366
|
if (!("runMutation" in ctx)) {
|
|
272
367
|
throw new Error("ctx is not a mutation ctx");
|
|
273
368
|
}
|
|
274
|
-
if (data.where?.length
|
|
369
|
+
if (data.where?.length && !data.where.some((w) => w.connector === "OR")) {
|
|
275
370
|
const onUpdateHandle =
|
|
276
371
|
config.authFunctions?.onUpdate &&
|
|
277
372
|
config.triggers?.[data.model]?.onUpdate
|
|
@@ -320,6 +415,22 @@ export const convexAdapter = <
|
|
|
320
415
|
config.authFunctions.onDelete
|
|
321
416
|
)) as FunctionHandle<"mutation">)
|
|
322
417
|
: undefined;
|
|
418
|
+
if (data.where?.some((w) => w.connector === "OR")) {
|
|
419
|
+
const ids = await collectIdsForOrWhere({
|
|
420
|
+
model: data.model as string,
|
|
421
|
+
where: data.where,
|
|
422
|
+
});
|
|
423
|
+
await asyncMap(ids, async (id) => {
|
|
424
|
+
await ctx.runMutation(api.adapter.deleteOne, {
|
|
425
|
+
input: {
|
|
426
|
+
model: data.model as TableNames,
|
|
427
|
+
where: [{ field: "_id", operator: "eq", value: id }],
|
|
428
|
+
},
|
|
429
|
+
onDeleteHandle: onDeleteHandle,
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
return ids.length;
|
|
433
|
+
}
|
|
323
434
|
const result = await handlePagination(async ({ paginationOpts }) => {
|
|
324
435
|
return await ctx.runMutation(api.adapter.deleteMany, {
|
|
325
436
|
input: {
|
|
@@ -344,6 +455,30 @@ export const convexAdapter = <
|
|
|
344
455
|
config.authFunctions.onUpdate
|
|
345
456
|
)) as FunctionHandle<"mutation">)
|
|
346
457
|
: undefined;
|
|
458
|
+
if (data.where?.some((w) => w.connector === "OR")) {
|
|
459
|
+
const ids = await collectIdsForOrWhere({
|
|
460
|
+
model: data.model as string,
|
|
461
|
+
where: data.where,
|
|
462
|
+
});
|
|
463
|
+
if (!ids.length) {
|
|
464
|
+
return 0;
|
|
465
|
+
}
|
|
466
|
+
const result = await handlePagination(
|
|
467
|
+
async ({ paginationOpts }) => {
|
|
468
|
+
return await ctx.runMutation(api.adapter.updateMany, {
|
|
469
|
+
input: {
|
|
470
|
+
model: data.model as TableNames,
|
|
471
|
+
where: [{ field: "_id", operator: "in", value: ids }],
|
|
472
|
+
update: data.update,
|
|
473
|
+
},
|
|
474
|
+
paginationOpts,
|
|
475
|
+
onUpdateHandle: onUpdateHandle,
|
|
476
|
+
});
|
|
477
|
+
},
|
|
478
|
+
{ limit: ids.length }
|
|
479
|
+
);
|
|
480
|
+
return result.count ?? 0;
|
|
481
|
+
}
|
|
347
482
|
const result = await handlePagination(async ({ paginationOpts }) => {
|
|
348
483
|
return await ctx.runMutation(api.adapter.updateMany, {
|
|
349
484
|
input: {
|