n8n-nodes-resilience 0.1.0

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 (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.d.ts +6 -0
  4. package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.d.ts.map +1 -0
  5. package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.js +268 -0
  6. package/dist/nodes/ConcurrencyGate/ConcurrencyGate.node.js.map +1 -0
  7. package/dist/nodes/ConcurrencyGate/concurrencyGate.svg +6 -0
  8. package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.d.ts +6 -0
  9. package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.d.ts.map +1 -0
  10. package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.js +175 -0
  11. package/dist/nodes/DeadLetterQueue/DeadLetterQueue.node.js.map +1 -0
  12. package/dist/nodes/DeadLetterQueue/deadLetterQueue.svg +6 -0
  13. package/dist/nodes/RetryStrategy/RetryStrategy.node.d.ts +6 -0
  14. package/dist/nodes/RetryStrategy/RetryStrategy.node.d.ts.map +1 -0
  15. package/dist/nodes/RetryStrategy/RetryStrategy.node.js +255 -0
  16. package/dist/nodes/RetryStrategy/RetryStrategy.node.js.map +1 -0
  17. package/dist/nodes/RetryStrategy/retryStrategy.svg +6 -0
  18. package/dist/nodes/shared/fieldPath.d.ts +6 -0
  19. package/dist/nodes/shared/fieldPath.d.ts.map +1 -0
  20. package/dist/nodes/shared/fieldPath.js +44 -0
  21. package/dist/nodes/shared/fieldPath.js.map +1 -0
  22. package/dist/nodes/shared/retry.d.ts +3 -0
  23. package/dist/nodes/shared/retry.d.ts.map +1 -0
  24. package/dist/nodes/shared/retry.js +23 -0
  25. package/dist/nodes/shared/retry.js.map +1 -0
  26. package/dist/nodes/shared/staticData.d.ts +14 -0
  27. package/dist/nodes/shared/staticData.d.ts.map +1 -0
  28. package/dist/nodes/shared/staticData.js +31 -0
  29. package/dist/nodes/shared/staticData.js.map +1 -0
  30. package/dist/nodes/shared/utils.d.ts +11 -0
  31. package/dist/nodes/shared/utils.d.ts.map +1 -0
  32. package/dist/nodes/shared/utils.js +69 -0
  33. package/dist/nodes/shared/utils.js.map +1 -0
  34. package/package.json +61 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Taiwo Hassan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # n8n-nodes-resilience
2
+
3
+ Production-grade resilience utilities for n8n workflows.
4
+
5
+ This community node package helps workflow builders make unreliable integrations easier to manage. The nodes inspect incoming item data, add structured metadata, and route items so the rest of the workflow can handle retries, circuit breaking, concurrency limits, and dead-letter handling with regular n8n nodes.
6
+
7
+ ## Installation
8
+
9
+ Follow the [n8n community node installation guide](https://docs.n8n.io/integrations/community-nodes/installation/), or install the package directly:
10
+
11
+ ```bash
12
+ npm install n8n-nodes-resilience
13
+ ```
14
+
15
+ ## Nodes
16
+
17
+ - **Retry Strategy**: Decide whether an item should continue, retry, or go to an exhausted failure path.
18
+ - **Concurrency Gate**: Limit how many executions/items can enter a protected section at once.
19
+ - **Dead Letter Queue**: Wrap failed items in a clean dead-letter payload for storage or replay.
20
+
21
+ ## Retry Strategy
22
+
23
+ Use this node after a risky operation such as an HTTP Request node.
24
+
25
+ ```text
26
+ HTTP Request
27
+ -> Retry Strategy
28
+ -> output 1 Success / Continue
29
+ -> output 2 Retry -> Wait -> loop back to HTTP Request
30
+ -> output 3 Exhausted -> Dead Letter Queue
31
+ ```
32
+
33
+ The Retry Strategy node does not sleep internally. It calculates `__retry.delaySeconds` and routes the item. Use an n8n Wait node on the Retry output to perform the actual delay before looping back to the risky operation.
34
+
35
+ Metadata added to each item:
36
+
37
+ ```json
38
+ {
39
+ "__retry": {
40
+ "shouldRetry": true,
41
+ "attempt": 1,
42
+ "maxAttempts": 3,
43
+ "strategy": "exponential",
44
+ "delaySeconds": 5,
45
+ "reason": "Status code 503 is retryable",
46
+ "exhausted": false
47
+ }
48
+ }
49
+ ```
50
+
51
+ Default retryable status codes are `408,429,500,502,503,504`. Default permanent stop codes are `400,401,403,404`.
52
+
53
+ ## Concurrency Gate
54
+
55
+ Use Concurrency Gate to protect a section that should only have a limited number of active items/executions.
56
+
57
+ ```text
58
+ Concurrency Gate (Acquire)
59
+ -> Acquired / Allowed -> protected work
60
+ -> Blocked -> wait, retry, or skip
61
+
62
+ protected work -> Concurrency Gate (Release)
63
+ ```
64
+
65
+ Acquire creates a lock with a TTL and outputs `__concurrencyGate.lockId`. Release can use that lock ID from `__concurrencyGate.lockId`, or an explicit Lock ID parameter.
66
+
67
+ Important limitation: Concurrency Gate v1 uses n8n workflow static data as a best-effort lock store. It is useful for simple local and single-worker setups, but it is not a perfect distributed lock in all multi-worker, queue-mode, or horizontally scaled deployments. For strict distributed concurrency, use an external lock service or database-backed workflow design.
68
+
69
+ Metadata added to each item:
70
+
71
+ ```json
72
+ {
73
+ "__concurrencyGate": {
74
+ "key": "customer-123",
75
+ "acquired": true,
76
+ "activeCount": 1,
77
+ "maxConcurrent": 1,
78
+ "reason": "Lock acquired",
79
+ "lockId": "lock_mabc1234_abcd5678",
80
+ "expiresAt": "2026-05-24T12:00:00.000Z"
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## Dead Letter Queue
86
+
87
+ Use Dead Letter Queue at permanent failure paths, especially after Retry Strategy's Exhausted output.
88
+
89
+ ```text
90
+ Retry Strategy (Exhausted)
91
+ -> Dead Letter Queue
92
+ -> Google Sheets / Postgres / Slack / Notion / S3 / Webhook / database node
93
+ ```
94
+
95
+ The v1 operation is **Format Failed Item** and the destination mode is Output Only. This is intentional: the node formats a durable dead-letter item, and users can connect any regular n8n destination node for storage, notification, or replay.
96
+
97
+ Example output:
98
+
99
+ ```json
100
+ {
101
+ "deadLetterId": "dlq_mabc1234_abcd5678",
102
+ "timestamp": "2026-05-24T12:00:00.000Z",
103
+ "reason": "Request failed",
104
+ "sourceNode": "Dead Letter Queue",
105
+ "workflowId": "workflow-id",
106
+ "workflowName": "Production workflow",
107
+ "executionId": "12345",
108
+ "originalPayload": {},
109
+ "error": {},
110
+ "retry": {}
111
+ }
112
+ ```
113
+
114
+ ## Example Workflows
115
+
116
+ ### HTTP Retry With Dead Letter
117
+
118
+ 1. HTTP Request calls an external API.
119
+ 2. Retry Strategy checks `statusCode` and `message`.
120
+ 3. Retry output goes to Wait using `{{$json.__retry.delaySeconds}}`.
121
+ 4. Wait loops back to HTTP Request.
122
+ 5. Exhausted output goes to Dead Letter Queue.
123
+ 6. Dead Letter Queue connects to a storage or alerting node.
124
+
125
+ ### Concurrency-Limited Section
126
+
127
+ 1. Concurrency Gate Acquire uses key `={{$json.customerId}}`.
128
+ 2. Acquired output does the protected work.
129
+ 3. The final node releases `{{$json.__concurrencyGate.lockId}}`.
130
+ 4. Blocked output waits, retries, or skips based on workflow needs.
131
+
132
+ ## Development
133
+
134
+ ```bash
135
+ npm install
136
+ npm run build
137
+ npm run lint
138
+ ```
139
+
140
+ ## License
141
+
142
+ [MIT](LICENSE)
@@ -0,0 +1,6 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
2
+ export declare class ConcurrencyGate implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=ConcurrencyGate.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConcurrencyGate.node.d.ts","sourceRoot":"","sources":["../../../nodes/ConcurrencyGate/ConcurrencyGate.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAGrB,MAAM,cAAc,CAAC;AAmBtB,qBAAa,eAAgB,YAAW,SAAS;IAC/C,WAAW,EAAE,oBAAoB,CAmK/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAyIxE"}
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConcurrencyGate = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const fieldPath_1 = require("../shared/fieldPath");
6
+ const staticData_1 = require("../shared/staticData");
7
+ const utils_1 = require("../shared/utils");
8
+ class ConcurrencyGate {
9
+ constructor() {
10
+ this.description = {
11
+ displayName: "Concurrency Gate",
12
+ name: "concurrencyGate",
13
+ icon: "file:concurrencyGate.svg",
14
+ group: ["transform"],
15
+ version: 1,
16
+ subtitle: '={{$parameter["operation"]}}',
17
+ description: "Best-effort static-data concurrency gate for workflow sections",
18
+ defaults: {
19
+ name: "Concurrency Gate",
20
+ },
21
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
22
+ outputs: [
23
+ {
24
+ type: n8n_workflow_1.NodeConnectionTypes.Main,
25
+ displayName: "Acquired / Allowed",
26
+ },
27
+ {
28
+ type: n8n_workflow_1.NodeConnectionTypes.Main,
29
+ displayName: "Blocked",
30
+ },
31
+ ],
32
+ usableAsTool: true,
33
+ outputNames: ["Acquired / Allowed", "Blocked"],
34
+ properties: [
35
+ {
36
+ displayName: "Operation",
37
+ name: "operation",
38
+ type: "options",
39
+ noDataExpression: true,
40
+ options: [
41
+ {
42
+ name: "Acquire",
43
+ value: "acquire",
44
+ description: "Try to acquire a lock for this gate key",
45
+ action: "Acquire concurrency lock",
46
+ },
47
+ {
48
+ name: "Force Release",
49
+ value: "forceRelease",
50
+ description: "Clear all active locks for this gate key",
51
+ action: "Force release concurrency locks",
52
+ },
53
+ {
54
+ name: "Inspect",
55
+ value: "inspect",
56
+ description: "Return current lock metadata for this gate key",
57
+ action: "Inspect concurrency gate",
58
+ },
59
+ {
60
+ name: "Release",
61
+ value: "release",
62
+ description: "Release a previously acquired lock",
63
+ action: "Release concurrency lock",
64
+ },
65
+ ],
66
+ default: "acquire",
67
+ },
68
+ {
69
+ displayName: "Gate Key",
70
+ name: "gateKey",
71
+ type: "string",
72
+ required: true,
73
+ default: "",
74
+ placeholder: "={{$json.customerId || 'global'}}",
75
+ description: "Unique key for the protected workflow section, such as a customer ID or external service name",
76
+ },
77
+ {
78
+ displayName: "Max Concurrent",
79
+ name: "maxConcurrent",
80
+ type: "number",
81
+ typeOptions: {
82
+ minValue: 1,
83
+ },
84
+ displayOptions: {
85
+ show: {
86
+ operation: ["acquire", "inspect"],
87
+ },
88
+ },
89
+ default: 1,
90
+ description: "Maximum active locks allowed for this gate key",
91
+ },
92
+ {
93
+ displayName: "Lock TTL Seconds",
94
+ name: "lockTtlSeconds",
95
+ type: "number",
96
+ typeOptions: {
97
+ minValue: 1,
98
+ },
99
+ displayOptions: {
100
+ show: {
101
+ operation: ["acquire", "inspect"],
102
+ },
103
+ },
104
+ default: 300,
105
+ description: "How long an acquired lock remains active if not released",
106
+ },
107
+ {
108
+ displayName: "On Limit Reached",
109
+ name: "onLimitReached",
110
+ type: "options",
111
+ noDataExpression: true,
112
+ displayOptions: {
113
+ show: {
114
+ operation: ["acquire"],
115
+ },
116
+ },
117
+ options: [
118
+ {
119
+ name: "Allow With Metadata Only",
120
+ value: "allowWithMetadata",
121
+ description: "Allow items through but mark that the lock was not acquired",
122
+ action: "Allow without acquiring",
123
+ },
124
+ {
125
+ name: "Route to Blocked Output",
126
+ value: "routeBlocked",
127
+ description: "Send items over the blocked output when the gate is full",
128
+ action: "Route blocked items",
129
+ },
130
+ ],
131
+ default: "routeBlocked",
132
+ description: "What to do when the active lock count is at the limit",
133
+ },
134
+ {
135
+ displayName: "Lock ID Field",
136
+ name: "lockIdField",
137
+ type: "string",
138
+ displayOptions: {
139
+ show: {
140
+ operation: ["release"],
141
+ },
142
+ },
143
+ default: "__concurrencyGate.lockId",
144
+ description: "Dot path containing the lock ID to release. Leave blank to use the metadata lock ID.",
145
+ },
146
+ {
147
+ displayName: "Lock ID",
148
+ name: "lockId",
149
+ type: "string",
150
+ displayOptions: {
151
+ show: {
152
+ operation: ["release"],
153
+ },
154
+ },
155
+ default: "",
156
+ description: "Optional explicit lock ID to release. Takes precedence over Lock ID Field.",
157
+ },
158
+ {
159
+ displayName: "Preserve Original Item",
160
+ name: "preserveOriginalItem",
161
+ type: "boolean",
162
+ default: true,
163
+ description: "Whether to keep the incoming JSON and binary data when adding gate metadata",
164
+ },
165
+ ],
166
+ };
167
+ }
168
+ async execute() {
169
+ const items = this.getInputData();
170
+ const allowedItems = [];
171
+ const blockedItems = [];
172
+ const states = (0, staticData_1.getConcurrencyStates)(this);
173
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
174
+ try {
175
+ const item = items[itemIndex];
176
+ const operation = this.getNodeParameter("operation", itemIndex);
177
+ const key = this.getNodeParameter("gateKey", itemIndex).trim();
178
+ const preserveOriginalItem = this.getNodeParameter("preserveOriginalItem", itemIndex);
179
+ const now = Date.now();
180
+ const state = (0, staticData_1.getConcurrencyState)(states, key);
181
+ (0, staticData_1.cleanExpiredLocks)(state, now);
182
+ let acquired = false;
183
+ let routeBlocked = false;
184
+ let lockId;
185
+ let expiresAt;
186
+ let reason = "Gate inspected";
187
+ const maxConcurrent = operation === "release" || operation === "forceRelease"
188
+ ? 1
189
+ : Math.max(1, this.getNodeParameter("maxConcurrent", itemIndex));
190
+ if (operation === "acquire") {
191
+ const lockTtlSeconds = Math.max(1, this.getNodeParameter("lockTtlSeconds", itemIndex));
192
+ const onLimitReached = this.getNodeParameter("onLimitReached", itemIndex);
193
+ if (state.locks.length < maxConcurrent) {
194
+ lockId = (0, utils_1.generateId)("lock");
195
+ expiresAt = (0, utils_1.isoFromTimestamp)(now + lockTtlSeconds * 1000);
196
+ const lock = {
197
+ id: lockId,
198
+ createdAt: (0, utils_1.isoFromTimestamp)(now),
199
+ expiresAt,
200
+ executionId: this.getExecutionId(),
201
+ };
202
+ state.locks.push(lock);
203
+ acquired = true;
204
+ reason = "Lock acquired";
205
+ }
206
+ else {
207
+ reason = "Concurrency limit reached";
208
+ routeBlocked = onLimitReached === "routeBlocked";
209
+ }
210
+ }
211
+ if (operation === "release") {
212
+ const explicitLockId = this.getNodeParameter("lockId", itemIndex).trim();
213
+ const lockIdField = this.getNodeParameter("lockIdField", itemIndex).trim();
214
+ const fieldLockId = lockIdField
215
+ ? (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, lockIdField))
216
+ : undefined;
217
+ lockId = explicitLockId || fieldLockId;
218
+ if (lockId) {
219
+ const beforeCount = state.locks.length;
220
+ state.locks = state.locks.filter((lock) => lock.id !== lockId);
221
+ reason =
222
+ state.locks.length < beforeCount
223
+ ? "Lock released"
224
+ : "Lock ID was not active";
225
+ }
226
+ else {
227
+ reason = "No lock ID provided";
228
+ }
229
+ }
230
+ if (operation === "forceRelease") {
231
+ state.locks = [];
232
+ reason = "All locks cleared for gate key";
233
+ }
234
+ const metadata = {
235
+ key,
236
+ acquired,
237
+ activeCount: state.locks.length,
238
+ maxConcurrent,
239
+ reason,
240
+ lockId,
241
+ expiresAt,
242
+ locks: operation === "inspect" ? state.locks : undefined,
243
+ };
244
+ const outputItem = (0, utils_1.createOutputItem)(item, itemIndex, preserveOriginalItem, "__concurrencyGate", metadata);
245
+ if (routeBlocked) {
246
+ blockedItems.push(outputItem);
247
+ }
248
+ else {
249
+ allowedItems.push(outputItem);
250
+ }
251
+ }
252
+ catch (error) {
253
+ const message = error instanceof Error ? error.message : "Unknown concurrency error";
254
+ if (this.continueOnFail()) {
255
+ blockedItems.push({
256
+ json: { error: message },
257
+ pairedItem: { item: itemIndex },
258
+ });
259
+ continue;
260
+ }
261
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
262
+ }
263
+ }
264
+ return [allowedItems, blockedItems];
265
+ }
266
+ }
267
+ exports.ConcurrencyGate = ConcurrencyGate;
268
+ //# sourceMappingURL=ConcurrencyGate.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConcurrencyGate.node.js","sourceRoot":"","sources":["../../../nodes/ConcurrencyGate/ConcurrencyGate.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Concurrency Gate">
2
+ <rect width="64" height="64" rx="14" fill="#0E8F7E"/>
3
+ <path d="M18 18h28v28H18z" fill="none" stroke="#fff" stroke-width="5" stroke-linejoin="round"/>
4
+ <path d="M12 28h12M12 38h12M40 28h12M40 38h12" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round"/>
5
+ <path d="M32 24v16" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round"/>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
2
+ export declare class DeadLetterQueue implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
6
+ //# sourceMappingURL=DeadLetterQueue.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeadLetterQueue.node.d.ts","sourceRoot":"","sources":["../../../nodes/DeadLetterQueue/DeadLetterQueue.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAGrB,MAAM,cAAc,CAAC;AAatB,qBAAa,eAAgB,YAAW,SAAS;IAC/C,WAAW,EAAE,oBAAoB,CAwG/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAqGxE"}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeadLetterQueue = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const fieldPath_1 = require("../shared/fieldPath");
6
+ const utils_1 = require("../shared/utils");
7
+ class DeadLetterQueue {
8
+ constructor() {
9
+ this.description = {
10
+ displayName: "Dead Letter Queue",
11
+ name: "deadLetterQueue",
12
+ icon: "file:deadLetterQueue.svg",
13
+ group: ["transform"],
14
+ version: 1,
15
+ subtitle: '={{$parameter["operation"]}}',
16
+ description: "Format failed workflow items for review or replay",
17
+ defaults: {
18
+ name: "Dead Letter Queue",
19
+ },
20
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
21
+ outputs: [
22
+ {
23
+ type: n8n_workflow_1.NodeConnectionTypes.Main,
24
+ displayName: "Dead Letter Item",
25
+ },
26
+ ],
27
+ usableAsTool: true,
28
+ properties: [
29
+ {
30
+ displayName: "Operation",
31
+ name: "operation",
32
+ type: "options",
33
+ noDataExpression: true,
34
+ options: [
35
+ {
36
+ name: "Format Failed Item",
37
+ value: "formatFailedItem",
38
+ description: "Wrap the input item as a dead-letter payload",
39
+ action: "Format failed item",
40
+ },
41
+ ],
42
+ default: "formatFailedItem",
43
+ },
44
+ {
45
+ displayName: "Failure Reason Field",
46
+ name: "failureReasonField",
47
+ type: "string",
48
+ default: "message",
49
+ description: "Dot path containing the failure reason. Falls back to error metadata when empty.",
50
+ },
51
+ {
52
+ displayName: "Source Node Field",
53
+ name: "sourceNodeField",
54
+ type: "string",
55
+ default: "sourceNode",
56
+ description: "Optional dot path containing the source node name",
57
+ },
58
+ {
59
+ displayName: "Workflow ID Field",
60
+ name: "workflowIdField",
61
+ type: "string",
62
+ default: "workflowId",
63
+ description: "Optional dot path containing a workflow ID override",
64
+ },
65
+ {
66
+ displayName: "Workflow Name Field",
67
+ name: "workflowNameField",
68
+ type: "string",
69
+ default: "workflowName",
70
+ description: "Optional dot path containing a workflow name override",
71
+ },
72
+ {
73
+ displayName: "Execution ID Field",
74
+ name: "executionIdField",
75
+ type: "string",
76
+ default: "executionId",
77
+ description: "Optional dot path containing an execution ID override",
78
+ },
79
+ {
80
+ displayName: "Include Original Payload",
81
+ name: "includeOriginalPayload",
82
+ type: "boolean",
83
+ default: true,
84
+ description: "Whether to include the incoming JSON as originalPayload",
85
+ },
86
+ {
87
+ displayName: "Include Error Metadata",
88
+ name: "includeErrorMetadata",
89
+ type: "boolean",
90
+ default: true,
91
+ description: "Whether to include error, retry, circuit breaker, and gate metadata",
92
+ },
93
+ {
94
+ displayName: "Destination Mode",
95
+ name: "destinationMode",
96
+ type: "options",
97
+ noDataExpression: true,
98
+ options: [
99
+ {
100
+ name: "Output Only",
101
+ value: "outputOnly",
102
+ description: "Send the dead-letter item to the node output",
103
+ action: "Output dead-letter item",
104
+ },
105
+ ],
106
+ default: "outputOnly",
107
+ description: "External dead-letter storage is intentionally left to downstream n8n nodes",
108
+ },
109
+ ],
110
+ };
111
+ }
112
+ async execute() {
113
+ var _a, _b, _c, _d, _e, _f, _g;
114
+ const items = this.getInputData();
115
+ const returnData = [];
116
+ const workflow = this.getWorkflow();
117
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
118
+ try {
119
+ const item = items[itemIndex];
120
+ const operation = this.getNodeParameter("operation", itemIndex);
121
+ const failureReasonField = this.getNodeParameter("failureReasonField", itemIndex);
122
+ const sourceNodeField = this.getNodeParameter("sourceNodeField", itemIndex);
123
+ const workflowIdField = this.getNodeParameter("workflowIdField", itemIndex);
124
+ const workflowNameField = this.getNodeParameter("workflowNameField", itemIndex);
125
+ const executionIdField = this.getNodeParameter("executionIdField", itemIndex);
126
+ const includeOriginalPayload = this.getNodeParameter("includeOriginalPayload", itemIndex);
127
+ const includeErrorMetadata = this.getNodeParameter("includeErrorMetadata", itemIndex);
128
+ const reason = (_c = (_b = (_a = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, failureReasonField))) !== null && _a !== void 0 ? _a : (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, "error.message"))) !== null && _b !== void 0 ? _b : (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, "error"))) !== null && _c !== void 0 ? _c : "Failed item";
129
+ const error = includeErrorMetadata
130
+ ? (0, utils_1.removeUndefinedValues)({
131
+ error: (0, fieldPath_1.getValueAtPath)(item.json, "error"),
132
+ message: (0, fieldPath_1.getValueAtPath)(item.json, "message"),
133
+ statusCode: (0, fieldPath_1.getValueAtPath)(item.json, "statusCode"),
134
+ concurrencyGate: (0, fieldPath_1.getValueAtPath)(item.json, "__concurrencyGate"),
135
+ })
136
+ : {};
137
+ const deadLetter = (0, utils_1.removeUndefinedValues)({
138
+ deadLetterId: (0, utils_1.generateId)("dlq"),
139
+ timestamp: new Date().toISOString(),
140
+ operation,
141
+ reason,
142
+ sourceNode: (_d = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, sourceNodeField))) !== null && _d !== void 0 ? _d : this.getNode().name,
143
+ workflowId: (_e = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, workflowIdField))) !== null && _e !== void 0 ? _e : workflow.id,
144
+ workflowName: (_f = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, workflowNameField))) !== null && _f !== void 0 ? _f : workflow.name,
145
+ executionId: (_g = (0, utils_1.toStringValue)((0, fieldPath_1.getValueAtPath)(item.json, executionIdField))) !== null && _g !== void 0 ? _g : this.getExecutionId(),
146
+ originalPayload: includeOriginalPayload
147
+ ? (0, utils_1.deepCopy)(item.json)
148
+ : undefined,
149
+ error,
150
+ retry: includeErrorMetadata
151
+ ? (0, utils_1.asDataObject)((0, fieldPath_1.getValueAtPath)(item.json, "__retry"))
152
+ : {},
153
+ });
154
+ returnData.push({
155
+ json: deadLetter,
156
+ pairedItem: { item: itemIndex },
157
+ });
158
+ }
159
+ catch (error) {
160
+ const message = error instanceof Error ? error.message : "Unknown dead-letter error";
161
+ if (this.continueOnFail()) {
162
+ returnData.push({
163
+ json: { error: message },
164
+ pairedItem: { item: itemIndex },
165
+ });
166
+ continue;
167
+ }
168
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
169
+ }
170
+ }
171
+ return [returnData];
172
+ }
173
+ }
174
+ exports.DeadLetterQueue = DeadLetterQueue;
175
+ //# sourceMappingURL=DeadLetterQueue.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeadLetterQueue.node.js","sourceRoot":"","sources":["../../../nodes/DeadLetterQueue/DeadLetterQueue.node.ts"],"names":[],"mappings":"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"}