@better-auth/test-utils 1.7.0-rc.1 → 1.7.0-rc.2

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.
@@ -3,7 +3,6 @@ import { Account, Session, User, Verification } from "@better-auth/core/db";
3
3
  import { DBAdapter } from "@better-auth/core/db/adapter";
4
4
  import { Auth } from "better-auth";
5
5
  import { BetterAuthOptions } from "@better-auth/core";
6
-
7
6
  //#region src/adapter/create-test-suite.d.ts
8
7
  /**
9
8
  * Test entry type that supports both callback and object formats.
@@ -1,4 +1,4 @@
1
- import { getAuthTables } from "@better-auth/core/db";
1
+ import { createLocalAccountIssuer, getAuthTables } from "@better-auth/core/db";
2
2
  import { createAdapterFactory, deepmerge, initGetDefaultModelName } from "@better-auth/core/db/adapter";
3
3
  import { TTY_COLORS } from "@better-auth/core/env";
4
4
  import { generateId } from "@better-auth/core/utils/id";
@@ -229,7 +229,8 @@ const createTestSuite = (suiteName, config, tests) => {
229
229
  id,
230
230
  createdAt: randomDate,
231
231
  updatedAt: /* @__PURE__ */ new Date(),
232
- accountId: generateId(),
232
+ issuer: createLocalAccountIssuer("test"),
233
+ providerAccountId: generateId(),
233
234
  providerId: "test",
234
235
  userId: generateId(),
235
236
  accessToken: generateId(),
@@ -1,7 +1,6 @@
1
1
  import { Logger } from "../test-adapter.mjs";
2
2
  import { TestSuiteStats } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
3
+ import "../../adapter.mjs";
5
4
  //#region src/adapter/suites/auth-flow.d.ts
