@@ -11,7 +11,7 @@ export class ProboApi implements ICredentialType {
|
||||
|
||||
displayName = 'Probo API';
|
||||
|
||||
icon: Icon = { light: 'file:../icons/probo.svg', dark: 'file:../icons/probo.svg' };
|
||||
icon: Icon = { light: 'file:../icons/probo-light.svg', dark: 'file:../icons/probo.svg' };
|
||||
|
||||
documentationUrl = 'https://www.getprobo.com/docs';
|
||||
|
||||
|
||||
24
packages/n8n-node/icons/probo-light.svg
Normal file
24
packages/n8n-node/icons/probo-light.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1030_164)">
|
||||
<rect width="300" height="300" rx="70" fill="#FFFFFF"/>
|
||||
<g clip-path="url(#clip1_1030_164)">
|
||||
<rect width="320" height="320" transform="translate(-9.69238 -10)" fill="#FFFFFF"/>
|
||||
<path d="M238.194 83.0279C274.406 137.651 160.574 258.266 -29.4255 142.266" stroke="#101E1C" stroke-width="42.6667"/>
|
||||
<path d="M238.194 83.0279C274.406 137.651 160.574 258.266 -29.4255 142.266" stroke="url(#paint0_linear_1030_164)" stroke-width="42.6667"/>
|
||||
<path d="M220.112 94.3364C226.365 104.327 239.53 107.363 249.515 101.118C259.501 94.873 262.527 81.7113 256.274 71.7206L238.193 83.0285L220.112 94.3364ZM97.9074 324.933L118.61 319.8C87.9762 196.62 115.788 133.041 146.656 105.377C162.52 91.1595 180.159 85.27 194.453 84.9721C209.505 84.6583 217.534 90.218 220.112 94.3364L238.193 83.0285L256.274 71.7206C242.999 50.5115 217.649 41.8122 193.53 42.315C168.652 42.8335 141.327 52.8361 118.165 73.5935C70.9833 115.879 44.5053 198.58 77.2047 330.066L97.9074 324.933Z" fill="#101E1C"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1030_164" x1="216.193" y1="173.319" x2="-18.0923" y2="173.319" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFFFFF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FFFFFF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_1030_164">
|
||||
<rect width="300" height="300" rx="70" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_1030_164">
|
||||
<rect width="320" height="320" fill="white" transform="translate(-9.69238 -10)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -11,7 +11,7 @@ export async function proboApiRequest(
|
||||
this: IExecuteFunctions | IHookFunctions,
|
||||
query: string,
|
||||
variables: IDataObject = {},
|
||||
): Promise<any> {
|
||||
): Promise<IDataObject> {
|
||||
const credentials = await this.getCredentials('proboApi');
|
||||
|
||||
if (!credentials?.apiKey) {
|
||||
@@ -44,11 +44,11 @@ export async function proboApiRequestAllItems(
|
||||
this: IExecuteFunctions,
|
||||
query: string,
|
||||
variables: IDataObject,
|
||||
getConnection: (response: any) => any,
|
||||
getConnection: (response: IDataObject) => IDataObject | undefined,
|
||||
returnAll: boolean = true,
|
||||
limit: number = 0,
|
||||
): Promise<any[]> {
|
||||
const items: any[] = [];
|
||||
): Promise<IDataObject[]> {
|
||||
const items: IDataObject[] = [];
|
||||
let hasNextPage = true;
|
||||
let cursor: string | null = null;
|
||||
const pageSize = 100;
|
||||
@@ -72,7 +72,8 @@ export async function proboApiRequestAllItems(
|
||||
const connection = getConnection(responseData);
|
||||
|
||||
if (connection?.edges) {
|
||||
items.push(...connection.edges.map((edge: any) => edge.node));
|
||||
const edges = connection.edges as Array<{ node: IDataObject }>;
|
||||
items.push(...edges.map((edge) => edge.node));
|
||||
}
|
||||
|
||||
if (connection?.pageInfo) {
|
||||
|
||||
@@ -15,7 +15,7 @@ export class Probo implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Probo',
|
||||
name: 'probo',
|
||||
icon: { light: 'file:../../icons/probo.svg', dark: 'file:../../icons/probo.svg' },
|
||||
icon: { light: 'file:../../icons/probo-light.svg', dark: 'file:../../icons/probo.svg' },
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["resource"]}} / {{$parameter["operation"]}}',
|
||||
|
||||
@@ -36,10 +36,10 @@ export const description: INodeProperties[] = [
|
||||
action: 'Get an asset',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get all assets',
|
||||
action: 'Get all assets',
|
||||
description: 'Get many assets',
|
||||
action: 'Get many assets',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
|
||||
@@ -75,7 +75,7 @@ export const description: INodeProperties[] = [
|
||||
value: 'VIRTUAL',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
default: 'PHYSICAL',
|
||||
description: 'The type of the asset',
|
||||
},
|
||||
{
|
||||
@@ -188,7 +188,7 @@ export async function execute(
|
||||
}
|
||||
`;
|
||||
|
||||
const input: Record<string, any> = { id };
|
||||
const input: Record<string, string | number | string[]> = { id };
|
||||
if (name) input.name = name;
|
||||
if (amount) input.amount = amount;
|
||||
if (ownerId) input.ownerId = ownerId;
|
||||
|
||||
@@ -36,10 +36,10 @@ export const description: INodeProperties[] = [
|
||||
action: 'Get a control',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get all controls',
|
||||
action: 'Get all controls',
|
||||
description: 'Get many controls',
|
||||
action: 'Get many controls',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
|
||||
@@ -75,7 +75,7 @@ export const description: INodeProperties[] = [
|
||||
value: 'EXCLUDED',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
default: 'INCLUDED',
|
||||
description: 'The status of the control',
|
||||
},
|
||||
{
|
||||
@@ -121,7 +121,7 @@ export async function execute(
|
||||
}
|
||||
`;
|
||||
|
||||
const input: Record<string, any> = { id };
|
||||
const input: Record<string, string> = { id };
|
||||
if (sectionTitle) input.sectionTitle = sectionTitle;
|
||||
if (name) input.name = name;
|
||||
if (description) input.description = description;
|
||||
|
||||
@@ -36,10 +36,10 @@ export const description: INodeProperties[] = [
|
||||
action: 'Get a datum',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get all data',
|
||||
action: 'Get all data',
|
||||
description: 'Get many data',
|
||||
action: 'Get many data',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
|
||||
@@ -57,7 +57,7 @@ export const description: INodeProperties[] = [
|
||||
value: 'SECRET',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
default: 'PUBLIC',
|
||||
description: 'The classification of the data',
|
||||
},
|
||||
{
|
||||
@@ -166,7 +166,7 @@ export async function execute(
|
||||
}
|
||||
`;
|
||||
|
||||
const input: Record<string, any> = { id };
|
||||
const input: Record<string, string | string[]> = { id };
|
||||
if (name) input.name = name;
|
||||
if (dataClassification) input.dataClassification = dataClassification;
|
||||
if (ownerId) input.ownerId = ownerId;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { parse, getOperationAST, type DocumentNode } from 'graphql';
|
||||
import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
import { proboApiRequest } from '../../GenericFunctions';
|
||||
|
||||
@@ -16,8 +15,7 @@ export const description: INodeProperties[] = [
|
||||
},
|
||||
},
|
||||
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 } }")',
|
||||
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,
|
||||
},
|
||||
{
|
||||
@@ -41,23 +39,17 @@ export async function execute(
|
||||
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)}`,
|
||||
);
|
||||
// Basic validation: check if query contains a GraphQL operation
|
||||
const trimmedQuery = query.trim();
|
||||
if (!trimmedQuery) {
|
||||
throw new Error('GraphQL query cannot be empty');
|
||||
}
|
||||
|
||||
const operationAST = getOperationAST(document);
|
||||
if (!operationAST) {
|
||||
throw new Error('GraphQL operation must contain a query, mutation, or subscription');
|
||||
}
|
||||
|
||||
if (!operationAST.name) {
|
||||
// Check for operation type (query, mutation, or subscription)
|
||||
const operationMatch = trimmedQuery.match(/^\s*(query|mutation|subscription)\s+(\w+)/i);
|
||||
if (!operationMatch) {
|
||||
throw new Error(
|
||||
'GraphQL operation must have a name (e.g., "query GetUser { ... }" or "mutation UpdateUser { ... }")',
|
||||
'GraphQL operation must start with "query", "mutation", or "subscription" followed by an operation name (e.g., "query GetUser { ... }" or "mutation UpdateUser { ... }")',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +59,7 @@ export async function execute(
|
||||
variables =
|
||||
typeof variablesParam === 'string' ? JSON.parse(variablesParam) : variablesParam;
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid JSON in Variables: ${error}`);
|
||||
throw new Error(`Invalid JSON in Variables: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export const description: INodeProperties[] = [
|
||||
name: 'Execute',
|
||||
value: 'execute',
|
||||
description: 'Execute a GraphQL query or mutation',
|
||||
action: 'Execute GraphQL',
|
||||
action: 'Execute graphql',
|
||||
},
|
||||
],
|
||||
default: 'execute',
|
||||
|
||||
@@ -36,10 +36,10 @@ export const description: INodeProperties[] = [
|
||||
action: 'Get a framework',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get all frameworks',
|
||||
action: 'Get all frameworks',
|
||||
description: 'Get many frameworks',
|
||||
action: 'Get many frameworks',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
|
||||
@@ -66,7 +66,7 @@ export async function execute(
|
||||
}
|
||||
`;
|
||||
|
||||
const input: Record<string, any> = { id };
|
||||
const input: Record<string, string> = { id };
|
||||
if (name) input.name = name;
|
||||
if (description) input.description = description;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as measure from './measure';
|
||||
|
||||
export interface ResourceModule {
|
||||
description: INodeProperties[];
|
||||
[key: string]: OperationModule | INodeProperties[] | any;
|
||||
[key: string]: OperationModule | INodeProperties[];
|
||||
}
|
||||
|
||||
export interface OperationModule {
|
||||
|
||||
@@ -36,10 +36,10 @@ export const description: INodeProperties[] = [
|
||||
action: 'Get a measure',
|
||||
},
|
||||
{
|
||||
name: 'Get All',
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get all measures',
|
||||
action: 'Get all measures',
|
||||
description: 'Get many measures',
|
||||
action: 'Get many measures',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
|
||||
@@ -83,7 +83,7 @@ export const description: INodeProperties[] = [
|
||||
value: 'IMPLEMENTED',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
default: 'NOT_STARTED',
|
||||
description: 'The state of the measure',
|
||||
},
|
||||
];
|
||||
@@ -114,7 +114,7 @@ export async function execute(
|
||||
}
|
||||
`;
|
||||
|
||||
const input: Record<string, any> = { id };
|
||||
const input: Record<string, string> = { id };
|
||||
if (name) input.name = name;
|
||||
if (description) input.description = description;
|
||||
if (category) input.category = category;
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
"release": "n8n-node release",
|
||||
"prepublishOnly": "n8n-node prerelease"
|
||||
},
|
||||
"author": "Probo Inc",
|
||||
"author": {
|
||||
"name": "Probo Inc"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user