@nxgt/janus-mail 0.6.0 → 0.7.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The e-mails of [`@nxgt/janus`](https://www.npmjs.com/package/@nxgt/janus)'s
4
4
  flows, ready to send: **e-mail verification, password reset, sign-in code,
5
- password changed, e-mail changed, two-factor authentication turned on or
5
+ sign-in link, password changed, e-mail changed, two-factor authentication turned on or
6
6
  off, a recovery code used, and a welcome to a new user**, in English and
7
7
  French, with your brand
8
8
  in them. `@nxgt/janus` sends no e-mail — its flows answer what to send — and
@@ -23,6 +23,7 @@ const mail = janusMail({
23
23
  secureAccount: () => 'https://acme.example/account/security',
24
24
  getStarted: () => 'https://acme.example/',
25
25
  recoveryCodes: () => 'https://acme.example/account/recovery-codes', // optional
26
+ magicLink: (token) => `https://acme.example/sign-in/link?token=${token}`, // optional
26
27
  },
27
28
  });
28
29
 
@@ -47,7 +48,7 @@ bun add -d typescript
47
48
 
48
49
  Three peers, all required: `@nxgt/mail` (0.1 or later, below 2 — 1.0 and
49
50
  its transports included), which defines the `Mailer` port and the errors;
50
- `@nxgt/janus` (0.14), whose flows' answers the methods take — types only,
51
+ `@nxgt/janus` (0.15), whose flows' answers the methods take — types only,
51
52
  nothing of it is loaded; and `typescript` (6). **No Maizzle, no Vue, no
52
53
  Tailwind**: they run at this package's build, not in yours.
53
54
 
@@ -64,12 +65,12 @@ needs Node `^22.22.3`, `^24.15.0` or `>=26`, for Maizzle — see
64
65
 
65
66
  | Export | What it is |
66
67
  | --- | --- |
67
- | `janusMail(options)` | The e-mails, over your mailer: `verifyEmail`, `resetPassword`, `signInCode`, `passwordChanged`, `emailChanged`, `twoFactorEnabled`, `twoFactorDisabled`, `recoveryCodeUsed`, `welcome`, and `templates` and `locales`. Options: `mailer`, `from`, `replyTo?`, `brand`, `links` (`verifyEmail`, `resetPassword`, `secureAccount`, `getStarted`, and `recoveryCodes?`), `locales?`, `fallbackLocale?`, `templates?`, `clock?`. A wrong option is a bare `TypeError`, thrown here |
68
- | `janusTemplates()` | The nine default templates alone, each `(variables & { locale }) => Rendered` |
68
+ | `janusMail(options)` | The e-mails, over your mailer: `verifyEmail`, `resetPassword`, `signInCode`, `magicLink`, `passwordChanged`, `emailChanged`, `twoFactorEnabled`, `twoFactorDisabled`, `recoveryCodeUsed`, `welcome`, and `templates` and `locales`. Options: `mailer`, `from`, `replyTo?`, `brand`, `links` (`verifyEmail`, `resetPassword`, `secureAccount`, `getStarted`, and `recoveryCodes?` and `magicLink?`), `locales?`, `fallbackLocale?`, `templates?`, `clock?`. A wrong option is a bare `TypeError`, thrown here |
69
+ | `janusTemplates()` | The ten default templates alone, each `(variables & { locale }) => Rendered` |
69
70
  | `JanusMail<L>`, `JanusMailOptions<L>` | What `janusMail()` answers and takes, for the locales `L` |
70
- | `JanusMailTemplate<V, L>`, `JanusMailTemplates<L>`, `JanusMailTemplateName` | One template, the nine of them, and their names |
71
+ | `JanusMailTemplate<V, L>`, `JanusMailTemplates<L>`, `JanusMailTemplateName` | One template, the ten of them, and their names |
71
72
  | `JanusMailVariables` | What each template is given: `brand`, and `name`, `link`, `code`, `expiresIn`, `newEmail`, `when` or `recoveryCodesLeft` as its e-mail needs |
72
- | `JanusMailSendOptions` | The third argument of `verifyEmail`, `resetPassword` and `signInCode`: `{ expiresIn? }`, the expiry as text, over the one derived |
73
+ | `JanusMailSendOptions` | The third argument of `verifyEmail`, `resetPassword`, `signInCode` and `magicLink`: `{ expiresIn? }`, the expiry as text, over the one derived |
73
74
  | `JanusMailLocale` | `'en' \| 'fr'`: the locales the defaults are built in |
74
75
  | `JanusMailLinks`, `Recipient` | The `links` option; who an e-mail is for — `{ name, locale? }` |
75
76
 
@@ -86,6 +87,7 @@ class. To retry a `MailFailure` or trace each send, wrap the mailer you pass:
86
87
  | `verifyEmail(issued, to, options?)` | `issued` from `auth.verifyEmail.send(user)`; a link from `links.verifyEmail(issued.token)`, and how long it lasts | `issued.email` |
87
88
  | `resetPassword(issued, to, options?)` | `issued` from `auth.resetPassword.request(email)`, checked for `null`; a link from `links.resetPassword(issued.token)`, and how long it lasts | `issued.email` |
88
89
  | `signInCode(issued, to?, options?)` | `issued.code` from `auth.signInCode.request(email)`, and how long it lasts — **never the challenge** | `issued.email` |
90
+ | `magicLink(issued, to?, options?)` | `issued` from `auth.magicLink.request(email)`, checked for `null`; a link from `links.magicLink(issued.token)`, and how long it lasts. A `TypeError` without `links.magicLink` | `issued.email` |
89
91
  | `passwordChanged(to)` | A notice, with `links.secureAccount()` | `to.email` |
90
92
  | `emailChanged(to)` | A notice naming `to.newEmail`, with `links.secureAccount()` | `to.formerEmail` |
91
93
  | `twoFactorEnabled(to)` | A notice: two-factor authentication was turned on, with `links.secureAccount()` | `to.email` |
@@ -93,7 +95,7 @@ class. To retry a `MailFailure` or trace each send, wrap the mailer you pass:
93
95
  | `recoveryCodeUsed(to, { when, recoveryCodesLeft })` | A notice: a recovery code was used, `when`, and how many are left — "You have 9 recovery codes left." — with `links.recoveryCodes()`, else `links.secureAccount()` | `to.email` |
94
96
  | `welcome(to)` | A welcome to a new user — "Welcome, Ada" — with `links.getStarted()` | `to.email` |
95
97
 
96
- The three e-mails of a link or a code say how long it lasts — "This link
98
+ The four e-mails of a link or a code say how long it lasts — "This link
97
99
  expires in 1 hour.", "Ce lien expire dans 1 heure." — from the flow's
98
100
  `issued.expiresAt`: the time left at send time, rounded to the minute, then
99
101
  down to the largest whole unit (days, hours or minutes), formatted with
@@ -138,6 +140,22 @@ if (issued !== null) {
138
140
  }
139
141
  ```
140
142
 
143
+ ### Signing in with a link
144
+
145
+ ```ts
146
+ const issued = await auth.magicLink.request(email);
147
+ if (issued !== null) {
148
+ await mail.magicLink(issued, { locale: issued.user.locale }); // "Your sign-in link", valid 15 minutes
149
+ }
150
+ return new Response(null, { status: 202 }); // the same answer whether or not someone holds the address
151
+ ```
152
+
153
+ `links.magicLink` should open **a page of yours that spends nothing**, whose
154
+ button posts the token to the route calling `auth.magicLink.confirm`: mail
155
+ scanners open every link in an e-mail, and one that signs in on `GET` signs
156
+ in for the scanner. [`@nxgt/janus`'s sign-in link guide](https://github.com/softistx/nxgt-janus/blob/develop/packages/janus/docs/guide/magic-link.md)
157
+ has that page.
158
+
141
159
  ### Saying the expiry yourself
142
160
 
143
161
  ```ts
@@ -330,14 +348,21 @@ send time and must return an `http(s)` or `mailto:` URL as a string: an
330
348
  `links`, `from` and `replyTo` are copied when `janusMail()` is called, so
331
349
  changing them afterwards changes nothing.
332
350
 
351
+ **`links.magicLink` is optional, and `magicLink` refuses to send without
352
+ it.** An application that sends no sign-in link leaves it out; calling
353
+ `mail.magicLink` then throws a `TypeError` —
354
+ `janusMail.magicLink: links.magicLink is missing — …` — before anything is
355
+ rendered or sent. Unlike `recoveryCodes`, it has no fallback: no other page
356
+ can carry the token.
357
+
333
358
  **Templates are own properties.** A class's methods live on its prototype
334
359
  and are refused with a `TypeError`; its fields (`signInCode = (variables) =>
335
360
  …`) pass.
336
361
 
337
362
  **A locale beyond `en` and `fr` needs every template.** The defaults are
338
- built in those two only, so `locales: ['en', 'fr', 'de']` without all nine
339
- templates — `recoveryCodeUsed` included, since 0.5 — is a compile error, and
340
- a `TypeError` in JavaScript.
363
+ built in those two only, so `locales: ['en', 'fr', 'de']` without all ten
364
+ templates — `recoveryCodeUsed` included, since 0.5, and `magicLink`, since
365
+ 0.7 — is a compile error, and a `TypeError` in JavaScript.
341
366
 
342
367
  **The brand is text only.** `brand: 'Acme'` is written in the header, the
343
368
  body and the footer, escaped: no logo, no link, no markup. For those, replace
@@ -394,8 +419,8 @@ The symptoms and fixes are in [troubleshooting](docs/troubleshooting.md).
394
419
 
395
420
  ## Type safety, counted
396
421
 
397
- **Thirty-six plausible mistakes, thirty-six refused at compile time.**
398
- Six files hold one `@ts-expect-error` per mistake, beside the calls that
422
+ **Forty plausible mistakes, forty refused at compile time.**
423
+ Seven files hold one `@ts-expect-error` per mistake, beside the calls that
399
424
  must keep compiling:
400
425
  [`test/types/send-refusals.ts`](test/types/send-refusals.ts) the eight of a
401
426
  send, 1 to 8;
