feat: migrate to docker-compose with selfhosted-supabase-mcp
- Replace legacy directory structure (api/, db/, functions/, logs/, pooler/) with single docker-compose.yml based self-hosted setup - Add selfhosted-supabase-mcp TypeScript MCP server for database management - Add .dockerignore for Docker build context - Update .gitignore to exclude .env files, volumes/, backups, logs
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { z } from 'zod';
|
||||
import { handleSqlResponse, executeSqlWithFallback } from './utils.js';
|
||||
import type { ToolContext } from './types.js';
|
||||
|
||||
// Schema for edge function output
|
||||
const EdgeFunctionSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
slug: z.string(),
|
||||
status: z.string().nullable(),
|
||||
version: z.number().nullable(),
|
||||
created_at: z.string().nullable(),
|
||||
updated_at: z.string().nullable(),
|
||||
});
|
||||
const ListEdgeFunctionsOutputSchema = z.array(EdgeFunctionSchema);
|
||||
type ListEdgeFunctionsOutput = z.infer<typeof ListEdgeFunctionsOutputSchema>;
|
||||
|
||||
// Input schema (none needed)
|
||||
const ListEdgeFunctionsInputSchema = z.object({});
|
||||
type ListEdgeFunctionsInput = z.infer<typeof ListEdgeFunctionsInputSchema>;
|
||||
|
||||
// Static JSON Schema for MCP capabilities
|
||||
const mcpInputSchema = {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
};
|
||||
|
||||
// Tool definition
|
||||
export const listEdgeFunctionsTool = {
|
||||
name: 'list_edge_functions',
|
||||
description: 'Lists all deployed Supabase Edge Functions. Returns empty array if edge functions are not available or none are deployed.',
|
||||
inputSchema: ListEdgeFunctionsInputSchema,
|
||||
mcpInputSchema: mcpInputSchema,
|
||||
outputSchema: ListEdgeFunctionsOutputSchema,
|
||||
execute: async (input: ListEdgeFunctionsInput, context: ToolContext): Promise<ListEdgeFunctionsOutput> => {
|
||||
const client = context.selfhostedClient;
|
||||
|
||||
// First check if supabase_functions schema exists
|
||||
const checkSchemaSql = `
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = 'supabase_functions'
|
||||
) AS exists
|
||||
`;
|
||||
|
||||
const schemaCheckResult = await executeSqlWithFallback(client, checkSchemaSql, true);
|
||||
|
||||
// Handle the schema check result
|
||||
if (Array.isArray(schemaCheckResult) && schemaCheckResult.length > 0) {
|
||||
const exists = schemaCheckResult[0]?.exists;
|
||||
if (!exists) {
|
||||
context.log('supabase_functions schema not found - Edge Functions may not be available in this installation', 'info');
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
context.log('Could not verify supabase_functions schema', 'warn');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Check if the functions table exists
|
||||
const checkTableSql = `
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_catalog.pg_tables
|
||||
WHERE schemaname = 'supabase_functions' AND tablename = 'functions'
|
||||
) AS exists
|
||||
`;
|
||||
|
||||
const tableCheckResult = await executeSqlWithFallback(client, checkTableSql, true);
|
||||
|
||||
if (Array.isArray(tableCheckResult) && tableCheckResult.length > 0) {
|
||||
const exists = tableCheckResult[0]?.exists;
|
||||
if (!exists) {
|
||||
context.log('supabase_functions.functions table not found', 'info');
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
context.log('Could not verify functions table', 'warn');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Query edge functions
|
||||
const listEdgeFunctionsSql = `
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
slug,
|
||||
status,
|
||||
version,
|
||||
created_at::text,
|
||||
updated_at::text
|
||||
FROM supabase_functions.functions
|
||||
ORDER BY name
|
||||
`;
|
||||
|
||||
const result = await executeSqlWithFallback(client, listEdgeFunctionsSql, true);
|
||||
return handleSqlResponse(result, ListEdgeFunctionsOutputSchema);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user