n8n-nodes-resend 2.6.2 → 2.6.4

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 (46) hide show
  1. package/README.md +1 -0
  2. package/dist/credentials/ResendApi.credentials.d.ts +2 -2
  3. package/dist/credentials/ResendOAuth2Api.credentials.d.ts +2 -2
  4. package/dist/credentials/ResendWebhookSigningSecretApi.credentials.d.ts +1 -1
  5. package/dist/nodes/Resend/Resend.node.d.ts +5 -3
  6. package/dist/nodes/Resend/Resend.node.js +14 -5
  7. package/dist/nodes/Resend/ResendTrigger.node.d.ts +13 -1
  8. package/dist/nodes/Resend/ResendTrigger.node.js +111 -6
  9. package/dist/nodes/Resend/actions/account/index.js +1 -1
  10. package/dist/nodes/Resend/actions/domain/listTrackingDomains.operation.js +2 -2
  11. package/dist/nodes/Resend/actions/email/send.operation.js +1 -1
  12. package/dist/nodes/Resend/actions/email/sendAndWait.operation.d.ts +1 -1
  13. package/dist/nodes/Resend/actions/email/sendAndWait.operation.js +1 -1
  14. package/dist/nodes/Resend/actions/email/sendBatch.operation.js +17 -4
  15. package/dist/nodes/Resend/actions/router.js +4 -1
  16. package/dist/nodes/Resend/actions/suppression/batchAdd.operation.d.ts +8 -0
  17. package/dist/nodes/Resend/actions/suppression/batchAdd.operation.js +41 -0
  18. package/dist/nodes/Resend/actions/suppression/batchRemove.operation.d.ts +8 -0
  19. package/dist/nodes/Resend/actions/suppression/batchRemove.operation.js +80 -0
  20. package/dist/nodes/Resend/actions/suppression/create.operation.d.ts +8 -0
  21. package/dist/nodes/Resend/actions/suppression/create.operation.js +37 -0
  22. package/dist/nodes/Resend/actions/suppression/delete.operation.d.ts +8 -0
  23. package/dist/nodes/Resend/actions/suppression/delete.operation.js +37 -0
  24. package/dist/nodes/Resend/actions/suppression/execute.d.ts +4 -0
  25. package/dist/nodes/Resend/actions/suppression/execute.js +18 -0
  26. package/dist/nodes/Resend/actions/suppression/get.operation.d.ts +8 -0
  27. package/dist/nodes/Resend/actions/suppression/get.operation.js +37 -0
  28. package/dist/nodes/Resend/actions/suppression/index.d.ts +13 -0
  29. package/dist/nodes/Resend/actions/suppression/index.js +122 -0
  30. package/dist/nodes/Resend/actions/suppression/list.operation.d.ts +8 -0
  31. package/dist/nodes/Resend/actions/suppression/list.operation.js +83 -0
  32. package/dist/nodes/Resend/actions/workflow/listRunSteps.operation.js +2 -2
  33. package/dist/nodes/Resend/actions/workflow/listRuns.operation.js +2 -2
  34. package/dist/nodes/Resend/methods/index.d.ts +3 -1
  35. package/dist/nodes/Resend/methods/index.js +35 -33
  36. package/dist/nodes/Resend/transport/index.d.ts +3 -2
  37. package/dist/nodes/Resend/transport/index.js +9 -3
  38. package/dist/nodes/Resend/utils/dynamicFields.d.ts +22 -20
  39. package/dist/nodes/Resend/utils/dynamicFields.js +2 -61
  40. package/dist/nodes/Resend/utils/sendAndWait/email-templates.d.ts +1 -3
  41. package/dist/nodes/Resend/utils/sendAndWait/email-templates.js +0 -10
  42. package/dist/nodes/Resend/utils/sendAndWait/index.d.ts +2 -2
  43. package/dist/nodes/Resend/utils/sendAndWait/index.js +0 -2
  44. package/dist/nodes/Resend/utils/sendAndWait/utils.d.ts +2 -2
  45. package/dist/nodes/Resend/utils/sendAndWait/utils.js +19 -15
  46. package/package.json +10 -5
