@nocobase/plugin-workflow-mailer 2.2.0-alpha.1 → 2.2.0-alpha.3

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.
@@ -42,7 +42,41 @@ module.exports = __toCommonJS(MailerInstruction_exports);
42
42
  var import_joi = __toESM(require("joi"));
43
43
  var import_nodemailer = __toESM(require("nodemailer"));
44
44
  var import_plugin_workflow = require("@nocobase/plugin-workflow");
45
+ var import_plugin_file_manager = __toESM(require("@nocobase/plugin-file-manager"));
45
46
  var import_get = __toESM(require("lodash/get"));
47
+ function isRecord(value) {
48
+ return value !== null && typeof value === "object";
49
+ }
50
+ function toPlainRecord(value) {
51
+ if (!isRecord(value)) {
52
+ return null;
53
+ }
54
+ if ("dataValues" in value && isRecord(value.dataValues)) {
55
+ return value.dataValues;
56
+ }
57
+ return value;
58
+ }
59
+ function isPlainFileRecord(record) {
60
+ return Boolean(
61
+ isRecord(record) && typeof record.title === "string" && typeof record.storageId === "number" && typeof record.path === "string" && typeof record.filename === "string" && record.filename.length > 0
62
+ );
63
+ }
64
+ function getAttachmentFilename(file) {
65
+ if (file.title && file.extname) {
66
+ return `${file.title}${file.extname}`;
67
+ }
68
+ return file.title || file.filename;
69
+ }
70
+ function normalizeFiles(value) {
71
+ if (Array.isArray(value)) {
72
+ return value.flatMap((item) => normalizeFiles(item));
73
+ }
74
+ const record = toPlainRecord(value);
75
+ if (isPlainFileRecord(record)) {
76
+ return [record];
77
+ }
78
+ return [];
79
+ }
46
80
  const transporterMap = /* @__PURE__ */ new Map();
47
81
  const configMap = /* @__PURE__ */ new Map();
48
82
  function getTransporterKey(provider) {
@@ -73,7 +107,11 @@ function getTransporter(provider) {
73
107
  }
74
108
  return createNewTransporter(key, newConfig);
75
109
  }
76
- return transporterMap.get(key);
110
+ const transporter = transporterMap.get(key);
111
+ if (!transporter) {
112
+ return createNewTransporter(key, newConfig);
113
+ }
114
+ return transporter;
77
115
  }
78
116
  function discardTransporter(key, transporter) {
79
117
  transporter.close();
@@ -180,40 +218,57 @@ class MailerInstruction extends import_plugin_workflow.Instruction {
180
218
  contentType: import_joi.default.string().valid("html", "text").default("html"),
181
219
  html: import_joi.default.string(),
182
220
  text: import_joi.default.string(),
221
+ attachments: import_joi.default.any(),
183
222
  ignoreFail: import_joi.default.boolean().default(false)
184
223
  });
