n8n-nodes-arubacentral
Version:
n8n community node for Aruba Central API integration with comprehensive monitoring, configuration, and management capabilities
150 lines (149 loc) • 7.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handlePagination = handlePagination;
const apiRequest_1 = require("./apiRequest");
/**
* Helper function to handle pagination for Aruba Central API endpoints
* @param this The IExecuteFunctions context
* @param endpoint API endpoint to call
* @param method HTTP method to use
* @param body Request body (if applicable)
* @param queryParams Query parameters
* @param dataLocator Information to locate data in the response
* @param returnAll Whether to return all results or respect limit parameter
* @param limit Maximum number of results to return if not returning all
* @param batchSize Optional batch size for pagination (if endpoint has specific limits)
* @returns Array of INodeExecutionData objects containing all results
*/
async function handlePagination(endpoint, method, body, queryParams, dataLocator, returnAll, limit, batchSize) {
console.log(`Starting enhanced pagination for endpoint ${endpoint}`);
// Deep clone query params to avoid modifying the original
const qs = JSON.parse(JSON.stringify(queryParams));
// Initialize variables
const allItems = [];
let hasMoreItems = true;
let offset = qs.offset || 0;
// Use the provided batch size or fall back to the default of 1000
const effectiveBatchSize = batchSize || 1000;
console.log(`Pagination configuration: returnAll=${returnAll}, requestedLimit=${limit}, batchSize=${effectiveBatchSize}`);
// Set initial limit for API requests
qs.limit = effectiveBatchSize;
// For logging path attempts
const logDataPath = (path) => path.join('.');
// Continue fetching batches while there are more items and we haven't reached the limit
while (hasMoreItems && (!limit || allItems.length < limit)) {
// Update offset for this request
qs.offset = offset;
console.log(`Making request with offset=${offset}, limit=${effectiveBatchSize}`);
// Make API call
const response = await apiRequest_1.apiRequest.call(this, method, endpoint, body, qs);
console.log('Response received. Extracting data...');
// Debug log the response keys
if (typeof response === 'object' && response !== null) {
console.log('Response top-level keys:', Object.keys(response));
// If there's a data property, log its keys too
if (response.data && typeof response.data === 'object') {
console.log('Response data keys:', Object.keys(response.data));
}
}
// Function to extract data from response based on path
const extractData = (obj, path) => {
let current = obj;
// Follow the path to the data
for (const key of path) {
if (current === undefined || current === null)
return null;
current = current[key];
}
// If we found an array, return it
if (Array.isArray(current)) {
return current;
}
return null;
};
// Try to extract data using the primary path
let items = extractData(response, dataLocator.path);
console.log(`Looking for data at path ${logDataPath(dataLocator.path)}: ${items ? 'Found' : 'Not found'}`);
// If not found, try fallback paths
if (!items && dataLocator.fallbackPaths) {
for (const fallbackPath of dataLocator.fallbackPaths) {
items = extractData(response, fallbackPath);
if (items) {
console.log(`Found data at fallback path ${logDataPath(fallbackPath)}`);
break;
}
}
}
// If no items found through defined paths, attempt auto-detection
if (!items) {
console.log('Could not find data at specified paths, attempting auto-detection');
// Try to find any array in the response
const findArrays = (obj, currentPath = []) => {
if (!obj || typeof obj !== 'object')
return [];
const paths = [];
Object.keys(obj).forEach((key) => {
const value = obj[key];
const newPath = [...currentPath, key];
if (Array.isArray(value) && value.length > 0) {
// Found an array with items
paths.push(newPath);
}
else if (value && typeof value === 'object') {
// Continue searching nested objects
paths.push(...findArrays(value, newPath));
}
});
return paths;
};
const possiblePaths = findArrays(response);
if (possiblePaths.length > 0) {
console.log('Auto-detected possible data paths:', possiblePaths.map(logDataPath));
// Use the first detected array
items = extractData(response, possiblePaths[0]);
console.log(`Using auto-detected path ${logDataPath(possiblePaths[0])}`);
}
}
// If we found items, process them
if (items && items.length > 0) {
console.log(`Retrieved ${items.length} items in this batch`);
// Add items to our result array, respecting the limit if specified
if (limit) {
const remainingCapacity = limit - allItems.length;
if (remainingCapacity < items.length) {
// Only add what we need to reach the limit
allItems.push(...items.slice(0, remainingCapacity));
console.log(`Added ${remainingCapacity} items to reach requested limit`);
hasMoreItems = false; // Stop pagination since we've reached the limit
}
else {
allItems.push(...items);
console.log(`Added all ${items.length} items to results`);
}
}
else {
allItems.push(...items);
console.log(`Added all ${items.length} items to results`);
}
// Check if we need to continue pagination
if (items.length < effectiveBatchSize) {
// Received fewer items than requested, so we've reached the end
console.log(`Received fewer items (${items.length}) than requested (${effectiveBatchSize}), pagination complete`);
hasMoreItems = false;
}
else {
// Prepare for next batch
offset += items.length;
console.log(`Moving to next batch, new offset: ${offset}`);
}
}
else {
// No items in this response, end pagination
console.log('No items found in response, ending pagination');
hasMoreItems = false;
}
}
console.log(`Pagination complete. Total items retrieved: ${allItems.length}`);
// Transform the items into INodeExecutionData objects
return allItems.map((item) => ({ json: item }));
}