@bumail/queue 0.8.0 → 0.10.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.
Files changed (73) hide show
  1. package/README.md +27 -1
  2. package/dist/chunks/index-r8wb840a.js +24 -0
  3. package/dist/chunks/index-r8wb840a.js.map +10 -0
  4. package/dist/chunks/{index-e5wa9f3j.js → index-sz13a17b.js} +103 -21
  5. package/dist/chunks/index-sz13a17b.js.map +14 -0
  6. package/dist/contract/checks.d.ts +2 -6
  7. package/dist/contract/checks.d.ts.map +1 -1
  8. package/dist/contract/dsn-checks.d.ts +4 -0
  9. package/dist/contract/dsn-checks.d.ts.map +1 -0
  10. package/dist/contract/dsn-column.d.ts +12 -0
  11. package/dist/contract/dsn-column.d.ts.map +1 -0
  12. package/dist/contract/storable.d.ts +7 -0
  13. package/dist/contract/storable.d.ts.map +1 -0
  14. package/dist/contract/types.d.ts +42 -0
  15. package/dist/contract/types.d.ts.map +1 -1
  16. package/dist/dsn/build.d.ts +2 -0
  17. package/dist/dsn/build.d.ts.map +1 -1
  18. package/dist/dsn/delivered.d.ts +25 -0
  19. package/dist/dsn/delivered.d.ts.map +1 -0
  20. package/dist/dsn/failed.d.ts +29 -0
  21. package/dist/dsn/failed.d.ts.map +1 -0
  22. package/dist/dsn/fields.d.ts +11 -2
  23. package/dist/dsn/fields.d.ts.map +1 -1
  24. package/dist/dsn/for.d.ts +26 -0
  25. package/dist/dsn/for.d.ts.map +1 -0
  26. package/dist/dsn/human.d.ts +7 -0
  27. package/dist/dsn/human.d.ts.map +1 -0
  28. package/dist/dsn/policy.d.ts +19 -0
  29. package/dist/dsn/policy.d.ts.map +1 -0
  30. package/dist/index.d.ts +4 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +404 -255
  33. package/dist/index.js.map +21 -16
  34. package/dist/memory/index.js +1 -1
  35. package/dist/postgres/index.js +17 -9
  36. package/dist/postgres/index.js.map +6 -6
  37. package/dist/postgres/rows.d.ts +6 -1
  38. package/dist/postgres/rows.d.ts.map +1 -1
  39. package/dist/postgres/schema.d.ts.map +1 -1
  40. package/dist/postgres/statements.d.ts +9 -8
  41. package/dist/postgres/statements.d.ts.map +1 -1
  42. package/dist/postgres/store.d.ts.map +1 -1
  43. package/dist/queue/envelope.d.ts +24 -4
  44. package/dist/queue/envelope.d.ts.map +1 -1
  45. package/dist/queue/events.d.ts +2 -1
  46. package/dist/queue/events.d.ts.map +1 -1
  47. package/dist/queue/notify.d.ts +6 -3
  48. package/dist/queue/notify.d.ts.map +1 -1
  49. package/dist/queue/outcome.d.ts.map +1 -1
  50. package/dist/queue/queue.d.ts.map +1 -1
  51. package/dist/queue/route.d.ts +7 -0
  52. package/dist/queue/route.d.ts.map +1 -1
  53. package/dist/queue/session.d.ts.map +1 -1
  54. package/dist/queue/settings/limits.d.ts.map +1 -1
  55. package/dist/queue/settle.d.ts.map +1 -1
  56. package/dist/redis/index.js +26 -13
  57. package/dist/redis/index.js.map +5 -5
  58. package/dist/redis/items.d.ts +2 -0
  59. package/dist/redis/items.d.ts.map +1 -1
  60. package/dist/redis/scripts.d.ts +1 -1
  61. package/dist/redis/scripts.d.ts.map +1 -1
  62. package/dist/redis/store.d.ts.map +1 -1
  63. package/dist/sqlite/index.js +15 -8
  64. package/dist/sqlite/index.js.map +5 -5
  65. package/dist/sqlite/rows.d.ts +2 -1
  66. package/dist/sqlite/rows.d.ts.map +1 -1
  67. package/dist/sqlite/schema.d.ts.map +1 -1
  68. package/dist/sqlite/store.d.ts.map +1 -1
  69. package/docs/guide.md +102 -3
  70. package/docs/roadmap.md +8 -3
  71. package/docs/troubleshooting.md +42 -0
  72. package/package.json +3 -3
  73. package/dist/chunks/index-e5wa9f3j.js.map +0 -12
package/README.md CHANGED
@@ -92,6 +92,30 @@ with the original's header fields; a recipient still deferred after
92
92
  `delayAfter` gets one "delayed" warning. A DSN is enqueued from the null
93
93
  sender `<>`, and a message from `<>` never causes one.
94
94
 
95
+ The envelope can carry the sender's DSN parameters (RFC 3461), which the
96
+ SMTP server hands over as they are and the queue passes on to the next
97
+ hop:
98
+
99
+ ```ts
100
+ await queue.enqueue(message, {
101
+ from: 'mary@example.net',
102
+ to: ['joe@example.com'],
103
+ ret: 'HDRS', // what a DSN returns: the headers only (FULL: the whole message)
104
+ envid: 'QQ314159', // echoed as Original-Envelope-Id
105
+ recipients: [
106
+ { address: 'joe@example.com', notify: ['SUCCESS', 'FAILURE'], orcpt: { type: 'rfc822', address: 'joe@old.example.org' } },
107
+ ],
108
+ });
109
+ ```
110
+
111
+ `notify: 'NEVER'` sends no DSN; absent, failure and delay as always; a
112
+ list, only those events. Upgrading a shared store: stop every old worker
113
+ before starting a new one (an old worker that keeps running ignores the
114
+ DSN parameters and drops them from the items it completes). `SUCCESS` with a next hop that does not offer DSN
115
+ sends a `relayed` DSN. For a message the application delivered itself,
116
+ `deliveredDsn()` writes the `delivered` one, and `failedDsn()` the `failed`
117
+ one for a recipient it could not deliver.
118
+
95
119
  ## Routing
96
120
 
