n8n-nodes-hudu 1.6.5 → 1.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/nodes/Hudu/Hudu.node.js +9 -0
  2. package/dist/nodes/Hudu/Hudu.node.js.map +1 -1
  3. package/dist/nodes/Hudu/Hudu.node.ts +11 -0
  4. package/dist/nodes/Hudu/descriptions/activity_logs.description.js +2 -0
  5. package/dist/nodes/Hudu/descriptions/activity_logs.description.js.map +1 -1
  6. package/dist/nodes/Hudu/descriptions/activity_logs.description.ts +2 -0
  7. package/dist/nodes/Hudu/descriptions/articles.description.js +2 -0
  8. package/dist/nodes/Hudu/descriptions/articles.description.js.map +1 -1
  9. package/dist/nodes/Hudu/descriptions/articles.description.ts +2 -0
  10. package/dist/nodes/Hudu/descriptions/asset_layout_fields.description.js +2 -0
  11. package/dist/nodes/Hudu/descriptions/asset_layout_fields.description.js.map +1 -1
  12. package/dist/nodes/Hudu/descriptions/asset_layout_fields.description.ts +2 -0
  13. package/dist/nodes/Hudu/descriptions/asset_layouts.description.js +2 -0
  14. package/dist/nodes/Hudu/descriptions/asset_layouts.description.js.map +1 -1
  15. package/dist/nodes/Hudu/descriptions/asset_layouts.description.ts +2 -0
  16. package/dist/nodes/Hudu/descriptions/asset_passwords.description.js +2 -0
  17. package/dist/nodes/Hudu/descriptions/asset_passwords.description.js.map +1 -1
  18. package/dist/nodes/Hudu/descriptions/asset_passwords.description.ts +2 -0
  19. package/dist/nodes/Hudu/descriptions/assets.description.js +2 -0
  20. package/dist/nodes/Hudu/descriptions/assets.description.js.map +1 -1
  21. package/dist/nodes/Hudu/descriptions/assets.description.ts +2 -0
  22. package/dist/nodes/Hudu/descriptions/companies.description.js +2 -0
  23. package/dist/nodes/Hudu/descriptions/companies.description.js.map +1 -1
  24. package/dist/nodes/Hudu/descriptions/companies.description.ts +2 -0
  25. package/dist/nodes/Hudu/descriptions/expirations.description.js +2 -0
  26. package/dist/nodes/Hudu/descriptions/expirations.description.js.map +1 -1
  27. package/dist/nodes/Hudu/descriptions/expirations.description.ts +2 -0
  28. package/dist/nodes/Hudu/descriptions/folders.description.js +2 -0
  29. package/dist/nodes/Hudu/descriptions/folders.description.js.map +1 -1
  30. package/dist/nodes/Hudu/descriptions/folders.description.ts +2 -0
  31. package/dist/nodes/Hudu/descriptions/groups.description.js +2 -0
  32. package/dist/nodes/Hudu/descriptions/groups.description.js.map +1 -1
  33. package/dist/nodes/Hudu/descriptions/groups.description.ts +2 -0
  34. package/dist/nodes/Hudu/descriptions/ip_addresses.description.js +2 -0
  35. package/dist/nodes/Hudu/descriptions/ip_addresses.description.js.map +1 -1
  36. package/dist/nodes/Hudu/descriptions/ip_addresses.description.ts +2 -0
  37. package/dist/nodes/Hudu/descriptions/lists.description.js +2 -0
  38. package/dist/nodes/Hudu/descriptions/lists.description.js.map +1 -1
  39. package/dist/nodes/Hudu/descriptions/lists.description.ts +2 -0
  40. package/dist/nodes/Hudu/descriptions/magic_dash.description.js +2 -0
  41. package/dist/nodes/Hudu/descriptions/magic_dash.description.js.map +1 -1
  42. package/dist/nodes/Hudu/descriptions/magic_dash.description.ts +310 -308
  43. package/dist/nodes/Hudu/descriptions/matchers.description.js +2 -0
  44. package/dist/nodes/Hudu/descriptions/matchers.description.js.map +1 -1
  45. package/dist/nodes/Hudu/descriptions/matchers.description.ts +2 -0
  46. package/dist/nodes/Hudu/descriptions/networks.description.js +2 -0
  47. package/dist/nodes/Hudu/descriptions/networks.description.js.map +1 -1
  48. package/dist/nodes/Hudu/descriptions/networks.description.ts +2 -0
  49. package/dist/nodes/Hudu/descriptions/passwordFolders.descriptions.js +2 -0
  50. package/dist/nodes/Hudu/descriptions/passwordFolders.descriptions.js.map +1 -1
  51. package/dist/nodes/Hudu/descriptions/passwordFolders.descriptions.ts +2 -0
  52. package/dist/nodes/Hudu/descriptions/procedure_tasks.description.js +2 -0
  53. package/dist/nodes/Hudu/descriptions/procedure_tasks.description.js.map +1 -1
  54. package/dist/nodes/Hudu/descriptions/procedure_tasks.description.ts +2 -0
  55. package/dist/nodes/Hudu/descriptions/procedures.description.js +2 -0
  56. package/dist/nodes/Hudu/descriptions/procedures.description.js.map +1 -1
  57. package/dist/nodes/Hudu/descriptions/procedures.description.ts +2 -0
  58. package/dist/nodes/Hudu/descriptions/public_photos.description.js +2 -0
  59. package/dist/nodes/Hudu/descriptions/public_photos.description.js.map +1 -1
  60. package/dist/nodes/Hudu/descriptions/public_photos.description.ts +2 -0
  61. package/dist/nodes/Hudu/descriptions/rack_storage_items.description.js +2 -0
  62. package/dist/nodes/Hudu/descriptions/rack_storage_items.description.js.map +1 -1
  63. package/dist/nodes/Hudu/descriptions/rack_storage_items.description.ts +2 -0
  64. package/dist/nodes/Hudu/descriptions/rack_storages.description.js +2 -0
  65. package/dist/nodes/Hudu/descriptions/rack_storages.description.js.map +1 -1
  66. package/dist/nodes/Hudu/descriptions/rack_storages.description.ts +2 -0
  67. package/dist/nodes/Hudu/descriptions/relations.description.js +2 -0
  68. package/dist/nodes/Hudu/descriptions/relations.description.js.map +1 -1
  69. package/dist/nodes/Hudu/descriptions/relations.description.ts +2 -0
  70. package/dist/nodes/Hudu/descriptions/resources.js +16 -0
  71. package/dist/nodes/Hudu/descriptions/resources.js.map +1 -1
  72. package/dist/nodes/Hudu/descriptions/resources.ts +21 -1
  73. package/dist/nodes/Hudu/descriptions/uploads.description.js +2 -0
  74. package/dist/nodes/Hudu/descriptions/uploads.description.js.map +1 -1
  75. package/dist/nodes/Hudu/descriptions/uploads.description.ts +2 -0
  76. package/dist/nodes/Hudu/descriptions/users.description.js +2 -0
  77. package/dist/nodes/Hudu/descriptions/users.description.js.map +1 -1
  78. package/dist/nodes/Hudu/descriptions/users.description.ts +2 -0
  79. package/dist/nodes/Hudu/descriptions/vlan_zones.description.js +2 -0
  80. package/dist/nodes/Hudu/descriptions/vlan_zones.description.js.map +1 -1
  81. package/dist/nodes/Hudu/descriptions/vlan_zones.description.ts +2 -0
  82. package/dist/nodes/Hudu/descriptions/vlans.description.js +2 -0
  83. package/dist/nodes/Hudu/descriptions/vlans.description.js.map +1 -1
  84. package/dist/nodes/Hudu/descriptions/vlans.description.ts +2 -0
  85. package/dist/nodes/Hudu/descriptions/websites.description.js +2 -0
  86. package/dist/nodes/Hudu/descriptions/websites.description.js.map +1 -1
  87. package/dist/nodes/Hudu/descriptions/websites.description.ts +2 -0
  88. package/dist/nodes/Hudu/resources/assets/assets.handler.js +21 -12
  89. package/dist/nodes/Hudu/resources/assets/assets.handler.js.map +1 -1
  90. package/dist/nodes/Hudu/resources/assets/assets.handler.ts +32 -15
  91. package/dist/nodes/Hudu/resources/magic_dash/magic_dash.handler.ts +100 -100
  92. package/dist/nodes/Hudu/utils/constants.js +9 -1
  93. package/dist/nodes/Hudu/utils/constants.js.map +1 -1
  94. package/dist/nodes/Hudu/utils/constants.ts +15 -0
  95. package/dist/nodes/Hudu/utils/operations/magic_dash.ts +68 -68
  96. package/dist/nodes/Hudu/utils/requestUtils.js +47 -33
  97. package/dist/nodes/Hudu/utils/requestUtils.js.map +1 -1
  98. package/dist/nodes/Hudu/utils/requestUtils.ts +73 -49
  99. package/package.json +1 -1
