n8n-nodes-base
Version:
Base nodes of n8n
174 lines • 6.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareWorkflowUpdateBody = exports.prepareWorkflowCreateBody = exports.parseAndSetBodyJson = exports.getCursorPaginator = void 0;
exports.apiRequest = apiRequest;
exports.apiRequestAllItems = apiRequestAllItems;
const n8n_workflow_1 = require("n8n-workflow");
/**
* A custom API request function to be used with the resourceLocator lookup queries.
*/
async function apiRequest(method, endpoint, body, query) {
query = query || {};
const credentials = await this.getCredentials('n8nApi');
const baseUrl = credentials.baseUrl;
const options = {
method,
body,
qs: query,
uri: `${baseUrl.replace(new RegExp('/$'), '')}/${endpoint}`,
json: true,
};
try {
return await this.helpers.requestWithAuthentication.call(this, 'n8nApi', options);
}
catch (error) {
if (error instanceof n8n_workflow_1.NodeApiError) {
throw error;
}
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
}
}
async function apiRequestAllItems(method, endpoint, body, query) {
query = query || {};
const returnData = [];
let nextCursor = undefined;
let responseData;
do {
query.cursor = nextCursor;
query.limit = 100;
responseData = await apiRequest.call(this, method, endpoint, body, query);
returnData.push.apply(returnData, responseData.data);
nextCursor = responseData.nextCursor;
} while (nextCursor);
return returnData;
}
/**
* Get a cursor-based paginator to use with n8n 'getAll' type endpoints.
*
* It will look up a 'nextCursor' in the response and if the node has
* 'returnAll' set to true, will consecutively include it as the 'cursor' query
* parameter for the next request, effectively getting everything in slices.
*
* Prequisites:
* - routing.send.paginate must be set to true, for all requests to go through here
* - node is expected to have a boolean parameter 'returnAll'
* - no postReceive action setting the rootProperty, to get the items mapped
*
* @returns A ready-to-use cursor-based paginator function.
*/
const getCursorPaginator = () => {
return async function cursorPagination(requestOptions) {
if (!requestOptions.options.qs) {
requestOptions.options.qs = {};
}
let executions = [];
let responseData;
let nextCursor = undefined;
const returnAll = this.getNodeParameter('returnAll', true);
const extractItems = (page) => {
const items = page.json.data;
if (items) {
// Extract the items themselves
executions = executions.concat(items.map((item) => ({ json: item })));
}
};
do {
requestOptions.options.qs.cursor = nextCursor;
responseData = await this.makeRoutingRequest(requestOptions);
// Check for another page of items
const lastItem = responseData[responseData.length - 1].json;
nextCursor = lastItem.nextCursor;
responseData.forEach(extractItems);
// If we don't return all, just return the first page
} while (returnAll && nextCursor);
return executions;
};
};
exports.getCursorPaginator = getCursorPaginator;
/**
* A helper function to parse a node parameter as JSON and set it in the request body.
* Throws a NodeOperationError is the content is not valid JSON or it cannot be set.
*
* Currently, parameters with type 'json' are not validated automatically.
* Also mapping the value for 'body.data' declaratively has it treated as a string,
* but some operations (e.g. POST /credentials) don't work unless it is set as an object.
* To get the JSON-body operations to work consistently, we need to parse and set the body
* manually.
*
* @param parameterName The name of the node parameter to parse
* @param setAsBodyProperty An optional property name to set the parsed data into
* @returns The requestOptions with its body replaced with the contents of the parameter
*/
const parseAndSetBodyJson = (parameterName, setAsBodyProperty) => {
return async function (requestOptions) {
try {
const rawData = this.getNodeParameter(parameterName, '{}');
const parsedObject = JSON.parse(rawData);
// Set the parsed object to either as the request body directly, or as its sub-property
if (setAsBodyProperty === undefined) {
requestOptions.body = parsedObject;
}
else {
requestOptions.body = Object.assign({}, requestOptions.body, {
[setAsBodyProperty]: parsedObject,
});
}
}
catch (err) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), new Error(`The '${parameterName}' property must be valid JSON, but cannot be parsed`, {
cause: err,
}));
}
return requestOptions;
};
};
exports.parseAndSetBodyJson = parseAndSetBodyJson;
/**
* A helper function to prepare the workflow object data for creation. It only sets
* known workflow properties, for pre-emptively avoiding a HTTP 400 Bad Request
* response until we have a better client-side schema validation mechanism.
*
* NOTE! This expects the requestOptions.body to already be set as an object,
* so take care to first call parseAndSetBodyJson().
*/
const prepareWorkflowCreateBody = async function (requestOptions) {
const body = requestOptions.body;
const newBody = {};
newBody.name = body.name || 'My workflow';
newBody.nodes = body.nodes || [];
newBody.settings = body.settings || {};
newBody.connections = body.connections || {};
newBody.staticData = body.staticData || null;
requestOptions.body = newBody;
return requestOptions;
};
exports.prepareWorkflowCreateBody = prepareWorkflowCreateBody;
/**
* A helper function to prepare the workflow object data for update.
*
* NOTE! This expects the requestOptions.body to already be set as an object,
* so take care to first call parseAndSetBodyJson().
*/
const prepareWorkflowUpdateBody = async function (requestOptions) {
const body = requestOptions.body;
const newBody = {};
if (body.name) {
newBody.name = body.name;
}
if (body.nodes) {
newBody.nodes = body.nodes;
}
if (body.settings) {
newBody.settings = body.settings;
}
if (body.connections) {
newBody.connections = body.connections;
}
if (body.staticData) {
newBody.staticData = body.staticData;
}
requestOptions.body = newBody;
return requestOptions;
};
exports.prepareWorkflowUpdateBody = prepareWorkflowUpdateBody;
//# sourceMappingURL=GenericFunctions.js.map