sounding 0.0.3 → 0.0.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.
package/README.md CHANGED
@@ -36,6 +36,8 @@ The default configuration story is intentionally calm:
36
36
  - managed SQLite artifacts live under `.tmp/db`
37
37
  - the default datastore identity is `default`
38
38
  - browser projects start with `desktop`
39
+ - mail capture previews use the `mail` layout by default, matching the current `sails-hook-mail` convention
40
+ - apps with a different mail layout can set `sounding.mail.layout`, for example `layout-email`
39
41
  - `inherit` remains available when an app already has a serious test datastore story
40
42
 
41
43
  For example:
@@ -1,6 +1,8 @@
1
1
  const path = require('node:path')
2
2
  const url = require('node:url')
3
3
 
4
+ const DEFAULT_MAIL_LAYOUT = 'mail'
5
+
4
6
  function normalizeList(value) {
5
7
  if (value === undefined || value === null || value === '') {
6
8
  return []
@@ -62,22 +64,21 @@ function createRenderViewPromise(view) {
62
64
  return Promise.resolve(view)
63
65
  }
64
66
 
65
- async function renderTemplatePreview(sails, {
66
- template,
67
- templateData = {},
68
- layout = 'layout-email',
69
- }) {
67
+ async function renderTemplatePreview(sails, inputs = {}, options = {}) {
68
+ const { template, templateData = {} } = inputs
69
+
70
70
  if (!template || typeof sails?.renderView !== 'function') {
71
71
  return undefined
72
72
  }
73
73
 
74
+ const resolvedLayout = resolvePreviewLayout(sails, inputs, options)
74
75
  const emailTemplatePath = path.join('emails/', template)
75
76
  let emailTemplateLayout = false
76
77
 
77
- if (layout) {
78
+ if (resolvedLayout) {
78
79
  emailTemplateLayout = path.relative(
79
80
  path.dirname(emailTemplatePath),
80
- path.resolve('layouts/', layout)
81
+ path.resolve('layouts/', resolvedLayout)
81
82
  )
82
83
  }
83
84
 
@@ -94,6 +95,31 @@ function resolveMailConfig(sails) {
94
95
  return sails?.config?.mail || {}
95
96
  }
96
97
 
98
+ function resolveSoundingMailConfig(sails, options = {}) {
99
+ if (options.mailSettings) {
100
+ return options.mailSettings
101
+ }
102
+
103
+ const soundingConfig =
104
+ options.soundingConfig || options.config || sails?.config?.sounding || {}
105
+
106
+ return soundingConfig.mail || {}
107
+ }
108
+
109
+ function resolvePreviewLayout(sails, inputs = {}, options = {}) {
110
+ if (Object.prototype.hasOwnProperty.call(inputs, 'layout')) {
111
+ return inputs.layout
112
+ }
113
+
114
+ const mailSettings = resolveSoundingMailConfig(sails, options)
115
+
116
+ if (Object.prototype.hasOwnProperty.call(mailSettings, 'layout')) {
117
+ return mailSettings.layout
118
+ }
119
+
120
+ return DEFAULT_MAIL_LAYOUT
121
+ }
122
+
97
123
  function resolveMailerName(sails, inputs = {}) {
98
124
  return inputs.mailer || process.env.MAIL_MAILER || resolveMailConfig(sails).default
99
125
  }
@@ -125,10 +151,11 @@ function toErrorShape(error) {
125
151
  }
126
152
  }
127
153
 
128
- async function buildCapturedMail(sails, inputs = {}) {
154
+ async function buildCapturedMail(sails, inputs = {}, options = {}) {
129
155
  const mailer = resolveMailerName(sails, inputs)
130
156
  const transport = resolveTransportName(sails, mailer)
131
- const html = await renderTemplatePreview(sails, inputs)
157
+ const layout = resolvePreviewLayout(sails, inputs, options)
158
+ const html = await renderTemplatePreview(sails, inputs, options)
132
159
  const links = extractLinks(html)
133
160
 
134
161
  return {
@@ -150,7 +177,7 @@ async function buildCapturedMail(sails, inputs = {}) {
150
177
  ctaUrl: resolvePrimaryLink(inputs, links),
151
178
  attachments: inputs.attachments || [],
152
179
  headers: inputs.headers || {},
153
- layout: inputs.layout === undefined ? 'layout-email' : inputs.layout,
180
+ layout,
154
181
  }
155
182
  }
156
183
 
@@ -173,6 +200,12 @@ function createMailCapture({ sails, mailbox, getConfig }) {
173
200
  return settings.deliver === true || settings.mode === 'passthrough'
174
201
  }
175
202
 
203
+ function resolveMessageLayout(inputs = {}) {
204
+ return resolvePreviewLayout(sails, inputs, {
205
+ mailSettings: resolveMailSettings(),
206
+ })
207
+ }
208
+
176
209
  function wrapDeferred(executor, onRejected) {
177
210
  let promise = Promise.resolve().then(executor)
178
211
 
@@ -267,7 +300,9 @@ function createMailCapture({ sails, mailbox, getConfig }) {
267
300
 
268
301
  async function captureSuccessfulSend(inputs = {}) {
269
302
  try {
270
- const message = await buildCapturedMail(sails, inputs)
303
+ const message = await buildCapturedMail(sails, inputs, {
304
+ mailSettings: resolveMailSettings(),
305
+ })
271
306
  mailbox.capture({
272
307
  ...message,
273
308
  status: 'sent',
@@ -279,6 +314,7 @@ function createMailCapture({ sails, mailbox, getConfig }) {
279
314
  to: normalizeList(inputs.to),
280
315
  subject: inputs.subject || '',
281
316
  template: inputs.template,
317
+ layout: resolveMessageLayout(inputs),
282
318
  status: 'sent',
283
319
  captureError: toErrorShape(error),
284
320
  })
@@ -289,7 +325,9 @@ function createMailCapture({ sails, mailbox, getConfig }) {
289
325
  let message
290
326
 
291
327
  try {
292
- message = await buildCapturedMail(sails, inputs)
328
+ message = await buildCapturedMail(sails, inputs, {
329
+ mailSettings: resolveMailSettings(),
330
+ })
293
331
  } catch (captureError) {
294
332
  message = {
295
333
  mailer: resolveMailerName(sails, inputs),
@@ -297,6 +335,7 @@ function createMailCapture({ sails, mailbox, getConfig }) {
297
335
  to: normalizeList(inputs.to),
298
336
  subject: inputs.subject || '',
299
337
  template: inputs.template,
338
+ layout: resolveMessageLayout(inputs),
300
339
  captureError: toErrorShape(captureError),
301
340
  }
302
341
  }
@@ -388,4 +427,5 @@ module.exports = {
388
427
  normalizeList,
389
428
  resolvePrimaryLink,
390
429
  renderTemplatePreview,
430
+ resolvePreviewLayout,
391
431
  }
@@ -30,6 +30,7 @@ const DEFAULT_CONFIG = Object.freeze({
30
30
  },
31
31
  mail: {
32
32
  capture: true,
33
+ layout: 'mail',
33
34
  },
34
35
  request: {
35
36
  transport: 'virtual',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sounding",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Testing framework for Sails applications and The Boring JavaScript Stack.",
5
5
  "main": "index.js",
6
6
  "license": "MIT",