@@ -19,7 +19,7 @@ import type {
19
19
  JsonObject,
20
20
  } from 'n8n-workflow';
21
21
  import { NodeApiError } from 'n8n-workflow';
22
- import { HUDU_API_CONSTANTS, RESOURCES_WITH_PAGE_SIZE } from './constants';
22
+ import { HUDU_API_CONSTANTS, RATE_LIMIT_CONFIG, RESOURCES_WITH_PAGE_SIZE } from './constants';
23
23
  import type { FilterMapping } from './types';
24
24
  import { applyPostFilters } from './filterUtils';
25
25
  import { DEBUG_CONFIG, debugLog } from './debugConfig';
@@ -57,13 +57,6 @@ export function sanitizeRequestPayload<T extends IDataObject>(body: T): T {
57
57
  return cleaned as T;
58
58
  }
59
59
 
60
- // Rate limiting constants
61
- const RATE_LIMIT_CONFIG = {
62
- MAX_RETRIES: 3,
63
- BASE_DELAY_MS: 1000, // Start with 1 second delay
64
- MAX_DELAY_MS: 10000, // Maximum delay of 10 seconds
65
- JITTER_MS: 500, // Add up to 500ms of random jitter
66
- } as const;
67
60
 
68
61
  // HTTP Status Code Messages