97
121
  ```ts
@@ -296,7 +320,9 @@ control character in it.
296
320
  | --- | --- |
297
321
  | `createQueue(options)`, `Queue` | the queue: `enqueue`, `deliverDue`, `start`, `stop`, `on`, `list`, `get`, `retryNow`, `cancel`, `owner` |
298
322
  | `QueueOptions` (`route`, `routes`, `fallback`), `Route`, `Smarthost`, `RetrySchedule`, `DsnOptions`, `QueueLimits`, `Clock`, `Sender` | what `createQueue` takes |
299
- | `MessageSource`, `QueueEnvelope` | what `enqueue` takes |
323
+ | `MessageSource`, `QueueEnvelope` (`ret`, `envid`, `recipients`), `RecipientDsn`, `RecipientNotify`, `NotifyEvent`, `OriginalRecipient`, `RetMode` | what `enqueue` takes, with the DSN parameters |
324
+ | `deliveredDsn(input)`, `DeliveredDsnInput`, `DeliveredRecipient` | the `delivered` DSN for a local delivery: the bytes to enqueue, or `undefined` when no recipient asked for `SUCCESS` |
325
+ | `failedDsn(input)`, `FailedDsnInput`, `FailedRecipient`, `DEFAULT_MAX_RETURN` | the `failed` DSN for a recipient the application could not deliver locally: the bytes to enqueue, or `undefined` for a null reverse-path or when no recipient asked for failures; `DEFAULT_MAX_RETURN` is the 64 KiB a DSN returns of the original by default |
300
326
  | `QueueEvents`, `QueueListener`, `RecipientEvent` (`route`, `fallback`, `mxReply`, `mayHaveReachedMx`, `mayHaveReachedFallback`), `DeferredEvent`, `DsnEvent`, `QueueErrorEvent` | the events |
301
327
  | `QueueStore` | the contract a store answers: `add`, `get`, `list`, `count`, `readMessage`, `claim`, `renew`, `complete`, `reschedule`, `cancel` |
302
328
  | `QueueItem`, `RecipientState`, `RecipientStatus`, `FinalStatus`, `Diagnostic`, `Lease` | an item, and where each recipient stands |
@@ -0,0 +1,24 @@
1
+ // src/contract/dsn-column.ts
2
+ function dsnColumn(item) {
3
+ if (item.ret === undefined && item.envid === undefined)
4
+ return null;
5
+ const params = {
6
+ ...item.ret === undefined ? {} : { ret: item.ret },
7
+ ...item.envid === undefined ? {} : { envid: item.envid }
8
+ };
9
+ return JSON.stringify(params);
10
+ }
11
+ function dsnParams(column) {
12
+ if (column === null || column === undefined)
13
+ return {};
14
+ const params = typeof column === "string" ? JSON.parse(column) : column;
15
+ return {
16
+ ...params.ret === undefined ? {} : { ret: params.ret },
17
+ ...params.envid === undefined ? {} : { envid: params.envid }
18
+ };
19
+ }
20
+
21
+ export { dsnColumn, dsnParams };
22
+
23
+ //# debugId=4C4AEC4A6A58C66564756E2164756E21
24
+ //# sourceMappingURL=index-r8wb840a.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/contract/dsn-column.ts"],
4
+ "sourcesContent": [
5
+ "import type { QueueItem, RetMode } from './types';\n\n/** The item-level DSN parameters, as the SQL stores keep them in one JSON column. */\ninterface Params {\n\tret?: RetMode;\n\tenvid?: string;\n}\n\n/** The column's JSON text, or `null` when the item has no `RET` and no `ENVID`. */\nexport function dsnColumn(\n\titem: Pick<QueueItem, 'ret' | 'envid'>,\n): string | null {\n\tif (item.ret === undefined && item.envid === undefined) return null;\n\tconst params: Params = {\n\t\t...(item.ret === undefined ? {} : { ret: item.ret }),\n\t\t...(item.envid === undefined ? {} : { envid: item.envid }),\n\t};\n\treturn JSON.stringify(params);\n}\n\n/** `ret` and `envid` from the column: nothing for a row written before the column existed (`null`). */\nexport function dsnParams(\n\tcolumn: string | Params | null | undefined,\n): Pick<QueueItem, 'ret' | 'envid'> {\n\tif (column === null || column === undefined) return {};\n\tconst params: Params =\n\t\ttypeof column === 'string' ? (JSON.parse(column) as Params) : column;\n\treturn {\n\t\t...(params.ret === undefined ? {} : { ret: params.ret }),\n\t\t...(params.envid === undefined ? {} : { envid: params.envid }),\n\t};\n}\n"
6
+ ],
7
+ "mappings": ";AASO,SAAS,SAAS,CACxB,MACgB;AAAA,EAChB,IAAI,KAAK,QAAQ,aAAa,KAAK,UAAU;AAAA,IAAW,OAAO;AAAA,EAC/D,MAAM,SAAiB;AAAA,OAClB,KAAK,QAAQ,YAAY,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI;AAAA,OAC9C,KAAK,UAAU,YAAY,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM;AAAA,EACzD;AAAA,EACA,OAAO,KAAK,UAAU,MAAM;AAAA;AAItB,SAAS,SAAS,CACxB,QACmC;AAAA,EACnC,IAAI,WAAW,QAAQ,WAAW;AAAA,IAAW,OAAO,CAAC;AAAA,EACrD,MAAM,SACL,OAAO,WAAW,WAAY,KAAK,MAAM,MAAM,IAAe;AAAA,EAC/D,OAAO;AAAA,OACF,OAAO,QAAQ,YAAY,CAAC,IAAI,EAAE,KAAK,OAAO,IAAI;AAAA,OAClD,OAAO,UAAU,YAAY,CAAC,IAAI,EAAE,OAAO,OAAO,MAAM;AAAA,EAC7D;AAAA;",
8
+ "debugId": "4C4AEC4A6A58C66564756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,14 +1,3 @@
1
- // src/errors.ts
2
- class QueueError2 extends Error {
3
- name = "QueueError";
4
- code;
5
- constructor(code, message) {
6
- super(message);
7
- this.code = code;
8
- }
9
- }
10
- var invalid = (message) => new QueueError2("INVALID", message);
11
-
12
1
  // src/text.ts
13
2
  var isControl = (code) => code < 32 || code >= 127 && code <= 159;
14
3
  function hasControl(text) {
@@ -37,6 +26,90 @@ function cut(text, length) {
37
26
  var isStorable = (text) => text.isWellFormed() && !text.includes("\x00");
38
27
  var asciiText = (text, max) => cleanText(text, max).replace(/[^ -~]/g, "?");
39
28
 
29
+ // src/errors.ts
30
+ class QueueError2 extends Error {
31
+ name = "QueueError";
32
+ code;
33
+ constructor(code, message) {
34
+ super(message);
35
+ this.code = code;
36
+ }
37
+ }
38
+ var invalid = (message) => new QueueError2("INVALID", message);
39
+
40
+ // src/contract/storable.ts
41
+ function checkStorable(name, text) {
42
+ if (!isStorable(text)) {
43
+ throw invalid(`${name} holds a NUL or a lone surrogate, which a store cannot keep`);
44
+ }
45
+ }
46
+
47
+ // src/contract/dsn-checks.ts
48
+ var EVENTS = ["SUCCESS", "FAILURE", "DELAY"];
49
+ function xtextLength(text) {
50
+ let length = 0;
51
+ for (const byte of new TextEncoder().encode(text)) {
52
+ length += byte >= 33 && byte <= 126 && byte !== 43 && byte !== 61 ? 1 : 3;
53
+ }
54
+ return length;
55
+ }
56
+ function utf8OrcptLength(text) {
57
+ let length = 0;
58
+ for (const char of text) {
59
+ const code = char.codePointAt(0);
60
+ if (code > 127)
61
+ length += new TextEncoder().encode(char).length;
62
+ else
63
+ length += code >= 33 && code !== 92 && code !== 43 && code !== 61 && code < 127 ? 1 : 6;
64
+ }
65
+ return length;
66
+ }
67
+ function checkRecipientDsn(entry, to) {
68
+ const { address, notify, orcpt } = entry ?? {};
69
+ if (typeof address !== "string" || !to.includes(address)) {
70
+ throw invalid(`recipients names ${JSON.stringify(address)}, which is not in to`);
71
+ }
72
+ if (notify !== undefined && notify !== "NEVER") {
73
+ const events = Array.isArray(notify) ? notify : [];
74
+ if (events.length === 0 || events.some((e, i) => !EVENTS.includes(e) || events.indexOf(e) !== i)) {
75
+ throw invalid(`notify of ${address} must be 'NEVER' or a list of 'SUCCESS', 'FAILURE', 'DELAY', each once`);
76
+ }
77
+ }
78
+ if (orcpt === undefined)
79
+ return;
80
+ if (typeof orcpt !== "object" || orcpt === null || typeof orcpt.type !== "string" || !/^[A-Za-z0-9-]+$/.test(orcpt.type) || typeof orcpt.address !== "string" || orcpt.address === "") {
81
+ throw invalid(`orcpt of ${address} must be { type, address }`);
82
+ }
83
+ const encoded = orcpt.type.toLowerCase() === "utf-8" ? utf8OrcptLength(orcpt.address) : xtextLength(orcpt.address);
84
+ if (orcpt.type.length + 1 + encoded > 500) {
85
+ throw invalid(`orcpt of ${address} is over 500 characters once encoded`);
86
+ }
87
+ checkStorable("orcpt.type", orcpt.type);
88
+ checkStorable("orcpt.address", orcpt.address);
89
+ }
90
+ function checkDsnParams(item) {
91
+ const { ret, envid, recipients } = item;
92
+ if (ret !== undefined && ret !== "FULL" && ret !== "HDRS") {
93
+ throw invalid(`ret must be 'FULL' or 'HDRS', not ${String(ret)}`);
94
+ }
95
+ if (envid !== undefined && (typeof envid !== "string" || !/^[ -~]{1,100}$/.test(envid) || xtextLength(envid) > 100)) {
96
+ throw invalid("envid must be 1 to 100 printable ASCII characters, at most 100 once encoded as xtext");
97
+ }
98
+ if (recipients === undefined)
99
+ return;
100
+ if (!Array.isArray(recipients)) {
101
+ throw invalid("recipients must be an array of { address, notify, orcpt }");
102
+ }
103
+ const seen = new Set;
104
+ for (const entry of recipients) {
105
+ checkRecipientDsn(entry, item.to);
106
+ if (seen.has(entry.address)) {
107
+ throw invalid(`recipients names ${entry.address} twice`);
108
+ }
109
+ seen.add(entry.address);
110
+ }
111
+ }
112
+
40
113
  // src/contract/checks.ts
41
114
  var isTime = (value) => typeof value === "number" && Number.isFinite(value);
42
115
  function checkTime(name, value) {
@@ -44,11 +117,6 @@ function checkTime(name, value) {
44
117
  throw invalid(`${name} must be a finite number`);
45
118
  return value;
46
119
  }
47
- function checkStorable(name, text) {
48
- if (!isStorable(text)) {
49
- throw invalid(`${name} holds a NUL or a lone surrogate, which a store cannot keep`);
50
- }
51
- }
52
120
  function checkOwner(owner) {
53
121
  if (typeof owner !== "string" || owner === "") {
54
122
  throw invalid("owner must be a non-empty string");
@@ -97,6 +165,7 @@ function checkNewItem(item) {
97
165
  throw invalid("message must be a Uint8Array");
98
166
  }
99
167
  checkTime("createdAt", item.createdAt);
168
+ checkDsnParams(item);
100
169
  }
101
170
  function checkMaxItems(max) {
102
171
  if (max === undefined)
@@ -156,6 +225,8 @@ function applyAttempt(item, result) {
156
225
  return {
157
226
  address: r.address,
158
227
  status: update.status,
228
+ ...r.notify === undefined ? {} : { notify: r.notify },
229
+ ...r.orcpt === undefined ? {} : { orcpt: r.orcpt },
159
230
  ...update.reply ? { reply: update.reply } : {},
160
231
  updatedAt: result.now,
161
232
  ...r.mayHaveReachedMx || update.mayHaveReachedMx ? { mayHaveReachedMx: true } : {},
@@ -172,20 +243,31 @@ function applyAttempt(item, result) {
172
243
  };
173
244
  }
174
245
  function newItem(id, item) {
246
+ const dsn = new Map(item.recipients?.map((r) => [r.address, r]));
175
247
  return {
176
248
  id,
177
249
  from: item.from,
178
- recipients: item.to.map((address) => ({ address, status: "pending" })),
250
+ recipients: item.to.map((address) => {
251
+ const { notify, orcpt } = dsn.get(address) ?? {};
252
+ return {
253
+ address,
254
+ status: "pending",
255
+ ...notify === undefined ? {} : { notify: notify === "NEVER" ? notify : [...notify] },
256
+ ...orcpt === undefined ? {} : { orcpt: { type: orcpt.type, address: orcpt.address } }
257
+ };
258
+ }),
179
259
  size: item.message.length,
180
260
  createdAt: item.createdAt,
181
261
  nextAttemptAt: item.createdAt,
182
262
  attempts: 0,
183
- delayNotified: false
263
+ delayNotified: false,
264
+ ...item.ret === undefined ? {} : { ret: item.ret },
265
+ ...item.envid === undefined ? {} : { envid: item.envid }
184
266
  };
185
267
  }
186
268
  var claimable = (item, now) => item.nextAttemptAt <= now && (item.lease === undefined || item.lease.expiresAt <= now);
187
269
 
188
- export { QueueError2, invalid, hasControl, replaceControls, cleanText, isStorable, asciiText, checkTime, checkOwner, checkNewItem, checkMaxItems, checkClaim, checkResult, checkList, isDone, applyAttempt, newItem, claimable };
270
+ export { hasControl, replaceControls, cleanText, isStorable, asciiText, QueueError2, invalid, checkTime, checkOwner, checkNewItem, checkMaxItems, checkClaim, checkResult, checkList, isDone, applyAttempt, newItem, claimable };
189
271
 
190
- //# debugId=16AF1EB72729D01E64756E2164756E21
191
- //# sourceMappingURL=index-e5wa9f3j.js.map
272
+ //# debugId=6F0F13A4EBC138E164756E2164756E21
273
+ //# sourceMappingURL=index-sz13a17b.js.map
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/text.ts", "../src/errors.ts", "../src/contract/storable.ts", "../src/contract/dsn-checks.ts", "../src/contract/checks.ts"],
4
+ "sourcesContent": [
5
+ "/** Text from the other side, made safe to keep and to write in a header field. */\n\n/** C0, DEL and C1: every control character, CR, LF and TAB included. */\nconst isControl = (code: number) =>\n\tcode < 0x20 || (code >= 0x7f && code <= 0x9f);\n\n/** Whether the text holds a control character. */\nexport function hasControl(text: string): boolean {\n\tfor (let i = 0; i < text.length; i++) {\n\t\tif (isControl(text.charCodeAt(i))) return true;\n\t}\n\treturn false;\n}\n\n/** Each control character replaced by `by`. */\nexport function replaceControls(text: string, by: string): string {\n\tlet out = '';\n\tfor (let i = 0; i < text.length; i++) {\n\t\tout += isControl(text.charCodeAt(i)) ? by : (text[i] as string);\n\t}\n\treturn out;\n}\n\n/**\n * Every control character (CR and LF included) as a space, a lone\n * surrogate as U+FFFD, runs of space as one, cut at `max` characters with\n * `...`, never inside a surrogate pair: what a reply leaves in an item,\n * an event and a DSN.\n */\nexport function cleanText(text: string, max: number): string {\n\tconst clean = replaceControls(text.toWellFormed(), ' ')\n\t\t.replace(/ {2,}/g, ' ')\n\t\t.trim();\n\treturn clean.length > max ? `${cut(clean, max - 3)}...` : clean;\n}\n\n/**\n * The first `length` UTF-16 units, never ending inside a surrogate pair:\n * a lone surrogate is text no store can keep (PostgreSQL's `jsonb` refuses\n * it), nor any UTF-8 encode.\n */\nfunction cut(text: string, length: number): string {\n\tconst head = text.slice(0, length);\n\tconst last = head.charCodeAt(head.length - 1);\n\treturn last >= 0xd800 && last <= 0xdbff ? head.slice(0, -1) : head;\n}\n\n/**\n * Text every store can keep: no NUL (PostgreSQL's `text` and `jsonb` hold\n * none) and no lone surrogate. `cleanText`'s output always is.\n */\nexport const isStorable = (text: string): boolean =>\n\ttext.isWellFormed() && !text.includes('\\0');\n\n/** `cleanText`, then anything not printable ASCII as `?`: for a `message/delivery-status` field. */\nexport const asciiText = (text: string, max: number): string =>\n\tcleanText(text, max).replace(/[^ -~]/g, '?');\n",
6
+ "/**\n * Why the queue or a store refused a call. `INVALID`: an option or an\n * argument it cannot take. `MESSAGE_TOO_BIG`, `TOO_MANY_RECIPIENTS` and\n * `QUEUE_FULL`: a limit `enqueue` enforces. `CLOSED`: a store used after\n * `close()`. `LEASE_LOST`: given to the `error` event when another worker\n * took an item before its outcome was recorded — or, once the lease's\n * expiry passed, when the item is gone: lost or cancelled.\n * `MESSAGE_UNREADABLE`: given to the `error` event when the store holds an\n * item but not its message, whose pending recipients then fail.\n */\nexport type QueueErrorCode =\n\t| 'INVALID'\n\t| 'MESSAGE_TOO_BIG'\n\t| 'TOO_MANY_RECIPIENTS'\n\t| 'QUEUE_FULL'\n\t| 'CLOSED'\n\t| 'LEASE_LOST'\n\t| 'MESSAGE_UNREADABLE';\n\n/** Thrown by the queue and by every store, whichever answers the contract, with the same codes. */\nexport class QueueError extends Error {\n\toverride readonly name = 'QueueError';\n\treadonly code: QueueErrorCode;\n\n\tconstructor(code: QueueErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.code = code;\n\t}\n}\n\n/** `INVALID`, for an option or an argument. */\nexport const invalid = (message: string) => new QueueError('INVALID', message);\n",
7
+ "import { invalid } from '../errors';\nimport { isStorable } from '../text';\n\n/**\n * Text a store keeps: refused, the same way by every store, when it holds\n * a NUL or a lone surrogate, which PostgreSQL cannot keep and no UTF-8\n * encode can carry.\n */\nexport function checkStorable(name: string, text: string): void {\n\tif (!isStorable(text)) {\n\t\tthrow invalid(\n\t\t\t`${name} holds a NUL or a lone surrogate, which a store cannot keep`,\n\t\t);\n\t}\n}\n",
8
+ "// The value rules (and utf8OrcptLength, RFC 6533) repeat packages/smtp/src/server/dsn-params.ts, packages/smtp/src/client/dsn.ts and\n// packages/jmap/src/submission/dsn.ts (AGENTS.md, Deliberate duplications); this copy guards the contract.\nimport { invalid } from '../errors';\nimport { checkStorable } from './storable';\nimport type { NewQueueItem, RecipientDsn } from './types';\n\nconst EVENTS: readonly unknown[] = ['SUCCESS', 'FAILURE', 'DELAY'];\n\n/**\n * The length the xtext of `text` takes on the wire (RFC 3461 §4): one\n * character for each byte of its UTF-8 form in `!` to `~` but `+` and `=`,\n * three for any other.\n */\nfunction xtextLength(text: string): number {\n\tlet length = 0;\n\tfor (const byte of new TextEncoder().encode(text)) {\n\t\tlength +=\n\t\t\tbyte >= 33 && byte <= 126 && byte !== 0x2b && byte !== 0x3d ? 1 : 3;\n\t}\n\treturn length;\n}\n\n/**\n * The length of a `utf-8` ORCPT address in its `utf-8-addr-unitext` form (RFC\n * 6533 §3), the shortest one: raw UTF-8 octets for a non-ASCII character, one\n * for printable ASCII but `\\`, `+` and `=`, and `\\x{HH}` (6) for the rest.\n * The SMTP server counts the value as sent, which is this for a unitext one.\n */\nfunction utf8OrcptLength(text: string): number {\n\tlet length = 0;\n\tfor (const char of text) {\n\t\tconst code = char.codePointAt(0) as number;\n\t\tif (code > 0x7f) length += new TextEncoder().encode(char).length;\n\t\telse\n\t\t\tlength +=\n\t\t\t\tcode >= 0x21 &&\n\t\t\t\tcode !== 0x5c &&\n\t\t\t\tcode !== 0x2b &&\n\t\t\t\tcode !== 0x3d &&\n\t\t\t\tcode < 0x7f\n\t\t\t\t\t? 1\n\t\t\t\t\t: 6;\n\t}\n\treturn length;\n}\n\n/** One recipient's `NOTIFY` (RFC 3461 §4.1) and `ORCPT` (§4.2). */\nfunction checkRecipientDsn(entry: RecipientDsn, to: readonly string[]): void {\n\tconst { address, notify, orcpt } = entry ?? {};\n\tif (typeof address !== 'string' || !to.includes(address)) {\n\t\tthrow invalid(\n\t\t\t`recipients names ${JSON.stringify(address)}, which is not in to`,\n\t\t);\n\t}\n\tif (notify !== undefined && notify !== 'NEVER') {\n\t\tconst events: readonly unknown[] = Array.isArray(notify) ? notify : [];\n\t\tif (\n\t\t\tevents.length === 0 ||\n\t\t\tevents.some((e, i) => !EVENTS.includes(e) || events.indexOf(e) !== i)\n\t\t) {\n\t\t\tthrow invalid(\n\t\t\t\t`notify of ${address} must be 'NEVER' or a list of 'SUCCESS', 'FAILURE', 'DELAY', each once`,\n\t\t\t);\n\t\t}\n\t}\n\tif (orcpt === undefined) return;\n\tif (\n\t\ttypeof orcpt !== 'object' ||\n\t\torcpt === null ||\n\t\ttypeof orcpt.type !== 'string' ||\n\t\t!/^[A-Za-z0-9-]+$/.test(orcpt.type) ||\n\t\ttypeof orcpt.address !== 'string' ||\n\t\torcpt.address === ''\n\t) {\n\t\tthrow invalid(`orcpt of ${address} must be { type, address }`);\n\t}\n\t// RFC 3461 §4.2: \"The entire ORCPT parameter MAY be up to 500 characters in length\", as sent.\n\tconst encoded =\n\t\torcpt.type.toLowerCase() === 'utf-8'\n\t\t\t? utf8OrcptLength(orcpt.address)\n\t\t\t: xtextLength(orcpt.address);\n\tif (orcpt.type.length + 1 + encoded > 500) {\n\t\tthrow invalid(`orcpt of ${address} is over 500 characters once encoded`);\n\t}\n\tcheckStorable('orcpt.type', orcpt.type);\n\tcheckStorable('orcpt.address', orcpt.address);\n}\n\n/** `ret`, `envid` and `recipients` of a new item. */\nexport function checkDsnParams(item: NewQueueItem): void {\n\tconst { ret, envid, recipients } = item;\n\tif (ret !== undefined && ret !== 'FULL' && ret !== 'HDRS') {\n\t\tthrow invalid(`ret must be 'FULL' or 'HDRS', not ${String(ret)}`);\n\t}\n\tif (\n\t\tenvid !== undefined &&\n\t\t(typeof envid !== 'string' ||\n\t\t\t!/^[ -~]{1,100}$/.test(envid) ||\n\t\t\t// RFC 3461 §4.4: \"The ENVID parameter MAY be up to 100 characters in length\", as sent.\n\t\t\txtextLength(envid) > 100)\n\t) {\n\t\tthrow invalid(\n\t\t\t'envid must be 1 to 100 printable ASCII characters, at most 100 once encoded as xtext',\n\t\t);\n\t}\n\tif (recipients === undefined) return;\n\tif (!Array.isArray(recipients)) {\n\t\tthrow invalid('recipients must be an array of { address, notify, orcpt }');\n\t}\n\tconst seen = new Set<string>();\n\tfor (const entry of recipients) {\n\t\tcheckRecipientDsn(entry, item.to);\n\t\tif (seen.has(entry.address)) {\n\t\t\tthrow invalid(`recipients names ${entry.address} twice`);\n\t\t}\n\t\tseen.add(entry.address);\n\t}\n}\n",
9
+ "import { invalid } from '../errors';\nimport { checkDsnParams } from './dsn-checks';\nimport { checkStorable } from './storable';\n\nexport { checkStorable };\n\nimport type {\n\tAttemptResult,\n\tClaimRequest,\n\tDiagnostic,\n\tNewQueueItem,\n\tQueueItem,\n\tQueueListOptions,\n\tRecipientState,\n\tRecipientUpdate,\n} from './types';\n\n/** What every store checks the same way, so each refuses the same input with the same error. */\n\nconst isTime = (value: unknown): value is number =>\n\ttypeof value === 'number' && Number.isFinite(value);\n\n/** A time in milliseconds since the epoch, or `INVALID` naming it. */\nexport function checkTime(name: string, value: unknown): number {\n\tif (!isTime(value)) throw invalid(`${name} must be a finite number`);\n\treturn value;\n}\n\n/** A lease owner: a non-empty string. */\nexport function checkOwner(owner: unknown): string {\n\tif (typeof owner !== 'string' || owner === '') {\n\t\tthrow invalid('owner must be a non-empty string');\n\t}\n\tcheckStorable('owner', owner);\n\treturn owner;\n}\n\n/** Every text of a recipient's outcome. */\nfunction checkUpdate(update: RecipientUpdate): void {\n\tcheckStorable('A recipient', update.address);\n\tfor (const key of ['mayHaveReachedMx', 'mayHaveReachedFallback'] as const) {\n\t\tconst mark = update[key] as unknown;\n\t\tif (mark !== undefined && mark !== true) {\n\t\t\tthrow invalid(`${key} must be true or absent`);\n\t\t}\n\t}\n\tconst reply = update.reply as Partial<Diagnostic> | undefined;\n\tif (reply === undefined) return;\n\tif (\n\t\ttypeof reply !== 'object' ||\n\t\treply === null ||\n\t\ttypeof reply.text !== 'string'\n\t) {\n\t\tthrow invalid('A reply is an object with a text');\n\t}\n\tcheckStorable('reply.text', reply.text);\n\tfor (const name of ['status', 'host'] as const) {\n\t\tconst value = reply[name];\n\t\tif (value === undefined) continue;\n\t\tif (typeof value !== 'string')\n\t\t\tthrow invalid(`reply.${name} must be a string`);\n\t\tcheckStorable(`reply.${name}`, value);\n\t}\n}\n\nexport function checkNewItem(item: NewQueueItem): void {\n\tif (typeof item !== 'object' || item === null) {\n\t\tthrow invalid('A new item is an object');\n\t}\n\tif (typeof item.from !== 'string') throw invalid('from must be a string');\n\tcheckStorable('from', item.from);\n\tconst to = item.to as unknown;\n\tif (\n\t\t!Array.isArray(to) ||\n\t\tto.length === 0 ||\n\t\t!to.every((a) => typeof a === 'string' && a !== '')\n\t) {\n\t\tthrow invalid('to must be a non-empty array of addresses');\n\t}\n\tfor (const address of to as string[]) checkStorable('A recipient', address);\n\tif (!(item.message instanceof Uint8Array)) {\n\t\tthrow invalid('message must be a Uint8Array');\n\t}\n\tcheckTime('createdAt', item.createdAt);\n\tcheckDsnParams(item);\n}\n\n/** `maxItems`: a positive integer, or nothing. */\nexport function checkMaxItems(max: unknown): number | undefined {\n\tif (max === undefined) return undefined;\n\tif (typeof max !== 'number' || !Number.isInteger(max) || max < 1) {\n\t\tthrow invalid(`maxItems must be an integer of at least 1, not ${max}`);\n\t}\n\treturn max;\n}\n\nexport function checkClaim(request: ClaimRequest): void {\n\tif (typeof request !== 'object' || request === null) {\n\t\tthrow invalid('A claim is an object');\n\t}\n\tcheckOwner(request.owner);\n\tcheckTime('now', request.now);\n\tif (!isTime(request.leaseMs) || request.leaseMs <= 0) {\n\t\tthrow invalid('leaseMs must be a positive number');\n\t}\n}\n\nexport function checkResult(result: AttemptResult): void {\n\tif (typeof result !== 'object' || result === null) {\n\t\tthrow invalid('An attempt result is an object');\n\t}\n\tcheckTime('now', result.now);\n\tcheckTime('nextAttemptAt', result.nextAttemptAt);\n\tif (!Number.isInteger(result.attempts) || result.attempts < 0) {\n\t\tthrow invalid('attempts must be an integer of at least 0');\n\t}\n\tif (typeof result.delayNotified !== 'boolean') {\n\t\tthrow invalid('delayNotified must be true or false');\n\t}\n\tconst statuses = ['delivered', 'deferred', 'failed'];\n\tif (\n\t\t!Array.isArray(result.recipients) ||\n\t\t!result.recipients.every(\n\t\t\t(u) => typeof u?.address === 'string' && statuses.includes(u.status),\n\t\t)\n\t) {\n\t\tthrow invalid(\n\t\t\t'recipients must be an array of { address, status: delivered, deferred or failed }',\n\t\t);\n\t}\n\tfor (const update of result.recipients) checkUpdate(update);\n}\n\n/** The offset and limit of a list: integers, the limit 1 to 1000. */\nexport function checkList(options: QueueListOptions = {}): {\n\toffset: number;\n\tlimit: number;\n} {\n\tconst offset = options.offset ?? 0;\n\tconst limit = options.limit ?? 100;\n\tif (!Number.isInteger(offset) || offset < 0) {\n\t\tthrow invalid(`offset must be an integer of at least 0, not ${offset}`);\n\t}\n\tif (!Number.isInteger(limit) || limit < 1 || limit > 1000) {\n\t\tthrow invalid(`limit must be an integer from 1 to 1000, not ${limit}`);\n\t}\n\treturn { offset, limit };\n}\n\n/** Every recipient is `delivered` or `failed`. */\nexport const isDone = (item: Pick<QueueItem, 'recipients'>): boolean =>\n\titem.recipients.every(\n\t\t(r) => r.status === 'delivered' || r.status === 'failed',\n\t);\n\n/**\n * The item once an attempt is recorded: its recipients' outcomes, a final\n * state never changed again, the schedule, and no lease.\n */\nexport function applyAttempt(\n\titem: QueueItem,\n\tresult: AttemptResult,\n): QueueItem {\n\tconst updates = new Map(result.recipients.map((u) => [u.address, u]));\n\tconst recipients = item.recipients.map((r): RecipientState => {\n\t\tconst update = updates.get(r.address);\n\t\tif (!update || r.status === 'delivered' || r.status === 'failed') return r;\n\t\treturn {\n\t\t\taddress: r.address,\n\t\t\tstatus: update.status,\n\t\t\t...(r.notify === undefined ? {} : { notify: r.notify }),\n\t\t\t...(r.orcpt === undefined ? {} : { orcpt: r.orcpt }),\n\t\t\t...(update.reply ? { reply: update.reply } : {}),\n\t\t\tupdatedAt: result.now,\n\t\t\t...(r.mayHaveReachedMx || update.mayHaveReachedMx\n\t\t\t\t? { mayHaveReachedMx: true as const }\n\t\t\t\t: {}),\n\t\t\t...(r.mayHaveReachedFallback || update.mayHaveReachedFallback\n\t\t\t\t? { mayHaveReachedFallback: true as const }\n\t\t\t\t: {}),\n\t\t};\n\t});\n\tconst { lease: _, ...rest } = item;\n\treturn {\n\t\t...rest,\n\t\trecipients,\n\t\tnextAttemptAt: result.nextAttemptAt,\n\t\tattempts: result.attempts,\n\t\tdelayNotified: result.delayNotified,\n\t};\n}\n\n/** A new item as a store first keeps it. */\nexport function newItem(id: string, item: NewQueueItem): QueueItem {\n\tconst dsn = new Map(item.recipients?.map((r) => [r.address, r]));\n\treturn {\n\t\tid,\n\t\tfrom: item.from,\n\t\trecipients: item.to.map((address): RecipientState => {\n\t\t\tconst { notify, orcpt } = dsn.get(address) ?? {};\n\t\t\treturn {\n\t\t\t\taddress,\n\t\t\t\tstatus: 'pending',\n\t\t\t\t...(notify === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { notify: notify === 'NEVER' ? notify : [...notify] }),\n\t\t\t\t...(orcpt === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { orcpt: { type: orcpt.type, address: orcpt.address } }),\n\t\t\t};\n\t\t}),\n\t\tsize: item.message.length,\n\t\tcreatedAt: item.createdAt,\n\t\tnextAttemptAt: item.createdAt,\n\t\tattempts: 0,\n\t\tdelayNotified: false,\n\t\t...(item.ret === undefined ? {} : { ret: item.ret }),\n\t\t...(item.envid === undefined ? {} : { envid: item.envid }),\n\t};\n}\n\n/** Whether a lease, if any, leaves the item free to claim at `now`. */\nexport const claimable = (item: QueueItem, now: number): boolean =>\n\titem.nextAttemptAt <= now &&\n\t(item.lease === undefined || item.lease.expiresAt <= now);\n"
10
+ ],
11
+ "mappings": "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",
12
+ "debugId": "6F0F13A4EBC138E164756E2164756E21",
13
+ "names": []
14
+ }
@@ -1,12 +1,8 @@
1
+ import { checkStorable } from './storable';
2
+ export { checkStorable };
1
3
  import type { AttemptResult, ClaimRequest, NewQueueItem, QueueItem, QueueListOptions } from './types';
2
4
  /** A time in milliseconds since the epoch, or `INVALID` naming it. */
3
5
  export declare function checkTime(name: string, value: unknown): number;
4
- /**
5
- * Text a store keeps: refused, the same way by every store, when it holds
6
- * a NUL or a lone surrogate, which PostgreSQL cannot keep and no UTF-8
7
- * encode can carry.
8
- */
9
- export declare function checkStorable(name: string, text: string): void;
10
6
  /** A lease owner: a non-empty string. */
11
7
  export declare function checkOwner(owner: unknown): string;
12
8
  export declare function checkNewItem(item: NewQueueItem): void;
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/contract/checks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAGhB,MAAM,SAAS,CAAC;AAOjB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAG9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM9D;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMjD;AA8BD,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAmBrD;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAStD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAwBvD;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd,CAUA;AAED,kDAAkD;AAClD,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,KAAG,OAG3D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,aAAa,GACnB,SAAS,CA0BX;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,SAAS,CAWjE;AAED,uEAAuE;AACvE,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,OAEC,CAAC"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/contract/checks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,OAAO,KAAK,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAGhB,MAAM,SAAS,CAAC;AAOjB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAG9D;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMjD;AA8BD,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAoBrD;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAStD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAwBvD;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd,CAUA;AAED,kDAAkD;AAClD,eAAO,MAAM,MAAM,GAAI,MAAM,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,KAAG,OAG3D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,aAAa,GACnB,SAAS,CA4BX;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,SAAS,CA0BjE;AAED,uEAAuE;AACvE,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,EAAE,KAAK,MAAM,KAAG,OAEC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { NewQueueItem } from './types';
2
+ /** `ret`, `envid` and `recipients` of a new item. */
3
+ export declare function checkDsnParams(item: NewQueueItem): void;
4
+ //# sourceMappingURL=dsn-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsn-checks.d.ts","sourceRoot":"","sources":["../../src/contract/dsn-checks.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAoF1D,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CA4BvD"}
@@ -0,0 +1,12 @@
1
+ import type { QueueItem, RetMode } from './types';
2
+ /** The item-level DSN parameters, as the SQL stores keep them in one JSON column. */
3
+ interface Params {
4
+ ret?: RetMode;
5
+ envid?: string;
6
+ }
7
+ /** The column's JSON text, or `null` when the item has no `RET` and no `ENVID`. */
8
+ export declare function dsnColumn(item: Pick<QueueItem, 'ret' | 'envid'>): string | null;
9
+ /** `ret` and `envid` from the column: nothing for a row written before the column existed (`null`). */
10
+ export declare function dsnParams(column: string | Params | null | undefined): Pick<QueueItem, 'ret' | 'envid'>;
11
+ export {};
12
+ //# sourceMappingURL=dsn-column.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsn-column.d.ts","sourceRoot":"","sources":["../../src/contract/dsn-column.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElD,qFAAqF;AACrF,UAAU,MAAM;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CACxB,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC,GACpC,MAAM,GAAG,IAAI,CAOf;AAED,uGAAuG;AACvG,wBAAgB,SAAS,CACxB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACxC,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC,CAQlC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Text a store keeps: refused, the same way by every store, when it holds
3
+ * a NUL or a lone surrogate, which PostgreSQL cannot keep and no UTF-8
4
+ * encode can carry.
5
+ */
6
+ export declare function checkStorable(name: string, text: string): void;
7
+ //# sourceMappingURL=storable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storable.d.ts","sourceRoot":"","sources":["../../src/contract/storable.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM9D"}
@@ -21,10 +21,37 @@ export interface Diagnostic {
21
21
  /** The host that answered, or that the attempt was for. */
22
22
  readonly host?: string;
23
23
  }
24
+ /** An event a sender may ask to be told of (RFC 3461 §4.1). */
25
+ export type NotifyEvent = 'SUCCESS' | 'FAILURE' | 'DELAY';
26
+ /**
27
+ * What a recipient's `NOTIFY` asked for (RFC 3461 §4.1): `'NEVER'`, or the
28
+ * events to be told of. Absent: failure and delay, the default.
29
+ */
30
+ export type RecipientNotify = 'NEVER' | readonly NotifyEvent[];
31
+ /** The recipient as the sender first named it (`ORCPT`, RFC 3461 §4.2). */
32
+ export interface OriginalRecipient {
33
+ /** The address type, `rfc822` for an ordinary mailbox. */
34
+ readonly type: string;
35
+ /** The address, decoded. */
36
+ readonly address: string;
37
+ }
38
+ /** What `RET` asked an original message be returned as (RFC 3461 §4.3). */
39
+ export type RetMode = 'FULL' | 'HDRS';
40
+ /** The DSN parameters of one recipient, as `enqueue` takes them. */
41
+ export interface RecipientDsn {
42
+ /** `local@domain`, one of the envelope's `to`. */
43
+ readonly address: string;
44
+ readonly notify?: RecipientNotify;
45
+ readonly orcpt?: OriginalRecipient;
46
+ }
24
47
  export interface RecipientState {
25
48
  /** `local@domain`, as enqueued. */
26
49
  readonly address: string;
27
50
  readonly status: RecipientStatus;
51
+ /** `NOTIFY` as the sender asked; absent when it did not. Kept for the item's life. */
52
+ readonly notify?: RecipientNotify;
53
+ /** `ORCPT` as the sender gave it; absent when it did not. Kept for the item's life. */
54
+ readonly orcpt?: OriginalRecipient;
28
55
  /** The last answer for this recipient. */
29
56
  readonly reply?: Diagnostic;
30
57
  /** When the status last changed, in milliseconds since the epoch. */
@@ -67,6 +94,10 @@ export interface QueueItem {
67
94
  readonly attempts: number;
68
95
  /** The "delayed" DSN was sent for it. */
69
96
  readonly delayNotified: boolean;
97
+ /** `RET` as the sender asked; absent when it did not. */
98
+ readonly ret?: RetMode;
99
+ /** `ENVID` as the sender gave it, decoded; absent when it did not. */
100
+ readonly envid?: string;
70
101
  /** Present while a worker holds the item. */
71
102
  readonly lease?: Lease;
72
103
  }
@@ -79,6 +110,12 @@ export interface NewQueueItem {
79
110
  readonly message: Uint8Array;
80
111
  /** Milliseconds since the epoch; due at once. */
81
112
  readonly createdAt: number;
113
+ /** `RET` (RFC 3461 §4.3). */
114
+ readonly ret?: RetMode;
115
+ /** `ENVID` (RFC 3461 §4.4): 1 to 100 printable ASCII characters. */
116
+ readonly envid?: string;
117
+ /** `NOTIFY` and `ORCPT` of the recipients that carry some, matched to `to` by address. */
118
+ readonly recipients?: readonly RecipientDsn[];
82
119
  }
83
120
  export interface AddOptions {
84
121
  /** Refuse with `QUEUE_FULL` when the store already holds this many items. */
@@ -101,6 +138,11 @@ export interface RecipientUpdate {
101
138
  readonly mayHaveReachedMx?: true;
102
139
  /** Marks the recipient `mayHaveReachedFallback`; `true` or absent, any other value is `INVALID`. */
103
140
  readonly mayHaveReachedFallback?: true;
141
+ /**
142
+ * With `delivered`: whether the next hop listed DSN (`SendMailResult.dsnOffered`).
143
+ * Read by the queue to issue a `relayed` DSN; never stored.
144
+ */
145
+ readonly dsnOffered?: boolean;
104
146
  }
105
147
  /** What `complete` records: the attempt's outcomes, and when to try again. */
106
148
  export interface AttemptResult {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,8 @@ export interface DsnInput {
13
13
  readonly arrival: Date;
14
14
  /** When the DSN is written. */
15
15
  readonly date: Date;
16
+ /** `ENVID` of the original, decoded: echoed as `Original-Envelope-Id`. */
17
+ readonly envid?: string;
16
18
  readonly recipients: readonly DsnRecipient[];
17
19
  /** With `delayed`: when the queue gives up. */
18
20
  readonly willRetryUntil?: Date;
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/dsn/build.ts"],"names":[],"mappings":"AAQA,OAAO,EACN,KAAK,OAAO,EACZ,KAAK,YAAY,EAGjB,MAAM,UAAU,CAAC;AAElB,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEtD,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3C,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAwFD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CA2CpD"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/dsn/build.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,UAAU,CAAC;AAG3E,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEtD,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3C,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AA6CD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,CA4CpD"}
@@ -0,0 +1,25 @@
1
+ import type { OriginalRecipient, RecipientNotify } from '../contract/types';
2
+ import { type LocalDsnInput } from './for';
3
+ /** One recipient the application put in a local mailbox. */
4
+ export interface DeliveredRecipient {
5
+ /** `local@domain`, the mailbox it was delivered to. */
6
+ readonly address: string;
7
+ /** Its `NOTIFY`; a `delivered` DSN goes only when `SUCCESS` was asked (RFC 3461 §5.2.3). */
8
+ readonly notify?: RecipientNotify;
9
+ /** Its `ORCPT`, echoed as `Original-Recipient`. */
10
+ readonly orcpt?: OriginalRecipient;
11
+ }
12
+ /** What `deliveredDsn` takes. */
13
+ export interface DeliveredDsnInput extends LocalDsnInput {
14
+ readonly recipients: readonly DeliveredRecipient[];
15
+ }
16
+ /**
17
+ * The `delivered` DSN (RFC 3464 `Action: delivered`, RFC 3461 §5.2.3) for a
18
+ * message the application put in local mailboxes: the bytes to
19
+ * `enqueue` from the null sender to `to`, or `undefined` when there is
20
+ * nothing to send — the original came from the null sender, or no
21
+ * recipient asked for `SUCCESS`. Only the recipients that asked are
22
+ * listed.
23
+ */
24
+ export declare function deliveredDsn(input: DeliveredDsnInput): Uint8Array | undefined;
25
+ //# sourceMappingURL=delivered.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivered.d.ts","sourceRoot":"","sources":["../../src/dsn/delivered.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAGnD,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IAClC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACvD,QAAQ,CAAC,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAc7E"}
@@ -0,0 +1,29 @@
1
+ import type { Diagnostic, OriginalRecipient, RecipientNotify, RetMode } from '../contract/types';
2
+ import { type LocalDsnInput } from './for';
3
+ /** One recipient the application could not deliver here. */
4
+ export interface FailedRecipient {
5
+ /** `local@domain`, as the sender named it. */
6
+ readonly address: string;
7
+ /** Its `NOTIFY`; a `failed` DSN goes unless `NEVER` or a list without `FAILURE` (RFC 3461 §4.1). */
8
+ readonly notify?: RecipientNotify;
9
+ /** Its `ORCPT`, echoed as `Original-Recipient`. */
10
+ readonly orcpt?: OriginalRecipient;
11
+ /** Why: the enhanced status and the text. */
12
+ readonly reply: Diagnostic;
13
+ }
14
+ /** What `failedDsn` takes. */
15
+ export interface FailedDsnInput extends LocalDsnInput {
16
+ readonly recipients: readonly FailedRecipient[];
17
+ /** `RET` of the original: what the DSN returns of it (RFC 3461 §4.3). Default: the headers. With `FULL`, give the whole message as `original`. */
18
+ readonly ret?: RetMode;
19
+ }
20
+ /**
21
+ * The `failed` DSN (RFC 3464 `Action: failed`) for a message the application
22
+ * could not put in a local mailbox: the bytes to `enqueue` from the null
23
+ * sender to `to`, or `undefined` when there is nothing to send — the
24
+ * original came from the null sender, or no recipient asked for failures
25
+ * (the default, unless `NOTIFY=NEVER` or a list without `FAILURE`). Only the
26
+ * recipients that asked are listed.
27
+ */
28
+ export declare function failedDsn(input: FailedDsnInput): Uint8Array | undefined;
29
+ //# sourceMappingURL=failed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failed.d.ts","sourceRoot":"","sources":["../../src/dsn/failed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,OAAO,EACP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAGnD,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC/B,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IACnC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC3B;AAED,8BAA8B;AAC9B,MAAM,WAAW,cAAe,SAAQ,aAAa;IACpD,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,kJAAkJ;IAClJ,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,GAAG,SAAS,CAcvE"}
@@ -1,12 +1,19 @@
1
- import type { Diagnostic } from '../contract/types';
1
+ import type { Diagnostic, OriginalRecipient } from '../contract/types';
2
2
  /** One recipient a DSN reports on. */
3
3
  export interface DsnRecipient {
4
4
  readonly address: string;
5
5
  readonly reply?: Diagnostic;
6
6
  /** When it was last tried. */
7
7
  readonly lastAttempt: Date;
8
+ /** `ORCPT`: the recipient as the sender named it (RFC 3464 §2.3.1). */
9
+ readonly orcpt?: OriginalRecipient;
8
10
  }
9
- export type DsnKind = 'delayed' | 'failed';
11
+ /**
12
+ * The `Action` of the report (RFC 3464 §2.3.3): `failed` and `delayed` for
13
+ * what went wrong, `relayed` for a message handed to a next hop that sends
14
+ * no DSN (RFC 3461 §5.2.2), `delivered` for one put in a local mailbox.
15
+ */
16
+ export type DsnKind = 'delayed' | 'failed' | 'relayed' | 'delivered';
10
17
  /** What a delivery-status part reports: who reports, on what, and each recipient. */
11
18
  export interface StatusReport {
12
19
  readonly kind: DsnKind;
@@ -14,6 +21,8 @@ export interface StatusReport {
14
21
  readonly reportingMta: string;
15
22
  /** When the message was enqueued. */
16
23
  readonly arrival: Date;
24
+ /** `ENVID` of the original, decoded (RFC 3464 §2.2.1). */
25
+ readonly envid?: string;
17
26
  readonly recipients: readonly DsnRecipient[];
18
27
  /** With `delayed`: when the queue gives up. */
19
28
  readonly willRetryUntil?: Date;
@@ -1 +1 @@
1
- {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/dsn/fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE3C,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;CAC/B;AAQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAapD;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAMlE;AA8BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAS3D"}
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/dsn/fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGvE,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAErE,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;CAC/B;AAQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpD;AAoBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAQlE;AA2DD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAW3D"}
@@ -0,0 +1,26 @@
1
+ import { type DsnKind, type DsnRecipient } from './build';
2
+ /** What the DSNs of a local delivery share. */
3
+ export interface LocalDsnInput {
4
+ /** This server's public name: the Reporting-MTA. */
5
+ readonly reportingMta: string;
6
+ /** The DSN's From: the postmaster's address. */
7
+ readonly from: string;
8
+ /** The original's reverse-path; `''` (the null sender) gets no DSN. */
9
+ readonly to: string;
10
+ /** When the original was received. */
11
+ readonly arrival: Date;
12
+ /** When the DSN is written. Default: now. */
13
+ readonly date?: Date;
14
+ readonly envid?: string;
15
+ /** The original as received; without it the DSN returns nothing of it. */
16
+ readonly original?: Uint8Array;
17
+ /** The most bytes of the original returned. Default `DEFAULT_MAX_RETURN`. */
18
+ readonly maxReturn?: number;
19
+ }
20
+ /**
21
+ * The DSN of `kind` for `recipients` (already filtered by `NOTIFY`), or
22
+ * `undefined` when there is nobody to tell: the null sender, or no
23
+ * recipient.
24
+ */
25
+ export declare function dsnFor(kind: DsnKind, input: LocalDsnInput, recipients: readonly DsnRecipient[], returnContent: 'headers' | 'full'): Uint8Array | undefined;
26
+ //# sourceMappingURL=for.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"for.d.ts","sourceRoot":"","sources":["../../src/dsn/for.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAGpE,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACrB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,SAAS,YAAY,EAAE,EACnC,aAAa,EAAE,SAAS,GAAG,MAAM,GAC/B,UAAU,GAAG,SAAS,CAexB"}