Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 230 additions & 22 deletions apps/sim/blocks/blocks/google_bigquery.ts

Large diffs are not rendered by default.

122 changes: 122 additions & 0 deletions apps/sim/tools/google_bigquery/create_dataset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import type {
GoogleBigQueryCreateDatasetParams,
GoogleBigQueryCreateDatasetResponse,
} from '@/tools/google_bigquery/types'
import type { ToolConfig } from '@/tools/types'

export const googleBigQueryCreateDatasetTool: ToolConfig<
GoogleBigQueryCreateDatasetParams,
GoogleBigQueryCreateDatasetResponse
> = {
id: 'google_bigquery_create_dataset',
name: 'BigQuery Create Dataset',
description: 'Create a new dataset in a Google BigQuery project',
version: '1.0.0',

oauth: {
required: true,
provider: 'google-bigquery',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Google Cloud project ID',
},
datasetId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID for the new BigQuery dataset',
},
location: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Geographic location for the dataset (e.g., "US", "EU")',
},
friendlyName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Human-readable name for the dataset',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of the dataset',
},
},

request: {
url: (params) =>
`https://bigquery.googleapis.com/bigquery/v2/projects/${encodeURIComponent(params.projectId)}/datasets`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {
datasetReference: {
projectId: params.projectId,
datasetId: params.datasetId.trim(),
},
Comment thread
waleedlatif1 marked this conversation as resolved.
}
if (params.location) body.location = params.location
if (params.friendlyName) body.friendlyName = params.friendlyName
if (params.description) body.description = params.description
return body
},
},

transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
const errorMessage = data.error?.message || 'Failed to create BigQuery dataset'
throw new Error(errorMessage)
}

return {
success: true,
output: {
datasetId: data.datasetReference?.datasetId ?? null,
projectId: data.datasetReference?.projectId ?? null,
friendlyName: data.friendlyName ?? null,
description: data.description ?? null,
location: data.location ?? null,
creationTime: data.creationTime ?? null,
},
}
},

outputs: {
datasetId: { type: 'string', description: 'Unique dataset identifier' },
projectId: { type: 'string', description: 'Project ID containing this dataset' },
friendlyName: {
type: 'string',
description: 'Descriptive name for the dataset',
optional: true,
},
description: { type: 'string', description: 'Dataset description', optional: true },
location: {
type: 'string',
description: 'Geographic location where the data resides',
optional: true,
},
creationTime: {
type: 'string',
description: 'Dataset creation time (milliseconds since epoch)',
optional: true,
},
},
}
173 changes: 173 additions & 0 deletions apps/sim/tools/google_bigquery/create_table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import type {
GoogleBigQueryCreateTableParams,
GoogleBigQueryCreateTableResponse,
} from '@/tools/google_bigquery/types'
import type { ToolConfig } from '@/tools/types'

export const googleBigQueryCreateTableTool: ToolConfig<
GoogleBigQueryCreateTableParams,
GoogleBigQueryCreateTableResponse
> = {
id: 'google_bigquery_create_table',
name: 'BigQuery Create Table',
description: 'Create a new table in a Google BigQuery dataset',
version: '1.0.0',

oauth: {
required: true,
provider: 'google-bigquery',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Google Cloud project ID',
},
datasetId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'BigQuery dataset ID',
},
tableId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'ID for the new BigQuery table',
},
schema: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'JSON array of column field definitions, e.g. [{"name":"id","type":"STRING","mode":"REQUIRED"}]',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Description of the table',
},
friendlyName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Human-readable name for the table',
},
},

