@protobase/server 0.47.1 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/admin-options.d.ts +2 -2
  2. package/dist/app-identity.d.ts +2 -2
  3. package/dist/app-name.d.ts +2 -0
  4. package/dist/auth-store.d.ts +3 -0
  5. package/dist/auth-store.js +3 -0
  6. package/dist/better-auth/auth-schema.d.ts +7 -8
  7. package/dist/better-auth/auth-schema.js +40 -42
  8. package/dist/better-auth/auth-settings.d.ts +8754 -0
  9. package/dist/better-auth/auth-settings.js +43 -0
  10. package/dist/better-auth/auth-tables.d.ts +1 -1
  11. package/dist/better-auth/auth-tables.js +11 -9
  12. package/dist/better-auth/authenticate-settings.d.ts +15 -0
  13. package/dist/better-auth/authenticate-settings.js +12 -0
  14. package/dist/better-auth/authenticator.d.ts +1 -1
  15. package/dist/better-auth/create-auth.d.ts +34 -14
  16. package/dist/better-auth/create-auth.js +27 -10
  17. package/dist/better-auth/mcp/mcp-auth-plugins.d.ts +2719 -0
  18. package/dist/better-auth/mcp/mcp-auth-plugins.js +68 -0
  19. package/dist/better-auth/mcp/mcp-plugins.d.ts +7 -2
  20. package/dist/better-auth/mcp/mcp-plugins.js +3 -68
  21. package/dist/better-auth/mcp/mcp-token-claims.js +1 -1
  22. package/dist/better-auth/organizations/store.d.ts +1 -0
  23. package/dist/better-auth/saml-plugin.d.ts +993 -0
  24. package/dist/better-auth/saml-plugin.js +36 -0
  25. package/dist/better-auth/saml-sign-in.d.ts +27 -1
  26. package/dist/better-auth/saml-sign-in.js +1 -33
  27. package/dist/better-auth/store/adoption.js +87 -0
  28. package/dist/better-auth/store/ddl.js +18 -0
  29. package/dist/better-auth/store/drift.d.ts +9 -0
  30. package/dist/better-auth/store/drift.js +18 -0
  31. package/dist/better-auth/store/migration-sql.js +15 -0
  32. package/dist/better-auth/store/migrations/001-core.js +80 -0
  33. package/dist/better-auth/store/migrations/002-two-factor.js +25 -0
  34. package/dist/better-auth/store/migrations/003-passkeys.js +29 -0
  35. package/dist/better-auth/store/migrations/004-sign-in-policy.js +22 -0
  36. package/dist/better-auth/store/migrations/005-staff-sign-in.js +25 -0
  37. package/dist/better-auth/store/migrations/006-organizations.js +50 -0
  38. package/dist/better-auth/store/migrations/007-mcp.js +150 -0
  39. package/dist/better-auth/store/migrations/index.js +22 -0
  40. package/dist/better-auth/store/migrations/migration.d.ts +3 -0
  41. package/dist/better-auth/store/migrations/migration.js +14 -0
  42. package/dist/better-auth/store/migrations-table.d.ts +7 -0
  43. package/dist/better-auth/store/migrations-table.js +23 -0
  44. package/dist/better-auth/store/resources-outside.d.ts +7 -0
  45. package/dist/better-auth/store/resources-outside.js +20 -0
  46. package/dist/better-auth/store/store-db.js +13 -0
  47. package/dist/better-auth/store/store-names.d.ts +2 -0
  48. package/dist/better-auth/store/store-names.js +14 -0
  49. package/dist/better-auth/store/table-names.d.ts +7 -0
  50. package/dist/better-auth/store/table-names.js +10 -0
  51. package/dist/better-auth/user-table.js +1 -1
  52. package/dist/better-auth/users.d.ts +2 -2
  53. package/dist/comments/comment-users.d.ts +1 -1
  54. package/dist/config-exports.d.ts +2 -0
  55. package/dist/config-exports.js +2 -0
  56. package/dist/create-admin.d.ts +6 -4
  57. package/dist/create-admin.js +3 -1
  58. package/dist/encryption/keyring.js +1 -1
  59. package/dist/files/options.d.ts +5 -8
  60. package/dist/files/provider-settings.d.ts +16 -0
  61. package/dist/files/provider-settings.js +17 -0
  62. package/dist/files/runtime.js +4 -4
  63. package/dist/forms/runtime.js +3 -3
  64. package/dist/index.d.ts +22 -19
  65. package/dist/index.js +11 -11
  66. package/dist/internal.d.ts +13 -0
  67. package/dist/internal.js +13 -0
  68. package/dist/jobs/declared-job.d.ts +24 -0
  69. package/dist/jobs/declared-job.js +26 -0
  70. package/dist/jobs/job-types.d.ts +2 -2
  71. package/dist/mcp/mcp-authenticator.js +3 -3
  72. package/dist/notifications/device-store-of.d.ts +2 -2
  73. package/dist/notifications/device-store-of.js +1 -1
  74. package/dist/notifications/device-store.d.ts +1 -1
  75. package/dist/notifications/device-store.js +1 -1
  76. package/dist/notifications/history-store-of.d.ts +2 -2
  77. package/dist/notifications/history-store-of.js +1 -1
  78. package/dist/notifications/history-store.d.ts +1 -1
  79. package/dist/notifications/history-store.js +1 -1
  80. package/dist/notifications/options.d.ts +3 -1
  81. package/dist/notifications/options.js +1 -1
  82. package/dist/notifications/schema.d.ts +3 -3
  83. package/dist/notifications/schema.js +8 -8
  84. package/dist/notifications/send-notification.js +1 -1
  85. package/dist/notifications/sender.d.ts +1 -1
  86. package/dist/notifications/sender.js +2 -2
  87. package/dist/notifications/senders-of.d.ts +1 -1
  88. package/dist/notifications/senders-of.js +1 -1
  89. package/dist/package.js +1 -1
  90. package/dist/webhooks/subscription.d.ts +1 -0
  91. package/dist/webhooks/table/options.d.ts +1 -1
  92. package/dist/webhooks/table/schema.d.ts +2 -2
  93. package/dist/webhooks/table/schema.js +2 -2
  94. package/dist/webhooks/table/webhook-table.js +2 -2
  95. package/dist/webhooks/table/webhooks-module.d.ts +108 -0
  96. package/dist/webhooks/table/webhooks-module.js +11 -0
  97. package/package.json +8 -5
  98. package/dist/better-auth/mcp/mcp-tables.js +0 -32
  99. package/dist/better-auth/snake-case-migration.js +0 -122
  100. package/dist/notifications/plugin.d.ts +0 -13
  101. package/dist/notifications/plugin.js +0 -16
  102. package/dist/project-config.d.ts +0 -54
  103. package/dist/project-config.js +0 -182
  104. package/dist/webhooks/table/plugin.d.ts +0 -10
  105. package/dist/webhooks/table/plugin.js +0 -18
