v0.5.40: supabase ops to allow non-public schemas, jira uuid

This commit is contained in:
Vikhyath Mondreti
2025-12-21 22:28:05 -08:00
committed by GitHub
11 changed files with 163 additions and 40 deletions

View File

@@ -253,10 +253,10 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
condition: { field: 'operation', value: 'write' }, condition: { field: 'operation', value: 'write' },
}, },
{ {
id: 'teamUuid', id: 'customFieldValue',
title: 'Team UUID', title: 'Custom Field Value',
type: 'short-input', type: 'short-input',
placeholder: 'e.g., b3aa307a-76ea-462d-b6f1-a6e89ce9858a', placeholder: 'Value for the custom field',
dependsOn: ['projectId'], dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' }, condition: { field: 'operation', value: 'write' },
}, },
@@ -561,6 +561,8 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
.filter((item) => item !== '') .filter((item) => item !== '')
} }
const customFieldValue = params.customFieldValue || undefined
const writeParams = { const writeParams = {
projectId: effectiveProjectId, projectId: effectiveProjectId,
summary: params.summary || '', summary: params.summary || '',
@@ -574,7 +576,7 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
reporter: params.reporter || undefined, reporter: params.reporter || undefined,
environment: params.environment || undefined, environment: params.environment || undefined,
customFieldId: params.customFieldId || undefined, customFieldId: params.customFieldId || undefined,
customFieldValue: params.customFieldValue || undefined, customFieldValue: customFieldValue,
} }
return { return {
...baseParams, ...baseParams,

View File

@@ -69,6 +69,16 @@ export const SupabaseBlock: BlockConfig<SupabaseResponse> = {
value: ['query', 'get_row', 'insert', 'update', 'delete', 'upsert', 'count', 'text_search'], 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', id: 'apiKey',
title: 'Service Role Secret', 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' }, operation: { type: 'string', description: 'Operation to perform' },
projectId: { type: 'string', description: 'Supabase project identifier' }, projectId: { type: 'string', description: 'Supabase project identifier' },
table: { type: 'string', description: 'Database table name' }, table: { type: 'string', description: 'Database table name' },
schema: { type: 'string', description: 'Database schema (default: public)' },
apiKey: { type: 'string', description: 'Service role secret key' }, apiKey: { type: 'string', description: 'Service role secret key' },
// Data for insert/update operations // Data for insert/update operations
data: { type: 'json', description: 'Row data' }, data: { type: 'json', description: 'Row data' },

View File

@@ -20,6 +20,13 @@ export const countTool: ToolConfig<SupabaseCountParams, SupabaseCountResponse> =
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to count rows from', 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: { filter: {
type: 'string', type: 'string',
required: false, required: false,
@@ -54,11 +61,15 @@ export const countTool: ToolConfig<SupabaseCountParams, SupabaseCountResponse> =
method: 'HEAD', method: 'HEAD',
headers: (params) => { headers: (params) => {
const countType = params.countType || 'exact' const countType = params.countType || 'exact'
return { const headers: Record<string, string> = {
apikey: params.apiKey, apikey: params.apiKey,
Authorization: `Bearer ${params.apiKey}`, Authorization: `Bearer ${params.apiKey}`,
Prefer: `count=${countType}`, Prefer: `count=${countType}`,
} }
if (params.schema) {
headers['Accept-Profile'] = params.schema
}
return headers
}, },
}, },

View File

@@ -20,6 +20,13 @@ export const deleteTool: ToolConfig<SupabaseDeleteParams, SupabaseDeleteResponse
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to delete from', 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: { filter: {
type: 'string', type: 'string',
required: true, required: true,
@@ -51,11 +58,17 @@ export const deleteTool: ToolConfig<SupabaseDeleteParams, SupabaseDeleteResponse
return url return url
}, },
method: 'DELETE', method: 'DELETE',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
Prefer: 'return=representation', Authorization: `Bearer ${params.apiKey}`,
}), Prefer: 'return=representation',
}
if (params.schema) {
headers['Content-Profile'] = params.schema
}
return headers
},
}, },
transformResponse: async (response: Response) => { transformResponse: async (response: Response) => {

View File

@@ -20,6 +20,13 @@ export const getRowTool: ToolConfig<SupabaseGetRowParams, SupabaseGetRowResponse
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to query', 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: { filter: {
type: 'string', type: 'string',
required: true, required: true,
@@ -50,10 +57,16 @@ export const getRowTool: ToolConfig<SupabaseGetRowParams, SupabaseGetRowResponse
return url return url
}, },
method: 'GET', method: 'GET',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
}), Authorization: `Bearer ${params.apiKey}`,
}
if (params.schema) {
headers['Accept-Profile'] = params.schema
}
return headers
},
}, },
transformResponse: async (response: Response) => { transformResponse: async (response: Response) => {

View File

@@ -20,6 +20,13 @@ export const insertTool: ToolConfig<SupabaseInsertParams, SupabaseInsertResponse
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to insert data into', 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: { data: {
type: 'array', type: 'array',
required: true, required: true,
@@ -37,12 +44,18 @@ export const insertTool: ToolConfig<SupabaseInsertParams, SupabaseInsertResponse
request: { request: {
url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`, url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`,
method: 'POST', method: 'POST',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
'Content-Type': 'application/json', Authorization: `Bearer ${params.apiKey}`,
Prefer: 'return=representation', 'Content-Type': 'application/json',
}), Prefer: 'return=representation',
}
if (params.schema) {
headers['Content-Profile'] = params.schema
}
return headers
},
body: (params) => { body: (params) => {
// Prepare the data - if it's an object but not an array, wrap it in an array // Prepare the data - if it's an object but not an array, wrap it in an array
const dataToSend = const dataToSend =

View File

@@ -20,6 +20,13 @@ export const queryTool: ToolConfig<SupabaseQueryParams, SupabaseQueryResponse> =
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to query', 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: { filter: {
type: 'string', type: 'string',
required: false, required: false,
@@ -84,10 +91,16 @@ export const queryTool: ToolConfig<SupabaseQueryParams, SupabaseQueryResponse> =
return url return url
}, },
method: 'GET', method: 'GET',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
}), Authorization: `Bearer ${params.apiKey}`,
}
if (params.schema) {
headers['Accept-Profile'] = params.schema
}
return headers
},
}, },
transformResponse: async (response: Response) => { transformResponse: async (response: Response) => {

View File

@@ -20,6 +20,13 @@ export const textSearchTool: ToolConfig<SupabaseTextSearchParams, SupabaseTextSe
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to search', 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: { column: {
type: 'string', type: 'string',
required: true, required: true,
@@ -86,10 +93,16 @@ export const textSearchTool: ToolConfig<SupabaseTextSearchParams, SupabaseTextSe
return url return url
}, },
method: 'GET', method: 'GET',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
}), Authorization: `Bearer ${params.apiKey}`,
}
if (params.schema) {
headers['Accept-Profile'] = params.schema
}
return headers
},
}, },
transformResponse: async (response: Response) => { transformResponse: async (response: Response) => {

View File

@@ -4,6 +4,7 @@ export interface SupabaseQueryParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
filter?: string filter?: string
orderBy?: string orderBy?: string
limit?: number limit?: number
@@ -13,6 +14,7 @@ export interface SupabaseInsertParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
data: any data: any
} }
@@ -20,6 +22,7 @@ export interface SupabaseGetRowParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
filter: string filter: string
} }
@@ -27,6 +30,7 @@ export interface SupabaseUpdateParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
filter: string filter: string
data: any data: any
} }
@@ -35,6 +39,7 @@ export interface SupabaseDeleteParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
filter: string filter: string
} }
@@ -42,6 +47,7 @@ export interface SupabaseUpsertParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
data: any data: any
} }
@@ -93,6 +99,7 @@ export interface SupabaseTextSearchParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
column: string column: string
query: string query: string
searchType?: string searchType?: string
@@ -107,6 +114,7 @@ export interface SupabaseCountParams {
apiKey: string apiKey: string
projectId: string projectId: string
table: string table: string
schema?: string
filter?: string filter?: string
countType?: string countType?: string
} }

