@serve.zone/dcrouter 17.0.0 → 17.1.1

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 (141) hide show
  1. package/.smartconfig.json +7 -4
  2. package/deno.json +1 -1
  3. package/dist_serve/bundle.js +1316 -1151
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/classes.dcrouter.d.ts +3 -1
  6. package/dist_ts/classes.dcrouter.js +113 -52
  7. package/dist_ts/db/classes.cache.cleaner.d.ts +3 -0
  8. package/dist_ts/db/classes.cache.cleaner.js +7 -3
  9. package/dist_ts/db/classes.dcrouter-db.js +1 -2
  10. package/dist_ts/db/documents/classes.cached.email.d.ts +41 -4
  11. package/dist_ts/db/documents/classes.cached.email.js +36 -5
  12. package/dist_ts/db/documents/classes.dns-record.doc.js +3 -1
  13. package/dist_ts/dns/classes.dns-server-runtime.d.ts +0 -1
  14. package/dist_ts/dns/classes.dns-server-runtime.js +4 -36
  15. package/dist_ts/dns/index.d.ts +1 -0
  16. package/dist_ts/dns/index.js +2 -1
  17. package/dist_ts/dns/manager.dns.d.ts +1 -0
  18. package/dist_ts/dns/manager.dns.js +49 -14
  19. package/dist_ts/dns/providers/cloudflare.provider.js +19 -4
  20. package/dist_ts/dns/txt-record-presentation.d.ts +20 -0
  21. package/dist_ts/dns/txt-record-presentation.js +131 -0
  22. package/dist_ts/email/classes.accepted-email-spool.d.ts +32 -3
  23. package/dist_ts/email/classes.accepted-email-spool.js +174 -13
  24. package/dist_ts/email/classes.email-domain.manager.d.ts +14 -1
  25. package/dist_ts/email/classes.email-domain.manager.js +151 -8
  26. package/dist_ts/email/classes.email-settings.manager.js +2 -2
  27. package/dist_ts/email/classes.mail-dns-sync.d.ts +31 -5
  28. package/dist_ts/email/classes.mail-dns-sync.js +508 -117
  29. package/dist_ts/email/classes.smartmta-blob-storage-manager.d.ts +2 -2
  30. package/dist_ts/email/classes.smartmta-blob-storage-manager.js +4 -3
  31. package/dist_ts/email/classes.workapp-mail-manager.d.ts +1 -0
  32. package/dist_ts/email/classes.workapp-mail-manager.js +26 -2
  33. package/dist_ts/email/index.d.ts +2 -0
  34. package/dist_ts/email/index.js +3 -1
  35. package/dist_ts/email/mail-dns-txt-policy.d.ts +18 -0
  36. package/dist_ts/email/mail-dns-txt-policy.js +466 -0
  37. package/dist_ts/email/reconcile-mail-dns-singleton.d.ts +47 -0
  38. package/dist_ts/email/reconcile-mail-dns-singleton.js +159 -0
  39. package/dist_ts/opsserver/classes.opsserver.d.ts +8 -0
  40. package/dist_ts/opsserver/classes.opsserver.js +34 -1
  41. package/dist_ts/opsserver/handlers/certificate.handler.js +25 -4
  42. package/dist_ts/opsserver/handlers/config.handler.js +9 -5
  43. package/dist_ts/opsserver/handlers/dns-provider.handler.js +19 -2
  44. package/dist_ts/opsserver/handlers/dns-record.handler.js +25 -4
  45. package/dist_ts/opsserver/handlers/domain.handler.js +37 -3
  46. package/dist_ts/opsserver/handlers/email-domain.handler.js +5 -7
  47. package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +1 -0
  48. package/dist_ts/opsserver/handlers/email-ops.handler.js +26 -7
  49. package/dist_ts/opsserver/handlers/index.d.ts +1 -0
  50. package/dist_ts/opsserver/handlers/index.js +2 -1
  51. package/dist_ts/opsserver/handlers/logs.handler.d.ts +1 -1
  52. package/dist_ts/opsserver/handlers/logs.handler.js +3 -3
  53. package/dist_ts/opsserver/handlers/realtime.handler.d.ts +37 -0
  54. package/dist_ts/opsserver/handlers/realtime.handler.js +154 -0
  55. package/dist_ts/opsserver/handlers/remoteingress.handler.js +22 -1
  56. package/dist_ts/opsserver/handlers/route-management.handler.js +47 -5
  57. package/dist_ts/opsserver/handlers/stats.handler.js +5 -1
  58. package/dist_ts/paths.d.ts +0 -11
  59. package/dist_ts/paths.js +1 -22
  60. package/dist_ts/plugins.d.ts +0 -34
  61. package/dist_ts/plugins.js +1 -62
  62. package/dist_ts_interfaces/data/email-domain.d.ts +14 -0
  63. package/dist_ts_interfaces/requests/config.d.ts +1 -1
  64. package/dist_ts_interfaces/requests/email-ops.d.ts +34 -1
  65. package/dist_ts_interfaces/requests/index.d.ts +1 -0
  66. package/dist_ts_interfaces/requests/index.js +2 -1
  67. package/dist_ts_interfaces/requests/realtime.d.ts +38 -0
  68. package/dist_ts_interfaces/requests/realtime.js +11 -0
  69. package/dist_ts_migrations/index.d.ts +6 -0
  70. package/dist_ts_migrations/index.js +208 -9
  71. package/dist_ts_web/00_commitinfo_data.js +1 -1
  72. package/dist_ts_web/appstate/certificates.js +9 -2
  73. package/dist_ts_web/appstate/domains.js +16 -5
  74. package/dist_ts_web/appstate/email-domains.d.ts +3 -0
  75. package/dist_ts_web/appstate/email-domains.js +47 -14
  76. package/dist_ts_web/appstate/email-ops.d.ts +1 -0
  77. package/dist_ts_web/appstate/email-ops.js +20 -2
  78. package/dist_ts_web/appstate/realtime.d.ts +27 -0
  79. package/dist_ts_web/appstate/realtime.js +71 -0
  80. package/dist_ts_web/appstate/remoteingress.js +9 -3
  81. package/dist_ts_web/appstate/routes.js +16 -5
  82. package/dist_ts_web/appstate/runtime.js +135 -7
  83. package/dist_ts_web/appstate.d.ts +1 -0
  84. package/dist_ts_web/appstate.js +2 -1
  85. package/dist_ts_web/elements/email/email-domain-creation-progress.d.ts +33 -0
  86. package/dist_ts_web/elements/email/email-domain-creation-progress.js +257 -0
  87. package/dist_ts_web/elements/email/ops-view-email-domains.js +233 -68
  88. package/dist_ts_web/elements/email/ops-view-emails.d.ts +4 -2
  89. package/dist_ts_web/elements/email/ops-view-emails.js +25 -13
  90. package/dist_ts_web/elements/overview/ops-view-config.js +5 -5
  91. package/package.json +22 -19
  92. package/ts/00_commitinfo_data.ts +1 -1
  93. package/ts/classes.dcrouter.ts +124 -57
  94. package/ts/db/classes.cache.cleaner.ts +18 -3
  95. package/ts/db/classes.dcrouter-db.ts +0 -2
  96. package/ts/db/documents/classes.cached.email.ts +78 -4
  97. package/ts/db/documents/classes.dns-record.doc.ts +1 -0
  98. package/ts/dns/classes.dns-server-runtime.ts +9 -45
  99. package/ts/dns/index.ts +1 -0
  100. package/ts/dns/manager.dns.ts +50 -16
  101. package/ts/dns/providers/cloudflare.provider.ts +21 -3
  102. package/ts/dns/txt-record-presentation.ts +134 -0
  103. package/ts/email/classes.accepted-email-spool.ts +220 -14
  104. package/ts/email/classes.email-domain.manager.ts +201 -7
  105. package/ts/email/classes.email-settings.manager.ts +1 -1
  106. package/ts/email/classes.mail-dns-sync.ts +588 -122
  107. package/ts/email/classes.smartmta-blob-storage-manager.ts +3 -2
  108. package/ts/email/classes.workapp-mail-manager.ts +34 -1
  109. package/ts/email/index.ts +2 -0
  110. package/ts/email/mail-dns-txt-policy.ts +505 -0
  111. package/ts/email/reconcile-mail-dns-singleton.ts +224 -0
  112. package/ts/opsserver/classes.opsserver.ts +42 -0
  113. package/ts/opsserver/handlers/certificate.handler.ts +24 -3
  114. package/ts/opsserver/handlers/config.handler.ts +9 -5
  115. package/ts/opsserver/handlers/dns-provider.handler.ts +18 -1
  116. package/ts/opsserver/handlers/dns-record.handler.ts +24 -3
  117. package/ts/opsserver/handlers/domain.handler.ts +36 -2
  118. package/ts/opsserver/handlers/email-domain.handler.ts +4 -5
  119. package/ts/opsserver/handlers/email-ops.handler.ts +29 -6
  120. package/ts/opsserver/handlers/index.ts +1 -0
  121. package/ts/opsserver/handlers/logs.handler.ts +2 -2
  122. package/ts/opsserver/handlers/realtime.handler.ts +222 -0
  123. package/ts/opsserver/handlers/remoteingress.handler.ts +21 -0
  124. package/ts/opsserver/handlers/route-management.handler.ts +46 -4
  125. package/ts/opsserver/handlers/stats.handler.ts +4 -0
  126. package/ts/paths.ts +0 -25
  127. package/ts/plugins.ts +0 -68
  128. package/ts_web/00_commitinfo_data.ts +1 -1
  129. package/ts_web/appstate/certificates.ts +6 -1
  130. package/ts_web/appstate/domains.ts +11 -4
  131. package/ts_web/appstate/email-domains.ts +68 -14
  132. package/ts_web/appstate/email-ops.ts +20 -1
  133. package/ts_web/appstate/realtime.ts +109 -0
  134. package/ts_web/appstate/remoteingress.ts +6 -2
  135. package/ts_web/appstate/routes.ts +11 -4
  136. package/ts_web/appstate/runtime.ts +176 -7
  137. package/ts_web/appstate.ts +1 -0
  138. package/ts_web/elements/email/email-domain-creation-progress.ts +340 -0
  139. package/ts_web/elements/email/ops-view-email-domains.ts +273 -74
  140. package/ts_web/elements/email/ops-view-emails.ts +23 -16
  141. package/ts_web/elements/overview/ops-view-config.ts +4 -4