224
+ async getAttachments(attachments = []) {
225
+ const files = normalizeFiles(attachments);
226
+ if (!files.length) {
227
+ return void 0;
228
+ }
229
+ const fileManager = this.workflow.app.pm.get(import_plugin_file_manager.default);
230
+ if (!fileManager) {
231
+ throw new Error("[workflow-mailer] file-manager plugin is required to send attachments");
232
+ }
233
+ return Promise.all(
234
+ files.map(async (file) => {
235
+ const { stream, contentType } = await fileManager.getFileStream(file);
236
+ const resolvedContentType = contentType || file.mimetype;
237
+ return {
238
+ filename: getAttachmentFilename(file),
239
+ content: stream,
240
+ ...resolvedContentType ? { contentType: resolvedContentType } : {}
241
+ };
242
+ })
243
+ );
244
+ }
245
+ async getPayload(config) {
246
+ const { provider, contentType, to = [], cc, bcc, subject, html, text, ignoreFail, attachments, ...others } = config;
247
+ return {
248
+ ...others,
249
+ ...contentType === "html" ? { html } : { text },
250
+ subject: subject == null ? void 0 : subject.trim(),
251
+ to: to ? to.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : void 0,
252
+ cc: cc ? cc.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : [],
253
+ bcc: bcc ? bcc.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : [],
254
+ attachments: await this.getAttachments(attachments)
255
+ };
256
+ }
185
257
  async run(node, prevJob, processor, options) {
186
258
  var _a, _b;
187
- const {
188
- provider,
189
- contentType,
190
- to = [],
191
- cc,
192
- bcc,
193
- subject,
194
- html,
195
- text,
196
- ignoreFail,
197
- ...others
198
- } = processor.getParsedValue(node.config, node.id);
259
+ const config = processor.getParsedValue(node.config, node.id);
260
+ const { provider, ignoreFail } = config;
199
261
  const { workflow } = processor.execution;
200
262
  const currentWorkflow = (workflow == null ? void 0 : workflow.options) || ((_a = workflow == null ? void 0 : workflow.get) == null ? void 0 : _a.call(workflow, "options")) ? workflow : await node.getWorkflow();
201
- const sync = this.workflow.isWorkflowSync(currentWorkflow);
263
+ const sync = processor.isInstructionSync(node);
202
264
  const workflowOptions = (currentWorkflow == null ? void 0 : currentWorkflow.options) ?? ((_b = currentWorkflow == null ? void 0 : currentWorkflow.get) == null ? void 0 : _b.call(currentWorkflow, "options")) ?? {};
203
265
  const workflowTimeout = Number(workflowOptions.timeout ?? 0);
204
266
  const transporterKey = getTransporterKey(provider);
205
267
  const transporter = getTransporter(provider);
206
268
  const mailAbort = createAbortSignal(processor, options == null ? void 0 : options.signal, workflowTimeout);
207
- const payload = {
208
- ...others,
209
- ...contentType === "html" ? { html } : { text },
210
- subject: subject == null ? void 0 : subject.trim(),
211
- to: to ? to.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : void 0,
212
- cc: cc ? cc.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : [],
213
- bcc: bcc ? bcc.flat().map((item) => item == null ? void 0 : item.trim()).filter(Boolean) : []
214
- };
215
269
  if (sync) {
216
270
  try {
271
+ const payload = await this.getPayload(config);
217
272
  const result = await sendMail(transporter, transporterKey, payload, mailAbort.signal);
218
273
  return {
219
274
  status: import_plugin_workflow.JOB_STATUS.RESOLVED,
@@ -240,6 +295,7 @@ class MailerInstruction extends import_plugin_workflow.Instruction {
240
295
  await processor.exit();
241
296
  const jobDone = { status: import_plugin_workflow.JOB_STATUS.PENDING };
242
297
  try {
298
+ const payload = await this.getPayload(config);
243
299
  const response = await sendMail(transporter, transporterKey, payload, mailAbort.signal);
244
300
  processor.logger.info(`smtp-mailer (#${node.id}) sent successfully.`);
245
301
  jobDone.status = import_plugin_workflow.JOB_STATUS.RESOLVED;
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Send email in workflow.",
7
7
  "description.ru-RU": "Отправляет электронное письмо в рамках рабочего процесса.",
8
8
  "description.zh-CN": "可用于在工作流中发送电子邮件。",
9
- "version": "2.2.0-alpha.1",
9
+ "version": "2.2.0-alpha.3",
10
10
  "license": "Apache-2.0",
11
11
  "main": "./dist/server/index.js",
12
12
  "homepage": "https://docs.nocobase.com/handbook/workflow-smtp-mailer",
@@ -20,12 +20,14 @@
20
20
  },
21
21
  "peerDependencies": {
22
22
  "@nocobase/client": "2.x",
23
+ "@nocobase/client-v2": "2.x",
23
24
  "@nocobase/database": "2.x",
25
+ "@nocobase/plugin-file-manager": "2.x",
24
26
  "@nocobase/plugin-workflow": ">=0.17.0-alpha.3",
25
27
  "@nocobase/server": "2.x",
26
28
  "@nocobase/test": "2.x"
27
29
  },
28
- "gitHead": "303663aba6c6eefa27e6a6435b4c0352074ec40f",
30
+ "gitHead": "e3ec19361fd7981af9fe2a7f24ad335025cbefcd",
29
31
  "keywords": [
30
32
  "NocoBase",
31
33
  "Workflow",