@protobase/server 0.34.2 → 0.34.3
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,14 +3,15 @@ import { AdminAuth } from "./create-auth.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* The SQL that brings the admin store up to what this version of Protobase and the project's Better Auth plugins need:
|
|
5
5
|
* for a store with the camelCase names of Protobase 0.6, their rename to snake_case (`snakeCaseMigration`); otherwise
|
|
6
|
-
* new tables, columns and indexes,
|
|
7
|
-
* change Better Auth cannot make safely, such as a required
|
|
6
|
+
* new tables, columns and indexes, each skipped where it exists, and never a drop but of MCP's tables once MCP is off
|
|
7
|
+
* (`dropMcpTables`). `undefined` when the store is current. A change Better Auth cannot make safely, such as a required
|
|
8
|
+
* column without a default on a table with rows, is an error.
|
|
8
9
|
*/
|
|
9
10
|
export declare const authSchemaMigration: (auth: AdminAuth) => Promise<string | undefined>;
|
|
10
11
|
/**
|
|
11
|
-
* Refuses to go on while the admin store lacks a table or column Better Auth needs,
|
|
12
|
-
*
|
|
13
|
-
* migrations do, before the new version serves.
|
|
12
|
+
* Refuses to go on while the admin store lacks a table or column Better Auth needs, still has the camelCase names of
|
|
13
|
+
* Protobase 0.6, since every sign-in would fail, or still has MCP's tables with MCP off, since their grants would come
|
|
14
|
+
* back with MCP. The server never changes the schema itself: the project's migrations do, before the new version serves.
|
|
14
15
|
*/
|
|
15
16
|
export declare const checkAuthSchema: (auth: AdminAuth) => Promise<void>;
|
|
16
17
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { dropMcpTables, leftoverMcpTables, mcpTableNames, withMcpTables } from "./mcp/mcp-tables.js";
|
|
1
2
|
import { snakeCaseMigration } from "./snake-case-migration.js";
|
|
2
3
|
import { getMigrations } from "better-auth/db/migration";
|
|
3
4
|
//#region src/better-auth/auth-schema.ts
|
|
@@ -18,28 +19,36 @@ const storeSchema = ({ options: { database } }) => database && "schemaName" in d
|
|
|
18
19
|
/**
|
|
19
20
|
* The SQL that brings the admin store up to what this version of Protobase and the project's Better Auth plugins need:
|
|
20
21
|
* for a store with the camelCase names of Protobase 0.6, their rename to snake_case (`snakeCaseMigration`); otherwise
|
|
21
|
-
* new tables, columns and indexes,
|
|
22
|
-
* change Better Auth cannot make safely, such as a required
|
|
22
|
+
* new tables, columns and indexes, each skipped where it exists, and never a drop but of MCP's tables once MCP is off
|
|
23
|
+
* (`dropMcpTables`). `undefined` when the store is current. A change Better Auth cannot make safely, such as a required
|
|
24
|
+
* column without a default on a table with rows, is an error.
|
|
23
25
|
*/
|
|
24
26
|
const authSchemaMigration = async (auth) => {
|
|
25
|
-
|
|
27
|
+
const found = await getMigrations(withMcpTables(auth), { throwOnUnsafe: false });
|
|
28
|
+
if (hasCamelCaseNames(found)) return snakeCaseMigration(storeSchema(auth));
|
|
29
|
+
const drop = leftoverMcpTables(auth, found).length > 0 ? [dropMcpTables(storeSchema(auth))] : [];
|
|
26
30
|
const { toBeCreated, toBeAdded, toBeAddedIndexes, compileMigrations } = await getMigrations(auth.options);
|
|
27
|
-
|
|
28
|
-
return
|
|
31
|
+
const statements = [...toBeCreated.length === 0 && toBeAdded.length === 0 && toBeAddedIndexes.length === 0 ? [] : [skipExisting(await compileMigrations())], ...drop];
|
|
32
|
+
return statements.length === 0 ? void 0 : statements.join("\n\n");
|
|
29
33
|
};
|
|
30
|
-
/** The tables and `table.column`s the admin store lacks; an index missing is not a reason to refuse requests. */
|
|
31
|
-
const missingTablesAndColumns = ({ toBeCreated, toBeAdded }) => [...toBeCreated.map(({ table }) => table), ...toBeAdded.flatMap(({ table, fields }) => Object.keys(fields).map((field) => `${table}.${field}`))];
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
|
|
35
|
+
* The tables and `table.column`s the admin store lacks; an index missing is not a reason to refuse requests. MCP's
|
|
36
|
+
* tables, named with MCP off only to find them left over, are never missing then.
|
|
37
|
+
*/
|
|
38
|
+
const missingTablesAndColumns = (auth, { toBeCreated, toBeAdded }) => [...toBeCreated.map(({ table }) => table).filter((table) => auth.mcp || !mcpTableNames.includes(table)), ...toBeAdded.flatMap(({ table, fields }) => Object.keys(fields).map((field) => `${table}.${field}`))];
|
|
39
|
+
/**
|
|
40
|
+
* Refuses to go on while the admin store lacks a table or column Better Auth needs, still has the camelCase names of
|
|
41
|
+
* Protobase 0.6, since every sign-in would fail, or still has MCP's tables with MCP off, since their grants would come
|
|
42
|
+
* back with MCP. The server never changes the schema itself: the project's migrations do, before the new version serves.
|
|
36
43
|
*/
|
|
37
44
|
const checkAuthSchema = async (auth) => {
|
|
38
|
-
const plan = await getMigrations(auth
|
|
45
|
+
const plan = await getMigrations(withMcpTables(auth), { throwOnUnsafe: false });
|
|
39
46
|
if (hasCamelCaseNames(plan)) throw new Error(`The auth schema still has the camelCase names of Protobase 0.6, which this version names in snake_case. Write their rename as a migration with \`${authMigrationCommand}\`, apply it with the project's migrations, then start again.`);
|
|
40
|
-
const missing = missingTablesAndColumns(plan);
|
|
41
|
-
if (missing.length
|
|
42
|
-
|
|
47
|
+
const missing = missingTablesAndColumns(auth, plan);
|
|
48
|
+
if (missing.length > 0) throw new Error(`The auth schema is behind this version of Protobase (missing ${missing.join(", ")}). Write the change as a migration with \`${authMigrationCommand}\`, apply it with the project's migrations, then start again.`);
|
|
49
|
+
const leftovers = leftoverMcpTables(auth, plan);
|
|
50
|
+
if (leftovers.length === 0) return;
|
|
51
|
+
throw new Error(`The auth schema still has the tables of the OAuth provider for MCP (${leftovers.join(", ")}), which is off. Write their removal as a migration with \`${authMigrationCommand}\`, apply it with the project's migrations, then start again; every MCP client then has to be allowed again.`);
|
|
43
52
|
};
|
|
44
53
|
//#endregion
|
|
45
54
|
export { authMigrationCommand, authSchemaMigration, checkAuthSchema, skipExisting };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { pluginNames } from "../snake-case-names.js";
|
|
2
|
+
//#region src/better-auth/mcp/mcp-tables.ts
|
|
3
|
+
/** The database names of MCP's tables. */
|
|
4
|
+
const mcpTableNames = Object.values(pluginNames.mcp).map(({ modelName }) => modelName);
|
|
5
|
+
const mcpTablesPlugin = {
|
|
6
|
+
id: "protobase-mcp-tables",
|
|
7
|
+
schema: Object.fromEntries(Object.entries(pluginNames.mcp).map(([model, { modelName }]) => [model, {
|
|
8
|
+
modelName,
|
|
9
|
+
fields: {}
|
|
10
|
+
}]))
|
|
11
|
+
};
|
|
12
|
+
/** The auth's options, which with MCP off also name MCP's tables, for a plan that tells whether they are left over. */
|
|
13
|
+
const withMcpTables = (auth) => auth.mcp ? auth.options : {
|
|
14
|
+
...auth.options,
|
|
15
|
+
plugins: [...auth.options.plugins ?? [], mcpTablesPlugin]
|
|
16
|
+
};
|
|
17
|
+
/** The MCP tables the store still has while MCP is off, from a plan made with `withMcpTables`; none with MCP on. */
|
|
18
|
+
const leftoverMcpTables = (auth, { toBeCreated }) => {
|
|
19
|
+
if (auth.mcp) return [];
|
|
20
|
+
const missing = new Set(toBeCreated.map(({ table }) => table));
|
|
21
|
+
return mcpTableNames.filter((table) => !missing.has(table));
|
|
22
|
+
};
|
|
23
|
+
const schemaName = /^[a-z_][a-z0-9_]*$/;
|
|
24
|
+
/** The statement that drops MCP's tables, in `schema` or the connection's current one. */
|
|
25
|
+
const dropMcpTables = (schema) => {
|
|
26
|
+
if (schema !== void 0 && !schemaName.test(schema)) throw new Error(`Invalid auth schema name "${schema}"`);
|
|
27
|
+
const s = schema === void 0 ? "" : `"${schema}".`;
|
|
28
|
+
return `-- MCP is off: dropping the tables of its OAuth provider disconnects every MCP client and forgets every grant.
|
|
29
|
+
drop table if exists ${mcpTableNames.map((table) => `${s}"${table}"`).join(", ")};`;
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { dropMcpTables, leftoverMcpTables, mcpTableNames, withMcpTables };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.3",
|
|
4
4
|
"description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"@better-auth/oauth-provider": "^1.7.12",
|
|
36
36
|
"@better-auth/passkey": "^1.7.12",
|
|
37
37
|
"@better-auth/sso": "^1.7.12",
|
|
38
|
-
"@protobase/layout": "0.34.
|
|
39
|
-
"@protobase/query": "0.34.
|
|
40
|
-
"@protobase/schema": "0.34.
|
|
38
|
+
"@protobase/layout": "0.34.3",
|
|
39
|
+
"@protobase/query": "0.34.3",
|
|
40
|
+
"@protobase/schema": "0.34.3",
|
|
41
41
|
"@react-email/render": "^2.1.0",
|
|
42
42
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
43
43
|
"@sentry/core": "^11.7.0",
|