View File

@@ -20,6 +20,13 @@ export const updateTool: ToolConfig<SupabaseUpdateParams, SupabaseUpdateResponse
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to update', 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: { filter: {
type: 'string', type: 'string',
required: true, required: true,
@@ -53,12 +60,18 @@ export const updateTool: ToolConfig<SupabaseUpdateParams, SupabaseUpdateResponse
return url return url
}, },
method: 'PATCH', method: 'PATCH',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
'Content-Type': 'application/json', Authorization: `Bearer ${params.apiKey}`,
Prefer: 'return=representation', 'Content-Type': 'application/json',
}), Prefer: 'return=representation',
}
if (params.schema) {
headers['Content-Profile'] = params.schema
}
return headers
},
body: (params) => params.data, body: (params) => params.data,
}, },

View File

@@ -20,6 +20,13 @@ export const upsertTool: ToolConfig<SupabaseUpsertParams, SupabaseUpsertResponse
visibility: 'user-or-llm', visibility: 'user-or-llm',
description: 'The name of the Supabase table to upsert data into', 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: { data: {
type: 'array', type: 'array',
required: true, required: true,
@@ -37,12 +44,18 @@ export const upsertTool: ToolConfig<SupabaseUpsertParams, SupabaseUpsertResponse
request: { request: {
url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`, url: (params) => `https://${params.projectId}.supabase.co/rest/v1/${params.table}?select=*`,
method: 'POST', method: 'POST',
headers: (params) => ({ headers: (params) => {
apikey: params.apiKey, const headers: Record<string, string> = {
Authorization: `Bearer ${params.apiKey}`, apikey: params.apiKey,
'Content-Type': 'application/json', Authorization: `Bearer ${params.apiKey}`,
Prefer: 'return=representation,resolution=merge-duplicates', 'Content-Type': 'application/json',
}), Prefer: 'return=representation,resolution=merge-duplicates',
}
if (params.schema) {
headers['Content-Profile'] = params.schema
}
return headers
},
body: (params) => { body: (params) => {
// Prepare the data - if it's an object but not an array, wrap it in an array // Prepare the data - if it's an object but not an array, wrap it in an array
const dataToSend = const dataToSend =