@@ -407,9 +432,11 @@ the expiry and the clock, 21 to 25;
407
432
  [`test/types/notice-refusals.ts`](test/types/notice-refusals.ts) the four of
408
433
  the two-factor notices and the welcome, 26 to 29;
409
434
  [`test/types/recovery-refusals.ts`](test/types/recovery-refusals.ts) the
410
- five of the recovery code notice, 30 to 34; and
435
+ five of the recovery code notice, 30 to 34;
411
436
  [`test/types/change-refusals.ts`](test/types/change-refusals.ts) the two of
412
- the e-mail change notice sent on its event, 35 and 36:
437
+ the e-mail change notice sent on its event, 35 and 36; and
438
+ [`test/types/magic-link-refusals.ts`](test/types/magic-link-refusals.ts) the
439
+ four of the sign-in link, 37 to 40:
413
440
 
414
441
  1. A sign-in code given to `verifyEmail`: it has no token.
415
442
  2. A one-time token given to `signInCode`: it has no code.
@@ -447,8 +474,12 @@ the e-mail change notice sent on its event, 35 and 36:
447
474
  34. `links.recoveryCodes` given as a URL rather than a function.
448
475
  35. `user.emailChanged`'s `formerEmail` given to `emailChanged` unchecked: it is `null` for a user who had none.
449
476
  36. The `user.emailChanged` event itself given to `emailChanged`: it has the former address, but neither a name nor the new one.
477
+ 37. A sign-in code given to `magicLink`: it has no token, and its challenge must never be mailed.
478
+ 38. `magicLink.request`'s answer, not checked for `null` first.
479
+ 39. The token alone given to `magicLink`, rather than what the flow answered.
480
+ 40. `links.magicLink` computed asynchronously.
450
481
 
451
- In JavaScript, 19 to 23, 26 to 28, 30 to 33, 35 and 36 are a `TypeError` at send
482
+ In JavaScript, 19 to 23, 26 to 28, 30 to 33 and 35 to 40 are a `TypeError` at send
452
483
  time instead, naming the call or the field, and 25, 29 and 34 one from
453
484
  `janusMail()`.
454
485
 
@@ -1,7 +1,7 @@
1
1
  import type { ResolvedOptions } from './options';
2
2
  import type { JanusMail } from './types';
3
- type ExpiringMails = Pick<JanusMail<string>, 'verifyEmail' | 'resetPassword' | 'signInCode'>;
4
- /** `verifyEmail`, `resetPassword` and `signInCode`, over the resolved options. */
3
+ type ExpiringMails = Pick<JanusMail<string>, 'verifyEmail' | 'resetPassword' | 'signInCode' | 'magicLink'>;
4
+ /** `verifyEmail`, `resetPassword`, `signInCode` and `magicLink`, over the resolved options. */
5
5
  export declare function expiringMails(options: ResolvedOptions): ExpiringMails;
6
6
  export {};
7
7
  //# sourceMappingURL=expiring-mails.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expiring-mails.d.ts","sourceRoot":"","sources":["../src/expiring-mails.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,KAAK,aAAa,GAAG,IAAI,CACxB,SAAS,CAAC,MAAM,CAAC,EACjB,aAAa,GAAG,eAAe,GAAG,YAAY,CAC9C,CAAC;AAoBF,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAqBrE"}
1
+ {"version":3,"file":"expiring-mails.d.ts","sourceRoot":"","sources":["../src/expiring-mails.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,KAAK,aAAa,GAAG,IAAI,CACxB,SAAS,CAAC,MAAM,CAAC,EACjB,aAAa,GAAG,eAAe,GAAG,YAAY,GAAG,WAAW,CAC5D,CAAC;AAmDF,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAsBrE"}
@@ -6,6 +6,11 @@ export interface MailEmails {
6
6
  readonly name: string | number;
7
7
  readonly newEmail: string | number;
8
8
  };
9
+ "magic-link": {
10
+ readonly brand: string | number;
11
+ readonly expiresIn: string | number;
12
+ readonly link: string;
13
+ };
9
14
  "password-changed": {
10
15
  readonly brand: string | number;
11
16
  readonly link: string;
@@ -1 +1 @@
1
- {"version":3,"file":"mail.d.ts","sourceRoot":"","sources":["../../src/generated/mail.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,MAAM,WAAW,UAAU;IAC1B,eAAe,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAChJ,kBAAkB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC/G,oBAAoB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC9L,gBAAgB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAClJ,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACzH,qBAAqB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAClH,oBAAoB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACjH,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAChJ,SAAS,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACtG"}
1
+ {"version":3,"file":"mail.d.ts","sourceRoot":"","sources":["../../src/generated/mail.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,MAAM,WAAW,UAAU;IAC1B,eAAe,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAChJ,YAAY,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9G,kBAAkB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC/G,oBAAoB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC9L,gBAAgB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAClJ,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACzH,qBAAqB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAClH,oBAAoB,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACjH,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAChJ,SAAS,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACtG"}
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  * `@nxgt/janus-mail` — the e-mails of `@nxgt/janus`'s flows.
3
3
  *
4
4
  * `@nxgt/janus` sends no e-mail: its flows answer what to send — a one-time
5
- * token, a sign-in code, the address — and this package turns that answer
6
- * into an e-mail and hands it to an `@nxgt/mail` transport. Nine e-mails, in
5
+ * token, a sign-in code, a sign-in link's token, the address — and this package turns that answer
6
+ * into an e-mail and hands it to an `@nxgt/mail` transport. Ten e-mails, in
7
7
  * English and French, prebuilt with Maizzle when this package is built, and
8
8
  * filled at send time with your brand, the recipient's name and your links.
9
9
  * Any of them can be replaced by a function of your own.
package/dist/index.js CHANGED
@@ -84,6 +84,22 @@ function linkMail(options, name) {
84
84
  });
85
85
  };
86
86
  }
87
+ function magicLinkMail(options) {
88
+ return async (issued, to, sendOptions) => {
89
+ const build = options.links.magicLink;
90
+ if (build === undefined) {
91
+ throw new TypeError("janusMail.magicLink: links.magicLink is missing — pass it to janusMail({ links }) to send sign-in links");
92
+ }
93
+ const token = field("magicLink", issued, "token");
94
+ const locale = localeFor(options, to);
95
+ return send(options, "magicLink", field("magicLink", issued, "email"), {
96
+ brand: options.brand,
97
+ link: link("magicLink", build(token), "magicLink(token)"),
98
+ expiresIn: expiresInFor("magicLink", issued, locale, sendOptions, options.clock),
99
+ locale
100
+ });
101
+ };
102
+ }
87
103
  function expiringMails(options) {
88
104
  return {
89
105
  verifyEmail: linkMail(options, "verifyEmail"),
@@ -96,7 +112,8 @@ function expiringMails(options) {
96
112
  expiresIn: expiresInFor("signInCode", issued, locale, sendOptions, options.clock),
97
113
  locale
98
114
  });
99
- }
115
+ },
116
+ magicLink: magicLinkMail(options)
100
117
  };
101
118
  }
102
119
 
@@ -141,7 +158,7 @@ var REQUIRED_LINKS = [
141
158
  "secureAccount",
142
159
  "getStarted"
143
160
  ];
