mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
improvement(supabase): allow non-public schemas (#2511)
This commit is contained in:
committed by
GitHub
parent
f21eaf1f10
commit
e4d211c2f0
@@ -69,6 +69,16 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
|
||||
value: ['query', 'get_row', 'insert', 'update', 'delete', 'upsert', 'count', 'text_search'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'schema',
|
||||
title: 'Schema',
|
||||
type: 'short-input',
|
||||
placeholder: 'public (default)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['query', 'get_row', 'insert', 'update', 'delete', 'upsert', 'count', 'text_search'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Service Role Secret',
|
||||
@@ -1026,6 +1036,7 @@ Return ONLY the PostgREST filter expression - no explanations, no markdown, no e
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
projectId: { type: 'string', description: 'Supabase project identifier' },
|
||||
table: { type: 'string', description: 'Database table name' },
|
||||
schema: { type: 'string', description: 'Database schema (default: public)' },
|
||||
apiKey: { type: 'string', description: 'Service role secret key' },
|
||||
// Data for insert/update operations
|
||||
data: { type: 'json', description: 'Row data' },
|
||||
|
||||
@@ -20,6 +20,13 @@ export const countTool: ToolConfig<SupabaseCountParams, SupabaseCountResponse> =
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to count rows from',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to count from (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
@@ -54,11 +61,15 @@ export const countTool: ToolConfig<SupabaseCountParams, SupabaseCountResponse> =
|
||||
method: 'HEAD',
|
||||
headers: (params) => {
|
||||
const countType = params.countType || 'exact'
|
||||
return {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
Prefer: `count=${countType}`,
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Accept-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ export const deleteTool: ToolConfig<SupabaseDeleteParams, SupabaseDeleteResponse
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to delete from',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to delete from (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
@@ -51,11 +58,17 @@ export const deleteTool: ToolConfig<SupabaseDeleteParams, SupabaseDeleteResponse
|
||||
return url
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
Prefer: 'return=representation',
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
Prefer: 'return=representation',
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Content-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
|
||||
@@ -20,6 +20,13 @@ export const getRowTool: ToolConfig<SupabaseGetRowParams, SupabaseGetRowResponse
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to query',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to query from (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
@@ -50,10 +57,16 @@ export const getRowTool: ToolConfig<SupabaseGetRowParams, SupabaseGetRowResponse
|
||||
return url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Accept-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
|
||||
@@ -20,6 +20,13 @@ export const insertTool: ToolConfig<SupabaseInsertParams, SupabaseInsertResponse
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to insert data into',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to insert into (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
data: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
@@ -37,12 +44,18 @@ export const insertTool: ToolConfig<SupabaseInsertParams, SupabaseInsertResponse
|
||||
request: {
|
||||
url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation',
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation',
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Content-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
body: (params) => {
|
||||
// Prepare the data - if it's an object but not an array, wrap it in an array
|
||||
const dataToSend =
|
||||
|
||||
@@ -20,6 +20,13 @@ export const queryTool: ToolConfig<SupabaseQueryParams, SupabaseQueryResponse> =
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to query',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to query from (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
@@ -84,10 +91,16 @@ export const queryTool: ToolConfig<SupabaseQueryParams, SupabaseQueryResponse> =
|
||||
return url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Accept-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
|
||||
@@ -20,6 +20,13 @@ export const textSearchTool: ToolConfig<SupabaseTextSearchParams, SupabaseTextSe
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to search',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to search in (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
column: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
@@ -86,10 +93,16 @@ export const textSearchTool: ToolConfig<SupabaseTextSearchParams, SupabaseTextSe
|
||||
return url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Accept-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface SupabaseQueryParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
filter?: string
|
||||
orderBy?: string
|
||||
limit?: number
|
||||
@@ -13,6 +14,7 @@ export interface SupabaseInsertParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
data: any
|
||||
}
|
||||
|
||||
@@ -20,6 +22,7 @@ export interface SupabaseGetRowParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
filter: string
|
||||
}
|
||||
|
||||
@@ -27,6 +30,7 @@ export interface SupabaseUpdateParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
filter: string
|
||||
data: any
|
||||
}
|
||||
@@ -35,6 +39,7 @@ export interface SupabaseDeleteParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
filter: string
|
||||
}
|
||||
|
||||
@@ -42,6 +47,7 @@ export interface SupabaseUpsertParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
data: any
|
||||
}
|
||||
|
||||
@@ -93,6 +99,7 @@ export interface SupabaseTextSearchParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
column: string
|
||||
query: string
|
||||
searchType?: string
|
||||
@@ -107,6 +114,7 @@ export interface SupabaseCountParams {
|
||||
apiKey: string
|
||||
projectId: string
|
||||
table: string
|
||||
schema?: string
|
||||
filter?: string
|
||||
countType?: string
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@ export const updateTool: ToolConfig<SupabaseUpdateParams, SupabaseUpdateResponse
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to update',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to update in (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
@@ -53,12 +60,18 @@ export const updateTool: ToolConfig<SupabaseUpdateParams, SupabaseUpdateResponse
|
||||
return url
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation',
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation',
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Content-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
body: (params) => params.data,
|
||||
},
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ export const upsertTool: ToolConfig<SupabaseUpsertParams, SupabaseUpsertResponse
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The name of the Supabase table to upsert data into',
|
||||
},
|
||||
schema: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Database schema to upsert into (default: public). Use this to access tables in other schemas.',
|
||||
},
|
||||
data: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
@@ -37,12 +44,18 @@ export const upsertTool: ToolConfig<SupabaseUpsertParams, SupabaseUpsertResponse
|
||||
request: {
|
||||
url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation,resolution=merge-duplicates',
|
||||
}),
|
||||
headers: (params) => {
|
||||
const headers: Record<string, string> = {
|
||||
apikey: params.apiKey,
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
Prefer: 'return=representation,resolution=merge-duplicates',
|
||||
}
|
||||
if (params.schema) {
|
||||
headers['Content-Profile'] = params.schema
|
||||
}
|
||||
return headers
|
||||
},
|
||||
body: (params) => {
|
||||
// Prepare the data - if it's an object but not an array, wrap it in an array
|
||||
const dataToSend =
|
||||
|
||||
Reference in New Issue
Block a user