first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,59 @@
import type { INodeProperties } from 'n8n-workflow';
export const alertsOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['alerts'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get specific alert',
routing: {
request: {
method: 'GET',
url: '={{"/api/alert/" + $parameter.alertId}}',
},
},
action: 'Get an alert',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many alerts',
routing: {
request: {
method: 'GET',
url: '/api/alert/',
},
},
action: 'Get many alerts',
},
],
default: 'getAll',
},
];
export const alertsFields: INodeProperties[] = [
{
displayName: 'Alert ID',
name: 'alertId',
type: 'string',
required: true,
placeholder: '0',
displayOptions: {
show: {
resource: ['alerts'],
operation: ['get'],
},
},
default: '',
},
];
@@ -0,0 +1,331 @@
import type { INodeProperties } from 'n8n-workflow';
export const databasesOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['databases'],
},
},
options: [
{
name: 'Add',
value: 'addNewDatasource',
description: 'Add a new datasource to the metabase instance',
routing: {
request: {
method: 'POST',
url: '/api/database',
},
},
action: 'Add a databases',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many databases',
routing: {
request: {
method: 'GET',
url: '/api/database/',
},
output: {
postReceive: [
{
type: 'rootProperty',
properties: {
property: 'data',
},
},
],
},
},
action: 'Get many databases',
},
{
name: 'Get Fields',
value: 'getFields',
description: 'Get fields from database',
routing: {
request: {
method: 'GET',
url: '={{"/api/database/" + $parameter.databaseId + "/fields"}}',
},
},
action: 'Get Fields a databases',
},
],
default: 'getAll',
},
];
export const databasesFields: INodeProperties[] = [
{
displayName: 'Database ID',
name: 'databaseId',
type: 'string',
required: true,
placeholder: '0',
displayOptions: {
show: {
resource: ['databases'],
operation: ['getFields'],
},
},
default: '',
},
{
displayName: 'Engine',
name: 'engine',
type: 'options',
required: true,
placeholder: 'PostgreSQL',
options: [
{
name: 'H2',
value: 'h2',
},
{
name: 'MongoDB',
value: 'mongo',
},
{
name: 'Mysql',
value: 'mysql',
},
{
name: 'PostgreSQL',
value: 'postgres',
},
{
name: 'Redshift',
value: 'redshift',
},
{
name: 'Sqlite',
value: 'sqlite',
},
],
default: 'postgres',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
},
},
routing: {
send: {
property: 'engine',
type: 'body',
},
},
},
{
displayName: 'Host',
name: 'host',
type: 'string',
required: true,
placeholder: 'localhost:5432',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['postgres', 'redshift', 'mysql', 'mongo'],
},
},
routing: {
send: {
property: 'details.host',
type: 'body',
},
},
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
required: true,
placeholder: 'Database 1',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
},
},
routing: {
send: {
property: 'name',
type: 'body',
},
},
default: '',
},
{
displayName: 'Port',
name: 'port',
type: 'number',
required: true,
placeholder: '5432',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['postgres', 'redshift', 'mysql', 'mongo'],
},
},
routing: {
send: {
property: 'details.port',
type: 'body',
},
},
default: 5432,
},
{
displayName: 'User',
name: 'user',
type: 'string',
required: true,
placeholder: 'Admin',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['postgres', 'redshift', 'mysql', 'mongo'],
},
},
routing: {
send: {
property: 'details.user',
type: 'body',
},
},
default: '',
},
{
displayName: 'Password',
name: 'password',
type: 'string',
typeOptions: { password: true },
required: true,
placeholder: 'password',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['postgres', 'redshift', 'mysql', 'mongo'],
},
},
routing: {
send: {
property: 'details.password',
type: 'body',
},
},
default: '',
},
{
displayName: 'Database Name',
name: 'dbName',
type: 'string',
placeholder: 'Users',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['postgres', 'redshift', 'mysql', 'mongo'],
},
},
routing: {
send: {
property: 'details.db',
type: 'body',
},
},
default: '',
},
{
displayName: 'File Path',
name: 'filePath',
type: 'string',
required: true,
placeholder: 'file:/Users/admin/Desktop/Users',
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
engine: ['h2', 'sqlite'],
},
},
routing: {
send: {
property: 'details.db',
type: 'body',
},
},
default: '',
},
{
displayName: 'Full Sync',
name: 'fullSync',
type: 'boolean',
required: true,
default: true,
displayOptions: {
show: {
resource: ['databases'],
operation: ['addNewDatasource'],
},
},
routing: {
send: {
property: 'is_full_sync',
type: 'body',
},
},
},
{
displayName: 'Simplify',
name: 'simple',
type: 'boolean',
description: 'Whether to return a simplified version of the response instead of the raw data',
displayOptions: {
show: {
resource: ['databases'],
operation: ['getAll'],
},
},
routing: {
output: {
postReceive: [
{
type: 'setKeyValue',
enabled: '={{$value}}',
properties: {
id: '={{$responseItem.id}}',
name: '={{$responseItem.name}}',
description: '={{$responseItem.description}}',
engine: '={{$responseItem.engine}}',
creator_id: '={{$responseItem.creator_id}}',
timezone: '={{$responseItem.timezone}}',
created_at: '={{$responseItem.created_at}}',
updated_at: '={{$responseItem.updated_at}}',
db: '={{$responseItem.details.db}}',
user: '={{$responseItem.details.user}}',
host: '={{$responseItem.details.host}}',
port: '={{$responseItem.details.port}}',
ssl: '={{$responseItem.details.ssl}}',
is_full_sync: '={{$responseItem.details.is_full_sync}}',
},
},
],
},
},
default: true,
},
];
@@ -0,0 +1,18 @@
{
"node": "n8n-nodes-base.metabase",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Development", "Data & Storage"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/metabase/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.metabase/"
}
]
}
}
@@ -0,0 +1,71 @@
import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { alertsFields, alertsOperations } from './AlertsDescription';
import { databasesFields, databasesOperations } from './DatabasesDescription';
import { metricsFields, metricsOperations } from './MetricsDescription';
import { questionsFields, questionsOperations } from './QuestionsDescription';
export class Metabase implements INodeType {
description: INodeTypeDescription = {
displayName: 'Metabase',
name: 'metabase',
icon: 'file:metabase.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Use the Metabase API',
defaults: {
name: 'Metabase',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'metabaseApi',
required: true,
},
],
requestDefaults: {
returnFullResponse: true,
baseURL: '={{$credentials.url.replace(new RegExp("/$"), "")}}',
headers: {},
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Alert',
value: 'alerts',
},
{
name: 'Database',
value: 'databases',
},
{
name: 'Metric',
value: 'metrics',
},
{
name: 'Question',
value: 'questions',
},
],
default: 'questions',
},
...questionsOperations,
...questionsFields,
...metricsOperations,
...metricsFields,
...databasesOperations,
...databasesFields,
...alertsOperations,
...alertsFields,
],
};
}
@@ -0,0 +1,60 @@
import type { INodeProperties } from 'n8n-workflow';
export const metricsOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['metrics'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get a specific metric',
routing: {
request: {
method: 'GET',
url: '={{"/api/metric/" + $parameter.metricId}}',
returnFullResponse: true,
},
},
action: 'Get a metric',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many metrics',
routing: {
request: {
method: 'GET',
url: '/api/metric/',
},
},
action: 'Get many metrics',
},
],
default: 'getAll',
},
];
export const metricsFields: INodeProperties[] = [
{
displayName: 'Metric ID',
name: 'metricId',
type: 'string',
required: true,
placeholder: '0',
displayOptions: {
show: {
resource: ['metrics'],
operation: ['get'],
},
},
default: '',
},
];
@@ -0,0 +1,133 @@
import type { IDataObject, INodeProperties } from 'n8n-workflow';
import { jsonParse } from 'n8n-workflow';
export const questionsOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['questions'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get a specific question',
routing: {
request: {
method: 'GET',
url: '={{"/api/card/" + $parameter.questionId}}',
},
},
action: 'Get a questions',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get many questions',
routing: {
request: {
method: 'GET',
url: '/api/card/',
},
},
action: 'Get many questions',
},
{
name: 'Result Data',
value: 'resultData',
description: 'Return the result of the question to a specific file format',
routing: {
request: {
method: 'POST',
url: '={{"/api/card/" + $parameter.questionId + "/query/" + $parameter.format}}',
returnFullResponse: true,
encoding: 'arraybuffer',
},
output: {
postReceive: [
async function (this, items, responseData) {
const datatype = this.getNodeParameter('format') as string;
if (datatype !== 'json') {
const binaryData = await this.helpers.prepareBinaryData(
responseData.body as Buffer,
'data',
responseData.headers['content-type'] as string,
);
// Transform items
items = items.map((item) => {
item.json = {};
item.binary = { ['data']: binaryData };
return item;
});
} else {
const results = jsonParse<IDataObject[]>(responseData.body as unknown as string);
items = results.map((result) => {
return {
json: {
...result,
},
};
});
}
return items;
},
],
},
},
action: 'Get the results from a question',
},
],
default: 'getAll',
},
];
export const questionsFields: INodeProperties[] = [
{
displayName: 'Question ID',
name: 'questionId',
type: 'string',
required: true,
placeholder: '0',
displayOptions: {
show: {
resource: ['questions'],
operation: ['get', 'resultData'],
},
},
default: '',
},
{
displayName: 'Format',
name: 'format',
type: 'options',
required: true,
options: [
{
name: 'CSV',
value: 'csv',
},
{
name: 'JSON',
value: 'json',
},
{
name: 'XLSX',
value: 'xlsx',
},
],
default: 'csv',
displayOptions: {
show: {
resource: ['questions'],
operation: ['resultData'],
},
},
},
];
@@ -0,0 +1,21 @@
{
"type": "object",
"properties": {
"created_at": {
"type": "string"
},
"engine": {
"type": "string"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"updated_at": {
"type": "string"
}
},
"version": 1
}
@@ -0,0 +1,24 @@
{
"type": "object",
"properties": {
"base_type": {
"type": "string"
},
"display_name": {
"type": "string"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"table_id": {
"type": "integer"
},
"table_name": {
"type": "string"
}
},
"version": 2
}
@@ -0,0 +1,259 @@
{
"type": "object",
"properties": {
"archived": {
"type": "boolean"
},
"archived_directly": {
"type": "boolean"
},
"cache_ttl": {
"type": "null"
},
"can_delete": {
"type": "boolean"
},
"can_manage_db": {
"type": "boolean"
},
"can_restore": {
"type": "boolean"
},
"can_run_adhoc_query": {
"type": "boolean"
},
"can_write": {
"type": "boolean"
},
"collection": {
"type": "object",
"properties": {
"archive_operation_id": {
"type": "null"
},
"archived": {
"type": "boolean"
},
"archived_directly": {
"type": "null"
},
"authority_level": {
"type": "null"
},
"created_at": {
"type": "string"
},
"is_personal": {
"type": "boolean"
},
"is_sample": {
"type": "boolean"
},
"location": {
"type": "string"
},
"name": {
"type": "string"
},
"namespace": {
"type": "null"
},
"slug": {
"type": "string"
},
"type": {
"type": "null"
}
}
},
"collection_preview": {
"type": "boolean"
},
"created_at": {
"type": "string"
},
"creator": {
"type": "object",
"properties": {
"common_name": {
"type": "string"
},
"date_joined": {
"type": "string"
},
"email": {
"type": "string"
},
"id": {
"type": "integer"
},
"is_qbnewb": {
"type": "boolean"
},
"is_superuser": {
"type": "boolean"
},
"tenant_id": {
"type": "null"
}
}
},
"creator_id": {
"type": "integer"
},
"dashboard_count": {
"type": "integer"
},
"database_id": {
"type": "integer"
},
"dataset_query": {
"type": "object",
"properties": {
"database": {
"type": "integer"
},
"native": {
"type": "object",
"properties": {
"query": {
"type": "string"
}
}
},
"type": {
"type": "string"
}
}
},
"display": {
"type": "string"
},
"embedding_params": {
"type": "null"
},
"enable_embedding": {
"type": "boolean"
},
"id": {
"type": "integer"
},
"initially_published_at": {
"type": "null"
},
"last_used_at": {
"type": "string"
},
"last-edit-info": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"id": {
"type": "integer"
},
"timestamp": {
"type": "string"
}
}
},
"moderation_reviews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"created_at": {
"type": "string"
},
"id": {
"type": "integer"
},
"moderated_item_id": {
"type": "integer"
},
"moderated_item_type": {
"type": "string"
},
"moderator_id": {
"type": "integer"
},
"most_recent": {
"type": "boolean"
},
"status": {
"type": "string"
},
"text": {
"type": "null"
},
"updated_at": {
"type": "string"
},
"user": {
"type": "object",
"properties": {
"common_name": {
"type": "string"
},
"date_joined": {
"type": "string"
},
"email": {
"type": "string"
},
"first_name": {
"type": "string"
},
"id": {
"type": "integer"
},
"is_qbnewb": {
"type": "boolean"
},
"is_superuser": {
"type": "boolean"
},
"last_login": {
"type": "string"
},
"last_name": {
"type": "string"
}
}
}
}
}
},
"name": {
"type": "string"
},
"parameter_usage_count": {
"type": "integer"
},
"query_type": {
"type": "string"
},
"type": {
"type": "string"
},
"updated_at": {
"type": "string"
},
"view_count": {
"type": "integer"
},
"visualization_settings": {
"type": "object",
"properties": {
"table.cell_column": {
"type": "string"
},
"table.pivot_column": {
"type": "string"
}
}
}
},
"version": 4
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="324" preserveAspectRatio="xMidYMid"><g fill="#509EE3"><ellipse cx="19.394" cy="82.757" rx="19.394" ry="19.704"/><ellipse cx="19.394" cy="137.928" rx="19.394" ry="19.704"/><ellipse cx="73.697" cy="82.757" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="73.697" cy="138.464" rx="19.394" ry="19.704"/><ellipse cx="128" cy="82.757" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="128" cy="19.704" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="128" cy="138.464" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="182.303" cy="82.757" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="236.606" cy="82.757" rx="19.394" ry="19.704"/><ellipse cx="182.303" cy="138.464" rx="19.394" ry="19.704"/><ellipse cx="236.606" cy="138.464" rx="19.394" ry="19.704"/><ellipse cx="19.394" cy="193.099" rx="19.394" ry="19.704"/><ellipse cx="73.697" cy="193.635" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="128" cy="193.635" rx="19.394" ry="19.704"/><ellipse cx="182.303" cy="193.635" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="236.606" cy="193.635" rx="19.394" ry="19.704"/><ellipse cx="19.394" cy="248.27" rx="19.394" ry="19.704"/><ellipse cx="73.697" cy="248.806" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="128" cy="248.806" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="128" cy="303.977" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="182.303" cy="248.806" opacity=".2" rx="19.394" ry="19.704"/><ellipse cx="236.606" cy="248.806" rx="19.394" ry="19.704"/></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB