@apify/n8n-nodes-apify
Version:
n8n nodes for Apify
221 lines • 7.89 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.apiRequest = apiRequest;
exports.retryWithExponentialBackoff = retryWithExponentialBackoff;
exports.apiRequestAllItems = apiRequestAllItems;
exports.pollRunStatus = pollRunStatus;
exports.getActorOrTaskId = getActorOrTaskId;
exports.getCondition = getCondition;
exports.normalizeEventTypes = normalizeEventTypes;
exports.generateIdempotencyKey = generateIdempotencyKey;
exports.compose = compose;
exports.customBodyParser = customBodyParser;
exports.isUsedAsAiTool = isUsedAsAiTool;
exports.executeAndLinkItems = executeAndLinkItems;
const n8n_workflow_1 = require("n8n-workflow");
const consts_1 = require("../helpers/consts");
async function apiRequest(requestOptions) {
const { method, qs, uri, ...rest } = requestOptions;
const query = qs || {};
const endpoint = `https://api.apify.com${uri}`;
const headers = {
'x-apify-integration-platform': 'n8n',
};
if (isUsedAsAiTool(this.getNode().type)) {
headers['x-apify-integration-ai-tool'] = 'true';
}
const options = {
json: true,
...rest,
method,
qs: query,
url: endpoint,
headers,
};
if (method === 'GET') {
delete options.body;
}
try {
const authenticationMethod = this.getNodeParameter('authentication', 0);
try {
await this.getCredentials(authenticationMethod);
}
catch {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No valid credentials found for ${authenticationMethod}. Please configure them first.`);
}
return await retryWithExponentialBackoff(() => this.helpers.httpRequestWithAuthentication.call(this, authenticationMethod, options));
}
catch (error) {
if (error instanceof n8n_workflow_1.NodeApiError)
throw error;
if (error.response && error.response.body) {
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, {
message: error.response.body,
description: error.message,
});
}
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
}
}
function isStatusCodeRetryable(statusCode) {
if (Number.isNaN(statusCode))
return false;
const RATE_LIMIT_EXCEEDED_STATUS_CODE = 429;
const isRateLimitError = statusCode === RATE_LIMIT_EXCEEDED_STATUS_CODE;
const isInternalError = statusCode >= 500;
return isRateLimitError || isInternalError;
}
async function retryWithExponentialBackoff(fn, interval = consts_1.DEFAULT_EXP_BACKOFF_INTERVAL, exponential = consts_1.DEFAULT_EXP_BACKOFF_EXPONENTIAL, maxRetries = consts_1.DEFAULT_EXP_BACKOFF_RETRIES) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
}
catch (error) {
lastError = error;
const status = Number(error === null || error === void 0 ? void 0 : error.httpCode);
if (isStatusCodeRetryable(status)) {
const sleepTimeSecs = interval * Math.pow(exponential, i);
const sleepTimeMs = sleepTimeSecs * 1000;
await (0, n8n_workflow_1.sleep)(sleepTimeMs);
continue;
}
throw error;
}
}
throw lastError;
}
async function apiRequestAllItems(requestOptions) {
const returnData = [];
if (!requestOptions.qs)
requestOptions.qs = {};
requestOptions.qs.limit = requestOptions.qs.limit || 999;
let responseData;
do {
responseData = await apiRequest.call(this, requestOptions);
returnData.push(responseData);
} while (requestOptions.qs.limit <= responseData.length);
const combinedData = {
data: {
total: 0,
count: 0,
offset: 0,
limit: 0,
desc: false,
items: [],
},
};
for (const result of returnData) {
combinedData.data.total += typeof result.total === 'number' ? result.total : 0;
combinedData.data.count += typeof result.count === 'number' ? result.count : 0;
combinedData.data.offset += typeof result.offset === 'number' ? result.offset : 0;
combinedData.data.limit += typeof result.limit === 'number' ? result.limit : 0;
if (result.data &&
typeof result.data === 'object' &&
'items' in result.data &&
Array.isArray(result.data.items)) {
combinedData.data.items = [
...combinedData.data.items,
...result.data.items,
];
}
}
return combinedData;
}
async function pollRunStatus(runId) {
var _a;
let lastRunData;
while (true) {
try {
const pollResult = await apiRequest.call(this, {
method: 'GET',
uri: `/v2/actor-runs/${runId}`,
});
const status = (_a = pollResult === null || pollResult === void 0 ? void 0 : pollResult.data) === null || _a === void 0 ? void 0 : _a.status;
lastRunData = pollResult === null || pollResult === void 0 ? void 0 : pollResult.data;
if (['SUCCEEDED', 'FAILED', 'TIMED-OUT', 'ABORTED'].includes(status)) {
break;
}
}
catch (err) {
throw new n8n_workflow_1.NodeApiError(this.getNode(), {
message: `Error polling run status: ${err}`,
});
}
await (0, n8n_workflow_1.sleep)(1000);
}
return lastRunData;
}
function getActorOrTaskId() {
const resource = this.getNodeParameter('resource', '');
const actorId = this.getNodeParameter('actorId', '');
const actorTaskId = this.getNodeParameter('actorTaskId', '');
if (resource === 'task') {
return actorTaskId.value;
}
return actorId.value;
}
function getCondition(resource, id) {
return resource === 'actor' ? { actorId: id } : { actorTaskId: id };
}
function normalizeEventTypes(selected) {
if (selected.includes('any')) {
return ['ACTOR.RUN.SUCCEEDED', 'ACTOR.RUN.FAILED', 'ACTOR.RUN.TIMED_OUT', 'ACTOR.RUN.ABORTED'];
}
return selected;
}
function generateIdempotencyKey(resource, actorOrTaskId, eventTypes) {
const sortedEventTypes = [...eventTypes].sort();
const raw = `${resource}:${actorOrTaskId}:${sortedEventTypes.join(',')}`;
return Buffer.from(raw).toString('base64');
}
function compose(...fns) {
return (x) => fns.reduce((v, f) => f(v), x);
}
function customBodyParser(input) {
if (!input) {
return {};
}
if (typeof input === 'string') {
return input ? JSON.parse(input) : {};
}
else {
return input;
}
}
function isUsedAsAiTool(nodeType) {
const parts = nodeType.split('.');
return parts[parts.length - 1] === 'apifyTool';
}
async function executeAndLinkItems(executeFn) {
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const addPairedItem = (item) => ({
...item,
pairedItem: { item: i },
});
const result = await executeFn.call(this);
if (Array.isArray(result)) {
returnData.push(...result.map(addPairedItem));
}
else {
returnData.push(addPairedItem(result));
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: { error: error.message || 'Unexpected error occured' },
pairedItem: { item: i },
});
}
else {
throw error;
}
}
}
return [returnData];
}
//# sourceMappingURL=genericFunctions.js.map