UNPKG

n8n-nodes-base

Version:

Base nodes of n8n

174 lines 6.88 kB
"use strict"; 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