request: {
url: (params) =>
`https://bigquery.googleapis.com/bigquery/v2/projects/${encodeURIComponent(params.projectId)}/datasets/${encodeURIComponent(params.datasetId.trim())}/tables`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}),
body: (params) => {
let fields: unknown
try {
fields = typeof params.schema === 'string' ? JSON.parse(params.schema) : params.schema
} catch {
fields = null
}
if (
!Array.isArray(fields) ||
fields.length === 0 ||
!fields.every(
(f) => f && typeof f === 'object' && typeof (f as { name?: unknown }).name === 'string'
)
) {
throw new Error(
'Schema must be a JSON array of column field definitions, e.g. [{"name":"id","type":"STRING"}]'
)
}

const body: Record<string, unknown> = {
tableReference: {
projectId: params.projectId,
datasetId: params.datasetId.trim(),
tableId: params.tableId.trim(),
},
Comment thread
waleedlatif1 marked this conversation as resolved.
schema: { fields },
}
Comment thread
waleedlatif1 marked this conversation as resolved.
if (params.description) body.description = params.description
if (params.friendlyName) body.friendlyName = params.friendlyName
return body
},
},

transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
const errorMessage = data.error?.message || 'Failed to create BigQuery table'
throw new Error(errorMessage)
}

const schema = (data.schema?.fields ?? []).map(
(f: { name: string; type: string; mode?: string; description?: string }) => ({
name: f.name,
type: f.type,
mode: f.mode ?? null,
description: f.description ?? null,
})
)

return {
success: true,
output: {
tableId: data.tableReference?.tableId ?? null,
datasetId: data.tableReference?.datasetId ?? null,
projectId: data.tableReference?.projectId ?? null,
type: data.type ?? null,
description: data.description ?? null,
schema,
creationTime: data.creationTime ?? null,
location: data.location ?? null,
},
}
},

outputs: {
tableId: { type: 'string', description: 'Table ID' },
datasetId: { type: 'string', description: 'Dataset ID' },
projectId: { type: 'string', description: 'Project ID' },
type: { type: 'string', description: 'Table type (usually TABLE)', optional: true },
description: { type: 'string', description: 'Table description', optional: true },
schema: {
type: 'array',
description: 'Array of column definitions',
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Column name' },
type: { type: 'string', description: 'Data type' },
mode: {
type: 'string',
description: 'Column mode (NULLABLE, REQUIRED, or REPEATED)',
optional: true,
},
description: { type: 'string', description: 'Column description', optional: true },
},
},
},
creationTime: {
type: 'string',
description: 'Table creation time (milliseconds since epoch)',
optional: true,
},
location: {
type: 'string',
description: 'Geographic location where the table resides',
optional: true,
},
},
}
82 changes: 82 additions & 0 deletions apps/sim/tools/google_bigquery/delete_dataset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type {
GoogleBigQueryDeleteDatasetParams,
GoogleBigQueryDeleteDatasetResponse,
} from '@/tools/google_bigquery/types'
import type { ToolConfig } from '@/tools/types'

export const googleBigQueryDeleteDatasetTool: ToolConfig<
GoogleBigQueryDeleteDatasetParams,
GoogleBigQueryDeleteDatasetResponse
> = {
id: 'google_bigquery_delete_dataset',
name: 'BigQuery Delete Dataset',
description: 'Delete a dataset from a Google BigQuery project',
version: '1.0.0',

oauth: {
required: true,
provider: 'google-bigquery',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token',
},
projectId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Google Cloud project ID',
},
datasetId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'BigQuery dataset ID to delete',
},
deleteContents: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to delete tables inside the dataset (default: false)',
},
},

request: {
url: (params) => {
const url = new URL(
`https://bigquery.googleapis.com/bigquery/v2/projects/${encodeURIComponent(params.projectId)}/datasets/${encodeURIComponent(params.datasetId.trim())}`
)
if (params.deleteContents !== undefined) {
url.searchParams.set('deleteContents', String(params.deleteContents))
}
return url.toString()
},
method: 'DELETE',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
}),
},

transformResponse: async (response: Response) => {
if (!response.ok) {
const data = await response.json()
const errorMessage = data.error?.message || 'Failed to delete BigQuery dataset'
throw new Error(errorMessage)
}

return {
success: true,
output: {
deleted: true,
},
}
},

outputs: {
deleted: { type: 'boolean', description: 'Whether the dataset was deleted' },
},
}
Loading
Loading