4
package-lock.json
generated
4
package-lock.json
generated
@@ -8943,7 +8943,6 @@
|
|||||||
"version": "16.12.0",
|
"version": "16.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz",
|
||||||
"integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==",
|
"integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
||||||
@@ -15554,6 +15553,9 @@
|
|||||||
"name": "@probo/n8n-nodes-probo",
|
"name": "@probo/n8n-nodes-probo",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"graphql": "^16.12.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@n8n/node-cli": "^0.17.0",
|
"@n8n/node-cli": "^0.17.0",
|
||||||
"eslint": "9.32.0"
|
"eslint": "9.32.0"
|
||||||
|
|||||||
19
packages/n8n-node/nodes/Probo/Probo.node.json
Normal file
19
packages/n8n-node/nodes/Probo/Probo.node.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"node": "n8n-nodes-probo",
|
||||||
|
"nodeVersion": "1.0",
|
||||||
|
"codexVersion": "1.0",
|
||||||
|
"categories": ["Development", "Developer Tools", "Automation"],
|
||||||
|
"resources": {
|
||||||
|
"credentialDocumentation": [
|
||||||
|
{
|
||||||
|
"url": "https://www.getprobo.com/docs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryDocumentation": [
|
||||||
|
{
|
||||||
|
"url": "https://www.getprobo.com/docs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generic": []
|
||||||
|
}
|
||||||
|
}
|
||||||
117
packages/n8n-node/nodes/Probo/Probo.node.ts
Normal file
117
packages/n8n-node/nodes/Probo/Probo.node.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import {
|
||||||
|
NodeConnectionTypes,
|
||||||
|
type IExecuteFunctions,
|
||||||
|
type INodeExecutionData,
|
||||||
|
type INodeType,
|
||||||
|
type INodeTypeDescription,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import { executeOperation } from './operations';
|
||||||
|
|
||||||
|
export class Probo implements INodeType {
|
||||||
|
description: INodeTypeDescription = {
|
||||||
|
displayName: 'Probo',
|
||||||
|
name: 'probo',
|
||||||
|
icon: { light: 'file:../../icons/probo.svg', dark: 'file:../../icons/probo.svg' },
|
||||||
|
group: ['input'],
|
||||||
|
version: 1,
|
||||||
|
subtitle: '={{$parameter["operation"]}}',
|
||||||
|
description: 'Consume data from the Probo API',
|
||||||
|
defaults: {
|
||||||
|
name: 'Probo',
|
||||||
|
},
|
||||||
|
usableAsTool: true,
|
||||||
|
inputs: [NodeConnectionTypes.Main],
|
||||||
|
outputs: [NodeConnectionTypes.Main],
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
name: 'proboApi',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
authentication: ['apiKey'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
requestDefaults: {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Authentication',
|
||||||
|
name: 'authentication',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'API Key',
|
||||||
|
value: 'apiKey',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'apiKey',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Execute',
|
||||||
|
value: 'execute',
|
||||||
|
description: 'Execute a GraphQL query or mutation',
|
||||||
|
action: 'Execute a GraphQL operation',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'execute',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
typeOptions: {
|
||||||
|
rows: 5,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['execute'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'The complete GraphQL operation including operation name and variable declarations (e.g., "query GetUser($userId: ID!) { node(id: $userId) { id } }" or "mutation UpdateUser($input: UpdateUserInput!) { updateUser(input: $input) { id } }")',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Variables',
|
||||||
|
name: 'variables',
|
||||||
|
type: 'json',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: ['execute'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '{}',
|
||||||
|
description: 'GraphQL variables as JSON object',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const items = this.getInputData();
|
||||||
|
const returnData: INodeExecutionData[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const operation = this.getNodeParameter('operation', i) as string;
|
||||||
|
const result = await executeOperation.call(this, operation, i);
|
||||||
|
returnData.push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [returnData];
|
||||||
|
}
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
listSearch: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
81
packages/n8n-node/nodes/Probo/operations/execute.ts
Normal file
81
packages/n8n-node/nodes/Probo/operations/execute.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { parse, getOperationAST, type DocumentNode } from 'graphql';
|
||||||
|
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||||
|
|
||||||
|
export interface GraphQLParameters {
|
||||||
|
query: string;
|
||||||
|
variables?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function executeGraphQL(
|
||||||
|
this: IExecuteFunctions,
|
||||||
|
itemIndex: number,
|
||||||
|
): Promise<INodeExecutionData> {
|
||||||
|
const query = this.getNodeParameter('query', itemIndex) as string;
|
||||||
|
const variablesParam = this.getNodeParameter('variables', itemIndex) as string;
|
||||||
|
|
||||||
|
let document: DocumentNode;
|
||||||
|
try {
|
||||||
|
document = parse(query);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Invalid GraphQL operation: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const operationAST = getOperationAST(document);
|
||||||
|
if (!operationAST) {
|
||||||
|
throw new Error('GraphQL operation must contain a query, mutation, or subscription');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!operationAST.name) {
|
||||||
|
throw new Error('GraphQL operation must have a name (e.g., "query GetUser { ... }" or "mutation UpdateUser { ... }")');
|
||||||
|
}
|
||||||
|
|
||||||
|
const operationName = operationAST.name.value;
|
||||||
|
|
||||||
|
let variables = {};
|
||||||
|
if (variablesParam) {
|
||||||
|
try {
|
||||||
|
variables =
|
||||||
|
typeof variablesParam === 'string' ? JSON.parse(variablesParam) : variablesParam;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Invalid JSON in Variables: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const body: {
|
||||||
|
query: string;
|
||||||
|
operationName?: string;
|
||||||
|
variables?: Record<string, any>;
|
||||||
|
} = {
|
||||||
|
query,
|
||||||
|
operationName,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Object.keys(variables).length > 0) {
|
||||||
|
body.variables = variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
const credentials = await this.getCredentials('proboApi');
|
||||||
|
|
||||||
|
if (!credentials!.apiKey) {
|
||||||
|
throw new Error('API Key is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseData = await this.helpers.httpRequest({
|
||||||
|
method: 'POST',
|
||||||
|
baseURL: `${credentials!.server}`,
|
||||||
|
url: '/api/console/v1/query',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${credentials!.apiKey}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: body,
|
||||||
|
json: true,
|
||||||
|
returnFullResponse: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
json: responseData,
|
||||||
|
pairedItem: { item: itemIndex },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
16
packages/n8n-node/nodes/Probo/operations/index.ts
Normal file
16
packages/n8n-node/nodes/Probo/operations/index.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||||
|
import { executeGraphQL } from './execute';
|
||||||
|
|
||||||
|
export async function executeOperation(
|
||||||
|
this: IExecuteFunctions,
|
||||||
|
operation: string,
|
||||||
|
itemIndex: number,
|
||||||
|
): Promise<INodeExecutionData> {
|
||||||
|
switch (operation) {
|
||||||
|
case 'execute':
|
||||||
|
return executeGraphQL.call(this, itemIndex);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operation: ${operation}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -31,5 +31,8 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"n8n-workflow": "*"
|
"n8n-workflow": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"graphql": "^16.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user