@@ -0,0 +1,36 @@
1
+ import { samlEntityId } from "./saml-sign-in.js";
2
+ import { sso } from "@better-auth/sso";
3
+ //#region src/better-auth/saml-plugin.ts
4
+ /** The provider as one of the SSO plugin's configured providers (`defaultSSO`). */
5
+ const defaultSsoEntry = (provider, baseURL) => {
6
+ const { idp, attributes = {} } = provider;
7
+ const mapping = Object.fromEntries(Object.entries(attributes).filter(([, name]) => name !== void 0));
8
+ return {
9
+ providerId: provider.id,
10
+ domain: provider.domains.join(","),
11
+ samlConfig: {
12
+ issuer: samlEntityId(baseURL, provider.id),
13
+ entryPoint: "ssoUrl" in idp ? idp.ssoUrl : "",
14
+ idpMetadata: "metadata" in idp ? { metadata: idp.metadata } : {
15
+ entityID: idp.entityId,
16
+ cert: idp.certificate
17
+ },
18
+ ...Object.keys(mapping).length > 0 && { mapping }
19
+ }
20
+ };
21
+ };
22
+ /**
23
+ * Better Auth's SSO plugin with the configured providers. Their domains are trusted, so an address there links to the
24
+ * account that has it; organizations are not assigned by provider, and nobody registers providers.
25
+ */
26
+ const samlPlugin = (providers, baseURL) => {
27
+ const { schema: _schema, ...plugin } = sso({
28
+ defaultSSO: providers.map((provider) => defaultSsoEntry(provider, baseURL)),
29
+ domainVerification: { enabled: true },
30
+ organizationProvisioning: { disabled: true },
31
+ providersLimit: 0
32
+ });
33
+ return plugin;
34
+ };
35
+ //#endregion
36
+ export { defaultSsoEntry, samlPlugin };
@@ -1,4 +1,3 @@
1
- import "@better-auth/sso";
2
1
  //#region src/better-auth/saml-sign-in.d.ts
3
2
  /**
4
3
  * A SAML 2.0 identity provider people of the app sign in with, for example the company's Okta, Entra ID or Google
@@ -34,4 +33,31 @@ export type SamlProvider = {
34
33
  export type SsoOptions = {
35
34
  saml: SamlProvider[];
36
35
  };
36
+ /**
37
+ * The providers with their defaults filled in: the name `SSO`, and the domains trimmed and lowercased. A malformed id,
38
+ * an id used twice or by another sign-in provider (`takenIds`), no domains or a domain that is not a host name, and IdP
39
+ * settings that are missing or not a URL are errors.
40
+ */
41
+ export declare const resolveSamlProviders: (saml: SamlProvider[], takenIds: string[]) => {
42
+ name: string;
43
+ domains: string[];
44
+ /** The id: the button's `?sign-in=` link, the provider's paths and the namespace of its accounts. Lowercase letters, digits or "-". */
45
+ id: string;
46
+ /** The provider's metadata XML, or its entity ID, sign-in URL and signing certificate(s) (PEM; several while one rotates). */
47
+ idp: {
48
+ metadata: string;
49
+ } | {
50
+ entityId: string;
51
+ ssoUrl: string;
52
+ certificate: string | string[];
53
+ };
54
+ /** The assertion's attribute names, when they are not `email`, `givenName`, `surname` and `displayName`. */
55
+ attributes?: {
56
+ email?: string;
57
+ name?: string;
58
+ firstName?: string;
59
+ lastName?: string;
60
+ };
61
+ }[];
62
+ export type ResolvedSamlProvider = ReturnType<typeof resolveSamlProviders>[number];
37
63
  //#endregion