6
5
  /**
7
6
  * This test suite tests basic authentication flow using the adapter.
@@ -13,11 +12,11 @@ declare const authFlowTestSuite: (options?: ({
13
12
  } & {
14
13
  showDB?: () => Promise<void>;
15
14
  }) | undefined) => (helpers: {
16
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
15
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
17
16
  log: Logger;
18
17
  adapterDisplayName: string;
19
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
20
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
18
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
19
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
21
20
  cleanup: () => Promise<void>;
22
21
  runMigrations: () => Promise<void>;
23
22
  prefixTests?: string | undefined;
@@ -24,8 +24,7 @@ const authFlowTestSuite = createTestSuite("auth-flow", { defaultBetterAuthOption
24
24
  name: user.name,
25
25
  image: user.image || ""
26
26
  } });
27
- const end = Date.now();
28
- console.log(`signUpEmail took ${end - start}ms (without hashing)`);
27
+ console.log(`signUpEmail took ${Date.now() - start}ms (without hashing)`);
29
28
  expect(result.user).toBeDefined();
30
29
  expect(result.user.email).toBe(user.email);
31
30
  expect(result.user.name).toBe(user.name);
@@ -49,11 +48,13 @@ const authFlowTestSuite = createTestSuite("auth-flow", { defaultBetterAuthOption
49
48
  email: user.email,
50
49
  password
51
50
  } });
52
- const end = Date.now();
53
- console.log(`signInEmail took ${end - start}ms (without hashing)`);
51
+ console.log(`signInEmail took ${Date.now() - start}ms (without hashing)`);
54
52
  expect(result.user).toBeDefined();
55
53
  expect(result.user.id).toBe(signUpResult.user.id);
56
54
  },
55
+ /**
56
+ * @see https://github.com/better-auth/better-auth/issues/10054
57
+ */
57
58
  "should reset password with a single-use token": async () => {
58
59
  let resetToken = "";
59
60
  await modifyBetterAuthOptions({ emailAndPassword: {
@@ -115,8 +116,7 @@ const authFlowTestSuite = createTestSuite("auth-flow", { defaultBetterAuthOption
115
116
  setCookieToHeader(headers)({ response });
116
117
  const start = Date.now();
117
118
  const result = await auth.api.getSession({ headers });
118
- const end = Date.now();
119
- console.log(`getSession took ${end - start}ms`);
119
+ console.log(`getSession took ${Date.now() - start}ms`);
120
120
  const signUpResult = await response.json();
121
121
  signUpResult.user.createdAt = new Date(signUpResult.user.createdAt);
122
122
  signUpResult.user.updatedAt = new Date(signUpResult.user.updatedAt);
@@ -1,23 +1,22 @@
1
1
  import { Logger } from "../test-adapter.mjs";
2
2
  import { TestSuiteStats, createTestSuite } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
3
+ import "../../adapter.mjs";
5
4
  //#region src/adapter/suites/basic.d.ts
6
5
  /**
7
6
  * This test suite tests the basic CRUD operations of the adapter.
8
7
  */
9
8
  declare const normalTestSuite: (options?: ({
10
- disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should use generateId if provided" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean> & {
9
+ disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should enforce the issuer-scoped account identity key" | "create - should use generateId if provided" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean> & {
11
10
  ALL?: boolean;
12
11
  }> | undefined;
13
12
  } & {
14
13
  showDB?: () => Promise<void>;
15
14
  }) | undefined) => (helpers: {
16
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
15
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
17
16
  log: Logger;
18
17
  adapterDisplayName: string;
19
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
20
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
18
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
19
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
21
20
  cleanup: () => Promise<void>;
22
21
  runMigrations: () => Promise<void>;
23
22
  prefixTests?: string | undefined;
@@ -25,21 +24,14 @@ declare const normalTestSuite: (options?: ({
25
24
  customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
26
25
  transformIdOutput?: ((id: any) => string | undefined) | undefined;
27
26
  }) => Promise<void>;
28
- declare const getNormalTestSuiteTests: ({
29
- adapter,
30
- generate,
31
- insertRandom,
32
- modifyBetterAuthOptions,
33
- sortModels,
34
- customIdGenerator,
35
- getBetterAuthOptions,
36
- transformGeneratedModel,
37
- transformIdOutput
38
- }: Parameters<Parameters<typeof createTestSuite>[2]>[0], debugTools?: {
27
+ declare const getNormalTestSuiteTests: ({ adapter, generate, insertRandom, modifyBetterAuthOptions, sortModels, customIdGenerator, getBetterAuthOptions, transformGeneratedModel, transformIdOutput }: Parameters<Parameters<typeof createTestSuite>[2]>[0], debugTools?: {
39
28
  showDB?: () => Promise<void>;
40
29
  }) => {
41
30
  "create - should create a model": () => Promise<void>;
42
31
  "create - should always return an id": () => Promise<void>;
32
+ "create - should enforce the issuer-scoped account identity key": ({ skip }: {
33
+ skip: (note?: string | undefined) => never;
34
+ }) => Promise<void>;
43
35
  "create - should use generateId if provided": () => Promise<void>;
44
36
  "create - should return null for nullable foreign keys": {
45
37
  migrateBetterAuth: {
@@ -207,6 +199,6 @@ declare const getNormalTestSuiteTests: ({
207
199
  "update - should return updated record when where condition uses null value": () => Promise<void>;
208
200
  "update - should return null when a multi-predicate where matches no row": () => Promise<void>;
209
201
  };
210
- declare const enableJoinTests: Partial<Record<"create - should create a model" | "create - should always return an id" | "create - should use generateId if provided" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean>>;
202
+ declare const enableJoinTests: Partial<Record<"create - should create a model" | "create - should always return an id" | "create - should enforce the issuer-scoped account identity key" | "create - should use generateId if provided" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean>>;
211
203
  //#endregion
212
204
  export { enableJoinTests, getNormalTestSuiteTests, normalTestSuite };
@@ -6,12 +6,11 @@ import { organization } from "better-auth/plugins/organization";
6
6
  * This test suite tests the basic CRUD operations of the adapter.
7
7
  */
8
8
  const normalTestSuite = createTestSuite("normal", {}, (helpers, debugTools) => {
9
- const tests = getNormalTestSuiteTests(helpers, debugTools);
10
9
  return {
11
10
  "init - tests": async () => {
12
11
  expect(helpers.getBetterAuthOptions().advanced?.database?.generateId !== "serial").toBeTruthy();
13
12
  },
14
- ...tests
13
+ ...getNormalTestSuiteTests(helpers, debugTools)
15
14
  };
16
15
  });
17
16
  const getNormalTestSuiteTests = ({ adapter, generate, insertRandom, modifyBetterAuthOptions, sortModels, customIdGenerator, getBetterAuthOptions, transformGeneratedModel, transformIdOutput }, debugTools) => {
@@ -38,6 +37,59 @@ const getNormalTestSuiteTests = ({ adapter, generate, insertRandom, modifyBetter
38
37
  expect(res).toHaveProperty("id");
39
38
  expect(typeof res.id).toEqual("string");
40
39
  },
40
+ "create - should enforce the issuer-scoped account identity key": async ({ skip }) => {
41
+ if (adapter.options?.adapterConfig.adapterId === "memory") {
42
+ skip("The memory adapter does not implement database indexes");
43
+ return;
44
+ }
45
+ const firstUser = await adapter.create({
46
+ model: "user",
47
+ data: await generate("user"),
48
+ forceAllowId: true
49
+ });
50
+ const secondUser = await adapter.create({
51
+ model: "user",
52
+ data: await generate("user"),
53
+ forceAllowId: true
54
+ });
55
+ const firstAccount = {
56
+ ...await generate("account"),
57
+ userId: firstUser.id,
58
+ providerId: "issuer-key-first-alias",
59
+ issuer: "https://issuer-key.example.com",
60
+ providerAccountId: "shared-subject"
61
+ };
62
+ await adapter.create({
63
+ model: "account",
64
+ data: firstAccount,
65
+ forceAllowId: true
66
+ });
67
+ await expect(adapter.create({
68
+ model: "account",
69
+ data: {
70
+ ...await generate("account"),
71
+ userId: secondUser.id,
72
+ providerId: "issuer-key-second-alias",
73
+ issuer: firstAccount.issuer,
74
+ providerAccountId: firstAccount.providerAccountId
75
+ },
76
+ forceAllowId: true
77
+ })).rejects.toThrow();
78
+ await expect(adapter.create({
79
+ model: "account",
80
+ data: {
81
+ ...await generate("account"),
82
+ userId: secondUser.id,
83
+ providerId: "issuer-key-other-issuer",
84
+ issuer: "https://other-issuer-key.example.com",
85
+ providerAccountId: firstAccount.providerAccountId
86
+ },
87
+ forceAllowId: true
88
+ })).resolves.toMatchObject({
89
+ issuer: "https://other-issuer-key.example.com",
90
+ providerAccountId: "shared-subject"
91
+ });
92
+ },
41
93
  "create - should use generateId if provided": async () => {
42
94
  const ID = await customIdGenerator?.() || "MOCK-ID";
43
95
  await modifyBetterAuthOptions({ advanced: { database: { generateId: () => ID } } }, false);
@@ -1843,6 +1895,9 @@ const getNormalTestSuiteTests = ({ adapter, generate, insertRandom, modifyBetter
1843
1895
  }]
1844
1896
  })).resolves.not.toThrow();
1845
1897
  },
1898
+ /**
1899
+ * @see https://github.com/better-auth/better-auth/issues/8313
1900
+ */
1846
1901
  "delete - should delete by non-unique field": async () => {
1847
1902
  const [verification] = await insertRandom("verification");
1848
1903
  await adapter.delete({
@@ -1,6 +1,3 @@
1
- import * as better_auth0 from "better-auth";
2
- import * as _better_auth_test_utils_adapter0 from "@better-auth/test-utils/adapter";
3
-
4
1
  //#region src/adapter/suites/case-insensitive.d.ts
5
2
  /**
6
3
  * Test suite for case-insensitive string operations across adapters.
@@ -11,15 +8,15 @@ declare const caseInsensitiveTestSuite: (options?: {
11
8
  ALL?: boolean;
12
9
  }> | undefined;
13
10
  } | undefined) => (helpers: {
14
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
15
- log: _better_auth_test_utils_adapter0.Logger;
11
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
12
+ log: import("@better-auth/test-utils/adapter").Logger;
16
13
  adapterDisplayName: string;
17
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
18
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
14
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
15
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
19
16
  cleanup: () => Promise<void>;
20
17
  runMigrations: () => Promise<void>;
21
18
  prefixTests?: string | undefined;
22
- onTestFinish: (stats: _better_auth_test_utils_adapter0.TestSuiteStats) => Promise<void>;
19
+ onTestFinish: (stats: import("@better-auth/test-utils/adapter").TestSuiteStats) => Promise<void>;
23
20
  customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
24
21
  transformIdOutput?: ((id: any) => string | undefined) | undefined;
25
22
  }) => Promise<void>;
@@ -4,4 +4,5 @@ import { caseInsensitiveTestSuite } from "./case-insensitive.mjs";
4
4
  import { joinsTestSuite } from "./joins.mjs";
5
5
  import { numberIdTestSuite } from "./number-id.mjs";
6
6
  import { transactionsTestSuite } from "./transactions.mjs";
7
- import { uuidTestSuite } from "./uuid.mjs";
7
+ import { uuidTestSuite } from "./uuid.mjs";
8
+ export { authFlowTestSuite, caseInsensitiveTestSuite, enableJoinTests, getNormalTestSuiteTests, joinsTestSuite, normalTestSuite, numberIdTestSuite, transactionsTestSuite, uuidTestSuite };
@@ -0,0 +1,23 @@
1
+ import { Logger } from "../test-adapter.mjs";
2
+ import { TestSuiteStats } from "../create-test-suite.mjs";
3
+ import "../../adapter.mjs";
4
+ //#region src/adapter/suites/joins.d.ts
5
+ declare const joinsTestSuite: (options?: {
6
+ disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should enforce the issuer-scoped account identity key" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean> & {
7
+ ALL?: boolean;
8
+ }> | undefined;
9
+ } | undefined) => (helpers: {
10
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
11
+ log: Logger;
12
+ adapterDisplayName: string;
13
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
14
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
15
+ cleanup: () => Promise<void>;
16
+ runMigrations: () => Promise<void>;
17
+ prefixTests?: string | undefined;
18
+ onTestFinish: (stats: TestSuiteStats) => Promise<void>;
19
+ customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
20
+ transformIdOutput?: ((id: any) => string | undefined) | undefined;
21
+ }) => Promise<void>;
22
+ //#endregion
23
+ export { joinsTestSuite };
@@ -3,14 +3,14 @@ import { getNormalTestSuiteTests } from "./basic.mjs";
3
3
  import { expect } from "vitest";
4
4
  //#region src/adapter/suites/joins.ts
5
5
  const joinsTestSuite = createTestSuite("joins", {
6
- defaultBetterAuthOptions: { experimental: { joins: true } },
6
+ defaultBetterAuthOptions: { advanced: { database: { joins: true } } },
7
7
  alwaysMigrate: true,
8
8
  prefixTests: "joins"
9
9
  }, (helpers) => {
10
10
  const { "create - should use generateId if provided": _, ...normalTests } = getNormalTestSuiteTests({ ...helpers });
11
11
  return {
12
12
  "init - tests": async () => {
13
- expect(helpers.getBetterAuthOptions().experimental?.joins).toBe(true);
13
+ expect(helpers.getBetterAuthOptions().advanced?.database?.joins).toBe(true);
14
14
  },
15
15
  ...normalTests
16
16
  };
@@ -0,0 +1,23 @@
1
+ import { Logger } from "../test-adapter.mjs";
2
+ import { TestSuiteStats } from "../create-test-suite.mjs";
3
+ import "../../adapter.mjs";
4
+ //#region src/adapter/suites/number-id.d.ts
5
+ declare const numberIdTestSuite: (options?: {
6
+ disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should enforce the issuer-scoped account identity key" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row" | "create - should return a number id", boolean> & {
7
+ ALL?: boolean;
8
+ }> | undefined;
9
+ } | undefined) => (helpers: {
10
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
11
+ log: Logger;
12
+ adapterDisplayName: string;
13
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
14
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
15
+ cleanup: () => Promise<void>;
16
+ runMigrations: () => Promise<void>;
17
+ prefixTests?: string | undefined;
18
+ onTestFinish: (stats: TestSuiteStats) => Promise<void>;
19
+ customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
20
+ transformIdOutput?: ((id: any) => string | undefined) | undefined;
21
+ }) => Promise<void>;
22
+ //#endregion
23
+ export { numberIdTestSuite };
@@ -1,7 +1,6 @@
1
1
  import { Logger } from "../test-adapter.mjs";
2
2
  import { TestSuiteStats } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
3
+ import "../../adapter.mjs";
5
4
  //#region src/adapter/suites/transactions.d.ts
6
5
  /**
7
6
  * This test suite tests the transaction functionality of the adapter.
@@ -11,11 +10,11 @@ declare const transactionsTestSuite: (options?: {
11
10
  ALL?: boolean;
12
11
  }> | undefined;
13
12
  } | undefined) => (helpers: {
14
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
13
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
15
14
  log: Logger;
16
15
  adapterDisplayName: string;
17
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
18
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
16
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
17
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
19
18
  cleanup: () => Promise<void>;
20
19
  runMigrations: () => Promise<void>;
21
20
  prefixTests?: string | undefined;
@@ -0,0 +1,23 @@
1
+ import { Logger } from "../test-adapter.mjs";
2
+ import { TestSuiteStats } from "../create-test-suite.mjs";
3
+ import "../../adapter.mjs";
4
+ //#region src/adapter/suites/uuid.d.ts
5
+ declare const uuidTestSuite: (options?: {
6
+ disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should enforce the issuer-scoped account identity key" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row" | "create - should return a uuid" | "findOne - should find a model using a uuid", boolean> & {
7
+ ALL?: boolean;
8
+ }> | undefined;
9
+ } | undefined) => (helpers: {
10
+ adapter: () => Promise<import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>>;
11
+ log: Logger;
12
+ adapterDisplayName: string;
13
+ getBetterAuthOptions: () => import("better-auth").BetterAuthOptions;
14
+ modifyBetterAuthOptions: (options: import("better-auth").BetterAuthOptions) => Promise<import("better-auth").BetterAuthOptions>;
15
+ cleanup: () => Promise<void>;
16
+ runMigrations: () => Promise<void>;
17
+ prefixTests?: string | undefined;
18
+ onTestFinish: (stats: TestSuiteStats) => Promise<void>;
19
+ customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
20
+ transformIdOutput?: ((id: any) => string | undefined) | undefined;
21
+ }) => Promise<void>;
22
+ //#endregion
23
+ export { uuidTestSuite };
@@ -1,7 +1,6 @@
1
1
  import { createTestSuite } from "./create-test-suite.mjs";
2
2
  import { DBAdapter } from "@better-auth/core/db/adapter";
3
3
  import { Awaitable, BetterAuthOptions } from "@better-auth/core";
4
-
5
4
  //#region src/adapter/test-adapter.d.ts
6
5
  type Logger = {
7
6
  info: (...args: any[]) => void;
@@ -10,17 +9,7 @@ type Logger = {
10
9
  error: (...args: any[]) => void;
11
10
  debug: (...args: any[]) => void;
12
11
  };
13
- declare const testAdapter: ({
14
- adapter: getAdapter,
15
- runMigrations,
16
- overrideBetterAuthOptions,
17
- additionalCleanups,
18
- tests,
19
- prefixTests,
20
- onFinish,
21
- customIdGenerator,
22
- transformIdOutput
23
- }: {
12
+ declare const testAdapter: ({ adapter: getAdapter, runMigrations, overrideBetterAuthOptions, additionalCleanups, tests, prefixTests, onFinish, customIdGenerator, transformIdOutput }: {
24
13
  /**
25
14
  * A function that will return the adapter instance to test with.
26
15
  *
@@ -5,10 +5,12 @@ import { getAuthTables } from "better-auth/db";
5
5
  //#region src/adapter/test-adapter.ts
6
6
  const testAdapter = async ({ adapter: getAdapter, runMigrations, overrideBetterAuthOptions, additionalCleanups, tests, prefixTests, onFinish, customIdGenerator, transformIdOutput }) => {
7
7
  const defaultBAOptions = {};
8
- let betterAuthOptions = {
9
- ...defaultBAOptions,
10
- ...overrideBetterAuthOptions?.(defaultBAOptions) || {}
11
- };
8
+ let betterAuthOptions = (() => {
9
+ return {
10
+ ...defaultBAOptions,
11
+ ...overrideBetterAuthOptions?.(defaultBAOptions) || {}
12
+ };
13
+ })();
12
14
  let adapter = (await getAdapter(betterAuthOptions))(betterAuthOptions);
13
15
  const adapterName = adapter.options?.adapterConfig.adapterName;
14
16
  const adapterId = adapter.options?.adapterConfig.adapterId || adapter.id;
@@ -19,13 +21,15 @@ const testAdapter = async ({ adapter: getAdapter, runMigrations, overrideBetterA
19
21
  /**
20
22
  * A helper function to log to the console.
21
23
  */
22
- const log = {
23
- info: (...args) => console.log(`${TTY_COLORS.fg.blue}INFO ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
24
- success: (...args) => console.log(`${TTY_COLORS.fg.green}SUCCESS${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
25
- warn: (...args) => console.log(`${TTY_COLORS.fg.yellow}WARN ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
26
- error: (...args) => console.log(`${TTY_COLORS.fg.red}ERROR ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
27
- debug: (...args) => console.log(`${TTY_COLORS.fg.magenta}DEBUG ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args)
28
- };
24
+ const log = (() => {
25
+ return {
26
+ info: (...args) => console.log(`${TTY_COLORS.fg.blue}INFO ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
27
+ success: (...args) => console.log(`${TTY_COLORS.fg.green}SUCCESS${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
28
+ warn: (...args) => console.log(`${TTY_COLORS.fg.yellow}WARN ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
29
+ error: (...args) => console.log(`${TTY_COLORS.fg.red}ERROR ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args),
30
+ debug: (...args) => console.log(`${TTY_COLORS.fg.magenta}DEBUG ${TTY_COLORS.reset} [${adapterDisplayName}]`, ...args)
31
+ };
32
+ })();
29
33
  /**
30
34
  * Cleanup function to remove all rows from the database.
31
35
  */
@@ -1,10 +1,11 @@
1
- import { Logger, testAdapter } from "./test-adapter.mjs";
2
- import { InsertRandomFn, TestEntry, TestSuiteStats, createTestSuite } from "./create-test-suite.mjs";
3
- import { authFlowTestSuite } from "./suites/auth-flow.mjs";
4
- import { enableJoinTests, getNormalTestSuiteTests, normalTestSuite } from "./suites/basic.mjs";
5
- import { caseInsensitiveTestSuite } from "./suites/case-insensitive.mjs";
6
- import { joinsTestSuite } from "./suites/joins.mjs";
7
- import { numberIdTestSuite } from "./suites/number-id.mjs";
8
- import { transactionsTestSuite } from "./suites/transactions.mjs";
9
- import { uuidTestSuite } from "./suites/uuid.mjs";
1
+ import { Logger, testAdapter } from "./adapter/test-adapter.mjs";
2
+ import { InsertRandomFn, TestEntry, TestSuiteStats, createTestSuite } from "./adapter/create-test-suite.mjs";
3
+ import { authFlowTestSuite } from "./adapter/suites/auth-flow.mjs";
4
+ import { enableJoinTests, getNormalTestSuiteTests, normalTestSuite } from "./adapter/suites/basic.mjs";
5
+ import { caseInsensitiveTestSuite } from "./adapter/suites/case-insensitive.mjs";
6
+ import { joinsTestSuite } from "./adapter/suites/joins.mjs";
7
+ import { numberIdTestSuite } from "./adapter/suites/number-id.mjs";
8
+ import { transactionsTestSuite } from "./adapter/suites/transactions.mjs";
9
+ import { uuidTestSuite } from "./adapter/suites/uuid.mjs";
10
+ import "./adapter/suites/index.mjs";
10
11
  export { type InsertRandomFn, type Logger, type TestEntry, type TestSuiteStats, authFlowTestSuite, caseInsensitiveTestSuite, createTestSuite, enableJoinTests, getNormalTestSuiteTests, joinsTestSuite, normalTestSuite, numberIdTestSuite, testAdapter, transactionsTestSuite, uuidTestSuite };
package/dist/adapter.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { createTestSuite } from "./create-test-suite.mjs";
2
- import { authFlowTestSuite } from "./suites/auth-flow.mjs";
3
- import { enableJoinTests, getNormalTestSuiteTests, normalTestSuite } from "./suites/basic.mjs";
4
- import { caseInsensitiveTestSuite } from "./suites/case-insensitive.mjs";
5
- import { joinsTestSuite } from "./suites/joins.mjs";
6
- import { numberIdTestSuite } from "./suites/number-id.mjs";
7
- import { transactionsTestSuite } from "./suites/transactions.mjs";
8
- import { uuidTestSuite } from "./suites/uuid.mjs";
9
- import { testAdapter } from "./test-adapter.mjs";
1
+ import { createTestSuite } from "./adapter/create-test-suite.mjs";
2
+ import { authFlowTestSuite } from "./adapter/suites/auth-flow.mjs";
3
+ import { enableJoinTests, getNormalTestSuiteTests, normalTestSuite } from "./adapter/suites/basic.mjs";
4
+ import { caseInsensitiveTestSuite } from "./adapter/suites/case-insensitive.mjs";
5
+ import { joinsTestSuite } from "./adapter/suites/joins.mjs";
6
+ import { numberIdTestSuite } from "./adapter/suites/number-id.mjs";
7
+ import { transactionsTestSuite } from "./adapter/suites/transactions.mjs";
8
+ import { uuidTestSuite } from "./adapter/suites/uuid.mjs";
9
+ import { testAdapter } from "./adapter/test-adapter.mjs";
10
10
  export { authFlowTestSuite, caseInsensitiveTestSuite, createTestSuite, enableJoinTests, getNormalTestSuiteTests, joinsTestSuite, normalTestSuite, numberIdTestSuite, testAdapter, transactionsTestSuite, uuidTestSuite };
@@ -0,0 +1,34 @@
1
+ //#region src/scim-lifecycle.d.ts
2
+ /** Observable lifecycle boundaries for database and application-state oracles. */
3
+ type SCIMLifecycleCheckpoint = "group-created" | "failed-add-rolled-back" | "member-added" | "okta-member-removed" | "entra-member-removed" | "member-restored" | "user-deactivated" | "user-reactivated" | "populated-user-deleted" | "user-reprovisioned" | "reprovisioned-member-added" | "populated-group-deleted" | "lifecycle-complete";
4
+ /** Input for the reusable SCIM black-box lifecycle contract. */
5
+ interface SCIMLifecycleOptions {
6
+ /** Better Auth origin exposed by a real HTTP listener. */
7
+ baseURL: string;
8
+ /** Bearer credential for the SCIM connection under test. */
9
+ token: string;
10
+ /** Stable suffix that isolates resources created by this execution. */
11
+ testId: string;
12
+ /** Optional harness control used to prove a failed Group mutation rolls back. */
13
+ projectionFailure?: {
14
+ enable: () => void;
15
+ disable: () => void;
16
+ };
17
+ /** Optional out-of-band oracle invoked after each verified HTTP boundary. */
18
+ onCheckpoint?: (checkpoint: SCIMLifecycleCheckpoint) => void | Promise<void>;
19
+ }
20
+ /** Identifiers created and deleted by a completed SCIM lifecycle. */
21
+ interface SCIMLifecycleResult {
22
+ userId: string;
23
+ groupId: string;
24
+ reprovisionedUserId: string;
25
+ userLocation: string;
26
+ groupLocation: string;
27
+ }
28
+ /**
29
+ * Executes one provider-shaped SCIM User and Group lifecycle exclusively over
30
+ * HTTP. The runner has no access to Better Auth APIs or database internals.
31
+ */
32
+ declare function runSCIMLifecycle(options: SCIMLifecycleOptions): Promise<SCIMLifecycleResult>;
33
+ //#endregion
34
+ export { SCIMLifecycleCheckpoint, SCIMLifecycleOptions, SCIMLifecycleResult, runSCIMLifecycle };
package/dist/scim.mjs ADDED
@@ -0,0 +1,393 @@
1
+ import { expect } from "vitest";
2
+ //#region src/scim-lifecycle.ts
3
+ const SCIM_MEDIA_TYPE = "application/scim+json";
4
+ const SCIM_USER_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:User";
5
+ const SCIM_GROUP_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:Group";
6
+ const SCIM_PATCH_SCHEMA = "urn:ietf:params:scim:api:messages:2.0:PatchOp";
7
+ const SCIM_LIST_SCHEMA = "urn:ietf:params:scim:api:messages:2.0:ListResponse";
8
+ const SCIM_ERROR_SCHEMA = "urn:ietf:params:scim:api:messages:2.0:Error";
9
+ async function readJson(response) {
10
+ return await response.json();
11
+ }
12
+ function expectSCIMResponse(response, status) {
13
+ expect(response.status).toBe(status);
14
+ if (status === 204) return;
15
+ expect(response.headers.get("content-type")?.split(";", 1)[0]).toBe(SCIM_MEDIA_TYPE);
16
+ }
17
+ async function expectSCIMErrorResponse(response, status) {
18
+ expectSCIMResponse(response, status);
19
+ const body = await readJson(response);
20
+ expect(body).toMatchObject({
21
+ schemas: [SCIM_ERROR_SCHEMA],
22
+ status: status.toString()
23
+ });
24
+ return body;
25
+ }
26
+ async function expectSCIMNoContent(response) {
27
+ expectSCIMResponse(response, 204);
28
+ expect(await response.text()).toBe("");
29
+ }
30
+ function createSCIMRequest(baseURL, token) {
31
+ return async (path, init = {}) => {
32
+ const headers = new Headers({
33
+ accept: SCIM_MEDIA_TYPE,
34
+ authorization: `Bearer ${token}`
35
+ });
36
+ if (init.body !== void 0) headers.set("content-type", SCIM_MEDIA_TYPE);
37
+ return fetch(`${baseURL}${path}`, {
38
+ method: init.method ?? "GET",
39
+ headers,
40
+ body: init.body === void 0 ? void 0 : JSON.stringify(init.body)
41
+ });
42
+ };
43
+ }
44
+ function userFilterPath(userName) {
45
+ return `/Users?${new URLSearchParams({ filter: `userName eq "${userName}"` }).toString()}`;
46
+ }
47
+ /**
48
+ * Executes one provider-shaped SCIM User and Group lifecycle exclusively over
49
+ * HTTP. The runner has no access to Better Auth APIs or database internals.
50
+ */
51
+ async function runSCIMLifecycle(options) {
52
+ const scimBaseURL = `${options.baseURL.replace(/\/$/, "")}/api/auth/scim/v2`;
53
+ const request = createSCIMRequest(scimBaseURL, options.token);
54
+ const checkpoint = async (value) => {
55
+ await options.onCheckpoint?.(value);
56
+ };
57
+ const userName = `${options.testId}.user@example.com`;
58
+ const email = `${options.testId}.primary@example.com`;
59
+ const userExternalId = `${options.testId}-directory-user`;
60
+ const groupExternalId = `${options.testId}-finance-admins`;
61
+ const userCreateBody = {
62
+ schemas: [SCIM_USER_SCHEMA],
63
+ externalId: userExternalId,
64
+ userName,
65
+ name: {
66
+ formatted: "Ada Lovelace",
67
+ givenName: "Ada",
68
+ familyName: "Lovelace"
69
+ },
70
+ displayName: "Ada Lovelace",
71
+ active: true,
72
+ emails: [{
73
+ value: email,
74
+ type: "work",
75
+ primary: true
76
+ }]
77
+ };
78
+ const unauthorized = await fetch(`${scimBaseURL}/Users`, { headers: { accept: SCIM_MEDIA_TYPE } });
79
+ await expectSCIMErrorResponse(unauthorized, 401);
80
+ expect(unauthorized.headers.get("www-authenticate")).toBe("Bearer realm=\"SCIM\"");
81
+ const discoveryResponse = await fetch(`${scimBaseURL}/ServiceProviderConfig`, { headers: { accept: SCIM_MEDIA_TYPE } });
82
+ expectSCIMResponse(discoveryResponse, 200);
83
+ expect(await readJson(discoveryResponse)).toMatchObject({
84
+ patch: { supported: true },
85
+ filter: { supported: true },
86
+ meta: {
87
+ resourceType: "ServiceProviderConfig",
88
+ location: `${scimBaseURL}/ServiceProviderConfig`
89
+ }
90
+ });
91
+ const initialListResponse = await request(userFilterPath(userName));
92
+ expectSCIMResponse(initialListResponse, 200);
93
+ expect(await readJson(initialListResponse)).toMatchObject({
94
+ schemas: [SCIM_LIST_SCHEMA],
95
+ totalResults: 0,
96
+ Resources: []
97
+ });
98
+ const createUserResponse = await request("/Users", {
99
+ method: "POST",
100
+ body: userCreateBody
101
+ });
102
+ expectSCIMResponse(createUserResponse, 201);
103
+ const createdUser = await readJson(createUserResponse);
104
+ const userLocation = `${scimBaseURL}/Users/${encodeURIComponent(createdUser.id)}`;
105
+ expect(createdUser).toMatchObject({
106
+ schemas: [SCIM_USER_SCHEMA],
107
+ externalId: userExternalId,
108
+ userName,
109
+ displayName: "Ada Lovelace",
110
+ active: true,
111
+ meta: {
112
+ resourceType: "User",
113
+ location: userLocation
114
+ }
115
+ });
116
+ expect(createUserResponse.headers.get("location")).toBe(userLocation);
117
+ expect(createUserResponse.headers.get("content-location")).toBe(userLocation);
118
+ const populatedListResponse = await request(userFilterPath(userName));
119
+ expectSCIMResponse(populatedListResponse, 200);
120
+ expect(await readJson(populatedListResponse)).toMatchObject({
121
+ totalResults: 1,
122
+ itemsPerPage: 1,
123
+ Resources: [{ id: createdUser.id }]
124
+ });
125
+ const replaceUserResponse = await request(`/Users/${encodeURIComponent(createdUser.id)}`, {
126
+ method: "PUT",
127
+ body: {
128
+ schemas: [SCIM_USER_SCHEMA],
129
+ externalId: userExternalId,
130
+ userName,
131
+ name: {
132
+ formatted: "Ada Byron",
133
+ givenName: "Ada",
134
+ familyName: "Byron"
135
+ },
136
+ displayName: "Ada Byron",
137
+ active: true,
138
+ emails: [{
139
+ value: email,
140
+ type: "work",
141
+ primary: true
142
+ }]
143
+ }
144
+ });
145
+ expectSCIMResponse(replaceUserResponse, 200);
146
+ expect(await readJson(replaceUserResponse)).toMatchObject({
147
+ id: createdUser.id,
148
+ externalId: userExternalId,
149
+ displayName: "Ada Byron",
150
+ active: true
151
+ });
152
+ const replacedUserResponse = await request(`/Users/${encodeURIComponent(createdUser.id)}`);
153
+ expectSCIMResponse(replacedUserResponse, 200);
154
+ const replacedUser = await readJson(replacedUserResponse);
155
+ expect(replacedUser).toMatchObject({
156
+ id: createdUser.id,
157
+ externalId: userExternalId,
158
+ displayName: "Ada Byron",
159
+ active: true
160
+ });
161
+ await expectSCIMNoContent(await request(`/Users/${encodeURIComponent(createdUser.id)}`, {
162
+ method: "PATCH",
163
+ body: {
164
+ schemas: [SCIM_PATCH_SCHEMA],
165
+ Operations: [{
166
+ op: "Replace",
167
+ path: "displayName",
168
+ value: "Ada Byron"
169
+ }]
170
+ }
171
+ }));
172
+ const unchangedUserResponse = await request(`/Users/${encodeURIComponent(createdUser.id)}`);
173
+ expectSCIMResponse(unchangedUserResponse, 200);
174
+ expect(await readJson(unchangedUserResponse)).toEqual(replacedUser);
175
+ const createGroupResponse = await request("/Groups", {
176
+ method: "POST",
177
+ body: {
178
+ schemas: [SCIM_GROUP_SCHEMA],
179
+ externalId: groupExternalId,
180
+ displayName: "Finance administrators"
181
+ }
182
+ });
183
+ expectSCIMResponse(createGroupResponse, 201);
184
+ const createdGroup = await readJson(createGroupResponse);
185
+ const groupLocation = `${scimBaseURL}/Groups/${encodeURIComponent(createdGroup.id)}`;
186
+ expect(createdGroup).toMatchObject({
187
+ schemas: [SCIM_GROUP_SCHEMA],
188
+ externalId: groupExternalId,
189
+ displayName: "Finance administrators",
190
+ members: [],
191
+ meta: {
192
+ resourceType: "Group",
193
+ location: groupLocation
194
+ }
195
+ });
196
+ expect(createGroupResponse.headers.get("location")).toBe(groupLocation);
197
+ expect(createGroupResponse.headers.get("content-location")).toBe(groupLocation);
198
+ await checkpoint("group-created");
199
+ const addMember = () => request(`/Groups/${encodeURIComponent(createdGroup.id)}`, {
200
+ method: "PATCH",
201
+ body: {
202
+ schemas: [SCIM_PATCH_SCHEMA],
203
+ Operations: [{
204
+ op: "Add",
205
+ path: "members",
206
+ value: [{ value: createdUser.id }]
207
+ }]
208
+ }
209
+ });
210
+ if (options.projectionFailure) {
211
+ options.projectionFailure.enable();
212
+ expect(await expectSCIMErrorResponse(await addMember().finally(() => {
213
+ options.projectionFailure?.disable();
214
+ }), 500)).toEqual({
215
+ schemas: [SCIM_ERROR_SCHEMA],
216
+ status: "500",
217
+ detail: "SCIM projection reconciliation failed"
218
+ });
219
+ const groupAfterFailedAddResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
220
+ expectSCIMResponse(groupAfterFailedAddResponse, 200);
221
+ expect((await readJson(groupAfterFailedAddResponse)).members).toEqual([]);
222
+ await checkpoint("failed-add-rolled-back");
223
+ }
224
+ await expectSCIMNoContent(await addMember());
225
+ const groupWithMemberResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
226
+ expectSCIMResponse(groupWithMemberResponse, 200);
227
+ expect((await readJson(groupWithMemberResponse)).members).toEqual([expect.objectContaining({
228
+ value: createdUser.id,
229
+ type: "User",
230
+ $ref: userLocation
231
+ })]);
232
+ await checkpoint("member-added");
233
+ await expectSCIMNoContent(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`, {
234
+ method: "PATCH",
235
+ body: {
236
+ schemas: [SCIM_PATCH_SCHEMA],
237
+ Operations: [{
238
+ op: "Remove",
239
+ path: `members[value eq "${createdUser.id}"]`
240
+ }]
241
+ }
242
+ }));
243
+ const groupAfterOktaRemovalResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
244
+ expectSCIMResponse(groupAfterOktaRemovalResponse, 200);
245
+ expect((await readJson(groupAfterOktaRemovalResponse)).members).toEqual([]);
246
+ await checkpoint("okta-member-removed");
247
+ await expectSCIMNoContent(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`, {
248
+ method: "PATCH",
249
+ body: {
250
+ schemas: [SCIM_PATCH_SCHEMA],
251
+ Operations: [{
252
+ op: "Add",
253
+ path: "members",
254
+ value: [{ value: createdUser.id }]
255
+ }]
256
+ }
257
+ }));
258
+ await expectSCIMNoContent(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`, {
259
+ method: "PATCH",
260
+ body: {
261
+ schemas: [SCIM_PATCH_SCHEMA],
262
+ Operations: [{
263
+ op: "Remove",
264
+ path: "members",
265
+ value: [{ value: createdUser.id }]
266
+ }]
267
+ }
268
+ }));
269
+ const groupAfterEntraRemovalResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
270
+ expectSCIMResponse(groupAfterEntraRemovalResponse, 200);
271
+ expect((await readJson(groupAfterEntraRemovalResponse)).members).toEqual([]);
272
+ await checkpoint("entra-member-removed");
273
+ await expectSCIMNoContent(await addMember());
274
+ const restoredGroupResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
275
+ expectSCIMResponse(restoredGroupResponse, 200);
276
+ expect((await readJson(restoredGroupResponse)).members).toEqual([expect.objectContaining({
277
+ value: createdUser.id,
278
+ $ref: userLocation
279
+ })]);
280
+ await checkpoint("member-restored");
281
+ await expectSCIMNoContent(await request(`/Users/${encodeURIComponent(createdUser.id)}`, {
282
+ method: "PATCH",
283
+ body: {
284
+ schemas: [SCIM_PATCH_SCHEMA],
285
+ Operations: [{
286
+ op: "Replace",
287
+ path: "active",
288
+ value: false
289
+ }]
290
+ }
291
+ }));
292
+ const inactiveUserResponse = await request(`/Users/${encodeURIComponent(createdUser.id)}`);
293
+ expectSCIMResponse(inactiveUserResponse, 200);
294
+ expect(await readJson(inactiveUserResponse)).toMatchObject({
295
+ id: createdUser.id,
296
+ active: false
297
+ });
298
+ const groupWithInactiveMemberResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
299
+ expectSCIMResponse(groupWithInactiveMemberResponse, 200);
300
+ expect((await readJson(groupWithInactiveMemberResponse)).members).toEqual([expect.objectContaining({ value: createdUser.id })]);
301
+ await checkpoint("user-deactivated");
302
+ await expectSCIMNoContent(await request(`/Users/${encodeURIComponent(createdUser.id)}`, {
303
+ method: "PATCH",
304
+ body: {
305
+ schemas: [SCIM_PATCH_SCHEMA],
306
+ Operations: [{
307
+ op: "Replace",
308
+ path: "active",
309
+ value: true
310
+ }]
311
+ }
312
+ }));
313
+ const activeUserResponse = await request(`/Users/${encodeURIComponent(createdUser.id)}`);
314
+ expectSCIMResponse(activeUserResponse, 200);
315
+ expect(await readJson(activeUserResponse)).toMatchObject({
316
+ id: createdUser.id,
317
+ active: true
318
+ });
319
+ await checkpoint("user-reactivated");
320
+ await expectSCIMNoContent(await request(`/Users/${encodeURIComponent(createdUser.id)}`, { method: "DELETE" }));
321
+ await expectSCIMErrorResponse(await request(`/Users/${encodeURIComponent(createdUser.id)}`), 404);
322
+ const groupAfterPopulatedUserDeleteResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
323
+ expectSCIMResponse(groupAfterPopulatedUserDeleteResponse, 200);
324
+ expect((await readJson(groupAfterPopulatedUserDeleteResponse)).members).toEqual([]);
325
+ await checkpoint("populated-user-deleted");
326
+ const emptyAfterDeleteResponse = await request(userFilterPath(userName));
327
+ expectSCIMResponse(emptyAfterDeleteResponse, 200);
328
+ expect(await readJson(emptyAfterDeleteResponse)).toMatchObject({
329
+ totalResults: 0,
330
+ Resources: []
331
+ });
332
+ const reprovisionResponse = await request("/Users", {
333
+ method: "POST",
334
+ body: userCreateBody
335
+ });
336
+ expectSCIMResponse(reprovisionResponse, 201);
337
+ const reprovisionedUser = await readJson(reprovisionResponse);
338
+ expect(reprovisionedUser).toMatchObject({
339
+ externalId: userExternalId,
340
+ userName,
341
+ active: true
342
+ });
343
+ expect(reprovisionedUser.id).not.toBe(createdUser.id);
344
+ const reprovisionedUserLocation = `${scimBaseURL}/Users/${encodeURIComponent(reprovisionedUser.id)}`;
345
+ expect(reprovisionedUser.meta.location).toBe(reprovisionedUserLocation);
346
+ expect(reprovisionResponse.headers.get("location")).toBe(reprovisionedUserLocation);
347
+ await checkpoint("user-reprovisioned");
348
+ await expectSCIMNoContent(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`, {
349
+ method: "PATCH",
350
+ body: {
351
+ schemas: [SCIM_PATCH_SCHEMA],
352
+ Operations: [{
353
+ op: "Add",
354
+ path: "members",
355
+ value: [{ value: reprovisionedUser.id }]
356
+ }]
357
+ }
358
+ }));
359
+ const groupWithReprovisionedMemberResponse = await request(`/Groups/${encodeURIComponent(createdGroup.id)}`);
360
+ expectSCIMResponse(groupWithReprovisionedMemberResponse, 200);
361
+ expect((await readJson(groupWithReprovisionedMemberResponse)).members).toEqual([expect.objectContaining({
362
+ value: reprovisionedUser.id,
363
+ $ref: reprovisionedUserLocation
364
+ })]);
365
+ await checkpoint("reprovisioned-member-added");
366
+ await expectSCIMNoContent(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`, { method: "DELETE" }));
367
+ await expectSCIMErrorResponse(await request(`/Groups/${encodeURIComponent(createdGroup.id)}`), 404);
368
+ const userAfterPopulatedGroupDeleteResponse = await request(`/Users/${encodeURIComponent(reprovisionedUser.id)}`);
369
+ expectSCIMResponse(userAfterPopulatedGroupDeleteResponse, 200);
370
+ expect(await readJson(userAfterPopulatedGroupDeleteResponse)).toMatchObject({
371
+ id: reprovisionedUser.id,
372
+ active: true
373
+ });
374
+ await checkpoint("populated-group-deleted");
375
+ await expectSCIMNoContent(await request(`/Users/${encodeURIComponent(reprovisionedUser.id)}`, { method: "DELETE" }));
376
+ await expectSCIMErrorResponse(await request(`/Users/${encodeURIComponent(reprovisionedUser.id)}`), 404);
377
+ const emptyFinalListResponse = await request(userFilterPath(userName));
378
+ expectSCIMResponse(emptyFinalListResponse, 200);
379
+ expect(await readJson(emptyFinalListResponse)).toMatchObject({
380
+ totalResults: 0,
381
+ Resources: []
382
+ });
383
+ await checkpoint("lifecycle-complete");
384
+ return {
385
+ userId: createdUser.id,
386
+ groupId: createdGroup.id,
387
+ reprovisionedUserId: reprovisionedUser.id,
388
+ userLocation,
389
+ groupLocation
390
+ };
391
+ }
392
+ //#endregion
393
+ export { runSCIMLifecycle };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/test-utils",
3
- "version": "1.7.0-rc.1",
3
+ "version": "1.7.0-rc.2",
4
4
  "description": "Testing utilities for Better Auth adapter development",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,18 +28,23 @@
28
28
  "dev-source": "./src/adapter/index.ts",
29
29
  "default": "./dist/adapter.mjs",
30
30
  "types": "./dist/adapter.d.mts"
31
+ },
32
+ "./scim": {
33
+ "dev-source": "./src/scim-lifecycle.ts",
34
+ "default": "./dist/scim.mjs",
35
+ "types": "./dist/scim.d.mts"
31
36
  }
32
37
  },
33
38
  "devDependencies": {
34
- "tsdown": "0.21.1",
39
+ "tsdown": "0.22.7",
35
40
  "vitest": "^4.1.9",
36
- "@better-auth/core": "1.7.0-rc.1",
37
- "better-auth": "1.7.0-rc.1"
41
+ "@better-auth/core": "1.7.0-rc.2",
42
+ "better-auth": "1.7.0-rc.2"
38
43
  },
39
44
  "peerDependencies": {
40
45
  "vitest": "^4.1.9",
41
- "@better-auth/core": "^1.7.0-rc.1",
42
- "better-auth": "^1.7.0-rc.1"
46
+ "@better-auth/core": "^1.7.0-rc.2",
47
+ "better-auth": "^1.7.0-rc.2"
43
48
  },
44
49
  "scripts": {
45
50
  "build": "tsdown",
@@ -1,24 +0,0 @@
1
- import { Logger } from "../test-adapter.mjs";
2
- import { TestSuiteStats } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
5
- //#region src/adapter/suites/joins.d.ts
6
- declare const joinsTestSuite: (options?: {
7
- disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row", boolean> & {
8
- ALL?: boolean;
9
- }> | undefined;
10
- } | undefined) => (helpers: {
11
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
12
- log: Logger;
13
- adapterDisplayName: string;
14
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
15
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
16
- cleanup: () => Promise<void>;
17
- runMigrations: () => Promise<void>;
18
- prefixTests?: string | undefined;
19
- onTestFinish: (stats: TestSuiteStats) => Promise<void>;
20
- customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
21
- transformIdOutput?: ((id: any) => string | undefined) | undefined;
22
- }) => Promise<void>;
23
- //#endregion
24
- export { joinsTestSuite };
@@ -1,24 +0,0 @@
1
- import { Logger } from "../test-adapter.mjs";
2
- import { TestSuiteStats } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
5
- //#region src/adapter/suites/number-id.d.ts
6
- declare const numberIdTestSuite: (options?: {
7
- disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row" | "create - should return a number id", boolean> & {
8
- ALL?: boolean;
9
- }> | undefined;
10
- } | undefined) => (helpers: {
11
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
12
- log: Logger;
13
- adapterDisplayName: string;
14
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
15
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
16
- cleanup: () => Promise<void>;
17
- runMigrations: () => Promise<void>;
18
- prefixTests?: string | undefined;
19
- onTestFinish: (stats: TestSuiteStats) => Promise<void>;
20
- customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
21
- transformIdOutput?: ((id: any) => string | undefined) | undefined;
22
- }) => Promise<void>;
23
- //#endregion
24
- export { numberIdTestSuite };
@@ -1,24 +0,0 @@
1
- import { Logger } from "../test-adapter.mjs";
2
- import { TestSuiteStats } from "../create-test-suite.mjs";
3
- import * as better_auth0 from "better-auth";
4
-
5
- //#region src/adapter/suites/uuid.d.ts
6
- declare const uuidTestSuite: (options?: {
7
- disableTests?: Partial<Record<"init - tests" | "create - should create a model" | "create - should always return an id" | "create - should return null for nullable foreign keys" | "create - should apply default values to fields" | "findOne - should find a model" | "findOne - should not apply defaultValue if value not found" | "findOne - should find a model using a reference field" | "findOne - should not throw on record not found" | "findOne - should find a model without id" | "findOne - should find a model with join" | "findOne - should find a model with modified field name" | "findOne - should find a model with modified model name" | "findOne - should find a model with additional fields" | "findOne - should select fields" | "findOne - should select fields with one-to-many join" | "findOne - should select fields with one-to-one join" | "findOne - should select fields with multiple joins" | "findOne - should find model with date field" | "findOne - should perform backwards joins" | "findOne - should return an object for one-to-one joins" | "findOne - should return an array for one-to-many joins" | "findOne - should work with both one-to-one and one-to-many joins" | "findOne - should return null for failed base model lookup that has joins" | "findOne - should join a model with modified field name" | "findMany - should find many models" | "findMany - should find many models with date fields" | "findMany - should find many models with join" | "findMany - should find many with join and limit" | "findMany - should select fields" | "findMany - should select fields with one-to-many join" | "findMany - should select fields with one-to-one join" | "findMany - should select fields with multiple joins" | "findMany - should find many with join and offset" | "findMany - should find many with join and sortBy" | "findMany - should find many with join and where clause" | "findMany - should find many with join, where, limit, and offset" | "findMany - should find many with one-to-one join" | "findMany - should find many with both one-to-one and one-to-many joins" | "findMany - should return an empty array when no models are found" | "findMany - should return empty array when base records don't exist with joins" | "findMany - should find many models with starts_with operator" | "findMany - starts_with should not interpret regex patterns" | "findMany - ends_with should not interpret regex patterns" | "findMany - contains should not interpret regex patterns" | "findMany - should find many models with ends_with operator" | "findMany - should find many models with contains operator" | "findMany - should handle multiple where conditions with different operators" | "findMany - should find many models with contains operator (using symbol)" | "findMany - should find many models with eq operator" | "findMany - should find many models with ne operator" | "findMany - should find many models with gt operator" | "findMany - should find many models with gte operator" | "findMany - should find many models with lte operator" | "findMany - should find many models with lt operator" | "findMany - should find many models with in operator" | "findMany - should find many models with not_in operator" | "findMany - should find many models with sortBy" | "findMany - should find many models with limit" | "findMany - should find many models with offset" | "findMany - should find many models with limit and offset" | "findMany - should find many models with sortBy and offset" | "findMany - should find many models with sortBy and limit" | "findMany - should find many models with sortBy and limit and offset" | "findMany - should find many models with sortBy and limit and offset and where" | "update - should update a model" | "update - should return null when where is empty" | "updateMany - should update all models when where is empty" | "updateMany - should update many models with a specific where" | "updateMany - should update many models with a multiple where" | "incrementOne - guarded set transition returns the row on a matching guard and null on a guard miss" | "delete - should delete a model" | "delete - should not throw on record not found" | "delete - should delete by non-unique field" | "deleteMany - should delete many models" | "deleteMany - starts_with should not interpret regex patterns" | "deleteMany - ends_with should not interpret regex patterns" | "deleteMany - contains should not interpret regex patterns" | "deleteMany - should delete many models with numeric values" | "deleteMany - should delete many models with boolean values" | "count - should count many models" | "count - should return 0 with no rows to count" | "count - should count with where clause" | "update - should correctly return record when updating a field used in where clause" | "update - should handle updating multiple fields including where clause field" | "update - should work when updated field is not in where clause" | "findOne - backwards join should only return single record not array" | "findMany - backwards join should only return single record not array" | "findOne - backwards join with modified field name (session base, users-table join)" | "findOne - multiple joins should return result even when some joined tables have no matching rows" | "findOne - should be able to perform a limited join" | "findOne - should be able to perform a complex limited join" | "findMany - should be able to perform a limited join" | "findMany - should be able to perform a complex limited join" | "findOne - should return null for one-to-one join when joined record doesn't exist" | "findMany - should return null for one-to-one join when joined records don't exist" | "findMany - should return empty array for one-to-many join when joined records don't exist" | "findMany - should handle mixed joins correctly when some are missing" | "create - should support arrays" | "create - should support json" | "update - should support multiple where conditions under AND connector with unique field" | "findMany - eq operator with null value (single condition) should use IS NULL" | "findMany - eq and ne operators with null value in AND group should use IS NULL / IS NOT NULL" | "findMany - eq and ne operators with null value in OR group should use IS NULL / IS NOT NULL" | "update - should return updated record when where condition uses null value" | "update - should return null when a multi-predicate where matches no row" | "create - should return a uuid" | "findOne - should find a model using a uuid", boolean> & {
8
- ALL?: boolean;
9
- }> | undefined;
10
- } | undefined) => (helpers: {
11
- adapter: () => Promise<better_auth0.DBAdapter<better_auth0.BetterAuthOptions>>;
12
- log: Logger;
13
- adapterDisplayName: string;
14
- getBetterAuthOptions: () => better_auth0.BetterAuthOptions;
15
- modifyBetterAuthOptions: (options: better_auth0.BetterAuthOptions) => Promise<better_auth0.BetterAuthOptions>;
16
- cleanup: () => Promise<void>;
17
- runMigrations: () => Promise<void>;
18
- prefixTests?: string | undefined;
19
- onTestFinish: (stats: TestSuiteStats) => Promise<void>;
20
- customIdGenerator?: (() => any | Promise<any> | undefined) | undefined;
21
- transformIdOutput?: ((id: any) => string | undefined) | undefined;
22
- }) => Promise<void>;
23
- //#endregion
24
- export { uuidTestSuite };
File without changes
File without changes