144
- var OPTIONAL_LINKS = ["recoveryCodes"];
161
+ var OPTIONAL_LINKS = ["recoveryCodes", "magicLink"];
145
162
  function checkLinks(links) {
146
163
  if (typeof links !== "object" || links === null || Array.isArray(links)) {
147
164
  refuse("links must be an object, as { verifyEmail, resetPassword, secureAccount, getStarted }");
@@ -186,6 +203,7 @@ function janusTemplates() {
186
203
  verifyEmail: ({ brand, name, link, expiresIn, locale }) => defaultRenderer().render("verify-email", { brand, name, link, expiresIn }, { locale }),
187
204
  resetPassword: ({ brand, name, link, expiresIn, locale }) => defaultRenderer().render("reset-password", { brand, name, link, expiresIn }, { locale }),
188
205
  signInCode: ({ brand, code, expiresIn, locale }) => defaultRenderer().render("sign-in-code", { brand, code, expiresIn }, { locale }),
206
+ magicLink: ({ brand, link, expiresIn, locale }) => defaultRenderer().render("magic-link", { brand, link, expiresIn }, { locale }),
189
207
  passwordChanged: ({ brand, name, link, locale }) => defaultRenderer().render("password-changed", { brand, name, link }, { locale }),
190
208
  emailChanged: ({ brand, name, link, newEmail, locale }) => defaultRenderer().render("email-changed", { brand, name, link, newEmail }, { locale }),
191
209
  twoFactorEnabled: ({ brand, name, link, locale }) => defaultRenderer().render("two-factor-enabled", { brand, name, link }, { locale }),
@@ -207,6 +225,7 @@ var TEMPLATE_NAMES = [
207
225
  "verifyEmail",
208
226
  "resetPassword",
209
227
  "signInCode",
228
+ "magicLink",
210
229
  "passwordChanged",
211
230
  "emailChanged",
212
231
  "twoFactorEnabled",
@@ -416,5 +435,5 @@ export {
416
435
  janusTemplates
417
436
  };
418
437
 
419
- //# debugId=E470EFFF013B3B0B64756E2164756E21
438
+ //# debugId=45A006F2B09A6D7D64756E2164756E21
420
439
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -4,20 +4,20 @@
4
4
  "sourcesContent": [
5
5
  "/**\n * `expiresIn`: how long the link or the code of an e-mail stays valid, as\n * the text the e-mail shows — \"1 hour\", \"1 heure\". Derived from the\n * `expiresAt` the flow answered and the locale the recipient gets, unless the\n * send passes its own.\n */\nimport type { Clock } from '@nxgt/janus';\n\nconst MINUTE_MS = 60_000;\nconst MINUTES_IN_HOUR = 60;\nconst MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR;\n\n/**\n * A duration in the locale, in the largest unit it holds at least once:\n * rounded to the minute first — the flow set `expiresAt` a moment before the\n * send, so an hour is 59 minutes and 59 seconds by then — and then down to a\n * whole unit: 90 minutes is \"1 hour\", 36 hours \"1 day\". At 30 seconds or\n * more, the e-mail never promises more than half a minute beyond what is\n * left; under that, it says \"1 minute\".\n *\n * ```ts\n * formatExpiry(3_600_000, 'fr'); // '1 heure'\n * ```\n */\nexport function formatExpiry(ms: number, locale: string): string {\n\tconst minutes = Math.max(1, Math.round(ms / MINUTE_MS));\n\tconst [value, unit] =\n\t\tminutes >= MINUTES_IN_DAY\n\t\t\t? [Math.floor(minutes / MINUTES_IN_DAY), 'day']\n\t\t\t: minutes >= MINUTES_IN_HOUR\n\t\t\t\t? [Math.floor(minutes / MINUTES_IN_HOUR), 'hour']\n\t\t\t\t: [minutes, 'minute'];\n\treturn new Intl.NumberFormat(locale, {\n\t\tstyle: 'unit',\n\t\tunit,\n\t\tunitDisplay: 'long',\n\t}).format(value);\n}\n\n/** The per-send `expiresIn`, when one was passed, or `undefined`; a `TypeError` when it is not a string. */\nfunction passedExpiresIn(method: string, options: unknown): string | undefined {\n\tconst read =\n\t\ttypeof options === 'object' && options !== null\n\t\t\t? (options as { expiresIn?: unknown }).expiresIn\n\t\t\t: undefined;\n\tif (read !== undefined && typeof read !== 'string') {\n\t\tthrow new TypeError(`janusMail.${method}: expiresIn must be a string`);\n\t}\n\treturn read;\n}\n\n/**\n * The `expiresIn` of one send: the one passed, as is, or the time left\n * until the flow's `expiresAt` by `clock` — the one given to `janus()`, when\n * it was given to `janusMail()` too — in `locale`. A `TypeError` naming the method\n * when `expiresAt` is not a valid `Date` — a flow's answer that went through\n * JSON holds a string there — or is already past.\n */\nexport function expiresInFor(\n\tmethod: string,\n\tissued: unknown,\n\tlocale: string,\n\toptions: unknown,\n\tclock: Clock,\n): string {\n\tconst passed = passedExpiresIn(method, options);\n\tif (passed !== undefined) return passed;\n\tconst expiresAt =\n\t\ttypeof issued === 'object' && issued !== null\n\t\t\t? (issued as { expiresAt?: unknown }).expiresAt\n\t\t\t: undefined;\n\tif (!(expiresAt instanceof Date) || Number.isNaN(expiresAt.getTime())) {\n\t\tthrow new TypeError(`janusMail.${method}: expiresAt must be a Date`);\n\t}\n\tconst now = clock.now();\n\tif (!(now instanceof Date) || Number.isNaN(now.getTime())) {\n\t\tthrow new TypeError(`janusMail.${method}: clock.now() must answer a Date`);\n\t}\n\tconst left = expiresAt.getTime() - now.getTime();\n\tif (left <= 0) {\n\t\tthrow new TypeError(\n\t\t\t`janusMail.${method}: expiresAt is past — the link or code would not work`,\n\t\t);\n\t}\n\treturn formatExpiry(left, locale);\n}\n",
6
6
  "/**\n * What every method shares: reading an argument's fields, a link, the\n * recipient's locale, and the send itself. A wrong argument is a `TypeError`\n * naming the method and the field — never its value.\n */\nimport type { Address, Rendered, SentMail, WantedLocales } from '@nxgt/mail';\nimport { pickLocale } from '@nxgt/mail';\nimport type { ResolvedOptions } from './options';\nimport type { JanusMailTemplateName, JanusMailVariables } from './types';\n\n/** A string field of an argument, or a `TypeError` naming the method and the field. */\nexport function field(method: string, value: unknown, key: string): string {\n\tconst read =\n\t\ttypeof value === 'object' && value !== null\n\t\t\t? (value as Record<string, unknown>)[key]\n\t\t\t: undefined;\n\tif (typeof read !== 'string') {\n\t\tthrow new TypeError(`janusMail.${method}: ${key} must be a string`);\n\t}\n\treturn read;\n}\n\n/**\n * What a `links` function answered, or a `TypeError` naming the method and\n * the call. Its scheme is the renderer's to check: `http(s)` and `mailto:`\n * pass, anything else is its `MailRefused`.\n */\nexport function link(method: string, value: unknown, call: string): string {\n\tif (typeof value !== 'string') {\n\t\tthrow new TypeError(\n\t\t\t`janusMail.${method}: links.${call} must answer a string`,\n\t\t);\n\t}\n\treturn value;\n}\n\n/** The locale the recipient gets: the first they want that is sent in, else the fallback. */\nexport function localeFor(options: ResolvedOptions, to: unknown): string {\n\tconst wanted =\n\t\ttypeof to === 'object' && to !== null\n\t\t\t? (to as { locale?: WantedLocales }).locale\n\t\t\t: undefined;\n\treturn pickLocale(wanted, options.locales, options.fallbackLocale);\n}\n\n/**\n * Renders one e-mail and hands it to the mailer. Only `subject`, `html` and\n * `text` are read from what the template answered: a template cannot add a\n * recipient or a header.\n */\nexport async function send<K extends JanusMailTemplateName>(\n\toptions: ResolvedOptions,\n\tname: K,\n\taddress: string,\n\tvariables: JanusMailVariables[K] & { readonly locale: string },\n): Promise<SentMail> {\n\tconst template = options.templates[name] as (\n\t\tvariables: JanusMailVariables[K] & { readonly locale: string },\n\t) => Rendered | PromiseLike<Rendered>;\n\tconst { subject, html, text }: Rendered = await template(variables);\n\tconst replyTo: { replyTo?: Address } =\n\t\toptions.replyTo === undefined ? {} : { replyTo: options.replyTo };\n\treturn options.mailer.send({\n\t\tto: address,\n\t\tfrom: options.from,\n\t\t...replyTo,\n\t\tsubject,\n\t\thtml,\n\t\ttext,\n\t});\n}\n",
7
- "/**\n * The three e-mails that carry what a flow issued — a one-time link or a\n * sign-in code — and say how long it lasts: `verifyEmail`, `resetPassword`\n * and `signInCode`.\n */\nimport { expiresInFor } from './expiry';\nimport type { ResolvedOptions } from './options';\nimport { field, link, localeFor, send } from './send';\nimport type { JanusMail } from './types';\n\ntype ExpiringMails = Pick<\n\tJanusMail<string>,\n\t'verifyEmail' | 'resetPassword' | 'signInCode'\n>;\n\n/** The two e-mails of a one-time token, which link to your page with it. */\ntype LinkMailName = 'verifyEmail' | 'resetPassword';\n\n/** One e-mail of a one-time token: to `issued.email`, its link built from `issued.token`. */\nfunction linkMail(options: ResolvedOptions, name: LinkMailName) {\n\treturn async (issued: unknown, to: unknown, sendOptions?: unknown) => {\n\t\tconst token = field(name, issued, 'token');\n\t\tconst locale = localeFor(options, to);\n\t\treturn send(options, name, field(name, issued, 'email'), {\n\t\t\tbrand: options.brand,\n\t\t\tname: field(name, to, 'name'),\n\t\t\tlink: link(name, options.links[name](token), `${name}(token)`),\n\t\t\texpiresIn: expiresInFor(name, issued, locale, sendOptions, options.clock),\n\t\t\tlocale,\n\t\t});\n\t};\n}\n\n/** `verifyEmail`, `resetPassword` and `signInCode`, over the resolved options. */\nexport function expiringMails(options: ResolvedOptions): ExpiringMails {\n\treturn {\n\t\tverifyEmail: linkMail(options, 'verifyEmail'),\n\t\tresetPassword: linkMail(options, 'resetPassword'),\n\t\tasync signInCode(issued, to, sendOptions) {\n\t\t\t// `code`, `email` and `expiresAt` only: the challenge is the visitor's secret.\n\t\t\tconst locale = localeFor(options, to);\n\t\t\treturn send(options, 'signInCode', field('signInCode', issued, 'email'), {\n\t\t\t\tbrand: options.brand,\n\t\t\t\tcode: field('signInCode', issued, 'code'),\n\t\t\t\texpiresIn: expiresInFor(\n\t\t\t\t\t'signInCode',\n\t\t\t\t\tissued,\n\t\t\t\t\tlocale,\n\t\t\t\t\tsendOptions,\n\t\t\t\t\toptions.clock,\n\t\t\t\t),\n\t\t\t\tlocale,\n\t\t\t});\n\t\t},\n\t};\n}\n",
7
+ "/**\n * The four e-mails that carry what a flow issued — a one-time link or a\n * sign-in code — and say how long it lasts: `verifyEmail`, `resetPassword`,\n * `signInCode` and `magicLink`.\n */\nimport { expiresInFor } from './expiry';\nimport type { ResolvedOptions } from './options';\nimport { field, link, localeFor, send } from './send';\nimport type { JanusMail } from './types';\n\ntype ExpiringMails = Pick<\n\tJanusMail<string>,\n\t'verifyEmail' | 'resetPassword' | 'signInCode' | 'magicLink'\n>;\n\n/** The two e-mails of a one-time token, which link to your page with it. */\ntype LinkMailName = 'verifyEmail' | 'resetPassword';\n\n/** One e-mail of a one-time token: to `issued.email`, its link built from `issued.token`. */\nfunction linkMail(options: ResolvedOptions, name: LinkMailName) {\n\treturn async (issued: unknown, to: unknown, sendOptions?: unknown) => {\n\t\tconst token = field(name, issued, 'token');\n\t\tconst locale = localeFor(options, to);\n\t\treturn send(options, name, field(name, issued, 'email'), {\n\t\t\tbrand: options.brand,\n\t\t\tname: field(name, to, 'name'),\n\t\t\tlink: link(name, options.links[name](token), `${name}(token)`),\n\t\t\texpiresIn: expiresInFor(name, issued, locale, sendOptions, options.clock),\n\t\t\tlocale,\n\t\t});\n\t};\n}\n\n/**\n * The sign-in link's e-mail: to `issued.email`, greeting nobody, its link\n * built from `issued.token` by the optional `links.magicLink` — checked\n * before anything else is read, so a missing link is refused whatever the\n * arguments.\n */\nfunction magicLinkMail(options: ResolvedOptions) {\n\treturn async (issued: unknown, to: unknown, sendOptions?: unknown) => {\n\t\tconst build = options.links.magicLink;\n\t\tif (build === undefined) {\n\t\t\tthrow new TypeError(\n\t\t\t\t'janusMail.magicLink: links.magicLink is missing — pass it to janusMail({ links }) to send sign-in links',\n\t\t\t);\n\t\t}\n\t\tconst token = field('magicLink', issued, 'token');\n\t\tconst locale = localeFor(options, to);\n\t\treturn send(options, 'magicLink', field('magicLink', issued, 'email'), {\n\t\t\tbrand: options.brand,\n\t\t\tlink: link('magicLink', build(token), 'magicLink(token)'),\n\t\t\texpiresIn: expiresInFor(\n\t\t\t\t'magicLink',\n\t\t\t\tissued,\n\t\t\t\tlocale,\n\t\t\t\tsendOptions,\n\t\t\t\toptions.clock,\n\t\t\t),\n\t\t\tlocale,\n\t\t});\n\t};\n}\n\n/** `verifyEmail`, `resetPassword`, `signInCode` and `magicLink`, over the resolved options. */\nexport function expiringMails(options: ResolvedOptions): ExpiringMails {\n\treturn {\n\t\tverifyEmail: linkMail(options, 'verifyEmail'),\n\t\tresetPassword: linkMail(options, 'resetPassword'),\n\t\tasync signInCode(issued, to, sendOptions) {\n\t\t\t// `code`, `email` and `expiresAt` only: the challenge is the visitor's secret.\n\t\t\tconst locale = localeFor(options, to);\n\t\t\treturn send(options, 'signInCode', field('signInCode', issued, 'email'), {\n\t\t\t\tbrand: options.brand,\n\t\t\t\tcode: field('signInCode', issued, 'code'),\n\t\t\t\texpiresIn: expiresInFor(\n\t\t\t\t\t'signInCode',\n\t\t\t\t\tissued,\n\t\t\t\t\tlocale,\n\t\t\t\t\tsendOptions,\n\t\t\t\t\toptions.clock,\n\t\t\t\t),\n\t\t\t\tlocale,\n\t\t\t});\n\t\t},\n\t\tmagicLink: magicLinkMail(options),\n\t};\n}\n",
8
8
  "/**\n * The e-mails about the account itself, sent on what happened to it rather\n * than on a flow's answer: the notices of a change the user made — or someone\n * else did — `passwordChanged`, `emailChanged`, `twoFactorEnabled` and\n * `twoFactorDisabled`, each linking to where the account is secured; and\n * `welcome`, once it was created, linking to where a new user starts.\n */\nimport type { ResolvedOptions } from './options';\nimport { field, link, localeFor, send } from './send';\nimport type { JanusMail } from './types';\n\ntype NoticeMails = Pick<\n\tJanusMail<string>,\n\t| 'passwordChanged'\n\t| 'emailChanged'\n\t| 'twoFactorEnabled'\n\t| 'twoFactorDisabled'\n\t| 'welcome'\n>;\n\n/** The e-mails that greet `to.name` at `to.email`, and link to one of `links`. */\ntype PlainNotice =\n\t| 'passwordChanged'\n\t| 'twoFactorEnabled'\n\t| 'twoFactorDisabled'\n\t| 'welcome';\n\n/** The links a plain notice may take: those called with nothing. */\ntype PlainLink = 'secureAccount' | 'getStarted';\n\n/** The notices and the welcome, over the resolved options. */\nexport function noticeMails(options: ResolvedOptions): NoticeMails {\n\tconst { brand, links } = options;\n\tconst plain =\n\t\t(method: PlainNotice, target: PlainLink) =>\n\t\t// Async, so a wrong argument rejects as the other methods' do.\n\t\tasync (to: unknown): ReturnType<NoticeMails[PlainNotice]> =>\n\t\t\tsend(options, method, field(method, to, 'email'), {\n\t\t\t\tbrand,\n\t\t\t\tname: field(method, to, 'name'),\n\t\t\t\tlink: link(method, links[target](), `${target}()`),\n\t\t\t\tlocale: localeFor(options, to),\n\t\t\t});\n\treturn {\n\t\tpasswordChanged: plain('passwordChanged', 'secureAccount'),\n\t\ttwoFactorEnabled: plain('twoFactorEnabled', 'secureAccount'),\n\t\ttwoFactorDisabled: plain('twoFactorDisabled', 'secureAccount'),\n\t\twelcome: plain('welcome', 'getStarted'),\n\t\tasync emailChanged(to) {\n\t\t\t// To the former address: the one a hijacker just took the account from.\n\t\t\treturn send(\n\t\t\t\toptions,\n\t\t\t\t'emailChanged',\n\t\t\t\tfield('emailChanged', to, 'formerEmail'),\n\t\t\t\t{\n\t\t\t\t\tbrand,\n\t\t\t\t\tname: field('emailChanged', to, 'name'),\n\t\t\t\t\tlink: link('emailChanged', links.secureAccount(), 'secureAccount()'),\n\t\t\t\t\tnewEmail: field('emailChanged', to, 'newEmail'),\n\t\t\t\t\tlocale: localeFor(options, to),\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t};\n}\n",
9
9
  "// Generated by scripts/build-mail.ts from mails/mail-manifest.json, after\n// each build of the default e-mails. Never edited; committed.\n\n/** The locales the default e-mails are built in, the fallback locale first. */\nexport const LOCALES = ['en', 'fr'] as const;\n\n/** A locale the default e-mails are built in. */\nexport type JanusMailLocale = (typeof LOCALES)[number];\n",
10
10
  "/** A wiring refusal of `janusMail()`: a `TypeError` naming the option. */\nexport function refuse(message: string): never {\n\tthrow new TypeError(`janusMail: ${message}`);\n}\n",
11
- "/**\n * `janusMail()`'s `links`, checked once when it is called and copied, so\n * the guarantee made there holds at every send. A mistake is a wiring\n * mistake: a bare `TypeError` naming the link, never its value.\n */\nimport { refuse } from './refuse';\nimport type { JanusMailLinks } from './types';\n\n/** The links every `janusMail()` needs: checked, then copied, by these names. */\nconst REQUIRED_LINKS = [\n\t'verifyEmail',\n\t'resetPassword',\n\t'secureAccount',\n\t'getStarted',\n] as const;\n\n/** The links a `janusMail()` may leave out, each with a fallback. */\nconst OPTIONAL_LINKS = ['recoveryCodes'] as const;\n\n/** `links`: an object of functions, every required one there. */\nexport function checkLinks(\n\tlinks: unknown,\n): asserts links is Record<string, unknown> {\n\tif (typeof links !== 'object' || links === null || Array.isArray(links)) {\n\t\trefuse(\n\t\t\t'links must be an object, as { verifyEmail, resetPassword, secureAccount, getStarted }',\n\t\t);\n\t}\n\tconst given = links as Record<string, unknown>;\n\tfor (const name of REQUIRED_LINKS) {\n\t\tif (typeof given[name] !== 'function') {\n\t\t\trefuse(`links.${name} must be a function`);\n\t\t}\n\t}\n\tfor (const name of OPTIONAL_LINKS) {\n\t\tif (given[name] !== undefined && typeof given[name] !== 'function') {\n\t\t\trefuse(`links.${name} must be a function, or left out`);\n\t\t}\n\t}\n}\n\n/**\n * A frozen copy of the checked links, each bound to the caller's object — a\n * class instance's methods keep their `this` — so replacing a link after\n * `janusMail()` cannot undo the check. An optional link left out stays out.\n */\nexport function frozenLinks(links: JanusMailLinks): JanusMailLinks {\n\tconst given = links as unknown as Record<\n\t\tstring,\n\t\t((...args: never[]) => unknown) | undefined\n\t>;\n\tconst names = [\n\t\t...REQUIRED_LINKS,\n\t\t...OPTIONAL_LINKS.filter((name) => given[name] !== undefined),\n\t];\n\t// Every name kept was checked a function by checkLinks.\n\treturn Object.freeze(\n\t\tObject.fromEntries(\n\t\t\tnames.map((name) => [\n\t\t\t\tname,\n\t\t\t\t(given[name] as (...args: never[]) => unknown).bind(links),\n\t\t\t]),\n\t\t),\n\t) as unknown as JanusMailLinks;\n}\n",
11
+ "/**\n * `janusMail()`'s `links`, checked once when it is called and copied, so\n * the guarantee made there holds at every send. A mistake is a wiring\n * mistake: a bare `TypeError` naming the link, never its value.\n */\nimport { refuse } from './refuse';\nimport type { JanusMailLinks } from './types';\n\n/** The links every `janusMail()` needs: checked, then copied, by these names. */\nconst REQUIRED_LINKS = [\n\t'verifyEmail',\n\t'resetPassword',\n\t'secureAccount',\n\t'getStarted',\n] as const;\n\n/**\n * The links a `janusMail()` may leave out: `recoveryCodes` falls back to\n * `secureAccount`; `magicLink` has none, and its send is refused without it.\n */\nconst OPTIONAL_LINKS = ['recoveryCodes', 'magicLink'] as const;\n\n/** `links`: an object of functions, every required one there. */\nexport function checkLinks(\n\tlinks: unknown,\n): asserts links is Record<string, unknown> {\n\tif (typeof links !== 'object' || links === null || Array.isArray(links)) {\n\t\trefuse(\n\t\t\t'links must be an object, as { verifyEmail, resetPassword, secureAccount, getStarted }',\n\t\t);\n\t}\n\tconst given = links as Record<string, unknown>;\n\tfor (const name of REQUIRED_LINKS) {\n\t\tif (typeof given[name] !== 'function') {\n\t\t\trefuse(`links.${name} must be a function`);\n\t\t}\n\t}\n\tfor (const name of OPTIONAL_LINKS) {\n\t\tif (given[name] !== undefined && typeof given[name] !== 'function') {\n\t\t\trefuse(`links.${name} must be a function, or left out`);\n\t\t}\n\t}\n}\n\n/**\n * A frozen copy of the checked links, each bound to the caller's object — a\n * class instance's methods keep their `this` — so replacing a link after\n * `janusMail()` cannot undo the check. An optional link left out stays out.\n */\nexport function frozenLinks(links: JanusMailLinks): JanusMailLinks {\n\tconst given = links as unknown as Record<\n\t\tstring,\n\t\t((...args: never[]) => unknown) | undefined\n\t>;\n\tconst names = [\n\t\t...REQUIRED_LINKS,\n\t\t...OPTIONAL_LINKS.filter((name) => given[name] !== undefined),\n\t];\n\t// Every name kept was checked a function by checkLinks.\n\treturn Object.freeze(\n\t\tObject.fromEntries(\n\t\t\tnames.map((name) => [\n\t\t\t\tname,\n\t\t\t\t(given[name] as (...args: never[]) => unknown).bind(links),\n\t\t\t]),\n\t\t),\n\t) as unknown as JanusMailLinks;\n}\n",
12
12
  "/**\n * Where the default e-mails are, and the one renderer that reads them.\n *\n * The package ships the built e-mails in `mails/`, beside `dist/` — not in\n * it, because the root `build.ts` removes from `dist/` every file it did not\n * write itself.\n */\nimport { fileURLToPath } from 'node:url';\nimport { createMailRenderer, type MailRenderer } from '@nxgt/mail/renderer';\nimport type { MailEmails } from './generated/mail';\n\n/**\n * The folder of the built e-mails, resolved from this module rather than from\n * the working directory, which is the consumer's.\n *\n * **This file must stay directly under `src/`.** `../mails/` is right from\n * `src/mails.ts` in the specs, and from `dist/index.js` in the tarball,\n * because the build bundles this module into the single entry\n * `dist/index.js`, one level under the package as `src/` is. Moved into a\n * subfolder, or bundled into `dist/chunks/` by a second entry point, it would\n * resolve a folder that does not exist — which the artifact spec, rendering\n * from `../dist`, would catch.\n */\nexport const MAILS_DIR = fileURLToPath(new URL('../mails/', import.meta.url));\n\nlet renderer: MailRenderer<MailEmails> | undefined;\n\n/**\n * The renderer of the default e-mails, created on first use and shared by\n * every `janusMail()` and `janusTemplates()` after it.\n *\n * Lazy, so importing the package reads nothing: an application that\n * overrides every template never opens `mails/`. The first default template\n * rendered reads the whole build once — a missing `mails/` throws there, with\n * `createMailRenderer`'s own message.\n */\nexport function defaultRenderer(): MailRenderer<MailEmails> {\n\trenderer ??= createMailRenderer<MailEmails>({ dir: MAILS_DIR });\n\treturn renderer;\n}\n",
13
- "/**\n * The default templates: the prebuilt e-mails, filled by `@nxgt/mail`'s\n * renderer. Each picks from its variables exactly what its e-mail takes — the\n * renderer refuses a variable too many — so the `locale` beside them goes to\n * the renderer's options, and nowhere else.\n */\nimport type { Rendered } from '@nxgt/mail';\nimport { defaultRenderer } from './mails';\nimport type { JanusMailTemplates } from './types';\n\n/**\n * The nine default templates, in the locales they are built in. The\n * renderer behind them is created on the first render, not here.\n *\n * ```ts\n * const defaults = janusTemplates();\n * const { subject } = await defaults.verifyEmail({ brand: 'Acme', name: 'Ada', link, locale: 'fr' });\n * ```\n *\n * A URL that is not `http:`, `https:` or `mailto:` throws `MailRefused`; a\n * missing `mails/` folder throws when the first one renders.\n */\nexport function janusTemplates(): JanusMailTemplates {\n\treturn Object.freeze({\n\t\tverifyEmail: ({ brand, name, link, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'verify-email',\n\t\t\t\t{ brand, name, link, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tresetPassword: ({ brand, name, link, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'reset-password',\n\t\t\t\t{ brand, name, link, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tsignInCode: ({ brand, code, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'sign-in-code',\n\t\t\t\t{ brand, code, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tpasswordChanged: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'password-changed',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\temailChanged: ({ brand, name, link, newEmail, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'email-changed',\n\t\t\t\t{ brand, name, link, newEmail },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\ttwoFactorEnabled: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'two-factor-enabled',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\ttwoFactorDisabled: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'two-factor-disabled',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\trecoveryCodeUsed: ({\n\t\t\tbrand,\n\t\t\tname,\n\t\t\twhen,\n\t\t\trecoveryCodesLeft,\n\t\t\tlink,\n\t\t\tlocale,\n\t\t}): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'recovery-code-used',\n\t\t\t\t{ brand, name, when, recoveryCodesLeft, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\twelcome: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render('welcome', { brand, name, link }, { locale }),\n\t});\n}\n",
14
- "/**\n * `janusMail()`'s options, checked once when it is called. A mistake is a\n * wiring mistake, so a bare `TypeError` naming the option — never its value —\n * thrown before anything is sent.\n */\nimport type { Clock } from '@nxgt/janus';\nimport type { Address, Mailer } from '@nxgt/mail';\nimport { LOCALES } from './generated/locales';\nimport { checkLinks, frozenLinks } from './links';\nimport { refuse } from './refuse';\nimport { janusTemplates } from './templates';\nimport type {\n\tJanusMailLinks,\n\tJanusMailTemplateName,\n\tJanusMailTemplates,\n} from './types';\n\n/** The templates in the order the documentation lists them. */\nexport const TEMPLATE_NAMES: readonly JanusMailTemplateName[] = [\n\t'verifyEmail',\n\t'resetPassword',\n\t'signInCode',\n\t'passwordChanged',\n\t'emailChanged',\n\t'twoFactorEnabled',\n\t'twoFactorDisabled',\n\t'recoveryCodeUsed',\n\t'welcome',\n];\n\n/** The options once checked, with `string` for the locales: the degenericised mirror. */\nexport interface ResolvedOptions {\n\treadonly mailer: Mailer;\n\treadonly from: Address;\n\treadonly replyTo: Address | undefined;\n\treadonly brand: string;\n\treadonly links: JanusMailLinks;\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly templates: JanusMailTemplates<string>;\n\treadonly clock: Clock;\n}\n\n/** The system clock, written here: `@nxgt/janus` is a peer for its types only. */\nconst SYSTEM_CLOCK: Clock = Object.freeze({ now: () => new Date() });\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isAddress(value: unknown): value is Address {\n\tif (typeof value === 'string') return value.trim() !== '';\n\treturn (\n\t\tisObject(value) &&\n\t\ttypeof value.name === 'string' &&\n\t\ttypeof value.address === 'string' &&\n\t\tvalue.address.trim() !== ''\n\t);\n}\n\n/** `mailer`, `from`, `replyTo`, `brand` and `links` (`./links`). */\nfunction checkSending(options: Record<string, unknown>): void {\n\tconst { mailer, from, replyTo, brand, links } = options;\n\tif (!isObject(mailer) || typeof mailer.send !== 'function') {\n\t\trefuse('mailer must be a Mailer — an object with a send function');\n\t}\n\tif (!isAddress(from)) {\n\t\trefuse(\n\t\t\t\"from must be an address, as 'noreply@example.com' or { name, address }\",\n\t\t);\n\t}\n\tif (replyTo !== undefined && !isAddress(replyTo)) {\n\t\trefuse(\n\t\t\t\"replyTo must be an address, as 'support@example.com' or { name, address }\",\n\t\t);\n\t}\n\tif (typeof brand !== 'string' || brand.trim() === '') {\n\t\trefuse(\"brand must be the name the e-mails show, as 'Acme'\");\n\t}\n\tcheckLinks(links);\n}\n\n/** `clock`, bound to the caller's object, or the system clock. */\nfunction resolveClock(clock: unknown): Clock {\n\tif (clock === undefined) return SYSTEM_CLOCK;\n\tif (!isObject(clock) || typeof clock.now !== 'function') {\n\t\trefuse('clock must be a Clock — an object with a now function');\n\t}\n\treturn Object.freeze({ now: (clock.now as () => Date).bind(clock) });\n}\n\n/** Whether `Intl` takes the locale — the expiry is formatted in it — as `fr-CA`, not `fr_CA`. */\nfunction isLanguageTag(locale: string): boolean {\n\ttry {\n\t\tIntl.getCanonicalLocales(locale);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/** `locales` and `fallbackLocale`, with their defaults. */\nfunction resolveLocales(options: Record<string, unknown>): {\n\tlocales: readonly string[];\n\tfallbackLocale: string;\n} {\n\tconst wanted = options.locales ?? LOCALES;\n\tif (\n\t\t!Array.isArray(wanted) ||\n\t\twanted.length === 0 ||\n\t\t!wanted.every((locale) => typeof locale === 'string' && locale !== '')\n\t) {\n\t\trefuse(\"locales must list at least one locale, as ['en', 'fr']\");\n\t}\n\tconst locales: readonly string[] = Object.freeze([...wanted]);\n\tif (!locales.every(isLanguageTag)) {\n\t\trefuse(\"locales must be BCP 47 language tags, as 'fr-CA'\");\n\t}\n\tif (new Set(locales).size !== locales.length) {\n\t\trefuse('locales holds the same locale twice');\n\t}\n\tconst fallbackLocale =\n\t\toptions.fallbackLocale ??\n\t\t(locales.includes('en') ? 'en' : (locales[0] as string));\n\tif (typeof fallbackLocale !== 'string' || !locales.includes(fallbackLocale)) {\n\t\trefuse('fallbackLocale must be one of locales');\n\t}\n\treturn { locales, fallbackLocale };\n}\n\n/** `templates` over the defaults — the defaults only while every locale is built. */\nfunction resolveTemplates(\n\toptions: Record<string, unknown>,\n\tlocales: readonly string[],\n): JanusMailTemplates<string> {\n\tconst given = options.templates ?? {};\n\tif (!isObject(given)) {\n\t\trefuse(\n\t\t\t'templates must be an object of functions, as { verifyEmail: (variables) => rendered }',\n\t\t);\n\t}\n\tfor (const [name, template] of Object.entries(given)) {\n\t\tif (!(TEMPLATE_NAMES as readonly string[]).includes(name)) {\n\t\t\trefuse(\n\t\t\t\t`templates has no template ${name} — name one of ${TEMPLATE_NAMES.join(', ')}`,\n\t\t\t);\n\t\t}\n\t\tif (typeof template !== 'function') {\n\t\t\trefuse(`templates.${name} must be a function`);\n\t\t}\n\t}\n\t// Own enumerable keys, the ones the spread below copies. A template on a\n\t// prototype — a class instance's method — or an own property that is not\n\t// enumerable would be dropped without a word, the default sent in its\n\t// place: `in` sees it and `passed` does not, so it is refused instead.\n\tconst passed = Object.keys(given);\n\tfor (const name of TEMPLATE_NAMES) {\n\t\tif (name in given && !passed.includes(name)) {\n\t\t\trefuse(\n\t\t\t\t`templates.${name} is not an own enumerable property — pass a plain object, as { ${name}: (variables) => rendered }`,\n\t\t\t);\n\t\t}\n\t}\n\tconst built = locales.every((locale) =>\n\t\t(LOCALES as readonly string[]).includes(locale),\n\t);\n\tconst missing = TEMPLATE_NAMES.filter((name) => !passed.includes(name));\n\tif (!built && missing.length > 0) {\n\t\trefuse(\n\t\t\t`the default templates are built in ${LOCALES.join(' and ')} only — with another ` +\n\t\t\t\t`locale in locales, pass every template in templates; ${missing.join(', ')} missing`,\n\t\t);\n\t}\n\t// The one cast: a default template takes a built locale only, and the check\n\t// above proves every locale is one whenever a default is kept.\n\tconst defaults = janusTemplates() as unknown as JanusMailTemplates<string>;\n\treturn Object.freeze({ ...defaults, ...given }) as JanusMailTemplates<string>;\n}\n\n/** A frozen copy of a checked address: a later change to the caller's object is not seen. */\nfunction frozenAddress(address: Address): Address {\n\treturn typeof address === 'string'\n\t\t? address\n\t\t: Object.freeze({ name: address.name, address: address.address });\n}\n\n/**\n * Checks `janusMail()`'s options and answers them resolved, or throws a\n * `TypeError`. What was checked is copied and frozen, so the guarantee made\n * here holds at every send.\n */\nexport function resolveOptions(options: unknown): ResolvedOptions {\n\tif (!isObject(options)) {\n\t\trefuse('options must be an object, as { mailer, from, brand, links }');\n\t}\n\tcheckSending(options);\n\tconst { locales, fallbackLocale } = resolveLocales(options);\n\treturn Object.freeze({\n\t\tmailer: options.mailer as Mailer,\n\t\tfrom: frozenAddress(options.from as Address),\n\t\treplyTo:\n\t\t\toptions.replyTo === undefined\n\t\t\t\t? undefined\n\t\t\t\t: frozenAddress(options.replyTo as Address),\n\t\tbrand: options.brand as string,\n\t\tlinks: frozenLinks(options.links as unknown as JanusMailLinks),\n\t\tlocales,\n\t\tfallbackLocale,\n\t\ttemplates: resolveTemplates(options, locales),\n\t\tclock: resolveClock(options.clock),\n\t});\n}\n",
13
+ "/**\n * The default templates: the prebuilt e-mails, filled by `@nxgt/mail`'s\n * renderer. Each picks from its variables exactly what its e-mail takes — the\n * renderer refuses a variable too many — so the `locale` beside them goes to\n * the renderer's options, and nowhere else.\n */\nimport type { Rendered } from '@nxgt/mail';\nimport { defaultRenderer } from './mails';\nimport type { JanusMailTemplates } from './types';\n\n/**\n * The ten default templates, in the locales they are built in. The\n * renderer behind them is created on the first render, not here.\n *\n * ```ts\n * const defaults = janusTemplates();\n * const { subject } = await defaults.verifyEmail({ brand: 'Acme', name: 'Ada', link, locale: 'fr' });\n * ```\n *\n * A URL that is not `http:`, `https:` or `mailto:` throws `MailRefused`; a\n * missing `mails/` folder throws when the first one renders.\n */\nexport function janusTemplates(): JanusMailTemplates {\n\treturn Object.freeze({\n\t\tverifyEmail: ({ brand, name, link, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'verify-email',\n\t\t\t\t{ brand, name, link, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tresetPassword: ({ brand, name, link, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'reset-password',\n\t\t\t\t{ brand, name, link, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tsignInCode: ({ brand, code, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'sign-in-code',\n\t\t\t\t{ brand, code, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tmagicLink: ({ brand, link, expiresIn, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'magic-link',\n\t\t\t\t{ brand, link, expiresIn },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\tpasswordChanged: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'password-changed',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\temailChanged: ({ brand, name, link, newEmail, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'email-changed',\n\t\t\t\t{ brand, name, link, newEmail },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\ttwoFactorEnabled: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'two-factor-enabled',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\ttwoFactorDisabled: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'two-factor-disabled',\n\t\t\t\t{ brand, name, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\trecoveryCodeUsed: ({\n\t\t\tbrand,\n\t\t\tname,\n\t\t\twhen,\n\t\t\trecoveryCodesLeft,\n\t\t\tlink,\n\t\t\tlocale,\n\t\t}): Rendered =>\n\t\t\tdefaultRenderer().render(\n\t\t\t\t'recovery-code-used',\n\t\t\t\t{ brand, name, when, recoveryCodesLeft, link },\n\t\t\t\t{ locale },\n\t\t\t),\n\t\twelcome: ({ brand, name, link, locale }): Rendered =>\n\t\t\tdefaultRenderer().render('welcome', { brand, name, link }, { locale }),\n\t});\n}\n",
14
+ "/**\n * `janusMail()`'s options, checked once when it is called. A mistake is a\n * wiring mistake, so a bare `TypeError` naming the option — never its value —\n * thrown before anything is sent.\n */\nimport type { Clock } from '@nxgt/janus';\nimport type { Address, Mailer } from '@nxgt/mail';\nimport { LOCALES } from './generated/locales';\nimport { checkLinks, frozenLinks } from './links';\nimport { refuse } from './refuse';\nimport { janusTemplates } from './templates';\nimport type {\n\tJanusMailLinks,\n\tJanusMailTemplateName,\n\tJanusMailTemplates,\n} from './types';\n\n/** The templates in the order the documentation lists them. */\nexport const TEMPLATE_NAMES: readonly JanusMailTemplateName[] = [\n\t'verifyEmail',\n\t'resetPassword',\n\t'signInCode',\n\t'magicLink',\n\t'passwordChanged',\n\t'emailChanged',\n\t'twoFactorEnabled',\n\t'twoFactorDisabled',\n\t'recoveryCodeUsed',\n\t'welcome',\n];\n\n/** The options once checked, with `string` for the locales: the degenericised mirror. */\nexport interface ResolvedOptions {\n\treadonly mailer: Mailer;\n\treadonly from: Address;\n\treadonly replyTo: Address | undefined;\n\treadonly brand: string;\n\treadonly links: JanusMailLinks;\n\treadonly locales: readonly string[];\n\treadonly fallbackLocale: string;\n\treadonly templates: JanusMailTemplates<string>;\n\treadonly clock: Clock;\n}\n\n/** The system clock, written here: `@nxgt/janus` is a peer for its types only. */\nconst SYSTEM_CLOCK: Clock = Object.freeze({ now: () => new Date() });\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isAddress(value: unknown): value is Address {\n\tif (typeof value === 'string') return value.trim() !== '';\n\treturn (\n\t\tisObject(value) &&\n\t\ttypeof value.name === 'string' &&\n\t\ttypeof value.address === 'string' &&\n\t\tvalue.address.trim() !== ''\n\t);\n}\n\n/** `mailer`, `from`, `replyTo`, `brand` and `links` (`./links`). */\nfunction checkSending(options: Record<string, unknown>): void {\n\tconst { mailer, from, replyTo, brand, links } = options;\n\tif (!isObject(mailer) || typeof mailer.send !== 'function') {\n\t\trefuse('mailer must be a Mailer — an object with a send function');\n\t}\n\tif (!isAddress(from)) {\n\t\trefuse(\n\t\t\t\"from must be an address, as 'noreply@example.com' or { name, address }\",\n\t\t);\n\t}\n\tif (replyTo !== undefined && !isAddress(replyTo)) {\n\t\trefuse(\n\t\t\t\"replyTo must be an address, as 'support@example.com' or { name, address }\",\n\t\t);\n\t}\n\tif (typeof brand !== 'string' || brand.trim() === '') {\n\t\trefuse(\"brand must be the name the e-mails show, as 'Acme'\");\n\t}\n\tcheckLinks(links);\n}\n\n/** `clock`, bound to the caller's object, or the system clock. */\nfunction resolveClock(clock: unknown): Clock {\n\tif (clock === undefined) return SYSTEM_CLOCK;\n\tif (!isObject(clock) || typeof clock.now !== 'function') {\n\t\trefuse('clock must be a Clock — an object with a now function');\n\t}\n\treturn Object.freeze({ now: (clock.now as () => Date).bind(clock) });\n}\n\n/** Whether `Intl` takes the locale — the expiry is formatted in it — as `fr-CA`, not `fr_CA`. */\nfunction isLanguageTag(locale: string): boolean {\n\ttry {\n\t\tIntl.getCanonicalLocales(locale);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/** `locales` and `fallbackLocale`, with their defaults. */\nfunction resolveLocales(options: Record<string, unknown>): {\n\tlocales: readonly string[];\n\tfallbackLocale: string;\n} {\n\tconst wanted = options.locales ?? LOCALES;\n\tif (\n\t\t!Array.isArray(wanted) ||\n\t\twanted.length === 0 ||\n\t\t!wanted.every((locale) => typeof locale === 'string' && locale !== '')\n\t) {\n\t\trefuse(\"locales must list at least one locale, as ['en', 'fr']\");\n\t}\n\tconst locales: readonly string[] = Object.freeze([...wanted]);\n\tif (!locales.every(isLanguageTag)) {\n\t\trefuse(\"locales must be BCP 47 language tags, as 'fr-CA'\");\n\t}\n\tif (new Set(locales).size !== locales.length) {\n\t\trefuse('locales holds the same locale twice');\n\t}\n\tconst fallbackLocale =\n\t\toptions.fallbackLocale ??\n\t\t(locales.includes('en') ? 'en' : (locales[0] as string));\n\tif (typeof fallbackLocale !== 'string' || !locales.includes(fallbackLocale)) {\n\t\trefuse('fallbackLocale must be one of locales');\n\t}\n\treturn { locales, fallbackLocale };\n}\n\n/** `templates` over the defaults — the defaults only while every locale is built. */\nfunction resolveTemplates(\n\toptions: Record<string, unknown>,\n\tlocales: readonly string[],\n): JanusMailTemplates<string> {\n\tconst given = options.templates ?? {};\n\tif (!isObject(given)) {\n\t\trefuse(\n\t\t\t'templates must be an object of functions, as { verifyEmail: (variables) => rendered }',\n\t\t);\n\t}\n\tfor (const [name, template] of Object.entries(given)) {\n\t\tif (!(TEMPLATE_NAMES as readonly string[]).includes(name)) {\n\t\t\trefuse(\n\t\t\t\t`templates has no template ${name} — name one of ${TEMPLATE_NAMES.join(', ')}`,\n\t\t\t);\n\t\t}\n\t\tif (typeof template !== 'function') {\n\t\t\trefuse(`templates.${name} must be a function`);\n\t\t}\n\t}\n\t// Own enumerable keys, the ones the spread below copies. A template on a\n\t// prototype — a class instance's method — or an own property that is not\n\t// enumerable would be dropped without a word, the default sent in its\n\t// place: `in` sees it and `passed` does not, so it is refused instead.\n\tconst passed = Object.keys(given);\n\tfor (const name of TEMPLATE_NAMES) {\n\t\tif (name in given && !passed.includes(name)) {\n\t\t\trefuse(\n\t\t\t\t`templates.${name} is not an own enumerable property — pass a plain object, as { ${name}: (variables) => rendered }`,\n\t\t\t);\n\t\t}\n\t}\n\tconst built = locales.every((locale) =>\n\t\t(LOCALES as readonly string[]).includes(locale),\n\t);\n\tconst missing = TEMPLATE_NAMES.filter((name) => !passed.includes(name));\n\tif (!built && missing.length > 0) {\n\t\trefuse(\n\t\t\t`the default templates are built in ${LOCALES.join(' and ')} only — with another ` +\n\t\t\t\t`locale in locales, pass every template in templates; ${missing.join(', ')} missing`,\n\t\t);\n\t}\n\t// The one cast: a default template takes a built locale only, and the check\n\t// above proves every locale is one whenever a default is kept.\n\tconst defaults = janusTemplates() as unknown as JanusMailTemplates<string>;\n\treturn Object.freeze({ ...defaults, ...given }) as JanusMailTemplates<string>;\n}\n\n/** A frozen copy of a checked address: a later change to the caller's object is not seen. */\nfunction frozenAddress(address: Address): Address {\n\treturn typeof address === 'string'\n\t\t? address\n\t\t: Object.freeze({ name: address.name, address: address.address });\n}\n\n/**\n * Checks `janusMail()`'s options and answers them resolved, or throws a\n * `TypeError`. What was checked is copied and frozen, so the guarantee made\n * here holds at every send.\n */\nexport function resolveOptions(options: unknown): ResolvedOptions {\n\tif (!isObject(options)) {\n\t\trefuse('options must be an object, as { mailer, from, brand, links }');\n\t}\n\tcheckSending(options);\n\tconst { locales, fallbackLocale } = resolveLocales(options);\n\treturn Object.freeze({\n\t\tmailer: options.mailer as Mailer,\n\t\tfrom: frozenAddress(options.from as Address),\n\t\treplyTo:\n\t\t\toptions.replyTo === undefined\n\t\t\t\t? undefined\n\t\t\t\t: frozenAddress(options.replyTo as Address),\n\t\tbrand: options.brand as string,\n\t\tlinks: frozenLinks(options.links as unknown as JanusMailLinks),\n\t\tlocales,\n\t\tfallbackLocale,\n\t\ttemplates: resolveTemplates(options, locales),\n\t\tclock: resolveClock(options.clock),\n\t});\n}\n",
15
15
  "// Generated by scripts/build-mail.ts from recovery-code-used.codes-left, after\n// each build of the default e-mails. Never edited; committed.\n\n/** Each locale's plural for the recovery codes left: branches by selector, `null` where the count goes. */\nexport const CODES_LEFT: Readonly<Record<string, Readonly<Record<string, readonly (string | null)[]>>>> = {\n\t\"en\": {\n\t\t\"=0\": [\n\t\t\t\"You have no recovery codes left.\"\n\t\t],\n\t\t\"one\": [\n\t\t\t\"You have \",\n\t\t\tnull,\n\t\t\t\" recovery code left.\"\n\t\t],\n\t\t\"other\": [\n\t\t\t\"You have \",\n\t\t\tnull,\n\t\t\t\" recovery codes left.\"\n\t\t]\n\t},\n\t\"fr\": {\n\t\t\"=0\": [\n\t\t\t\"Il ne vous reste aucun code de récupération.\"\n\t\t],\n\t\t\"one\": [\n\t\t\t\"Il vous reste \",\n\t\t\tnull,\n\t\t\t\" code de récupération.\"\n\t\t],\n\t\t\"other\": [\n\t\t\t\"Il vous reste \",\n\t\t\tnull,\n\t\t\t\" codes de récupération.\"\n\t\t]\n\t}\n};\n",
16
16
  "/**\n * The sentence of the recovery codes left, in the recipient's locale:\n * \"You have 1 recovery code left.\" — the `recovery-code-used` e-mail's\n * `recoveryCodesLeft`, which the build could not write since the count is a\n * send's.\n *\n * Formatted from `src/generated/codes-left.ts`, the preset's ICU plural\n * parsed at our build, as `@nxgt/mail-i18n`'s `createTranslator` formats\n * it: an exact branch (`=0`) first, then the locale's plural category, then\n * `other`, with `#` as the count in the locale's digits. No Maizzle and no\n * ICU parser at send time.\n */\nimport { CODES_LEFT } from './generated/codes-left';\n\n/**\n * The sentence for `count` codes left in `locale`, or `undefined` for a\n * locale the default e-mails are not built in.\n */\nexport function codesLeftText(\n\tlocale: string,\n\tcount: number,\n): string | undefined {\n\tif (!Object.hasOwn(CODES_LEFT, locale)) return undefined;\n\tconst branches = CODES_LEFT[locale] as (typeof CODES_LEFT)[string];\n\tconst branch =\n\t\tbranches[`=${count}`] ??\n\t\tbranches[new Intl.PluralRules(locale).select(count)] ??\n\t\tbranches.other;\n\tconst digits = new Intl.NumberFormat(locale).format(count);\n\treturn (branch ?? []).map((part) => part ?? digits).join('');\n}\n",
17
17
  "/**\n * `recoveryCodeUsed`: the notice of a recovery code spent — a sign-in\n * without the user's phone — saying when, and how many codes are left.\n *\n * Apart from the other notices because of its count: the build could not\n * choose the plural, so the send does, in the recipient's locale\n * (`./codes-left`).\n */\nimport { codesLeftText } from './codes-left';\nimport type { ResolvedOptions } from './options';\nimport { field, link, localeFor, send } from './send';\nimport type { JanusMail } from './types';\n\nconst METHOD = 'recoveryCodeUsed';\n\n/** A count of codes: a whole number, 0 or more. */\nconst isCount = (value: unknown): value is number =>\n\ttypeof value === 'number' && Number.isSafeInteger(value) && value >= 0;\n\n/**\n * The sentence of the codes left: the count formatted in `locale`, or the\n * sender's own text. A `TypeError` for anything else, or for a count in a\n * locale the default e-mails hold no sentence for.\n */\nfunction codesLeft(used: unknown, locale: string): string {\n\tconst given =\n\t\ttypeof used === 'object' && used !== null\n\t\t\t? (used as { recoveryCodesLeft?: unknown }).recoveryCodesLeft\n\t\t\t: undefined;\n\tif (typeof given === 'string') return given;\n\tif (!isCount(given)) {\n\t\tthrow new TypeError(\n\t\t\t`janusMail.${METHOD}: recoveryCodesLeft must be a count — a whole number, 0 or more — or the sentence to show`,\n\t\t);\n\t}\n\tconst text = codesLeftText(locale, given);\n\tif (text === undefined) {\n\t\tthrow new TypeError(\n\t\t\t`janusMail.${METHOD}: recoveryCodesLeft must be the sentence to show in a locale the default e-mails are not built in`,\n\t\t);\n\t}\n\treturn text;\n}\n\n/** The recovery code notice, over the resolved options. */\nexport function recoveryMail(\n\toptions: ResolvedOptions,\n): Pick<JanusMail<string>, 'recoveryCodeUsed'> {\n\tconst { brand, links } = options;\n\treturn {\n\t\t// Async, so a wrong argument rejects as the other methods' do.\n\t\tasync recoveryCodeUsed(to, used) {\n\t\t\tconst locale = localeFor(options, to);\n\t\t\treturn send(options, METHOD, field(METHOD, to, 'email'), {\n\t\t\t\tbrand,\n\t\t\t\tname: field(METHOD, to, 'name'),\n\t\t\t\twhen: field(METHOD, used, 'when'),\n\t\t\t\trecoveryCodesLeft: codesLeft(used, locale),\n\t\t\t\tlink:\n\t\t\t\t\tlinks.recoveryCodes === undefined\n\t\t\t\t\t\t? link(METHOD, links.secureAccount(), 'secureAccount()')\n\t\t\t\t\t\t: link(METHOD, links.recoveryCodes(), 'recoveryCodes()'),\n\t\t\t\tlocale,\n\t\t\t});\n\t\t},\n\t};\n}\n",
18
18
  "/**\n * `janusMail()`: the e-mails of Janus's flows, rendered by the templates and\n * handed to the mailer. It sends what a flow answered, to the address the\n * flow answered, and nothing else: no retry, no queue, no error of its own —\n * the mailer's `MailFailure` and `MailRefused` reach the caller untouched.\n */\n\nimport { expiringMails } from './expiring-mails';\nimport { noticeMails } from './notice-mails';\nimport { resolveOptions } from './options';\nimport { recoveryMail } from './recovery-mail';\nimport type { JanusMail, JanusMailLocale, JanusMailOptions } from './types';\n\n/**\n * The e-mails of Janus's flows, over your mailer:\n *\n * ```ts\n * const mail = janusMail({\n * \tmailer,\n * \tfrom: 'noreply@acme.example',\n * \tbrand: 'Acme',\n * \tlinks: {\n * \t\tverifyEmail: (token) => `https://acme.example/verify?token=${token}`,\n * \t\tresetPassword: (token) => `https://acme.example/reset?token=${token}`,\n * \t\tsecureAccount: () => 'https://acme.example/account/security',\n * \t\tgetStarted: () => 'https://acme.example/',\n * \t\trecoveryCodes: () => 'https://acme.example/account/recovery-codes', // optional\n * \t},\n * });\n *\n * await mail.verifyEmail(await auth.verifyEmail.send(user), { name: user.name, locale: user.locale });\n * ```\n *\n * Reads nothing when called: the default e-mails are read on the first one\n * sent. A wrong option is a bare `TypeError`, thrown here.\n */\nexport function janusMail<const L extends string = JanusMailLocale>(\n\toptions: JanusMailOptions<L>,\n): JanusMail<L> {\n\tconst resolved = resolveOptions(options);\n\tconst mail: JanusMail<string> = Object.freeze({\n\t\t...expiringMails(resolved),\n\t\t...noticeMails(resolved),\n\t\t...recoveryMail(resolved),\n\t\ttemplates: resolved.templates,\n\t\tlocales: resolved.locales,\n\t});\n\t// The one cast at the boundary: the mirror above works on `string` locales.\n\treturn mail as unknown as JanusMail<L>;\n}\n"
19
19
  ],
20
- "mappings": "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",
21
- "debugId": "E470EFFF013B3B0B64756E2164756E21",
20
+ "mappings": "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",
21
+ "debugId": "45A006F2B09A6D7D64756E2164756E21",
22
22
  "names": []
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAa9C,iEAAiE;AACjE,wBAAgB,UAAU,CACzB,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB1C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAkBjE"}
1
+ {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAgB9C,iEAAiE;AACjE,wBAAgB,UAAU,CACzB,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB1C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAkBjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKlD,OAAO,KAAK,EACX,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,MAAM,SAAS,CAAC;AAEjB,+DAA+D;AAC/D,eAAO,MAAM,cAAc,EAAE,SAAS,qBAAqB,EAU1D,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACtB;AAiJD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAoBhE"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKlD,OAAO,KAAK,EACX,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,MAAM,SAAS,CAAC;AAEjB,+DAA+D;AAC/D,eAAO,MAAM,cAAc,EAAE,SAAS,qBAAqB,EAW1D,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACtB;AAiJD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAoBhE"}
@@ -33,6 +33,12 @@ export interface JanusMailVariables {
33
33
  readonly code: string;
34
34
  readonly expiresIn: string;
35
35
  };
36
+ /** No `name`: the e-mail greets nobody, as the sign-in code's does not. */
37
+ readonly magicLink: {
38
+ readonly brand: string;
39
+ readonly link: string;
40
+ readonly expiresIn: string;
41
+ };
36
42
  readonly passwordChanged: {
37
43
  readonly brand: string;
38
44
  readonly name: string;
@@ -74,7 +80,7 @@ export interface JanusMailVariables {
74
80
  readonly link: string;
75
81
  };
76
82
  }
77
- /** The name of one of the nine templates: `verifyEmail`, `resetPassword`, … */
83
+ /** The name of one of the ten templates: `verifyEmail`, `resetPassword`, … */
78
84
  export type JanusMailTemplateName = keyof JanusMailVariables;
79
85
  /**
80
86
  * One e-mail: its variables and the locale picked for the recipient, in; its
@@ -85,7 +91,7 @@ export type JanusMailTemplateName = keyof JanusMailVariables;
85
91
  export type JanusMailTemplate<V, L extends string = JanusMailLocale> = (variables: V & {
86
92
  readonly locale: L;
87
93
  }) => Rendered | PromiseLike<Rendered>;
88
- /** The nine templates, each for the locales `L`. */
94
+ /** The ten templates, each for the locales `L`. */
89
95
  export type JanusMailTemplates<L extends string = JanusMailLocale> = {
90
96
  readonly [K in JanusMailTemplateName]: JanusMailTemplate<JanusMailVariables[K], L>;
91
97
  };
@@ -1 +1 @@
1
- {"version":3,"file":"template-types.d.ts","sourceRoot":"","sources":["../src/template-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"template-types.d.ts","sourceRoot":"","sources":["../src/template-types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { JanusMailTemplates } from './types';
2
2
  /**
3
- * The nine default templates, in the locales they are built in. The
3
+ * The ten default templates, in the locales they are built in. The
4
4
  * renderer behind them is created on the first render, not here.
5
5
  *
6
6
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CA4DnD"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CAkEnD"}
package/dist/types.d.ts CHANGED
@@ -54,6 +54,15 @@ export interface JanusMailLinks {
54
54
  * the codes usually are.
55
55
  */
56
56
  readonly recoveryCodes?: () => string;
57
+ /**
58
+ * The page a sign-in link opens, given its one-time token —
59
+ * `magicLink` links to it. **Optional**, for an application that sends no
60
+ * sign-in link; without it, `magicLink` throws a `TypeError` before
61
+ * anything is rendered. That page spends nothing: its button posts the
62
+ * token to the route that calls `auth.magicLink.confirm`, so a mail
63
+ * scanner that opens the link does not sign in for the user.
64
+ */
65
+ readonly magicLink?: (token: string) => string;
57
66
  }
58
67
  /** The options every locale set shares. */
59
68
  interface JanusMailBaseOptions<L extends string> {
@@ -78,7 +87,7 @@ interface JanusMailBaseOptions<L extends string> {
78
87
  readonly clock?: Clock;
79
88
  }
80
89
  /**
81
- * What one send of `verifyEmail`, `resetPassword` or `signInCode` may pass
90
+ * What one send of `verifyEmail`, `resetPassword`, `signInCode` or `magicLink` may pass
82
91
  * besides the flow's answer and the recipient.
83
92
  */
84
93
  export interface JanusMailSendOptions {
@@ -120,6 +129,14 @@ export interface JanusMail<L extends string = JanusMailLocale> {
120
129
  * the e-mail.
121
130
  */
122
131
  signInCode(issued: Pick<IssuedCode<unknown>, 'code' | 'email' | 'expiresAt'>, to?: Pick<Recipient, 'locale'>, options?: JanusMailSendOptions): Promise<SentMail>;
132
+ /**
133
+ * The sign-in link `auth.magicLink.request(email)` answered, once checked
134
+ * for `null`, to `issued.email` — its button and its fallback link built
135
+ * by `links.magicLink(issued.token)`, saying how long it stays valid.
136
+ * Greets nobody by name, as a sign-in code does not. A `TypeError`, before
137
+ * anything is rendered, when `janusMail()` was given no `links.magicLink`.
138
+ */
139
+ magicLink(issued: IssuedToken, to?: Pick<Recipient, 'locale'>, options?: JanusMailSendOptions): Promise<SentMail>;
123
140
  /** Tells `to.email` their password was changed, with a link to secure the account. */
124
141
  passwordChanged(to: Recipient & {
125
142
  readonly email: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/docs/README.md CHANGED
@@ -23,11 +23,11 @@ They mean the same here. These pages add:
23
23
 
24
24
  | Word | Means | Not |
25
25
  | --- | --- | --- |
26
- | **e-mail** | One of the nine this package sends: `verify-email`, `reset-password`, `sign-in-code`, `password-changed`, `email-changed`, `two-factor-enabled`, `two-factor-disabled`, `recovery-code-used`, `welcome` — by the name of its built file | "mail", "message" — a *message* is what a mailer sends, addressed |
26
+ | **e-mail** | One of the ten this package sends: `verify-email`, `reset-password`, `sign-in-code`, `magic-link`, `password-changed`, `email-changed`, `two-factor-enabled`, `two-factor-disabled`, `recovery-code-used`, `welcome` — by the name of its built file | "mail", "message" — a *message* is what a mailer sends, addressed |
27
27
  | **template** | The function that renders one e-mail: `(variables & { locale }) => Rendered`. Named in camelCase, after the method that sends it: `verifyEmail`, `signInCode` | "renderer" — the renderer is `@nxgt/mail`'s, and reads the build |
28
28
  | **default template** | A template of `janusTemplates()`: the prebuilt e-mail, filled by the renderer | "preset" — a preset is `@nxgt/mail-presets`' source, which the build compiles |
29
29
  | **override** | A template of yours, passed in `templates`, used instead of the default | "custom template" |
30
- | **issued** | What a flow answered: an `IssuedToken` from `verifyEmail.send` or `resetPassword.request`, an `IssuedCode` from `signInCode.request` | "result", "payload" |
30
+ | **issued** | What a flow answered: an `IssuedToken` from `verifyEmail.send`, `resetPassword.request` or `magicLink.request`, an `IssuedCode` from `signInCode.request` | "result", "payload" |
31
31
  | **recipient** | Who an e-mail is for besides the address: a `Recipient`, `{ name, locale? }` | "user" — a user is a record of `@nxgt/janus`; "to" is the address |
32
32
  | **notice** | An e-mail that tells, and asks for nothing: `passwordChanged`, `emailChanged`, `twoFactorEnabled`, `twoFactorDisabled`, `recoveryCodeUsed`. It links to `links.secureAccount()` — `recoveryCodeUsed` to `links.recoveryCodes()` when given | "alert", "notification" |
33
33
  | **welcome** | The e-mail sent once a user was created, on `@nxgt/janus`'s `user.created`: `welcome`. It links to `links.getStarted()` — not a notice, since it warns of nothing | "onboarding", "greeting" |