@@ -1,7 +1,6 @@
1
1
  import { authBasePath } from "./auth-base-path.js";
2
2
  import { providerIdPattern } from "./platform-sign-in.js";
3
3
  import { APIError, createAuthMiddleware } from "better-auth/api";
4
- import { sso } from "@better-auth/sso";
5
4
  //#region src/better-auth/saml-sign-in.ts
6
5
  const domainPattern = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/;
7
6
  const checkIdp = (id, idp) => {
@@ -37,37 +36,6 @@ const resolveSamlProviders = (saml, takenIds) => {
37
36
  };
38
37
  /** The app's SP entity ID for a provider: its metadata URL on `baseURL`, the same on every origin. */
39
38
  const samlEntityId = (baseURL, id) => `${baseURL.replace(/\/$/, "")}${authBasePath}/sso/saml2/sp/metadata?providerId=${encodeURIComponent(id)}`;
40
- /** The provider as one of the SSO plugin's configured providers (`defaultSSO`). */
41
- const defaultSsoEntry = (provider, baseURL) => {
42
- const { idp, attributes = {} } = provider;
43
- const mapping = Object.fromEntries(Object.entries(attributes).filter(([, name]) => name !== void 0));
44
- return {
45
- providerId: provider.id,
46
- domain: provider.domains.join(","),
47
- samlConfig: {
48
- issuer: samlEntityId(baseURL, provider.id),
49
- entryPoint: "ssoUrl" in idp ? idp.ssoUrl : "",
50
- idpMetadata: "metadata" in idp ? { metadata: idp.metadata } : {
51
- entityID: idp.entityId,
52
- cert: idp.certificate
53
- },
54
- ...Object.keys(mapping).length > 0 && { mapping }
55
- }
56
- };
57
- };
58
- /**
59
- * Better Auth's SSO plugin with the configured providers. Their domains are trusted, so an address there links to the
60
- * account that has it; organizations are not assigned by provider, and nobody registers providers.
61
- */
62
- const samlPlugin = (providers, baseURL) => {
63
- const { schema: _schema, ...plugin } = sso({
64
- defaultSSO: providers.map((provider) => defaultSsoEntry(provider, baseURL)),
65
- domainVerification: { enabled: true },
66
- organizationProvisioning: { disabled: true },
67
- providersLimit: 0
68
- });
69
- return plugin;
70
- };
71
39
  /** The SSO plugin's endpoints for providers kept in its table, and its OIDC callback, which Protobase does not serve. */
72
40
  const samlDisabledPaths = [
73
41
  "/sso/register",
@@ -130,4 +98,4 @@ const emailInDomains = (email, domains) => {
130
98
  return domains.some((allowed) => domain === allowed || domain.endsWith(`.${allowed}`));
131
99
  };
132
100
  //#endregion
133
- export { defaultSsoEntry, emailInDomains, isSamlPath, resolveSamlProviders, samlDisabledPaths, samlEntityId, samlGuardPlugin, samlPlugin, samlRefusal };
101
+ export { emailInDomains, isSamlPath, resolveSamlProviders, samlDisabledPaths, samlEntityId, samlGuardPlugin, samlRefusal };
@@ -0,0 +1,87 @@
1
+ import { ddl } from "./ddl.js";
2
+ import { migrationNames } from "./migrations/migration.js";
3
+ import { storeMigrations } from "./migrations/index.js";
4
+ import { recordMigrations } from "./migrations-table.js";
5
+ import { statementsSql } from "./migration-sql.js";
6
+ import { sql } from "kysely";
7
+ //#region src/better-auth/store/adoption.ts
8
+ const key = ({ table, column }) => `${table}.${column}`;
9
+ const columnsIn = async (db, schema) => (await sql`select table_name as "table", column_name as "column", udt_name as "type" from information_schema.columns
10
+ where table_schema = ${schema === void 0 ? sql`current_schema()` : schema} order by table_name, ordinal_position`.execute(db)).rows;
11
+ const scratchSchema = "protobase_auth_adoption";
12
+ /** For each migration, the columns it makes: every one runs in a scratch schema, in a transaction that is rolled back. */
13
+ const madeColumns = async (db, names) => {
14
+ const tx = await db.startTransaction().execute();
15
+ const run = async () => {
16
+ await sql`create schema ${sql.id(scratchSchema)}`.execute(tx);
17
+ const scratch = migrationNames({
18
+ ...names,
19
+ schema: scratchSchema
20
+ });
21
+ const made = [];
22
+ let before = [];
23
+ for (const migration of storeMigrations) {
24
+ for (const statement of migration.statements(scratch)) await statement.execute(tx);
25
+ const after = await columnsIn(tx, scratchSchema);
26
+ made.push(after.filter((column) => !before.some((earlier) => key(earlier) === key(column))));
27
+ before = after;
28
+ }
29
+ return made;
30
+ };
31
+ return run().finally(() => tx.rollback().execute());
32
+ };
33
+ /** Whether the store has any table of the migrations besides the user table, which may be another system's. */
34
+ const storeHasTables = async (db, names) => {
35
+ const tables = new Set((await columnsIn(db, names.schema)).map((column) => column.table));
36
+ return storeMigrations.some((migration) => migration.tables.some((table) => tables.has(table)));
37
+ };
38
+ /** Which migrations the store matches and which it still needs; a migration it matches only partly is an error. */
39
+ const planAdoption = async (db, names) => {
40
+ const made = await madeColumns(db, names);
41
+ const found = new Map((await columnsIn(db, names.schema)).map((column) => [key(column), column.type]));
42
+ const adoption = {
43
+ adopted: [],
44
+ pending: []
45
+ };
46
+ const problems = [];
47
+ storeMigrations.forEach((migration, i) => {
48
+ const columns = made[i];
49
+ const there = columns.filter((column) => found.has(key(column)));
50
+ if (there.length === 0) return void adoption.pending.push(migration);
51
+ const missing = columns.filter((column) => !found.has(key(column))).map((column) => `lacks ${key(column)}`);
52
+ const otherType = there.filter((column) => found.get(key(column)) !== column.type).map((column) => `has ${key(column)} as ${found.get(key(column))}, not ${column.type}`);
53
+ if (missing.length === 0 && otherType.length === 0) return void adoption.adopted.push({
54
+ migration,
55
+ columns
56
+ });
57
+ problems.push(`${migration.version} ${migration.name} ${[...missing, ...otherType].join(", ")}`);
58
+ });
59
+ if (problems.length > 0) throw new Error(`The auth store an earlier Protobase made matches none of its migrations' versions: ${problems.join("; ")}. Bring it to the schema of Protobase 0.47 first, with that version's \`protobase auth migration\`, then run this again.`);
60
+ return adoption;
61
+ };
62
+ /**
63
+ * The SQL that records the adopted migrations as applied, once it finds every column they make with its type; it
64
+ * stops the migration, naming what it lacks, on a database that differs from the one it was written from.
65
+ */
66
+ const adoptionSql = (names, adopted) => {
67
+ const expected = adopted.flatMap(({ columns }) => columns).map(({ table, column, type }) => ddl`(${sql.lit(table)}, ${sql.lit(column)}, ${sql.lit(type)})`);
68
+ const schema = names.schema === void 0 ? sql`current_schema()` : sql.lit(names.schema);
69
+ const check = ddl`do $adopt$
70
+ declare
71
+ missing text;
72
+ begin
73
+ select string_agg(expected.table_name || '.' || expected.column_name, ', ' order by expected.table_name, expected.column_name) into missing
74
+ from (values ${sql.join(expected, sql`,\n `)}) as expected (table_name, column_name, udt_name)
75
+ where not exists (
76
+ select from information_schema.columns found
77
+ where found.table_schema = ${schema} and found.table_name = expected.table_name and found.column_name = expected.column_name and found.udt_name = expected.udt_name
78
+ );
79
+ if missing is not null then
80
+ raise exception 'The auth store does not match the migrations this file adopts: it lacks %, or has them as other types', missing;
81
+ end if;
82
+ end
83
+ $adopt$`;
84
+ return `-- The auth store an earlier Protobase made, without a record of its migrations, adopted: ${adopted.map(({ migration }) => `${migration.version} ${migration.name}`).join(", ")}\n-- recorded as applied, once every table and column they make is there.\n${statementsSql([check, recordMigrations(names, adopted.map(({ migration }) => migration))])}`;
85
+ };
86
+ //#endregion
87
+ export { adoptionSql, planAdoption, storeHasTables };
@@ -0,0 +1,18 @@
1
+ import { DummyDriver, Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler, sql } from "kysely";
2
+ //#region src/better-auth/store/ddl.ts
3
+ /** A fragment of SQL whose strings are identifiers: `ddl\`create table ${'user'} (...)\`` is `create table "user" (...)`. */
4
+ const ddl = (strings, ...parts) => sql(strings, ...parts.map((part) => typeof part === "string" ? sql.id(part) : part));
5
+ const compiler = new Kysely({ dialect: {
6
+ createAdapter: () => new PostgresAdapter(),
7
+ createDriver: () => new DummyDriver(),
8
+ createIntrospector: (db) => new PostgresIntrospector(db),
9
+ createQueryCompiler: () => new PostgresQueryCompiler()
10
+ } });
11
+ /** The text of a fragment. One that holds a parameter, a value given as neither identifier nor `sql.lit`, is an error. */
12
+ const ddlText = (fragment) => {
13
+ const { sql: text, parameters } = fragment.compile(compiler);
14
+ if (parameters.length > 0) throw new Error(`A migration statement has no parameters; give each value with sql.lit: ${text}`);
15
+ return text;
16
+ };
17
+ //#endregion
18
+ export { ddl, ddlText };
@@ -0,0 +1,9 @@
1
+ import { AdminAuth } from "../create-auth.js";
2
+ //#region src/better-auth/store/drift.d.ts
3
+ /**
4
+ * What Better Auth, with the features the app turns on, finds the store lacks or has otherwise: tables, `table.column`s,
5
+ * indexes and its other findings; none when the store matches. It compares the database's tables, so only
6
+ * `protobase dev` runs it, on the developer's machine: a deploy reads the record of migrations instead (`checkAuthSchema`).
7
+ */
8
+ export declare const authSchemaDrift: (auth: AdminAuth) => Promise<string[]>;
9
+ //#endregion
@@ -0,0 +1,18 @@
1
+ import { getMigrations } from "better-auth/db/migration";
2
+ //#region src/better-auth/store/drift.ts
3
+ /**
4
+ * What Better Auth, with the features the app turns on, finds the store lacks or has otherwise: tables, `table.column`s,
5
+ * indexes and its other findings; none when the store matches. It compares the database's tables, so only
6
+ * `protobase dev` runs it, on the developer's machine: a deploy reads the record of migrations instead (`checkAuthSchema`).
7
+ */
8
+ const authSchemaDrift = async (auth) => {
9
+ const { toBeCreated, toBeAdded, toBeAddedIndexes, schemaProblems } = await getMigrations(auth.options, { throwOnUnsafe: false });
10
+ return [
11
+ ...toBeCreated.map(({ table }) => `lacks the table ${table}`),
12
+ ...toBeAdded.flatMap(({ table, fields }) => Object.keys(fields).map((field) => `lacks the column ${table}.${field}`)),
13
+ ...toBeAddedIndexes.map(({ name }) => `lacks the index ${name}`),
14
+ ...schemaProblems
15
+ ];
16
+ };
17
+ //#endregion
18
+ export { authSchemaDrift };
@@ -0,0 +1,15 @@
1
+ import { ddl, ddlText } from "./ddl.js";
2
+ import { migrationNames } from "./migrations/migration.js";
3
+ import { createMigrationsTable, recordMigrations } from "./migrations-table.js";
4
+ //#region src/better-auth/store/migration-sql.ts
5
+ /** The statements as SQL text. */
6
+ const statementsSql = (statements) => statements.map((statement) => `${ddlText(statement)};`).join("\n\n");
7
+ /** A migration's statements, then the row that records it, under a comment naming it. */
8
+ const migrationSql = (names, migration) => `-- ${migration.version} ${migration.name}: ${migration.title}.\n${statementsSql([...migration.statements(migrationNames(names)), recordMigrations(names, [migration])])}`;
9
+ /** The migrations table, for a store that has none yet, in the store's schema, made when it is missing. */
10
+ const migrationsTableSql = (names) => {
11
+ const schema = names.schema === void 0 ? [] : [ddl`create schema if not exists ${names.schema}`];
12
+ return `-- The record of the auth store's migrations.\n${statementsSql([...schema, createMigrationsTable(names)])}`;
13
+ };
14
+ //#endregion
15
+ export { migrationSql, migrationsTableSql, statementsSql };
@@ -0,0 +1,80 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/001-core.ts
3
+ /** Sign-in itself: users, with their roles and bans, sessions, accounts, codes and the token signing keys. */
4
+ const core = {
5
+ version: 1,
6
+ name: "core",
7
+ title: "Better Auth's users, sessions, accounts, verifications and signing keys",
8
+ tables: [
9
+ "session",
10
+ "account",
11
+ "verification",
12
+ "jwks"
13
+ ],
14
+ statements: ({ table, user, userColumn: column, metadata, id, idRef }) => [
15
+ ddl`create table if not exists ${user} (id ${id} primary key)`,
16
+ ddl`alter table ${user}
17
+ add column if not exists ${column("name")} text not null,
18
+ add column if not exists ${column("email")} text not null unique,
19
+ add column if not exists ${column("email_verified")} boolean not null,
20
+ add column if not exists ${column("image")} text,
21
+ add column if not exists ${column("created_at")} timestamptz default current_timestamp not null,
22
+ add column if not exists ${column("updated_at")} timestamptz default current_timestamp not null,
23
+ add column if not exists ${column("role")} text,
24
+ add column if not exists ${column("banned")} boolean,
25
+ add column if not exists ${column("ban_reason")} text,
26
+ add column if not exists ${column("ban_expires")} timestamptz,
27
+ add column if not exists ${column("last_role")} text,
28
+ add column if not exists ${column("email_confirmed_at")} timestamptz`,
29
+ ...metadata ? [ddl`alter table ${user} add column if not exists ${metadata} jsonb`] : [],
30
+ ddl`create table ${table("session")} (
31
+ id ${id} primary key,
32
+ expires_at timestamptz not null,
33
+ token text not null unique,
34
+ created_at timestamptz default current_timestamp not null,
35
+ updated_at timestamptz not null,
36
+ ip_address text,
37
+ user_agent text,
38
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
39
+ impersonated_by text,
40
+ active_role text
41
+ )`,
42
+ ddl`create index session_user_id_idx on ${table("session")} (user_id)`,
43
+ ddl`create table ${table("account")} (
44
+ id ${id} primary key,
45
+ account_id text not null,
46
+ provider_id text not null,
47
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
48
+ access_token text,
49
+ refresh_token text,
50
+ id_token text,
51
+ access_token_expires_at timestamptz,
52
+ refresh_token_expires_at timestamptz,
53
+ scope text,
54
+ password text,
55
+ created_at timestamptz default current_timestamp not null,
56
+ updated_at timestamptz not null
57
+ )`,
58
+ ddl`create index account_user_id_idx on ${table("account")} (user_id)`,
59
+ ddl`create table ${table("verification")} (
60
+ id ${id} primary key,
61
+ identifier text not null,
62
+ value text not null,
63
+ expires_at timestamptz not null,
64
+ created_at timestamptz default current_timestamp not null,
65
+ updated_at timestamptz default current_timestamp not null
66
+ )`,
67
+ ddl`create index verification_identifier_idx on ${table("verification")} (identifier)`,
68
+ ddl`create table ${table("jwks")} (
69
+ id ${id} primary key,
70
+ public_key text not null,
71
+ private_key text not null,
72
+ created_at timestamptz not null,
73
+ expires_at timestamptz,
74
+ alg text,
75
+ crv text
76
+ )`
77
+ ]
78
+ };
79
+ //#endregion
80
+ export { core };
@@ -0,0 +1,25 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/002-two-factor.ts
3
+ /** Two-step sign-in: each user's authenticator secret and backup codes. */
4
+ const twoFactor = {
5
+ version: 2,
6
+ name: "two_factor",
7
+ title: "The authenticator secrets and backup codes of two-step sign-in",
8
+ tables: ["two_factor"],
9
+ statements: ({ table, user, userColumn: column, id, idRef }) => [
10
+ ddl`alter table ${user} add column if not exists ${column("two_factor_enabled")} boolean`,
11
+ ddl`create table ${table("two_factor")} (
12
+ id ${id} primary key,
13
+ secret text not null,
14
+ backup_codes text not null,
15
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
16
+ verified boolean,
17
+ failed_verification_count integer,
18
+ locked_until timestamptz
19
+ )`,
20
+ ddl`create index two_factor_secret_idx on ${table("two_factor")} (secret)`,
21
+ ddl`create index two_factor_user_id_idx on ${table("two_factor")} (user_id)`
22
+ ]
23
+ };
24
+ //#endregion
25
+ export { twoFactor };
@@ -0,0 +1,29 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/003-passkeys.ts
3
+ /** Passkeys, each with the RP ID it was made for. */
4
+ const passkeys = {
5
+ version: 3,
6
+ name: "passkeys",
7
+ title: "The users' passkeys",
8
+ tables: ["passkey"],
9
+ statements: ({ table, user, id, idRef }) => [
10
+ ddl`create table ${table("passkey")} (
11
+ id ${id} primary key,
12
+ name text,
13
+ public_key text not null,
14
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
15
+ credential_id text not null,
16
+ counter integer not null,
17
+ device_type text not null,
18
+ backed_up boolean not null,
19
+ transports text,
20
+ created_at timestamptz,
21
+ aaguid text,
22
+ rp_id text
23
+ )`,
24
+ ddl`create index passkey_user_id_idx on ${table("passkey")} (user_id)`,
25
+ ddl`create index passkey_credential_id_idx on ${table("passkey")} (credential_id)`
26
+ ]
27
+ };
28
+ //#endregion
29
+ export { passkeys };
@@ -0,0 +1,22 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/004-sign-in-policy.ts
3
+ /** The sign-in policy admins save, each save a row of its own. */
4
+ const signInPolicy = {
5
+ version: 4,
6
+ name: "sign_in_policy",
7
+ title: "The sign-in policies admins saved",
8
+ tables: ["sign_in_policy"],
9
+ statements: ({ table, id }) => [ddl`create table ${table("sign_in_policy")} (
10
+ id ${id} primary key,
11
+ password text not null,
12
+ email_code text not null,
13
+ passkey text not null,
14
+ two_factor text not null,
15
+ staff_access text not null,
16
+ platform_sign_in text not null,
17
+ created_at timestamptz not null,
18
+ created_by text
19
+ )`]
20
+ };
21
+ //#endregion
22
+ export { signInPolicy };
@@ -0,0 +1,25 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/005-staff-sign-in.ts
3
+ /** The log of the operator's staff signing in as the app's people. */
4
+ const staffSignIn = {
5
+ version: 5,
6
+ name: "staff_sign_in",
7
+ title: "The log of staff sign-ins as the app's people",
8
+ tables: ["staff_sign_in"],
9
+ statements: ({ table, id }) => [ddl`create table ${table("staff_sign_in")} (
10
+ id ${id} primary key,
11
+ user_id text not null,
12
+ user_email text not null,
13
+ staff text not null,
14
+ staff_name text,
15
+ staff_subject text not null,
16
+ issuer text not null,
17
+ reason text not null,
18
+ session_id text not null,
19
+ started_at timestamptz not null,
20
+ expires_at timestamptz not null,
21
+ ended_at timestamptz
22
+ )`]
23
+ };
24
+ //#endregion
25
+ export { staffSignIn };
@@ -0,0 +1,50 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/006-organizations.ts
3
+ /** Organizations, their members and invitations, and the organization each user and session works in. */
4
+ const organizations = {
5
+ version: 6,
6
+ name: "organizations",
7
+ title: "Organizations, their members and their invitations",
8
+ tables: [
9
+ "organization",
10
+ "member",
11
+ "invitation"
12
+ ],
13
+ statements: ({ table, user, userColumn: column, id, idRef }) => [
14
+ ddl`alter table ${user} add column if not exists ${column("last_organization_id")} text`,
15
+ ddl`alter table ${table("session")} add column active_organization_id text`,
16
+ ddl`create table ${table("organization")} (
17
+ id ${id} primary key,
18
+ name text not null,
19
+ slug text not null unique,
20
+ logo text,
21
+ created_at timestamptz not null,
22
+ metadata text
23
+ )`,
24
+ ddl`create table ${table("member")} (
25
+ id ${id} primary key,
26
+ organization_id ${idRef} not null references ${table("organization")} (id) on delete cascade,
27
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
28
+ role text not null,
29
+ created_at timestamptz not null,
30
+ app_roles jsonb
31
+ )`,
32
+ ddl`create index member_organization_id_idx on ${table("member")} (organization_id)`,
33
+ ddl`create index member_user_id_idx on ${table("member")} (user_id)`,
34
+ ddl`create table ${table("invitation")} (
35
+ id ${id} primary key,
36
+ organization_id ${idRef} not null references ${table("organization")} (id) on delete cascade,
37
+ email text not null,
38
+ role text,
39
+ status text not null,
40
+ expires_at timestamptz not null,
41
+ created_at timestamptz default current_timestamp not null,
42
+ inviter_id ${idRef} not null references ${user} (id) on delete cascade,
43
+ app_roles jsonb
44
+ )`,
45
+ ddl`create index invitation_organization_id_idx on ${table("invitation")} (organization_id)`,
46
+ ddl`create index invitation_email_idx on ${table("invitation")} (email)`
47
+ ]
48
+ };
49
+ //#endregion
50
+ export { organizations };
@@ -0,0 +1,150 @@
1
+ import { ddl } from "../ddl.js";
2
+ //#region src/better-auth/store/migrations/007-mcp.ts
3
+ /** The OAuth provider MCP clients sign in through: its clients, resources, tokens and consents. */
4
+ const mcp = {
5
+ version: 7,
6
+ name: "mcp",
7
+ title: "The clients, resources, tokens and consents of the OAuth provider for MCP",
8
+ tables: [
9
+ "oauth_client",
10
+ "oauth_resource",
11
+ "oauth_client_resource",
12
+ "oauth_refresh_token",
13
+ "oauth_access_token",
14
+ "oauth_consent",
15
+ "oauth_client_assertion"
16
+ ],
17
+ statements: ({ table, user, id, idRef }) => [
18
+ ddl`create table ${table("oauth_client")} (
19
+ id ${id} primary key,
20
+ client_id text not null unique,
21
+ client_secret text,
22
+ client_discovery_id text,
23
+ disabled boolean,
24
+ skip_consent boolean,
25
+ enable_end_session boolean,
26
+ subject_type text,
27
+ scopes jsonb,
28
+ client_credentials_scopes jsonb,
29
+ user_id ${idRef} references ${user} (id) on delete cascade,
30
+ created_at timestamptz,
31
+ updated_at timestamptz,
32
+ name text,
33
+ uri text,
34
+ icon text,
35
+ contacts jsonb,
36
+ tos text,
37
+ policy text,
38
+ software_id text,
39
+ software_version text,
40
+ software_statement text,
41
+ redirect_uris jsonb not null,
42
+ post_logout_redirect_uris jsonb,
43
+ backchannel_logout_uri text,
44
+ backchannel_logout_session_required boolean,
45
+ token_endpoint_auth_method text,
46
+ application_type text,
47
+ jwks text,
48
+ jwks_uri text,
49
+ grant_types jsonb,
50
+ response_types jsonb,
51
+ require_pkce boolean,
52
+ dpop_bound_access_tokens boolean,
53
+ reference_id text,
54
+ metadata jsonb
55
+ )`,
56
+ ddl`create index oauth_client_user_id_idx on ${table("oauth_client")} (user_id)`,
57
+ ddl`create table ${table("oauth_resource")} (
58
+ id ${id} primary key,
59
+ identifier text not null unique,
60
+ name text not null,
61
+ access_token_ttl integer,
62
+ refresh_token_ttl integer,
63
+ signing_algorithm text,
64
+ signing_key_id text,
65
+ allowed_scopes jsonb,
66
+ custom_claims jsonb,
67
+ dpop_bound_access_tokens_required boolean,
68
+ disabled boolean,
69
+ created_at timestamptz,
70
+ updated_at timestamptz,
71
+ policy_version integer,
72
+ metadata jsonb
73
+ )`,
74
+ ddl`create table ${table("oauth_client_resource")} (
75
+ id ${id} primary key,
76
+ client_id text not null references ${table("oauth_client")} (client_id) on delete cascade,
77
+ resource_id text not null references ${table("oauth_resource")} (identifier) on delete cascade,
78
+ metadata jsonb,
79
+ created_at timestamptz
80
+ )`,
81
+ ddl`create index oauth_client_resource_client_id_idx on ${table("oauth_client_resource")} (client_id)`,
82
+ ddl`create index oauth_client_resource_resource_id_idx on ${table("oauth_client_resource")} (resource_id)`,
83
+ ddl`create unique index oauth_client_resource_client_id_resource_id_uidx on ${table("oauth_client_resource")} (client_id, resource_id)`,
84
+ ddl`create table ${table("oauth_refresh_token")} (
85
+ id ${id} primary key,
86
+ token text not null unique,
87
+ client_id text not null references ${table("oauth_client")} (client_id) on delete cascade,
88
+ session_id ${idRef} references ${table("session")} (id) on delete set null,
89
+ user_id ${idRef} not null references ${user} (id) on delete cascade,
90
+ reference_id text,
91
+ authorization_code_id text,
92
+ resources jsonb,
93
+ requested_user_info_claims jsonb,
94
+ expires_at timestamptz not null,
95
+ created_at timestamptz not null,
96
+ revoked timestamptz,
97
+ rotated_at timestamptz,
98
+ rotation_replay_response text,
99
+ rotation_replay_expires_at timestamptz,
100
+ auth_time timestamptz,
101
+ confirmation jsonb,
102
+ scopes jsonb not null
103
+ )`,
104
+ ddl`create index oauth_refresh_token_client_id_idx on ${table("oauth_refresh_token")} (client_id)`,
105
+ ddl`create index oauth_refresh_token_session_id_idx on ${table("oauth_refresh_token")} (session_id)`,
106
+ ddl`create index oauth_refresh_token_user_id_idx on ${table("oauth_refresh_token")} (user_id)`,
107
+ ddl`create index oauth_refresh_token_authorization_code_id_idx on ${table("oauth_refresh_token")} (authorization_code_id)`,
108
+ ddl`create table ${table("oauth_access_token")} (
109
+ id ${id} primary key,
110
+ token text not null unique,
111
+ client_id text not null references ${table("oauth_client")} (client_id) on delete cascade,
112
+ session_id ${idRef} references ${table("session")} (id) on delete set null,
113
+ user_id ${idRef} references ${user} (id) on delete cascade,
114
+ reference_id text,
115
+ authorization_code_id text,
116
+ resources jsonb,
117
+ requested_user_info_claims jsonb,
118
+ refresh_id ${idRef} references ${table("oauth_refresh_token")} (id) on delete cascade,
119
+ expires_at timestamptz not null,
120
+ created_at timestamptz not null,
121
+ revoked timestamptz,
122
+ confirmation jsonb,
123
+ scopes jsonb not null
124
+ )`,
125
+ ddl`create index oauth_access_token_client_id_idx on ${table("oauth_access_token")} (client_id)`,
126
+ ddl`create index oauth_access_token_session_id_idx on ${table("oauth_access_token")} (session_id)`,
127
+ ddl`create index oauth_access_token_user_id_idx on ${table("oauth_access_token")} (user_id)`,
128
+ ddl`create index oauth_access_token_authorization_code_id_idx on ${table("oauth_access_token")} (authorization_code_id)`,
129
+ ddl`create index oauth_access_token_refresh_id_idx on ${table("oauth_access_token")} (refresh_id)`,
130
+ ddl`create table ${table("oauth_consent")} (
131
+ id ${id} primary key,
132
+ client_id text not null references ${table("oauth_client")} (client_id) on delete cascade,
133
+ user_id ${idRef} references ${user} (id) on delete cascade,
134
+ reference_id text,
135
+ resources jsonb,
136
+ requested_user_info_claims jsonb,
137
+ scopes jsonb not null,
138
+ created_at timestamptz not null,
139
+ updated_at timestamptz not null
140
+ )`,
141
+ ddl`create index oauth_consent_client_id_idx on ${table("oauth_consent")} (client_id)`,
142
+ ddl`create index oauth_consent_user_id_idx on ${table("oauth_consent")} (user_id)`,
143
+ ddl`create table ${table("oauth_client_assertion")} (
144
+ id ${id} primary key,
145
+ expires_at timestamptz not null
146
+ )`
147
+ ]
148
+ };
149
+ //#endregion
150
+ export { mcp };