@@ -18,8 +18,10 @@ function extractResendError(error) {
18
18
  if (!trimmed.startsWith("{")) return void 0;
19
19
  try {
20
20
  const parsed = JSON.parse(trimmed);
21
- if (isResendShape(parsed)) return parsed;
22
- } catch {}
21
+ return isResendShape(parsed) ? parsed : void 0;
22
+ } catch {
23
+ return;
24
+ }
23
25
  };
24
26
  if (isResendShape(error)) return error;
25
27
  const err = error;
@@ -133,7 +135,10 @@ function handleResendApiError(node, error, itemIndex) {
133
135
  }
134
136
  const RESEND_API_BASE = "https://api.resend.com";
135
137
  function getCredentialType(context) {
136
- return context.getNodeParameter("authentication", 0, "apiKey") === "oAuth2" ? "resendOAuth2Api" : "resendApi";
138
+ let authentication;
139
+ if ("getInputData" in context) authentication = context.getNodeParameter("authentication", 0, "apiKey");
140
+ else authentication = context.getNodeParameter("authentication", "apiKey");
141
+ return authentication === "oAuth2" ? "resendOAuth2Api" : "resendApi";
137
142
  }
138
143
  async function apiRequest(method, endpoint, body, qs) {
139
144
  const options = {
@@ -265,6 +270,7 @@ exports.assertHttpsEndpoint = assertHttpsEndpoint;
265
270
  exports.buildTemplateSendVariables = buildTemplateSendVariables;
266
271
  exports.createListExecutionData = createListExecutionData;
267
272
  exports.createOperationRouter = createOperationRouter;
273
+ exports.getCredentialType = getCredentialType;
268
274
  exports.handleResendApiError = handleResendApiError;
269
275
  exports.normalizeEmailList = normalizeEmailList;
270
276
  exports.parseTemplateVariables = parseTemplateVariables;
@@ -1,28 +1,30 @@
1
1
  import { IExecuteFunctions, INodeProperties } from "n8n-workflow";
2
2
  //#region nodes/Resend/utils/dynamicFields.d.ts
3
3
  declare const RESOURCE_METHOD_MAP: {
4
- readonly broadcast: 'getBroadcasts';
5
- readonly contact: 'getContacts';
6
- readonly domain: 'getDomains';
7
- readonly webhook: 'getWebhooks';
8
- readonly contactProperty: 'getContactProperties';
9
- readonly email: 'getEmails';
10
- readonly receivedEmail: 'getReceivedEmails';
11
- readonly segment: 'getSegments';
12
- readonly template: 'getTemplates';
13
- readonly topic: 'getTopics';
4
+ readonly broadcast: "getBroadcasts";
5
+ readonly contact: "getContacts";
6
+ readonly domain: "getDomains";
7
+ readonly webhook: "getWebhooks";
8
+ readonly contactProperty: "getContactProperties";
9
+ readonly email: "getEmails";
10
+ readonly receivedEmail: "getReceivedEmails";
11
+ readonly segment: "getSegments";
12
+ readonly suppression: "getSuppressions";
13
+ readonly template: "getTemplates";
14
+ readonly topic: "getTopics";
14
15
  };
15
16
  declare const RESOURCE_DISPLAY_MAP: {
16
- readonly broadcast: 'Broadcast';
17
- readonly contact: 'Contact';
18
- readonly domain: 'Domain';
19
- readonly webhook: 'Webhook';
20
- readonly contactProperty: 'Contact Property';
21
- readonly email: 'Email';
22
- readonly receivedEmail: 'Received Email';
23
- readonly segment: 'Segment';
24
- readonly template: 'Template';
25
- readonly topic: 'Topic';
17
+ readonly broadcast: "Broadcast";
18
+ readonly contact: "Contact";
19
+ readonly domain: "Domain";
20
+ readonly webhook: "Webhook";
21
+ readonly contactProperty: "Contact Property";
22
+ readonly email: "Email";
23
+ readonly receivedEmail: "Received Email";
24
+ readonly segment: "Segment";
25
+ readonly suppression: "Suppression";
26
+ readonly template: "Template";
27
+ readonly topic: "Topic";
26
28
  };
27
29
  interface DynamicIdFieldOptions {
28
30
  fieldName: string;
@@ -1,9 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region nodes/Resend/utils/dynamicFields.ts
3
- /**
4
- * Maps resource names to their corresponding API methods for loading dropdown options.
5
- * Used to dynamically determine which method to call for each resource type.
6
- */
7
3
  const RESOURCE_METHOD_MAP = {
8
4
  broadcast: "getBroadcasts",
9
5
  contact: "getContacts",
@@ -13,13 +9,10 @@ const RESOURCE_METHOD_MAP = {
13
9
  email: "getEmails",
14
10
  receivedEmail: "getReceivedEmails",
15
11
  segment: "getSegments",
12
+ suppression: "getSuppressions",
16
13
  template: "getTemplates",
17
14
  topic: "getTopics"
18
15
  };
19
- /**
20
- * Maps resource names to their human-readable display names.
21
- * Used for generating consistent field labels across the application.
22
- */
23
16
  const RESOURCE_DISPLAY_MAP = {
24
17
  broadcast: "Broadcast",
25
18
  contact: "Contact",
@@ -29,40 +22,10 @@ const RESOURCE_DISPLAY_MAP = {
29
22
  email: "Email",
30
23
  receivedEmail: "Received Email",
31
24
  segment: "Segment",
25
+ suppression: "Suppression",
32
26
  template: "Template",
33
27
  topic: "Topic"
34
28
  };
35
- /**
36
- * Creates a single resourceLocator field that provides inline dropdown selection and manual input.
37
- *
38
- * This function generates a single field with two modes:
39
- * - 'list' mode: Shows API-populated dropdown for selecting from existing resources
40
- * - 'id' mode: Shows manual text input for entering IDs directly
41
- *
42
- * The field uses n8n's resourceLocator type for inline mode switching.
43
- *
44
- * @param options Configuration options for the resourceLocator field
45
- * @returns Single INodeProperties representing the resourceLocator field
46
- *
47
- * @example
48
- * ```typescript
49
- * // Create resourceLocator field for template selection
50
- * const templateField = createDynamicIdField({
51
- * fieldName: 'templateId',
52
- * resourceName: 'template',
53
- * displayName: 'Template',
54
- * required: true,
55
- * placeholder: '34a080c9-b17d-4187-ad80-5af20266e535',
56
- * description: 'The template to use for this operation',
57
- * displayOptions: {
58
- * show: {
59
- * resource: ['email'],
60
- * operation: ['send']
61
- * }
62
- * }
63
- * });
64
- * ```
65
- */
66
29
  function createDynamicIdField(options) {
67
30
  const { fieldName, resourceName, displayName, required = false, placeholder, description, displayOptions } = options;
68
31
  const resourceDisplayName = RESOURCE_DISPLAY_MAP[resourceName];
@@ -92,28 +55,6 @@ function createDynamicIdField(options) {
92
55
  }]
93
56
  };
94
57
  }
95
- /**
96
- * Resolves the actual ID value from a resourceLocator field during workflow execution.
97
- *
98
- * This helper function extracts the ID value from the resourceLocator structure
99
- * based on the selected mode and returns the appropriate value for use in API calls.
100
- *
101
- * @param executeFunctions The n8n execution context
102
- * @param fieldName Field name used when creating the resourceLocator field
103
- * @param index Current item index in the workflow execution
104
- * @returns The resolved ID value as a string
105
- *
106
- * @example
107
- * ```typescript
108
- * // In an operation's execute function
109
- * export async function execute(this: IExecuteFunctions, index: number): Promise<INodeExecutionData[]> {
110
- * const templateId = resolveDynamicIdValue(this, 'templateId', index);
111
- *
112
- * const response = await apiRequest.call(this, 'GET', `/templates/${templateId}`);
113
- * return [{ json: response }];
114
- * }
115
- * ```
116
- */
117
58
  function resolveDynamicIdValue(executeFunctions, fieldName, index) {
118
59
  return executeFunctions.getNodeParameter(fieldName, index).value;
119
60
  }
@@ -5,7 +5,5 @@ declare const ACTION_RECORDED_PAGE = "\n\t<html lang='en'>\n\n\t<head>\n\t\t<met
5
5
  declare function createEmailBody(message: string, buttons: string, options?: {
6
6
  instanceId?: string;
7
7
  }): string;
8
- declare function createEmailBodyWithN8nAttribution(message: string, buttons: string, instanceId?: string): string;
9
- declare function createEmailBodyWithoutN8nAttribution(message: string, buttons: string): string;
10
8
  //#endregion
11
- export { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, createEmailBody, createEmailBodyWithN8nAttribution, createEmailBodyWithoutN8nAttribution };
9
+ export { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, createEmailBody };
@@ -153,18 +153,8 @@ function createEmailBody(message, buttons, options) {
153
153
  </html>
154
154
  `;
155
155
  }
156
- /** @deprecated Use createEmailBody instead */
157
- function createEmailBodyWithN8nAttribution(message, buttons, instanceId) {
158
- return createEmailBody(message, buttons, { instanceId: instanceId !== null && instanceId !== void 0 ? instanceId : "" });
159
- }
160
- /** @deprecated Use createEmailBody instead */
161
- function createEmailBodyWithoutN8nAttribution(message, buttons) {
162
- return createEmailBody(message, buttons);
163
- }
164
156
  //#endregion
165
157
  exports.ACTION_RECORDED_PAGE = ACTION_RECORDED_PAGE;
166
158
  exports.BUTTON_STYLE_PRIMARY = BUTTON_STYLE_PRIMARY;
167
159
  exports.BUTTON_STYLE_SECONDARY = BUTTON_STYLE_SECONDARY;
168
160
  exports.createEmailBody = createEmailBody;
169
- exports.createEmailBodyWithN8nAttribution = createEmailBodyWithN8nAttribution;
170
- exports.createEmailBodyWithoutN8nAttribution = createEmailBodyWithoutN8nAttribution;
@@ -1,5 +1,5 @@
1
1
  import { limitWaitTimeOption, sendAndWaitWebhooksDescription } from "./descriptions.js";
2
- import { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, createEmailBody, createEmailBodyWithN8nAttribution, createEmailBodyWithoutN8nAttribution } from "./email-templates.js";
2
+ import { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, createEmailBody } from "./email-templates.js";
3
3
  import { FormResponseTypeOptions, IEmail, SendAndWaitConfig } from "./interfaces.js";
4
4
  import { SEND_AND_WAIT_WAITING_TOOLTIP, configureWaitTillDate, createButton, createEmail, getSendAndWaitConfig, getSendAndWaitProperties, sendAndWaitWebhook, sendResendEmail } from "./utils.js";
5
- export { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, type FormResponseTypeOptions, type IEmail, SEND_AND_WAIT_WAITING_TOOLTIP, type SendAndWaitConfig, configureWaitTillDate, createButton, createEmail, createEmailBody, createEmailBodyWithN8nAttribution, createEmailBodyWithoutN8nAttribution, getSendAndWaitConfig, getSendAndWaitProperties, limitWaitTimeOption, sendAndWaitWebhook, sendAndWaitWebhooksDescription, sendResendEmail };
5
+ export { ACTION_RECORDED_PAGE, BUTTON_STYLE_PRIMARY, BUTTON_STYLE_SECONDARY, type FormResponseTypeOptions, type IEmail, SEND_AND_WAIT_WAITING_TOOLTIP, type SendAndWaitConfig, configureWaitTillDate, createButton, createEmail, createEmailBody, getSendAndWaitConfig, getSendAndWaitProperties, limitWaitTimeOption, sendAndWaitWebhook, sendAndWaitWebhooksDescription, sendResendEmail };
@@ -10,8 +10,6 @@ exports.configureWaitTillDate = require_nodes_Resend_utils_sendAndWait_utils.con
10
10
  exports.createButton = require_nodes_Resend_utils_sendAndWait_utils.createButton;
11
11
  exports.createEmail = require_nodes_Resend_utils_sendAndWait_utils.createEmail;
12
12
  exports.createEmailBody = require_nodes_Resend_utils_sendAndWait_email_templates.createEmailBody;
13
- exports.createEmailBodyWithN8nAttribution = require_nodes_Resend_utils_sendAndWait_email_templates.createEmailBodyWithN8nAttribution;
14
- exports.createEmailBodyWithoutN8nAttribution = require_nodes_Resend_utils_sendAndWait_email_templates.createEmailBodyWithoutN8nAttribution;
15
13
  exports.getSendAndWaitConfig = require_nodes_Resend_utils_sendAndWait_utils.getSendAndWaitConfig;
16
14
  exports.getSendAndWaitProperties = require_nodes_Resend_utils_sendAndWait_utils.getSendAndWaitProperties;
17
15
  exports.limitWaitTimeOption = require_nodes_Resend_utils_sendAndWait_descriptions.limitWaitTimeOption;
@@ -12,7 +12,6 @@ declare function sendAndWaitWebhook(this: IWebhookFunctions): Promise<{
12
12
  webhookResponse?: undefined;
13
13
  workflowData?: undefined;
14
14
  } | {
15
- noWebhookResponse?: undefined;
16
15
  webhookResponse: undefined;
17
16
  workflowData: {
18
17
  json: {
@@ -21,8 +20,8 @@ declare function sendAndWaitWebhook(this: IWebhookFunctions): Promise<{
21
20
  };
22
21
  };
23
22
  }[][];
24
- } | {
25
23
  noWebhookResponse?: undefined;
24
+ } | {
26
25
  webhookResponse: undefined;
27
26
  workflowData: {
28
27
  json: {
@@ -31,6 +30,7 @@ declare function sendAndWaitWebhook(this: IWebhookFunctions): Promise<{
31
30
  };
32
31
  };
33
32
  }[][];
33
+ noWebhookResponse?: undefined;
34
34
  }>;
35
35
  declare function getSendAndWaitConfig(context: IExecuteFunctions): SendAndWaitConfig;
36
36
  declare function createButton(url: string, label: string, style: string): string;
@@ -36,6 +36,22 @@ function getSendAndWaitProperties(targetProperties, resource = "email", addition
36
36
  value: "secondary"
37
37
  }]
38
38
  };
39
+ const approveLabelProperty = {
40
+ displayName: "Approve Button Label",
41
+ name: "approveLabel",
42
+ type: "string",
43
+ default: "Approve",
44
+ displayOptions: { show: { approvalType: ["single", "double"] } }
45
+ };
46
+ if (options === null || options === void 0 ? void 0 : options.defaultApproveLabel) approveLabelProperty.default = options.defaultApproveLabel;
47
+ const disapproveLabelProperty = {
48
+ displayName: "Disapprove Button Label",
49
+ name: "disapproveLabel",
50
+ type: "string",
51
+ default: "Decline",
52
+ displayOptions: { show: { approvalType: ["double"] } }
53
+ };
54
+ if (options === null || options === void 0 ? void 0 : options.defaultDisapproveLabel) disapproveLabelProperty.default = options.defaultDisapproveLabel;
39
55
  const approvalOptionsValues = [
40
56
  {
41
57
  displayName: "Type of Approval",
@@ -51,26 +67,14 @@ function getSendAndWaitProperties(targetProperties, resource = "email", addition
51
67
  value: "double"
52
68
  }]
53
69
  },
54
- {
55
- displayName: "Approve Button Label",
56
- name: "approveLabel",
57
- type: "string",
58
- default: (options === null || options === void 0 ? void 0 : options.defaultApproveLabel) || "Approve",
59
- displayOptions: { show: { approvalType: ["single", "double"] } }
60
- },
70
+ approveLabelProperty,
61
71
  ...[(options === null || options === void 0 ? void 0 : options.noButtonStyle) ? {} : {
62
72
  ...buttonStyle,
63
73
  displayName: "Approve Button Style",
64
74
  name: "buttonApprovalStyle",
65
75
  displayOptions: { show: { approvalType: ["single", "double"] } }
66
76
  }],
67
- {
68
- displayName: "Disapprove Button Label",
69
- name: "disapproveLabel",
70
- type: "string",
71
- default: (options === null || options === void 0 ? void 0 : options.defaultDisapproveLabel) || "Decline",
72
- displayOptions: { show: { approvalType: ["double"] } }
73
- },
77
+ disapproveLabelProperty,
74
78
  ...[(options === null || options === void 0 ? void 0 : options.noButtonStyle) ? {} : {
75
79
  ...buttonStyle,
76
80
  displayName: "Disapprove Button Style",
@@ -456,7 +460,7 @@ async function sendResendEmail(context, email) {
456
460
  if (email.bcc) requestBody.bcc = email.bcc;
457
461
  if (email.replyTo) requestBody.reply_to = email.replyTo;
458
462
  try {
459
- await context.helpers.httpRequestWithAuthentication.call(context, "resendApi", {
463
+ await context.helpers.httpRequestWithAuthentication.call(context, require_nodes_Resend_transport_index.getCredentialType(context), {
460
464
  url: `${require_nodes_Resend_transport_index.RESEND_API_BASE}/emails`,
461
465
  method: "POST",
462
466
  headers: { "Content-Type": "application/json" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-resend",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "description": "Resend integration for n8n: Email, Broadcasts, Templates, Domains, Contacts, Segments, Topics, Webhooks, Workflows, Events, and more",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -48,13 +48,15 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@biomejs/biome": "~2.5.3",
51
- "@types/jest": "^30.0.0",
51
+ "@n8n/node-cli": "^0.39.3",
52
52
  "@types/node": "^26.1.1",
53
53
  "auto-changelog": "^2.6.0",
54
+ "eslint": "9.29.0",
54
55
  "rimraf": "^6.1.3",
55
56
  "tsdown": "^0.22.4",
56
- "typescript": "^7.0.2",
57
- "unrun": "^0.3.1"
57
+ "typescript": "~5.9.3",
58
+ "unrun": "^0.3.1",
59
+ "vitest": "^4.1.10"
58
60
  },
59
61
  "peerDependencies": {
60
62
  "n8n-workflow": "*"
@@ -63,9 +65,12 @@
63
65
  "clean": "rimraf dist",
64
66
  "build": "tsdown && auto-changelog",
65
67
  "dev": "tsdown --watch",
66
- "format": "biome format --write nodes credentials",
68
+ "format": "biome format --write nodes credentials tests",
67
69
  "lint": "biome check",
68
70
  "lint:fix": "biome check --write",
71
+ "lint:n8n": "n8n-node lint",
72
+ "test": "vitest run",
73
+ "test:watch": "vitest",
69
74
  "typecheck": "tsc --noEmit"
70
75
  }
71
76
  }