Description
!Logo
n8n Custom Nodes Framework
A small framework to create custom n8n nodes using the resource -> operation -> execute pattern.
What it solves
- Central registry for resources
- Automatic composition of node
properties - Execution routing by
resourceandoperation - Uniform error handling with
NodeOperationError - Simple base for creating multi-resource nodes without repeating boilerplate
Usage
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { ResourceOperation, Resource, ResourceRegistry, ResourceNode } from '@devantage/n8n-custom-nodes-framework';class PingOperation extends ResourceOperation {
public readonly name = 'ping';
public readonly displayName = 'Ping';
public readonly description = 'Returns a ping payload';
public readonly properties = [];
public async execute(this: IExecuteFunctions, itemIndex: number): Promise {
return {
json: { ok: true },
pairedItem: itemIndex,
};
}
}
class HealthResource extends Resource {
public constructor() {
super('health', 'Health', PingOperation);
}
}
const registry = new ResourceRegistry(new HealthResource());
export class ExampleNode extends ResourceNode {
public constructor() {
super(registry, {
displayName: 'Example',
name: 'example',
icon: 'file:icon.svg',
version: 1,
description: 'Example node',
credentials: [],
});
}
}
HTTP client
HttpClient wraps httpRequestWithAuthentication with a fixed base URL and
credential type:
import { HttpClient } from '@devantage/n8n-custom-nodes-framework';const client = new HttpClient({
baseURL: 'https://api.example.com/v2',
credentialType: 'exampleApi',
});
// inside an operation's execute()
const user = await client.get(this, '/users/1');
Besides head, get, post, put, patch and delete, it offers graphql,
which POSTs the body, unwraps the data envelope and throws when the response
carries errors:
const response = await client.graphql(this, '/graphql', { query, variables });
Pass a FormData body (with its headers and json: false) to perform a
multipart upload:
const response = await client.graphql(this, '/graphql', form, {
headers: form.getHeaders(),
json: false,
});
Test utilities
The framework also provides some helpers to reduce boilerplate in node tests:
import { TestUtil } from '@devantage/n8n-custom-nodes-framework';const context = TestUtil.createExecuteFunctionsMock({
resource: 'health',
operation: 'ping',
});
const result = await TestUtil.executeNode(node, context as IExecuteFunctions);
Available helpers:
TestUtil.createExecuteFunctionsMock(): creates a basic mock of IExecuteFunctions, including the assertBinaryData, getBinaryDataBuffer and httpRequestWithAuthentication helpersTestUtil.createNodeExecutionData(): builds input/output items for testsTestUtil.createBinaryData(): generates a simple IBinaryData for file testsTestUtil.executeNode(): runs node.execute without repeating casts in every test