@@ -0,0 +1,257 @@
1
+ const settledIntentStatuses = new Set([
2
+ 'satisfied',
3
+ 'valid',
4
+ 'conflict',
5
+ 'failed',
6
+ ]);
7
+ const formatOperationError = (errorArg) => {
8
+ const location = errorArg.recordKey ? `${errorArg.recordKey}: ` : '';
9
+ return `${location}${errorArg.message} [${errorArg.code}]`;
10
+ };
11
+ const appendDnsStatusLines = (linesArg, dnsStatusArg) => {
12
+ for (const [label, status] of [
13
+ ['MX', dnsStatusArg.mx],
14
+ ['SPF', dnsStatusArg.spf],
15
+ ['DKIM', dnsStatusArg.dkim],
16
+ ['DMARC', dnsStatusArg.dmarc],
17
+ ]) {
18
+ if (status !== 'unchecked') {
19
+ linesArg.push(`${label}: ${status}`);
20
+ }
21
+ }
22
+ };
23
+ export const getEmailDomainCreationProgress = (inputArg) => {
24
+ const { domain, operation, requestCompleted } = inputArg;
25
+ if (!domain) {
26
+ if (!requestCompleted) {
27
+ return {
28
+ percentage: 0,
29
+ indeterminate: true,
30
+ showPercentage: false,
31
+ statusText: 'Generating DKIM material and creating the domain record...',
32
+ terminalLines: ['Submitting email domain configuration'],
33
+ };
34
+ }
35
+ const lines = ['Email domain creation request completed without a persisted domain'];
36
+ for (const error of operation?.errors || []) {
37
+ lines.push(formatOperationError(error));
38
+ }
39
+ if (operation?.message && !lines.includes(operation.message)) {
40
+ lines.push(operation.message);
41
+ }
42
+ return {
43
+ percentage: 100,
44
+ indeterminate: false,
45
+ showPercentage: false,
46
+ statusText: operation?.message || 'Email domain creation failed.',
47
+ terminalLines: lines,
48
+ };
49
+ }
50
+ const reconciliation = domain.reconciliation;
51
+ const lines = [`Domain record persisted: ${domain.domain}`];
52
+ if (!reconciliation || reconciliation.intents.length === 0) {
53
+ if (!requestCompleted) {
54
+ lines.push('Preparing the managed DNS plan');
55
+ return {
56
+ percentage: 0,
57
+ indeterminate: true,
58
+ showPercentage: false,
59
+ statusText: 'Preparing the managed DNS plan...',
60
+ terminalLines: lines,
61
+ };
62
+ }
63
+ lines.push('No DNS reconciliation plan is available');
64
+ const errors = reconciliation?.errors.length
65
+ ? reconciliation.errors
66
+ : operation?.errors || [];
67
+ for (const error of errors) {
68
+ lines.push(formatOperationError(error));
69
+ }
70
+ const retryAt = reconciliation?.retryAt || operation?.retryAt;
71
+ if (retryAt) {
72
+ lines.push(`Retry scheduled for ${retryAt}`);
73
+ }
74
+ const statusText = reconciliation?.lifecycleStatus === 'failed'
75
+ ? operation?.message || `DNS setup failed for ${domain.domain}.`
76
+ : retryAt
77
+ ? 'DNS reconciliation is pending and will retry automatically.'
78
+ : operation?.message || 'The domain was created without a DNS reconciliation plan.';
79
+ return {
80
+ percentage: 100,
81
+ indeterminate: false,
82
+ showPercentage: false,
83
+ statusText,
84
+ terminalLines: lines,
85
+ };
86
+ }
87
+ const settledCount = reconciliation.intents.filter((intent) => settledIntentStatuses.has(intent.status)).length;
88
+ lines.push(`DNS plan prepared: ${reconciliation.intents.length} managed records`);
89
+ lines.push(`DNS reconciliation: ${settledCount} settled, ${reconciliation.intents.length - settledCount} pending`);
90
+ appendDnsStatusLines(lines, domain.dnsStatus);
91
+ if (reconciliation.lifecycleStatus === 'active') {
92
+ lines.push('Email domain is active');
93
+ return {
94
+ percentage: 100,
95
+ indeterminate: false,
96
+ showPercentage: true,
97
+ statusText: `${domain.domain} is active.`,
98
+ terminalLines: lines,
99
+ };
100
+ }
101
+ if (!requestCompleted) {
102
+ return {
103
+ percentage: 0,
104
+ indeterminate: true,
105
+ showPercentage: false,
106
+ statusText: 'Reconciling and validating managed DNS records...',
107
+ terminalLines: lines,
108
+ };
109
+ }
110
+ const errors = reconciliation.errors.length > 0
111
+ ? reconciliation.errors
112
+ : operation?.errors || [];
113
+ for (const error of errors) {
114
+ lines.push(formatOperationError(error));
115
+ }
116
+ const retryAt = reconciliation.retryAt || operation?.retryAt;
117
+ if (retryAt) {
118
+ lines.push(`Retry scheduled for ${retryAt}`);
119
+ }
120
+ if (reconciliation.lifecycleStatus === 'failed') {
121
+ return {
122
+ percentage: 100,
123
+ indeterminate: false,
124
+ showPercentage: false,
125
+ statusText: operation?.message || `DNS setup failed for ${domain.domain}.`,
126
+ terminalLines: lines,
127
+ };
128
+ }
129
+ return {
130
+ percentage: 100,
131
+ indeterminate: false,
132
+ showPercentage: false,
133
+ statusText: retryAt
134
+ ? `DNS reconciliation is pending and will retry automatically.`
135
+ : `DNS reconciliation is pending for ${domain.domain}.`,
136
+ terminalLines: lines,
137
+ };
138
+ };
139
+ export const findNewEmailDomain = (domainsArg, expectedDomainArg, existingIdsArg) => {
140
+ const expectedDomain = expectedDomainArg.trim().toLowerCase();
141
+ const candidates = domainsArg.filter((domain) => domain.domain.toLowerCase() === expectedDomain && !existingIdsArg.has(domain.id));
142
+ if (candidates.length > 1) {
143
+ throw new Error(`Multiple new email domains appeared for ${expectedDomain}`);
144
+ }
145
+ return candidates[0];
146
+ };
147
+ const waitForPollInterval = async (delayMsArg, signalArg) => {
148
+ if (signalArg.aborted)
149
+ return;
150
+ await new Promise((resolve) => {
151
+ const finish = () => {
152
+ signalArg.removeEventListener('abort', handleAbort);
153
+ resolve();
154
+ };
155
+ const handleAbort = () => {
156
+ clearTimeout(timeoutId);
157
+ finish();
158
+ };
159
+ const timeoutId = setTimeout(finish, delayMsArg);
160
+ signalArg.addEventListener('abort', handleAbort, { once: true });
161
+ });
162
+ };
163
+ export const observeNewEmailDomain = async (optionsArg) => {
164
+ const startedAt = Date.now();
165
+ const pollIntervalMs = optionsArg.pollIntervalMs ?? (optionsArg.subscribeToDomains ? 15_000 : 600);
166
+ const timeoutMs = optionsArg.timeoutMs ?? 120_000;
167
+ let observedId;
168
+ let latestDomain;
169
+ let pushedDomains;
170
+ let wakeObserver;
171
+ const unsubscribe = optionsArg.subscribeToDomains?.((domainsArg) => {
172
+ pushedDomains = domainsArg;
173
+ wakeObserver?.();
174
+ });
175
+ try {
176
+ while (!optionsArg.signal.aborted && Date.now() - startedAt < timeoutMs) {
177
+ try {
178
+ let domain;
179
+ if (!observedId) {
180
+ const domainSnapshot = pushedDomains || await optionsArg.listDomains();
181
+ pushedDomains = undefined;
182
+ const foundDomain = findNewEmailDomain(domainSnapshot, optionsArg.expectedDomain, optionsArg.existingIds);
183
+ observedId = foundDomain?.id;
184
+ domain = foundDomain;
185
+ }
186
+ else if (pushedDomains) {
187
+ domain = pushedDomains.find((candidate) => candidate.id === observedId);
188
+ pushedDomains = undefined;
189
+ }
190
+ else {
191
+ domain = await optionsArg.getDomain(observedId);
192
+ }
193
+ if (optionsArg.signal.aborted)
194
+ break;
195
+ if (domain) {
196
+ if (domain !== latestDomain) {
197
+ latestDomain = domain;
198
+ optionsArg.onDomain(domain);
199
+ }
200
+ const lifecycleStatus = domain.reconciliation?.lifecycleStatus;
201
+ if (lifecycleStatus === 'active' || lifecycleStatus === 'failed') {
202
+ return domain;
203
+ }
204
+ }
205
+ }
206
+ catch (error) {
207
+ if (error instanceof Error && error.message.startsWith('Multiple new email domains')) {
208
+ throw error;
209
+ }
210
+ // The realtime subscription or bounded fallback read will retry.
211
+ }
212
+ const updatePromise = new Promise((resolve) => {
213
+ wakeObserver = resolve;
214
+ });
215
+ if (pushedDomains) {
216
+ wakeObserver = undefined;
217
+ continue;
218
+ }
219
+ await Promise.race([
220
+ updatePromise,
221
+ waitForPollInterval(pollIntervalMs, optionsArg.signal),
222
+ ]);
223
+ wakeObserver = undefined;
224
+ }
225
+ }
226
+ finally {
227
+ unsubscribe?.();
228
+ wakeObserver?.();
229
+ }
230
+ return latestDomain;
231
+ };
232
+ export const withAbortableDeadline = async (promiseArg, optionsArg) => {
233
+ return new Promise((resolve, reject) => {
234
+ let settled = false;
235
+ const finish = (callbackArg) => {
236
+ if (settled)
237
+ return;
238
+ settled = true;
239
+ clearTimeout(timeoutId);
240
+ optionsArg.signal?.removeEventListener('abort', handleAbort);
241
+ callbackArg();
242
+ };
243
+ const handleAbort = () => {
244
+ finish(() => reject(new Error('Email domain creation progress was interrupted')));
245
+ };
246
+ const timeoutId = setTimeout(() => {
247
+ finish(() => reject(new Error(optionsArg.timeoutMessage)));
248
+ }, optionsArg.timeoutMs);
249
+ if (optionsArg.signal?.aborted) {
250
+ handleAbort();
251
+ return;
252
+ }
253
+ optionsArg.signal?.addEventListener('abort', handleAbort, { once: true });
254
+ promiseArg.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
255
+ });
256
+ };
257
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtZG9tYWluLWNyZWF0aW9uLXByb2dyZXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHNfd2ViL2VsZW1lbnRzL2VtYWlsL2VtYWlsLWRvbWFpbi1jcmVhdGlvbi1wcm9ncmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFnQkEsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLEdBQUcsQ0FBd0M7SUFDM0UsV0FBVztJQUNYLE9BQU87SUFDUCxVQUFVO0lBQ1YsUUFBUTtDQUNULENBQUMsQ0FBQztBQUVILE1BQU0sb0JBQW9CLEdBQUcsQ0FDM0IsUUFBa0csRUFDMUYsRUFBRTtJQUNWLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDckUsT0FBTyxHQUFHLFFBQVEsR0FBRyxRQUFRLENBQUMsT0FBTyxLQUFLLFFBQVEsQ0FBQyxJQUFJLEdBQUcsQ0FBQztBQUM3RCxDQUFDLENBQUM7QUFFRixNQUFNLG9CQUFvQixHQUFHLENBQzNCLFFBQWtCLEVBQ2xCLFlBQW1ELEVBQzdDLEVBQUU7SUFDUixLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUk7UUFDNUIsQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQztRQUN2QixDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDO1FBQ3pCLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxJQUFJLENBQUM7UUFDM0IsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLEtBQUssQ0FBQztLQUNyQixFQUFFLENBQUM7UUFDWCxJQUFJLE1BQU0sS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUMzQixRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxLQUFLLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENB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