@nxgt/mail-presets 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.
- package/LICENSE +21 -0
- package/README.md +222 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +221 -0
- package/dist/index.js.map +10 -0
- package/dist/presets.d.ts +37 -0
- package/dist/presets.d.ts.map +1 -0
- package/docs/README.md +21 -0
- package/docs/guide/emails.md +337 -0
- package/docs/guide/presets.md +365 -0
- package/docs/roadmap.md +63 -0
- package/docs/troubleshooting.md +395 -0
- package/emails/email-changed.vue +14 -0
- package/emails/invitation.vue +12 -0
- package/emails/magic-link.vue +13 -0
- package/emails/new-sign-in.vue +21 -0
- package/emails/password-changed.vue +14 -0
- package/emails/reset-password.vue +14 -0
- package/emails/sign-in-code.vue +8 -0
- package/emails/verify-email.vue +14 -0
- package/emails/welcome.vue +13 -0
- package/package.json +68 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Wiring the presets
|
|
2
|
+
|
|
3
|
+
This page is for adding the presets to a project: what `presets()` answers,
|
|
4
|
+
how `@nxgt/mail-i18n` builds it beside your own templates, and how your
|
|
5
|
+
project replaces a template, overrides a message, or adds a locale.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// maizzle.config.ts
|
|
9
|
+
import { defineMailConfig } from '@nxgt/mail-config';
|
|
10
|
+
import { i18n } from '@nxgt/mail-i18n';
|
|
11
|
+
import { presets } from '@nxgt/mail-presets';
|
|
12
|
+
import { ui, uiCatalogues } from '@nxgt/mail-ui';
|
|
13
|
+
|
|
14
|
+
const mails = presets({ only: ['verify-email', 'reset-password'] });
|
|
15
|
+
|
|
16
|
+
export default defineMailConfig({
|
|
17
|
+
plugins: [
|
|
18
|
+
ui({ brand: { name: 'Acme', url: 'https://acme.example' } }),
|
|
19
|
+
i18n({
|
|
20
|
+
locales: ['en', 'fr'],
|
|
21
|
+
catalogues: [uiCatalogues, mails.catalogues],
|
|
22
|
+
templates: [mails.templates],
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
// locales/en.json, and the same in locales/fr.json — nothing to override yet
|
|
30
|
+
{}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`maizzle build` writes:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
dist/
|
|
37
|
+
en/reset-password.html en/reset-password.txt
|
|
38
|
+
en/verify-email.html en/verify-email.txt
|
|
39
|
+
fr/reset-password.html fr/reset-password.txt
|
|
40
|
+
fr/verify-email.html fr/verify-email.txt
|
|
41
|
+
mail-manifest.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The header and the footer show `Acme`, the button is in `ui()`'s theme, and
|
|
45
|
+
`{{ name }}` and `{{ link }}` wait for the values the sender fills.
|
|
46
|
+
|
|
47
|
+
## The signature
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import type { Catalogues, TemplateSource } from '@nxgt/mail-i18n';
|
|
51
|
+
|
|
52
|
+
const PRESETS: readonly [
|
|
53
|
+
'verify-email',
|
|
54
|
+
'reset-password',
|
|
55
|
+
'password-changed',
|
|
56
|
+
'email-changed',
|
|
57
|
+
'sign-in-code',
|
|
58
|
+
'magic-link',
|
|
59
|
+
'new-sign-in',
|
|
60
|
+
'welcome',
|
|
61
|
+
'invitation',
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
type PresetName = (typeof PRESETS)[number];
|
|
65
|
+
|
|
66
|
+
interface PresetsOptions {
|
|
67
|
+
/** The presets to build, at least one. Default every one. */
|
|
68
|
+
readonly only?: readonly [PresetName, ...PresetName[]];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface Presets {
|
|
72
|
+
/** For i18n({ templates }). */
|
|
73
|
+
readonly templates: TemplateSource;
|
|
74
|
+
/** For i18n({ catalogues }): the messages of the presets kept, and the shared presets.*. */
|
|
75
|
+
readonly catalogues: Catalogues;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function presets(options?: PresetsOptions): Presets;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`presets()` reads nothing and writes nothing: it answers where the templates
|
|
82
|
+
are and which messages go with them. The build is `@nxgt/mail-i18n`'s, with
|
|
83
|
+
your `ui()` — your brand, your theme, your components.
|
|
84
|
+
|
|
85
|
+
## Options
|
|
86
|
+
|
|
87
|
+
| Option | Type | Default | Effect |
|
|
88
|
+
| --- | --- | --- | --- |
|
|
89
|
+
| `only` | `readonly [PresetName, ...PresetName[]]` | every preset | The presets to build, at least one. The others are neither built nor in the manifest, and their messages are left out of `catalogues` |
|
|
90
|
+
|
|
91
|
+
`only: []` does not compile: leave `only` out for every preset. The options
|
|
92
|
+
are an object even for one preset — `presets(['welcome'])` does not compile,
|
|
93
|
+
and throws when the config loads.
|
|
94
|
+
|
|
95
|
+
## What it answers
|
|
96
|
+
|
|
97
|
+
With no option, the whole folder and every message:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { presetCatalogues, presets, TEMPLATES_DIR } from '@nxgt/mail-presets';
|
|
101
|
+
|
|
102
|
+
const all = presets();
|
|
103
|
+
// all.templates → { dir: TEMPLATES_DIR }
|
|
104
|
+
// all.catalogues → presetCatalogues, { en: {…}, fr: {…} }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`presetCatalogues` is frozen, every group in it: read it, never change it.
|
|
108
|
+
Your `locales/<locale>.json` is where a message changes — see
|
|
109
|
+
[Overriding a message](#overriding-a-message).
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { presetCatalogues } from '@nxgt/mail-presets';
|
|
113
|
+
|
|
114
|
+
Object.isFrozen(presetCatalogues.en?.verifyEmail); // true — and its type is readonly
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
With `only`, the folder with the e-mails to keep, and only their messages
|
|
118
|
+
with the shared `presets.*` group:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const one = presets({ only: ['sign-in-code'] });
|
|
122
|
+
// one.templates → { dir: TEMPLATES_DIR, emails: ['sign-in-code'] }
|
|
123
|
+
// Object.keys(one.catalogues.en) → ['presets', 'signInCode']
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
| Field | What `i18n()` does with it |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `templates.dir` | `TEMPLATES_DIR`, the absolute path of the package's `emails/`. Its templates are built once per locale, like yours; a name your own `emails/` also has is taken from yours |
|
|
129
|
+
| `templates.emails` | Present with `only`: the templates of the folder to build, and no other |
|
|
130
|
+
| `catalogues` | Merged under your `locales/<locale>.json`, key by key, in the order `catalogues` lists it |
|
|
131
|
+
|
|
132
|
+
Pass `mails.templates` whole: `templates: [mails.templates.dir]` does not
|
|
133
|
+
compile, and `i18n()` would refuse it with a `TypeError` if it did.
|
|
134
|
+
|
|
135
|
+
The rest of the exports serve a project that wants to look inside:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { PRESETS, type PresetName, TEMPLATES_DIR } from '@nxgt/mail-presets';
|
|
139
|
+
|
|
140
|
+
const wanted: PresetName[] = PRESETS.filter((name) => name !== 'invitation');
|
|
141
|
+
const source = `${TEMPLATES_DIR}/verify-email.vue`; // to copy it into your emails/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Your templates beside them
|
|
145
|
+
|
|
146
|
+
Your `emails/` is built as before. Its templates and the presets end up in
|
|
147
|
+
the same `dist/` and the same manifest:
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<!-- emails/order-shipped.vue -->
|
|
151
|
+
<template>
|
|
152
|
+
<NxLayout>
|
|
153
|
+
<NxTypography>{{ t('orderShipped.body', { order: placeholder('order') }) }}</NxTypography>
|
|
154
|
+
</NxLayout>
|
|
155
|
+
</template>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
// locales/en.json
|
|
160
|
+
{ "orderShipped": { "subject": "Order {order} is on its way", "body": "Order {order} has shipped." } }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The presets' messages are under their own keys (`verifyEmail.*`,
|
|
164
|
+
`presets.*`), so yours do not collide with them unless you mean them to.
|
|
165
|
+
|
|
166
|
+
## Replacing a template
|
|
167
|
+
|
|
168
|
+
A template in your `emails/` with the name of a preset is built instead of
|
|
169
|
+
the package's. Your folder is read first, and a name found there is never
|
|
170
|
+
taken from the package:
|
|
171
|
+
|
|
172
|
+
```vue
|
|
173
|
+
<!-- emails/welcome.vue -->
|
|
174
|
+
<template>
|
|
175
|
+
<NxLayout :preheader="t('welcome.preheader')">
|
|
176
|
+
<NxTypography variant="headline-small">{{ t('welcome.title', { brand: brand.name }) }}</NxTypography>
|
|
177
|
+
<NxTypography>{{ t('common.greeting', { name: placeholder('name') }) }}</NxTypography>
|
|
178
|
+
<NxTypography>{{ t('welcome.body') }}</NxTypography>
|
|
179
|
+
<NxButton :href="placeholder('link')">{{ t('welcome.action') }}</NxButton>
|
|
180
|
+
<NxTypography variant="caption">{{ t('welcome.help') }}</NxTypography>
|
|
181
|
+
</NxLayout>
|
|
182
|
+
</template>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
// locales/en.json
|
|
187
|
+
{ "welcome": { "help": "Questions? Reply to this e-mail." } }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
// locales/fr.json
|
|
192
|
+
{ "welcome": { "help": "Une question ? Répondez à cet e-mail." } }
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
It uses the preset's `welcome.*` messages and adds one. Its placeholders are
|
|
196
|
+
whatever it writes: the manifest records yours, not the package's. To start
|
|
197
|
+
from the package's template, copy `${TEMPLATES_DIR}/welcome.vue`.
|
|
198
|
+
|
|
199
|
+
A replaced preset still needs its messages when your template calls them:
|
|
200
|
+
keep it in `only` (or leave `only` out), or write every key it uses in your
|
|
201
|
+
catalogues.
|
|
202
|
+
|
|
203
|
+
## Overriding a message
|
|
204
|
+
|
|
205
|
+
Your `locales/<locale>.json` goes over the package's messages, key by key, in
|
|
206
|
+
each locale:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
// locales/en.json
|
|
210
|
+
{ "verifyEmail": { "action": "Yes, this is my address" } }
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
// locales/fr.json — no override: the French button stays "Confirmer mon adresse"
|
|
215
|
+
{}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The English button says `Yes, this is my address`; every other message,
|
|
219
|
+
English or French, stays the package's. An override keeps the arguments
|
|
220
|
+
the template passes: in `en`, the fallback locale, `verifyEmail.body` keeps
|
|
221
|
+
`{brand}`, or the build fails with
|
|
222
|
+
`i18n: en: verify-email passes {brand} to verifyEmail.body, which does not use it`.
|
|
223
|
+
In `fr` it may leave `{brand}` out, and never use an argument `en` does not
|
|
224
|
+
declare. To change what a template passes, replace the template. The keys of
|
|
225
|
+
every preset are in [The e-mails](emails.md), and the merge rules in
|
|
226
|
+
`@nxgt/mail-i18n`'s
|
|
227
|
+
[Catalogues](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-i18n/docs/guide/catalogues.md#catalogues-from-a-package).
|
|
228
|
+
|
|
229
|
+
## `ui()` and `uiCatalogues` are required
|
|
230
|
+
|
|
231
|
+
The templates are made of `@nxgt/mail-ui`'s components (`<NxLayout>`,
|
|
232
|
+
`<NxButton>`, `<NxCode>`…) and call its shared messages: `common.greeting`,
|
|
233
|
+
`common.footer.ignore`, and `common.footer.why`, which `<NxLayout>` writes in
|
|
234
|
+
every footer. So:
|
|
235
|
+
|
|
236
|
+
- `ui({ brand })` is in `plugins`, or no component renders. The templates
|
|
237
|
+
are installed under `node_modules`, where Maizzle resolves no tag: `ui()`
|
|
238
|
+
resolves them — your `components/` first, then its `Nx*` components, then
|
|
239
|
+
Maizzle's built-ins (see its
|
|
240
|
+
[Components from a package](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-ui/docs/guide/plugin.md#components-from-a-package)).
|
|
241
|
+
Without it, every preset renders empty and the build fails:
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
Error: i18n: en/verify-email.html is empty — a tag of its template resolved to no component; list the plugin that brings it, as ui()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- `uiCatalogues` is in `catalogues`, or your catalogues hold the `common`
|
|
248
|
+
keys, or the build fails:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
Error: i18n: en: verify-email calls t('common.footer.why'), which is not a key of the catalogues
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Without `mails.catalogues`, it fails on the first preset message instead:
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
Error: i18n: en: verify-email calls t('verifyEmail.preheader'), which is not a key of the catalogues
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Another locale
|
|
261
|
+
|
|
262
|
+
The presets are written in `en` and `fr`. A project that builds another
|
|
263
|
+
locale writes, in its catalogue for it, every key the fallback locale has:
|
|
264
|
+
the three `common` keys, the two `presets` keys, and the group of each preset
|
|
265
|
+
it builds. Otherwise the build fails on the first one missing:
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
Error: i18n: de: presets.linkFallback is missing — en, the fallback locale, has it
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
With `presets({ only: ['sign-in-code'] })` and `locales: ['en', 'fr', 'de']`:
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
// locales/de.json
|
|
275
|
+
{
|
|
276
|
+
"common": {
|
|
277
|
+
"greeting": "Hallo {name},",
|
|
278
|
+
"footer": {
|
|
279
|
+
"why": "Sie erhalten diese E-Mail, weil Sie ein Konto bei {brand} haben.",
|
|
280
|
+
"ignore": "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren."
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
"presets": {
|
|
284
|
+
"linkFallback": "Wenn die Schaltfläche nicht funktioniert, öffnen Sie diesen Link:",
|
|
285
|
+
"notYou": "Wenn Sie das nicht waren, sichern Sie jetzt Ihr Konto."
|
|
286
|
+
},
|
|
287
|
+
"signInCode": {
|
|
288
|
+
"subject": "Ihr Anmeldecode: {code}",
|
|
289
|
+
"preheader": "Geben Sie diesen Code ein, um sich anzumelden.",
|
|
290
|
+
"title": "Ihr Anmeldecode",
|
|
291
|
+
"body": "Geben Sie diesen Code ein, um sich bei {brand} anzumelden. Er gilt einmal.",
|
|
292
|
+
"ignore": "Wenn Sie sich nicht anmelden wollten, können Sie diese E-Mail ignorieren."
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The manifest then has `"de": "Ihr Anmeldecode: {{ code }}"` for its subject.
|
|
298
|
+
`presetCatalogues.en` is the list of keys to translate.
|
|
299
|
+
|
|
300
|
+
## Checking what your build sends
|
|
301
|
+
|
|
302
|
+
The manifest is the contract between the build and the code that sends. A
|
|
303
|
+
spec in your project keeps it from drifting when you replace a template or
|
|
304
|
+
upgrade the package:
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
// mail.spec.ts
|
|
308
|
+
import { expect, test } from 'bun:test';
|
|
309
|
+
import type { Manifest } from '@nxgt/mail-i18n';
|
|
310
|
+
import built from './dist/mail-manifest.json';
|
|
311
|
+
|
|
312
|
+
const manifest = built as Manifest;
|
|
313
|
+
|
|
314
|
+
test('the verification e-mail takes a name and a link', () => {
|
|
315
|
+
expect(manifest.emails['verify-email']?.variables).toEqual(['link', 'name']);
|
|
316
|
+
expect(manifest.emails['verify-email']?.urlVariables).toEqual(['link']);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test('the verification e-mail is built in every locale', () => {
|
|
320
|
+
expect(Object.keys(manifest.emails['verify-email']?.files ?? {})).toEqual(['en', 'fr']);
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Run it after `maizzle build`. Each preset's placeholders are in
|
|
325
|
+
[The e-mails](emails.md).
|
|
326
|
+
|
|
327
|
+
## Errors
|
|
328
|
+
|
|
329
|
+
`presets()` throws a bare `TypeError` when `maizzle.config.ts` loads:
|
|
330
|
+
|
|
331
|
+
| Message | Cause |
|
|
332
|
+
| --- | --- |
|
|
333
|
+
| `presets: options must be an object, as { only: ['verify-email'] }` | `presets(null)`, `presets(['welcome'])` — a list rather than `{ only: [...] }` — or anything that is not an object |
|
|
334
|
+
| `presets: only must list at least one preset, as ['verify-email']` | `only: []`, or `only: 'welcome'` |
|
|
335
|
+
| `presets: only holds something that is not a preset — name one of verify-email, reset-password, password-changed, email-changed, sign-in-code, magic-link, new-sign-in, welcome, invitation` | `only: ['sign-in']` |
|
|
336
|
+
| `presets: only holds the same preset twice` | `only: ['welcome', 'welcome']` |
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
presets({ only: [] });
|
|
340
|
+
// TypeError: presets: only must list at least one preset, as ['verify-email']
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Four more come from `i18n()`'s `templates` option, when the config loads —
|
|
344
|
+
see `@nxgt/mail-i18n`'s
|
|
345
|
+
[Templates from a package](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-i18n/docs/guide/templates.md#templates-from-a-package):
|
|
346
|
+
|
|
347
|
+
| Message | When |
|
|
348
|
+
| --- | --- |
|
|
349
|
+
| `i18n: templates must be a list of template folders, as [{ dir: '/abs/path/emails' }] — emails, when given, names at least one, each once` | A `TypeError` when the config loads: `templates: mails.templates` without the list, a relative `dir`, or an empty `emails` |
|
|
350
|
+
| `i18n: templates[0] has no template sign-in.vue — name one of its e-mails` | A plain `Error` when the config loads: an `emails` list written by hand, naming a template the folder does not have |
|
|
351
|
+
| `i18n: templates[0] holds no template — is /…/emails the folder of a package's e-mails?` | A plain `Error` when the config loads: a `dir` written by hand that is missing or has no template — use `TEMPLATES_DIR` |
|
|
352
|
+
| `i18n: templates[0] and templates[1] both have welcome.vue — keep one with emails: [...], or write the project's own in its folder` | A plain `Error` when the config loads: another package ships an e-mail of the same name as a preset. Keep one with `only`, or write your own `emails/welcome.vue` |
|
|
353
|
+
|
|
354
|
+
Every other failure is the build's, from the catalogues or the templates, and
|
|
355
|
+
is in `@nxgt/mail-i18n`'s
|
|
356
|
+
[Troubleshooting](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-i18n/docs/troubleshooting.md).
|
|
357
|
+
|
|
358
|
+
## See also
|
|
359
|
+
|
|
360
|
+
- [The e-mails](emails.md) — each preset's placeholders, subject and messages.
|
|
361
|
+
- `@nxgt/mail-ui`'s
|
|
362
|
+
[plugin](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-ui/docs/guide/plugin.md)
|
|
363
|
+
— the brand and the theme the presets are built with.
|
|
364
|
+
- [Samples](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-presets/samples/README.md)
|
|
365
|
+
— every preset, built.
|
package/docs/roadmap.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
Where `@nxgt/mail-presets` is heading. A direction, not a commitment: there
|
|
4
|
+
are no dates here, and the version something shipped in is the only number.
|
|
5
|
+
|
|
6
|
+
## Now
|
|
7
|
+
|
|
8
|
+
Nothing between releases.
|
|
9
|
+
|
|
10
|
+
## Next
|
|
11
|
+
|
|
12
|
+
Nothing yet.
|
|
13
|
+
|
|
14
|
+
## Later
|
|
15
|
+
|
|
16
|
+
Nothing yet. A request is welcome as an
|
|
17
|
+
[issue](https://github.com/softistx/nxgt-mail/issues).
|
|
18
|
+
|
|
19
|
+
## Not planned
|
|
20
|
+
|
|
21
|
+
- **E-mails in a brand of ours** — a preset carries no brand and no colours
|
|
22
|
+
of its own: your project builds it with your `ui({ brand, theme })`. The
|
|
23
|
+
samples use the brand `Acme` only to be looked at.
|
|
24
|
+
- **Built HTML to send as is** — `samples/` lives in the repository and is
|
|
25
|
+
not in the package. Sending the samples would send someone else's brand; a
|
|
26
|
+
preset is built by your project, with `maizzle build`.
|
|
27
|
+
- **Options to patch a preset** — a preset is changed the way any template is:
|
|
28
|
+
your template of the same name replaces it, and your catalogue overrides its
|
|
29
|
+
messages. There is no per-preset option to learn.
|
|
30
|
+
|
|
31
|
+
## Shipped
|
|
32
|
+
|
|
33
|
+
The last ten, newest first, each with the version it came in. Everything
|
|
34
|
+
before is in the [CHANGELOG](../CHANGELOG.md).
|
|
35
|
+
|
|
36
|
+
- **Nine ready e-mails, v0.1.0** — `verify-email`, `reset-password`,
|
|
37
|
+
`password-changed` and `email-changed` for accounts; `sign-in-code` and
|
|
38
|
+
`magic-link` for passwordless sign-in; `new-sign-in` for security; `welcome`
|
|
39
|
+
and `invitation` for the lifecycle. Each is a template of `@nxgt/mail-ui`
|
|
40
|
+
components with its messages in `en` and `fr`, and leaves the values only
|
|
41
|
+
known at send time (`{{ name }}`, `{{ link }}`, …) as placeholders.
|
|
42
|
+
- **Presets for the i18n plugin, v0.1.0** — `presets({ only })` answers
|
|
43
|
+
`{ templates, catalogues }` for `i18n({ templates, catalogues })`, so the
|
|
44
|
+
presets are built by your own Maizzle project, with your
|
|
45
|
+
`ui({ brand, theme })`, in every locale you list. `only` keeps the presets
|
|
46
|
+
you name and their messages; a preset that does not exist, or one named
|
|
47
|
+
twice, is refused.
|
|
48
|
+
- **Overriding a preset, v0.1.0** — a template of the same name in your project's
|
|
49
|
+
`emails/` replaces a preset, and your `locales/<locale>.json` overrides any
|
|
50
|
+
of its messages key by key.
|
|
51
|
+
- **Samples, v0.1.0** — every preset built in `en` and `fr` with the brand `Acme` and
|
|
52
|
+
the default theme, in the repository's
|
|
53
|
+
[`samples/`](https://github.com/softistx/nxgt-mail/tree/develop/packages/mail-presets/samples),
|
|
54
|
+
checked against a fresh build, so you can see an e-mail before installing
|
|
55
|
+
anything.
|
|
56
|
+
- **A renderer that sends them, v0.1.0** — `createMailRenderer` from
|
|
57
|
+
`@nxgt/mail/renderer` renders the presets' build at send time, each value
|
|
58
|
+
filled and escaped; the build spec renders every preset with it.
|
|
59
|
+
- **A starter that uses one, with v0.1.0** — the official Maizzle starter with
|
|
60
|
+
`presets({ only: ['sign-in-code'] })` next to its own e-mail, built,
|
|
61
|
+
rendered in `en` and `fr` and served in CI:
|
|
62
|
+
[`examples/starter`](https://github.com/softistx/nxgt-mail/tree/develop/examples/starter).
|
|
63
|
+
In the repository; its README says how to start your own from npm.
|