69
62
  const HTTP_STATUS_MESSAGES = {
@@ -453,8 +446,17 @@ export async function handleListing<T extends IDataObject>(
453
446
  RESOURCES_WITH_PAGE_SIZE.includes(resourcePath as any) ||
454
447
  (resourcePath.startsWith('companies/') && resourcePath.endsWith('/assets'));
455
448
 
449
+ // Rate limiting: track delay and consecutive rate limit errors
450
+ let currentDelay: number = RATE_LIMIT_CONFIG.DELAY_MS;
451
+ let consecutiveRateLimits = 0;
452
+
456
453
  // Keep fetching until we have enough filtered results or no more data
457
454
  while (hasMore) {
455
+ // Add delay between pagination requests (skip first page)
456
+ if (page > 1) {
457
+ await sleep(currentDelay);
458
+ }
459
+
458
460
  // Only include pagination parameters if the resource supports them
459
461
  const queryParams = { ...query };
460
462
 
@@ -463,54 +465,76 @@ export async function handleListing<T extends IDataObject>(
463
465
  queryParams.page_size = pageSize;
464
466
  }
465
467
 
466
- const response = await huduApiRequest.call(this, method, endpoint, body, queryParams, resourceName);
467
- const batchResults = parseHuduResponse(response, resourceName);
468
-
469
- //debugLog('[handleListing] Page fetched', {
470
- // endpoint,
471
- // resourceName,
472
- // page,
473
- // supportsPagination,
474
- // batchCount: batchResults.length,
475
- // cumulativeCount: results.length + batchResults.length
476
- //});
477
-
478
- if (batchResults.length === 0) {
479
- hasMore = false;
480
- continue;
481
- }
468
+ try {
469
+ const response = await huduApiRequest.call(this, method, endpoint, body, queryParams, resourceName);
470
+ const batchResults = parseHuduResponse(response, resourceName);
471
+
472
+ // Reset consecutive rate limit counter on success
473
+ consecutiveRateLimits = 0;
474
+
475
+ //debugLog('[handleListing] Page fetched', {
476
+ // endpoint,
477
+ // resourceName,
478
+ // page,
479
+ // supportsPagination,
480
+ // batchCount: batchResults.length,
481
+ // cumulativeCount: results.length + batchResults.length
482
+ //});
483
+
484
+ if (batchResults.length === 0) {
485
+ hasMore = false;
486
+ continue;
487
+ }
482
488
 
483
- results.push(...batchResults);
484
-
485
- // Apply filters to all results we have so far
486
- if (postProcessFilters && filterMapping) {
487
- filteredResults = applyPostFilters(
488
- results,
489
- postProcessFilters,
490
- filterMapping as Record<string, (item: IDataObject, value: unknown) => boolean>,
491
- );
492
- } else {
493
- filteredResults = results;
494
- }
489
+ results.push(...batchResults);
490
+
491
+ // Apply filters to all results we have so far
492
+ if (postProcessFilters && filterMapping) {
493
+ filteredResults = applyPostFilters(
494
+ results,
495
+ postProcessFilters,
496
+ filterMapping as Record<string, (item: IDataObject, value: unknown) => boolean>,
497
+ );
498
+ } else {
499
+ filteredResults = results;
500
+ }
495
501
 
496
- // If resource doesn't support pagination, we get all data in one request
497
- if (!supportsPagination) {
498
- hasMore = false;
499
- } else {
500
- // Determine if we should continue fetching for resources with pagination
501
- if (!returnAll) {
502
- if (filteredResults.length >= limit) {
503
- hasMore = false;
502
+ // If resource doesn't support pagination, we get all data in one request
503
+ if (!supportsPagination) {
504
+ hasMore = false;
505
+ } else {
506
+ // Determine if we should continue fetching for resources with pagination
507
+ if (!returnAll) {
508
+ if (filteredResults.length >= limit) {
509
+ hasMore = false;
510
+ } else {
511
+ // Continue if there might be more results
512
+ hasMore = batchResults.length === pageSize;
513
+ }
504
514
  } else {
505
- // Continue if there might be more results
515
+ // If returning all, continue if there might be more results
506
516
  hasMore = batchResults.length === pageSize;
507
517
  }
508
- } else {
509
- // If returning all, continue if there might be more results
510
- hasMore = batchResults.length === pageSize;
518
+
519
+ page++;
511
520
  }
521
+ } catch (error) {
522
+ // If rate limited, apply exponential backoff for remaining requests
523
+ const err = error as IDataObject;
524
+ const context = err.context as IDataObject | undefined;
525
+ const responseContext = context?.response as IDataObject | undefined;
526
+ const statusCode = err.statusCode ?? responseContext?.statusCode;
512
527
 
513
- page++;
528
+ if (statusCode === 429) {
529
+ consecutiveRateLimits++;
530
+ // Exponential backoff: 1s, 2s, 4s, 8s... capped at MAX_DELAY_MS
531
+ currentDelay = Math.min(
532
+ RATE_LIMIT_CONFIG.BACKOFF_DELAY_MS * (2 ** (consecutiveRateLimits - 1)),
533
+ RATE_LIMIT_CONFIG.MAX_DELAY_MS
534
+ );
535
+ }
536
+ // Re-throw error to let existing retry logic in executeHuduRequest handle it
537
+ throw error;
514
538
  }
515
539
  }
516
540
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-hudu",
3
- "version": "1.6.5",
3
+ "version": "1.6.7",
4
4
  "description": "This n8n custom node facilitates integration with Hudu's API.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",