sumba 2.4.1 → 2.5.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.
@@ -1,16 +1,16 @@
1
- async function afterCreateRecord (body, options = {}, rec) {
2
- if (!options.req) return
3
- if (!this.app.waibu) return
4
- const { sendMail } = this.app.waibu
1
+ async function afterCreateRecord (body, rec, options = {}) {
5
2
  const { data } = rec
6
3
  const { req } = options
4
+ const { get } = this.app.lib._
5
+ const t = get(req, 't', this.t)
7
6
  const to = `${data.firstName} ${data.lastName} <${data.email}>`
8
7
  let bcc
9
- if (req && req.site) bcc = req.site.email
10
- const subject = options.req.t('contactForm')
11
- await sendMail(
8
+ if (req.site) bcc = req.site.email
9
+ const subject = t('contactForm')
10
+ const payload = { to, bcc, subject, data }
11
+ await this.sendMail(
12
12
  'sumba.template:/_mail/help-contact-form.html',
13
- { to, bcc, subject, data, options, source: this.ns }
13
+ { payload, options, source: this.ns }
14
14
  )
15
15
  }
16
16
 
@@ -1,13 +1,14 @@
1
1
  async function afterCreateRecord (body, rec, options = {}) {
2
- if (!options.req) return
3
- if (!this.app.waibu) return
4
- const { sendMail } = this.app.waibu
5
2
  const { data } = rec
3
+ const { req } = options
4
+ const { get } = this.app.lib._
5
+ const t = get(req, 't', this.t)
6
6
  const to = `${data.firstName} ${data.lastName} <${data.email}>`
7
- const subject = options.req.t('newUserSignup')
8
- await sendMail(
7
+ const subject = t('newUserSignup')
8
+ const payload = { to, subject, data }
9
+ await this.sendMail(
9
10
  `sumba.template:/_mail/user-signup-success${data.status === 'ACTIVE' ? '-active' : ''}.html`,
10
- { to, subject, data, options, source: this.ns }
11
+ { payload, options, source: this.ns }
11
12
  )
12
13
  }
13
14
 
@@ -1,28 +1,30 @@
1
1
  async function afterUpdateRecord (id, body, rec, options = {}) {
2
- if (!options.req) return
3
- if (!this.app.waibu) return
4
2
  const { data, oldData } = rec
5
- const { sendMail } = this.app.waibu
3
+ const { req } = options
4
+ const { get } = this.app.lib._
5
+ const t = get(req, 't', this.t)
6
6
  const to = `${data.firstName} ${data.lastName} <${data.email}>`
7
+ const source = this.ns
7
8
  let subject
9
+ const payload = { to, subject, data }
8
10
 
9
11
  if (oldData.status === 'UNVERIFIED' && data.status === 'ACTIVE') {
10
- subject = options.req.t('userActivation')
11
- await sendMail(
12
+ payload.subject = t('userActivation')
13
+ await this.sendMail(
12
14
  'sumba.template:/_mail/user-activation-success.html',
13
- { to, subject, data, options, source: this.ns }
15
+ { payload, options, source }
14
16
  )
15
17
  } else if (oldData.token !== data.token) {
16
- subject = options.req.t('resetApiKey')
17
- await sendMail(
18
+ payload.subject = t('resetApiKey')
19
+ await this.sendMail(
18
20
  'sumba.template:/_mail/mystuff-reset-api-key.html',
19
- { to, subject, data, options, source: this.ns }
21
+ { payload, options, source }
20
22
  )
21
23
  } else if (body.password) {
22
- subject = options.req.t('changePassword')
23
- await sendMail(
24
+ payload.subject = t('changePassword')
25
+ await this.sendMail(
24
26
  'sumba.template:/_mail/mystuff-change-password.html',
25
- { to, subject, data, options, source: this.ns }
27
+ { payload, options, source }
26
28
  )
27
29
  }
28
30
  }
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <head lang="<%= _meta.lang %>">
3
+ <meta charset="UTF-8">
4
+ <title><%= page.fullTitle %></title>
5
+ <style type="text/css">
6
+ </style>
7
+ </head>
8
+ <body>
9
+ <% if (arguments[0].firstName && arguments[0].lastName) { %>
10
+ <p>Dear <%= firstName %> <%= lastName %>,</p>
11
+ <% } %>
12
+ <!-- body -->
13
+ <p>Sincerely,</p>
14
+
15
+ <p><%= _meta.site.title %></p>
16
+ </body>
17
+ </html>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= _meta.lang %>">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title><%= page.fullTitle %></title>
6
+ <style type="text/css">
7
+ </style>
8
+ </head>
9
+ <body>
10
+ <% if (arguments[0].firstName && arguments[0].lastName) { %>
11
+ <p>Yth <%= firstName %> <%= lastName %>,</p>
12
+ <% } %>
13
+ <!-- body -->
14
+ <p>Hormat kami,</p>
15
+
16
+ <p><%= _meta.site.title %></p>
17
+ </body>
18
+ </html>
@@ -4,7 +4,7 @@
4
4
  <table>
5
5
  <tr>
6
6
  <td>Category:</td>
7
- <td><%= cat %></td>
7
+ <td><%= category %></td>
8
8
  </tr>
9
9
  <tr>
10
10
  <td>Subject:</td>
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -1,3 +1,3 @@
1
1
  ---
2
- layout: waibu.layout:/email.html
2
+ layout: sumba.layout:/email.html
3
3
  ---
@@ -3,7 +3,7 @@
3
3
  "firstName,,50,true,true",
4
4
  "lastName,,50,true,true",
5
5
  "email,,50,true,true",
6
- "cat,,50,true",
6
+ "category,,50,true",
7
7
  "subject,,255,,true",
8
8
  "message,text"
9
9
  ],
@@ -17,7 +17,6 @@ async function getUser (req, reply) {
17
17
  const forgotPasswordLink = {
18
18
  method: ['GET', 'POST'],
19
19
  handler: async function (req, reply) {
20
- const { sendMail } = this.app.waibu
21
20
  const { defaultsDeep } = this.app.lib.aneka
22
21
  const { importPkg } = this.app.bajo
23
22
  const { isString } = this.app.lib._
@@ -45,9 +44,10 @@ const forgotPasswordLink = {
45
44
  const to = `${user.firstName} ${user.lastName} <${user.email}>`
46
45
  const subject = req.t('forgotPasswordChanged')
47
46
  const options = { req, reply, tpl: '' }
48
- await sendMail(
47
+ const payload = { to, subject, data: user }
48
+ await this.sendMail(
49
49
  'sumba.template:/_mail/user-forgot-password-changed.html',
50
- { to, subject, data: user, options, source: this.ns }
50
+ { payload, options, source: this.ns }
51
51
  )
52
52
  req.flash('notify', req.t('passwordChangedReSignin'))
53
53
  return reply.redirectTo(this.config.redirect.signin)
@@ -2,7 +2,6 @@ const profile = {
2
2
  method: ['GET', 'POST'],
3
3
  handler: async function (req, reply) {
4
4
  if (!this.app.masohiMail) return await reply.view('sumba.template:/user/forgot-password.html')
5
- const { sendMail } = this.app.waibu
6
5
  const { defaultsDeep } = this.app.lib.aneka
7
6
  const { dayjs } = this.app.lib
8
7
  const model = this.app.dobo.getModel('SumbaUser')
@@ -20,9 +19,10 @@ const profile = {
20
19
  const exp = req.site.setting.sumba.forgotPasswordExpDur
21
20
  data.fpToken = Buffer.from(`${data.token}:${dayjs().add(exp, 'ms').unix()}`).toString('base64')
22
21
  data._meta = { hostHeader: req.headers.host }
23
- await sendMail(
22
+ const payload = { to, subject, data }
23
+ await this.sendMail(
24
24
  'sumba.template:/_mail/user-forgot-password-link.html',
25
- { to, subject, data, options, source: this.ns }
25
+ { payload, options, source: this.ns }
26
26
  )
27
27
  req.flash('notify', req.t('emailSent'))
28
28
  return reply.redirectTo(this.config.redirect.signin)
package/index.js CHANGED
@@ -541,6 +541,39 @@ async function factory (pkgName) {
541
541
  const items = await model.findAllRecord()
542
542
  return items.map(item => ({ value: item.id, text: item.name }))
543
543
  }
544
+
545
+ /**
546
+ * Method to send mail through Masohi Messaging System. It is a thin wrapper
547
+ * for {@link https://github.com/ardhi/masohi-mail|masohi-mail} send method.
548
+ *
549
+ * If both masohiMail and waibu are not loaded, nothing is delivered.
550
+ *
551
+ * @method
552
+ * @async
553
+ * @param {(string|Array)} tpl - Mail's template to use. If a string is given, the same template will be used for html & plaintext versions. Otherwise, the first template will be used for html mail, and the second one is for it's plaintext version
554
+ * @param {Object} [params={}] - {@link https://github.com/ardhi/masohi-mail|masohi-mail}'s params object.
555
+ * @returns
556
+ */
557
+ sendMail = async (tpl, { payload = {}, conn, source, options = {} } = {}) => {
558
+ if (!this.app.masohiMail || !this.app.waibu) return
559
+ conn = conn ?? 'masohiMail:default'
560
+ const { importModule } = this.app.bajo
561
+ const { get, isString } = this.app.lib._
562
+ const { generateId } = this.app.lib.aneka
563
+ const { render } = this.app.bajoTemplate
564
+ const buildLocals = await importModule('waibu:/lib/build-locals.js')
565
+
566
+ if (isString(tpl)) tpl = [tpl]
567
+ const locals = await buildLocals.call(this, { params: payload.data, opts: options })
568
+ payload.from = payload.from ?? get(options, 'req.site.email', payload.from)
569
+ const opts = {
570
+ lang: get(options, 'req.lang'),
571
+ groupId: get(options, 'req.id', generateId())
572
+ }
573
+ payload.html = await render(tpl[0], locals, opts)
574
+ if (tpl[1]) payload.text = await render(tpl[1], locals, opts)
575
+ await this.app.masohiMail.send({ payload, source: source ?? this.ns, conn })
576
+ }
544
577
  }
545
578
 
546
579
  return Sumba
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sumba",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
4
4
  "description": "Biz Suite for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-03-02
4
+
5
+ - [2.5.0] Add ```sendMail()``` to send mail using ```masohiMail```
6
+ - [2.5.0] Update all mail templates and hooks to match with the new specs
7
+
3
8
  ## 2026-02-21
4
9
 
5
10
  - [2.4.1] Bug fix on intl functions. Now moved to ```preParsing``` instead of ```onRequest```