@serve.zone/coremail 1.0.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/.smartconfig.json +50 -0
- package/changelog.md +10 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.auth.d.ts +45 -0
- package/dist_ts/classes.auth.js +204 -0
- package/dist_ts/classes.config.d.ts +2 -0
- package/dist_ts/classes.config.js +72 -0
- package/dist_ts/classes.coremail.d.ts +41 -0
- package/dist_ts/classes.coremail.js +155 -0
- package/dist_ts/classes.desiredstate.d.ts +40 -0
- package/dist_ts/classes.desiredstate.js +382 -0
- package/dist_ts/classes.gateway.d.ts +62 -0
- package/dist_ts/classes.gateway.js +669 -0
- package/dist_ts/classes.inbound.d.ts +49 -0
- package/dist_ts/classes.inbound.js +702 -0
- package/dist_ts/classes.maintenance.d.ts +16 -0
- package/dist_ts/classes.maintenance.js +339 -0
- package/dist_ts/classes.models.d.ts +161 -0
- package/dist_ts/classes.models.js +595 -0
- package/dist_ts/classes.server.d.ts +40 -0
- package/dist_ts/classes.server.js +309 -0
- package/dist_ts/classes.storage.d.ts +32 -0
- package/dist_ts/classes.storage.js +317 -0
- package/dist_ts/classes.submissions.d.ts +33 -0
- package/dist_ts/classes.submissions.js +385 -0
- package/dist_ts/classes.transfer.d.ts +41 -0
- package/dist_ts/classes.transfer.js +289 -0
- package/dist_ts/coremail.cursor.d.ts +20 -0
- package/dist_ts/coremail.cursor.js +191 -0
- package/dist_ts/coremail.log.d.ts +3 -0
- package/dist_ts/coremail.log.js +11 -0
- package/dist_ts/coremail.mime.d.ts +8 -0
- package/dist_ts/coremail.mime.js +63 -0
- package/dist_ts/coremail.persistence.d.ts +148 -0
- package/dist_ts/coremail.persistence.js +695 -0
- package/dist_ts/coremail.quota.d.ts +29 -0
- package/dist_ts/coremail.quota.js +149 -0
- package/dist_ts/coremail.selectors.d.ts +3 -0
- package/dist_ts/coremail.selectors.js +21 -0
- package/dist_ts/coremail.validation.d.ts +9 -0
- package/dist_ts/coremail.validation.js +325 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +39 -0
- package/dist_ts/interfaces.d.ts +92 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +11 -0
- package/dist_ts/plugins.js +12 -0
- package/license.md +19 -0
- package/package.json +48 -0
- package/readme.md +199 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.auth.ts +321 -0
- package/ts/classes.config.ts +104 -0
- package/ts/classes.coremail.ts +249 -0
- package/ts/classes.desiredstate.ts +508 -0
- package/ts/classes.gateway.ts +811 -0
- package/ts/classes.inbound.ts +898 -0
- package/ts/classes.maintenance.ts +335 -0
- package/ts/classes.models.ts +530 -0
- package/ts/classes.server.ts +444 -0
- package/ts/classes.storage.ts +448 -0
- package/ts/classes.submissions.ts +554 -0
- package/ts/classes.transfer.ts +379 -0
- package/ts/coremail.cursor.ts +328 -0
- package/ts/coremail.log.ts +21 -0
- package/ts/coremail.mime.ts +94 -0
- package/ts/coremail.persistence.ts +1156 -0
- package/ts/coremail.quota.ts +214 -0
- package/ts/coremail.selectors.ts +35 -0
- package/ts/coremail.validation.ts +446 -0
- package/ts/index.ts +38 -0
- package/ts/interfaces.ts +109 -0
- package/ts/plugins.ts +11 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import type { ICoreMailModels } from './classes.models.js';
|
|
3
|
+
import type { ICoreMailQuotaCounterRecord } from './coremail.persistence.js';
|
|
4
|
+
export interface ICoreMailQuotaAuthority {
|
|
5
|
+
tenantId: string;
|
|
6
|
+
serviceId: string;
|
|
7
|
+
bindingId: string;
|
|
8
|
+
bindingRevision: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ICoreMailQuotaDescriptor extends ICoreMailQuotaAuthority {
|
|
11
|
+
counterId: plugins.serveZoneInterfaces.data.TCoreMailSha256;
|
|
12
|
+
kind: ICoreMailQuotaCounterRecord['kind'];
|
|
13
|
+
windowStartedAt?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class CoreMailQuotaExceededError extends Error {
|
|
16
|
+
readonly retryAfterMs?: number | undefined;
|
|
17
|
+
constructor(retryAfterMs?: number | undefined);
|
|
18
|
+
}
|
|
19
|
+
export declare const createCoreMailOutboundQuotaDescriptors: (authorityArg: ICoreMailQuotaAuthority, nowArg: number) => {
|
|
20
|
+
minute: ICoreMailQuotaDescriptor;
|
|
21
|
+
day: ICoreMailQuotaDescriptor;
|
|
22
|
+
minuteRetryAfterMs: number;
|
|
23
|
+
dayRetryAfterMs: number;
|
|
24
|
+
};
|
|
25
|
+
export declare const createCoreMailPendingQuotaDescriptor: (authorityArg: ICoreMailQuotaAuthority) => ICoreMailQuotaDescriptor;
|
|
26
|
+
export declare const ensureCoreMailQuotaCounter: (modelsArg: ICoreMailModels, descriptorArg: ICoreMailQuotaDescriptor) => Promise<void>;
|
|
27
|
+
export declare const incrementCoreMailQuotaCounter: (modelsArg: ICoreMailModels, descriptorArg: ICoreMailQuotaDescriptor, limitArg: number, updatedAtArg: number, sessionArg: plugins.smartdata.SmartdataSession, retryAfterMsArg?: number) => Promise<void>;
|
|
28
|
+
export declare const decrementCoreMailQuotaCounter: (modelsArg: ICoreMailModels, descriptorArg: ICoreMailQuotaDescriptor, updatedAtArg: number, sessionArg: plugins.smartdata.SmartdataSession) => Promise<void>;
|
|
29
|
+
export declare const withCoreMailTransaction: <T>(databaseArg: plugins.smartdata.SmartdataDb, callbackArg: (sessionArg: plugins.smartdata.SmartdataSession) => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { createSha256 } from './classes.storage.js';
|
|
3
|
+
export class CoreMailQuotaExceededError extends Error {
|
|
4
|
+
retryAfterMs;
|
|
5
|
+
constructor(retryAfterMs) {
|
|
6
|
+
super('CoreMail quota is exhausted.');
|
|
7
|
+
this.retryAfterMs = retryAfterMs;
|
|
8
|
+
this.name = 'CoreMailQuotaExceededError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const createDescriptor = (authorityArg, kindArg, windowStartedAtArg) => {
|
|
12
|
+
const identity = JSON.stringify({
|
|
13
|
+
tenantId: authorityArg.tenantId,
|
|
14
|
+
serviceId: authorityArg.serviceId,
|
|
15
|
+
bindingId: authorityArg.bindingId,
|
|
16
|
+
bindingRevision: authorityArg.bindingRevision,
|
|
17
|
+
kind: kindArg,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
tenantId: authorityArg.tenantId,
|
|
21
|
+
serviceId: authorityArg.serviceId,
|
|
22
|
+
bindingId: authorityArg.bindingId,
|
|
23
|
+
bindingRevision: authorityArg.bindingRevision,
|
|
24
|
+
counterId: createSha256(identity),
|
|
25
|
+
kind: kindArg,
|
|
26
|
+
...(windowStartedAtArg === undefined
|
|
27
|
+
? {}
|
|
28
|
+
: { windowStartedAt: windowStartedAtArg }),
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export const createCoreMailOutboundQuotaDescriptors = (authorityArg, nowArg) => {
|
|
32
|
+
const minuteStartedAt = Math.floor(nowArg / 60_000) * 60_000;
|
|
33
|
+
const dayStartedAt = Math.floor(nowArg / 86_400_000) * 86_400_000;
|
|
34
|
+
return {
|
|
35
|
+
minute: createDescriptor(authorityArg, 'outbound-minute', minuteStartedAt),
|
|
36
|
+
day: createDescriptor(authorityArg, 'outbound-day', dayStartedAt),
|
|
37
|
+
minuteRetryAfterMs: minuteStartedAt + 60_000 - nowArg,
|
|
38
|
+
dayRetryAfterMs: dayStartedAt + 86_400_000 - nowArg,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export const createCoreMailPendingQuotaDescriptor = (authorityArg) => createDescriptor(authorityArg, 'pending-inbound');
|
|
42
|
+
export const ensureCoreMailQuotaCounter = async (modelsArg, descriptorArg) => {
|
|
43
|
+
const matchesDescriptor = (counterArg) => counterArg.tenantId === descriptorArg.tenantId
|
|
44
|
+
&& counterArg.serviceId === descriptorArg.serviceId
|
|
45
|
+
&& counterArg.bindingId === descriptorArg.bindingId
|
|
46
|
+
&& counterArg.bindingRevision === descriptorArg.bindingRevision
|
|
47
|
+
&& counterArg.kind === descriptorArg.kind;
|
|
48
|
+
const existing = await modelsArg.QuotaCounter.exact.findStoredOne({
|
|
49
|
+
counterId: descriptorArg.counterId,
|
|
50
|
+
});
|
|
51
|
+
if (existing) {
|
|
52
|
+
if (!matchesDescriptor(existing)) {
|
|
53
|
+
throw new Error('CoreMail quota counter identity conflicts with persisted state.');
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const deterministicTimestamp = 0;
|
|
58
|
+
try {
|
|
59
|
+
const result = await modelsArg.QuotaCounter.exact.insert({
|
|
60
|
+
...descriptorArg,
|
|
61
|
+
count: 0,
|
|
62
|
+
createdAt: deterministicTimestamp,
|
|
63
|
+
updatedAt: deterministicTimestamp,
|
|
64
|
+
});
|
|
65
|
+
if (result.status !== 'conflict') {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (!(error instanceof plugins.smartdata.SmartdataExactPersistenceError)
|
|
71
|
+
|| error.code !== 'unique_conflict') {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const concurrent = await modelsArg.QuotaCounter.exact.findStoredOne({
|
|
76
|
+
counterId: descriptorArg.counterId,
|
|
77
|
+
});
|
|
78
|
+
if (!concurrent || !matchesDescriptor(concurrent)) {
|
|
79
|
+
throw new Error('CoreMail quota counter identity conflicts with persisted state.');
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
export const incrementCoreMailQuotaCounter = async (modelsArg, descriptorArg, limitArg, updatedAtArg, sessionArg, retryAfterMsArg) => {
|
|
83
|
+
const counter = await modelsArg.QuotaCounter.exact.findStoredOne({ counterId: descriptorArg.counterId }, { session: sessionArg });
|
|
84
|
+
if (!counter) {
|
|
85
|
+
throw new Error('CoreMail quota counter is unavailable.');
|
|
86
|
+
}
|
|
87
|
+
if (descriptorArg.windowStartedAt !== undefined
|
|
88
|
+
&& counter.windowStartedAt !== descriptorArg.windowStartedAt) {
|
|
89
|
+
if (counter.windowStartedAt !== undefined
|
|
90
|
+
&& descriptorArg.windowStartedAt < counter.windowStartedAt) {
|
|
91
|
+
throw new Error('CoreMail quota window fence advanced.');
|
|
92
|
+
}
|
|
93
|
+
const reset = await modelsArg.QuotaCounter.exact.transition({
|
|
94
|
+
current: counter,
|
|
95
|
+
change: (modelArg) => {
|
|
96
|
+
modelArg.windowStartedAt = descriptorArg.windowStartedAt;
|
|
97
|
+
modelArg.count = 1;
|
|
98
|
+
modelArg.updatedAt = updatedAtArg;
|
|
99
|
+
},
|
|
100
|
+
}, { session: sessionArg });
|
|
101
|
+
if (reset.status !== 'transitioned') {
|
|
102
|
+
throw new Error('CoreMail quota counter transition was contended.');
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (counter.count >= limitArg) {
|
|
107
|
+
throw new CoreMailQuotaExceededError(retryAfterMsArg);
|
|
108
|
+
}
|
|
109
|
+
const update = await modelsArg.QuotaCounter.exact.transition({
|
|
110
|
+
current: counter,
|
|
111
|
+
change: (modelArg) => {
|
|
112
|
+
modelArg.count += 1;
|
|
113
|
+
modelArg.updatedAt = updatedAtArg;
|
|
114
|
+
},
|
|
115
|
+
}, { session: sessionArg });
|
|
116
|
+
if (update.status !== 'transitioned') {
|
|
117
|
+
throw new Error('CoreMail quota counter transition was contended.');
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export const decrementCoreMailQuotaCounter = async (modelsArg, descriptorArg, updatedAtArg, sessionArg) => {
|
|
121
|
+
const counter = await modelsArg.QuotaCounter.exact.findStoredOne({ counterId: descriptorArg.counterId }, { session: sessionArg });
|
|
122
|
+
if (!counter || counter.count <= 0) {
|
|
123
|
+
throw new Error('CoreMail pending-inbound quota counter would underflow.');
|
|
124
|
+
}
|
|
125
|
+
const update = await modelsArg.QuotaCounter.exact.transition({
|
|
126
|
+
current: counter,
|
|
127
|
+
change: (modelArg) => {
|
|
128
|
+
modelArg.count -= 1;
|
|
129
|
+
modelArg.updatedAt = updatedAtArg;
|
|
130
|
+
},
|
|
131
|
+
}, { session: sessionArg });
|
|
132
|
+
if (update.status !== 'transitioned') {
|
|
133
|
+
throw new Error('CoreMail quota counter transition was contended.');
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
export const withCoreMailTransaction = async (databaseArg, callbackArg) => {
|
|
137
|
+
const session = databaseArg.createSession();
|
|
138
|
+
try {
|
|
139
|
+
const result = await session.withTransaction(callbackArg);
|
|
140
|
+
if (result === undefined) {
|
|
141
|
+
throw new Error('CoreMail transaction did not commit a result.');
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
await session.close();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZW1haWwucXVvdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jb3JlbWFpbC5xdW90YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFnQnBELE1BQU0sT0FBTywwQkFBMkIsU0FBUSxLQUFLO0lBQ2hCO0lBQW5DLFlBQW1DLFlBQXFCO1FBQ3RELEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1FBREwsaUJBQVksR0FBWixZQUFZLENBQVM7UUFFdEQsSUFBSSxDQUFDLElBQUksR0FBRyw0QkFBNEIsQ0FBQztJQUMzQyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLGdCQUFnQixHQUFHLENBQ3ZCLFlBQXFDLEVBQ3JDLE9BQTRDLEVBQzVDLGtCQUEyQixFQUNELEVBQUU7SUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUM5QixRQUFRLEVBQUUsWUFBWSxDQUFDLFFBQVE7UUFDL0IsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUFTO1FBQ2pDLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUztRQUNqQyxlQUFlLEVBQUUsWUFBWSxDQUFDLGVBQWU7UUFDN0MsSUFBSSxFQUFFLE9BQU87S0FDZCxDQUFDLENBQUM7SUFDSCxPQUFPO1FBQ0wsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRO1FBQy9CLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUztRQUNqQyxTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVM7UUFDakMsZUFBZSxFQUFFLFlBQVksQ0FBQyxlQUFlO1FBQzdDLFNBQVMsRUFBRSxZQUFZLENBQUMsUUFBUSxDQUFDO1FBQ2pDLElBQUksRUFBRSxPQUFPO1FBQ2IsR0FBRyxDQUFDLGtCQUFrQixLQUFLLFNBQVM7WUFDbEMsQ0FBQyxDQUFDLEVBQUU7WUFDSixDQUFDLENBQUMsRUFBRSxl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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const requireCoreMailIdentifier: (valueArg: unknown, labelArg: string) => string;
|
|
2
|
+
export declare const requireCoreMailUuid: (valueArg: unknown, labelArg: string) => string;
|
|
3
|
+
export declare const requireCoreMailSafeInteger: (valueArg: unknown, labelArg: string, minimumArg?: number) => number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const identifierRegex = /^[A-Za-z0-9](?:[A-Za-z0-9._:-]{0,126}[A-Za-z0-9])?$/;
|
|
2
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
3
|
+
export const requireCoreMailIdentifier = (valueArg, labelArg) => {
|
|
4
|
+
if (typeof valueArg !== 'string' || !identifierRegex.test(valueArg)) {
|
|
5
|
+
throw new Error(`${labelArg} must be a canonical CoreMail identifier.`);
|
|
6
|
+
}
|
|
7
|
+
return valueArg;
|
|
8
|
+
};
|
|
9
|
+
export const requireCoreMailUuid = (valueArg, labelArg) => {
|
|
10
|
+
if (typeof valueArg !== 'string' || !uuidRegex.test(valueArg)) {
|
|
11
|
+
throw new Error(`${labelArg} must be a canonical UUID.`);
|
|
12
|
+
}
|
|
13
|
+
return valueArg;
|
|
14
|
+
};
|
|
15
|
+
export const requireCoreMailSafeInteger = (valueArg, labelArg, minimumArg = 0) => {
|
|
16
|
+
if (!Number.isSafeInteger(valueArg) || Number(valueArg) < minimumArg) {
|
|
17
|
+
throw new Error(`${labelArg} must be a bounded safe integer.`);
|
|
18
|
+
}
|
|
19
|
+
return Number(valueArg);
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZW1haWwuc2VsZWN0b3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY29yZW1haWwuc2VsZWN0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sZUFBZSxHQUNuQixxREFBcUQsQ0FBQztBQUN4RCxNQUFNLFNBQVMsR0FDYiwyRUFBMkUsQ0FBQztBQUU5RSxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxRQUFpQixFQUNqQixRQUFnQixFQUNSLEVBQUU7SUFDVixJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUNwRSxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSwyQ0FBMkMsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUNqQyxRQUFpQixFQUNqQixRQUFnQixFQUNSLEVBQUU7SUFDVixJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSw0QkFBNEIsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxDQUN4QyxRQUFpQixFQUNqQixRQUFnQixFQUNoQixVQUFVLEdBQUcsQ0FBQyxFQUNOLEVBQUU7SUFDVixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsVUFBVSxFQUFFLENBQUM7UUFDckUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsa0NBQWtDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDMUIsQ0FBQyxDQUFDIn0=
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
type TMessage = plugins.serveZoneInterfaces.data.ICoreMailOutboundMessageDescriptor;
|
|
3
|
+
export declare const normalizeCoreMailMailboxAddress: (valueArg: unknown) => string;
|
|
4
|
+
export declare const normalizeCoreMailEnvelope: (valueArg: unknown) => plugins.serveZoneInterfaces.data.ICoreMailEnvelope;
|
|
5
|
+
export declare const normalizeCoreMailConnectionInfo: (valueArg: unknown) => plugins.serveZoneInterfaces.data.IMailConnectionInfo;
|
|
6
|
+
export declare const normalizeCoreMailGatewayMessage: (valueArg: unknown) => plugins.serveZoneInterfaces.data.ICoreMailGatewayMessageDescriptor;
|
|
7
|
+
export declare const normalizeCoreMailOutboundMessage: (valueArg: unknown, bindingArg: plugins.serveZoneInterfaces.data.ICoreMailBindingDesiredState) => TMessage;
|
|
8
|
+
export declare const createCoreMailSubmissionDigest: (idempotencyKeyArg: string, messageArg: TMessage) => plugins.serveZoneInterfaces.data.TCoreMailSha256;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { createSha256 } from './classes.storage.js';
|
|
3
|
+
const mailboxLocalPartRegex = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+$/;
|
|
4
|
+
const mailboxDomainLabelRegex = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
5
|
+
const idRegex = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
6
|
+
const contentTypeRegex = /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+(?:; ?[a-z0-9!#$&^_.+-]+=(?:"[^"\r\n]{1,100}"|[a-z0-9!#$&^_.+-]+))*$/i;
|
|
7
|
+
const requirePlainRecord = (valueArg, labelArg) => {
|
|
8
|
+
if (!valueArg
|
|
9
|
+
|| typeof valueArg !== 'object'
|
|
10
|
+
|| Array.isArray(valueArg)
|
|
11
|
+
|| (Object.getPrototypeOf(valueArg) !== Object.prototype
|
|
12
|
+
&& Object.getPrototypeOf(valueArg) !== null)) {
|
|
13
|
+
throw new Error(`${labelArg} must be a plain object.`);
|
|
14
|
+
}
|
|
15
|
+
return valueArg;
|
|
16
|
+
};
|
|
17
|
+
const requireExactKeys = (recordArg, requiredArg, optionalArg, labelArg) => {
|
|
18
|
+
const allowed = new Set([...requiredArg, ...optionalArg]);
|
|
19
|
+
if (requiredArg.some((keyArg) => !Object.hasOwn(recordArg, keyArg))
|
|
20
|
+
|| Object.keys(recordArg).some((keyArg) => !allowed.has(keyArg))) {
|
|
21
|
+
throw new Error(`${labelArg} contains missing or unknown fields.`);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const normalizeCoreMailMailboxAddress = (valueArg) => {
|
|
25
|
+
if (typeof valueArg !== 'string'
|
|
26
|
+
|| valueArg.length < 3
|
|
27
|
+
|| Buffer.byteLength(valueArg, 'utf8') > 254
|
|
28
|
+
|| valueArg !== valueArg.toLowerCase()) {
|
|
29
|
+
throw new Error('CoreMail mailbox must be canonical lowercase ASCII.');
|
|
30
|
+
}
|
|
31
|
+
const atIndex = valueArg.lastIndexOf('@');
|
|
32
|
+
const localPart = atIndex > 0 ? valueArg.slice(0, atIndex) : '';
|
|
33
|
+
const domain = atIndex > 0 ? valueArg.slice(atIndex + 1) : '';
|
|
34
|
+
const labels = domain.split('.');
|
|
35
|
+
if (localPart.length === 0
|
|
36
|
+
|| localPart.length > 64
|
|
37
|
+
|| !mailboxLocalPartRegex.test(localPart)
|
|
38
|
+
|| localPart.startsWith('.')
|
|
39
|
+
|| localPart.endsWith('.')
|
|
40
|
+
|| localPart.includes('..')
|
|
41
|
+
|| domain.length === 0
|
|
42
|
+
|| domain.length > 253
|
|
43
|
+
|| labels.length < 2
|
|
44
|
+
|| labels.some((labelArg) => !mailboxDomainLabelRegex.test(labelArg))) {
|
|
45
|
+
throw new Error('CoreMail mailbox is invalid.');
|
|
46
|
+
}
|
|
47
|
+
return valueArg;
|
|
48
|
+
};
|
|
49
|
+
export const normalizeCoreMailEnvelope = (valueArg) => {
|
|
50
|
+
const value = requirePlainRecord(valueArg, 'envelope');
|
|
51
|
+
requireExactKeys(value, ['mailFrom', 'rcptTo'], [], 'envelope');
|
|
52
|
+
if (typeof value.mailFrom !== 'string'
|
|
53
|
+
|| !Array.isArray(value.rcptTo)
|
|
54
|
+
|| value.rcptTo.length === 0
|
|
55
|
+
|| value.rcptTo.length > 100) {
|
|
56
|
+
throw new Error('CoreMail gateway envelope is invalid.');
|
|
57
|
+
}
|
|
58
|
+
const mailFrom = value.mailFrom === ''
|
|
59
|
+
? ''
|
|
60
|
+
: normalizeCoreMailMailboxAddress(value.mailFrom);
|
|
61
|
+
const rcptTo = value.rcptTo.map(normalizeCoreMailMailboxAddress);
|
|
62
|
+
if (new Set(rcptTo).size !== rcptTo.length) {
|
|
63
|
+
throw new Error('CoreMail gateway envelope contains duplicate recipients.');
|
|
64
|
+
}
|
|
65
|
+
return { mailFrom, rcptTo };
|
|
66
|
+
};
|
|
67
|
+
export const normalizeCoreMailConnectionInfo = (valueArg) => {
|
|
68
|
+
const value = requirePlainRecord(valueArg, 'connectionInfo');
|
|
69
|
+
requireExactKeys(value, ['protocol'], [
|
|
70
|
+
'remoteAddress',
|
|
71
|
+
'proxyAddress',
|
|
72
|
+
'heloName',
|
|
73
|
+
'tls',
|
|
74
|
+
'authUsername',
|
|
75
|
+
'authenticatedCredentialId',
|
|
76
|
+
], 'connectionInfo');
|
|
77
|
+
if (value.protocol !== 'smtp'
|
|
78
|
+
&& value.protocol !== 'submission'
|
|
79
|
+
&& value.protocol !== 'api') {
|
|
80
|
+
throw new Error('CoreMail gateway connection protocol is invalid.');
|
|
81
|
+
}
|
|
82
|
+
for (const key of [
|
|
83
|
+
'remoteAddress',
|
|
84
|
+
'proxyAddress',
|
|
85
|
+
'heloName',
|
|
86
|
+
'authUsername',
|
|
87
|
+
'authenticatedCredentialId',
|
|
88
|
+
]) {
|
|
89
|
+
if (value[key] !== undefined
|
|
90
|
+
&& (typeof value[key] !== 'string'
|
|
91
|
+
|| value[key].length === 0
|
|
92
|
+
|| Buffer.byteLength(value[key], 'utf8') > 512
|
|
93
|
+
|| value[key].trim() !== value[key])) {
|
|
94
|
+
throw new Error(`CoreMail gateway connection ${key} is invalid.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (value.tls !== undefined && typeof value.tls !== 'boolean') {
|
|
98
|
+
throw new Error('CoreMail gateway connection TLS state is invalid.');
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
protocol: value.protocol,
|
|
102
|
+
...(value.remoteAddress === undefined
|
|
103
|
+
? {}
|
|
104
|
+
: { remoteAddress: value.remoteAddress }),
|
|
105
|
+
...(value.proxyAddress === undefined
|
|
106
|
+
? {}
|
|
107
|
+
: { proxyAddress: value.proxyAddress }),
|
|
108
|
+
...(value.heloName === undefined
|
|
109
|
+
? {}
|
|
110
|
+
: { heloName: value.heloName }),
|
|
111
|
+
...(value.tls === undefined ? {} : { tls: value.tls }),
|
|
112
|
+
...(value.authUsername === undefined
|
|
113
|
+
? {}
|
|
114
|
+
: { authUsername: value.authUsername }),
|
|
115
|
+
...(value.authenticatedCredentialId === undefined
|
|
116
|
+
? {}
|
|
117
|
+
: {
|
|
118
|
+
authenticatedCredentialId: value.authenticatedCredentialId,
|
|
119
|
+
}),
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
export const normalizeCoreMailGatewayMessage = (valueArg) => {
|
|
123
|
+
const value = requirePlainRecord(valueArg, 'gatewayMessage');
|
|
124
|
+
requireExactKeys(value, ['envelope', 'rawMime'], [], 'gatewayMessage');
|
|
125
|
+
const rawMime = requirePlainRecord(value.rawMime, 'gatewayMessage.rawMime');
|
|
126
|
+
requireExactKeys(rawMime, ['sha256', 'lengthBytes', 'contentType'], [], 'gatewayMessage.rawMime');
|
|
127
|
+
if (rawMime.contentType !== 'message/rfc822'
|
|
128
|
+
|| !Number.isSafeInteger(rawMime.lengthBytes)
|
|
129
|
+
|| Number(rawMime.lengthBytes) < 1
|
|
130
|
+
|| Number(rawMime.lengthBytes)
|
|
131
|
+
> plugins.serveZoneInterfaces.data.coreMailLimits.serializedMimeBytes) {
|
|
132
|
+
throw new Error('CoreMail gateway MIME descriptor is invalid.');
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
envelope: normalizeCoreMailEnvelope(value.envelope),
|
|
136
|
+
rawMime: {
|
|
137
|
+
sha256: plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(rawMime.sha256),
|
|
138
|
+
lengthBytes: Number(rawMime.lengthBytes),
|
|
139
|
+
contentType: 'message/rfc822',
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
const normalizeDisplayText = (valueArg, labelArg, maximumBytesArg, allowEmptyArg = false) => {
|
|
144
|
+
if (typeof valueArg !== 'string'
|
|
145
|
+
|| (!allowEmptyArg && valueArg.length === 0)
|
|
146
|
+
|| valueArg.trim() !== valueArg
|
|
147
|
+
|| /[\u0000-\u001f\u007f]/.test(valueArg)
|
|
148
|
+
|| Buffer.byteLength(valueArg, 'utf8') > maximumBytesArg) {
|
|
149
|
+
throw new Error(`${labelArg} is invalid.`);
|
|
150
|
+
}
|
|
151
|
+
return valueArg;
|
|
152
|
+
};
|
|
153
|
+
const normalizeMailbox = (valueArg, labelArg) => {
|
|
154
|
+
const value = requirePlainRecord(valueArg, labelArg);
|
|
155
|
+
requireExactKeys(value, ['address'], ['displayName'], labelArg);
|
|
156
|
+
return {
|
|
157
|
+
address: normalizeCoreMailMailboxAddress(value.address),
|
|
158
|
+
...(value.displayName === undefined
|
|
159
|
+
? {}
|
|
160
|
+
: {
|
|
161
|
+
displayName: normalizeDisplayText(value.displayName, `${labelArg}.displayName`, 256),
|
|
162
|
+
}),
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
const normalizeMailboxArray = (valueArg, labelArg, allowEmptyArg = false) => {
|
|
166
|
+
if (!Array.isArray(valueArg)
|
|
167
|
+
|| (!allowEmptyArg && valueArg.length === 0)
|
|
168
|
+
|| valueArg.length > 100) {
|
|
169
|
+
throw new Error(`${labelArg} must be a bounded mailbox array.`);
|
|
170
|
+
}
|
|
171
|
+
const normalized = valueArg.map((entryArg, indexArg) => normalizeMailbox(entryArg, `${labelArg}[${indexArg}]`));
|
|
172
|
+
const addresses = normalized.map((entryArg) => entryArg.address);
|
|
173
|
+
if (new Set(addresses).size !== addresses.length) {
|
|
174
|
+
throw new Error(`${labelArg} contains duplicate addresses.`);
|
|
175
|
+
}
|
|
176
|
+
return normalized;
|
|
177
|
+
};
|
|
178
|
+
const forbiddenHeaderNames = new Set([
|
|
179
|
+
'bcc',
|
|
180
|
+
'cc',
|
|
181
|
+
'content-transfer-encoding',
|
|
182
|
+
'content-type',
|
|
183
|
+
'date',
|
|
184
|
+
'dkim-signature',
|
|
185
|
+
'from',
|
|
186
|
+
'message-id',
|
|
187
|
+
'mime-version',
|
|
188
|
+
'received',
|
|
189
|
+
'reply-to',
|
|
190
|
+
'return-path',
|
|
191
|
+
'subject',
|
|
192
|
+
'to',
|
|
193
|
+
]);
|
|
194
|
+
const normalizePart = (valueArg, labelArg) => {
|
|
195
|
+
const value = requirePlainRecord(valueArg, labelArg);
|
|
196
|
+
requireExactKeys(value, ['partId', 'kind', 'contentType', 'sha256', 'lengthBytes'], ['filename', 'contentId'], labelArg);
|
|
197
|
+
if (typeof value.partId !== 'string' || !idRegex.test(value.partId)) {
|
|
198
|
+
throw new Error(`${labelArg}.partId is invalid.`);
|
|
199
|
+
}
|
|
200
|
+
if (value.kind !== 'text' && value.kind !== 'html' && value.kind !== 'attachment') {
|
|
201
|
+
throw new Error(`${labelArg}.kind is invalid.`);
|
|
202
|
+
}
|
|
203
|
+
if (typeof value.contentType !== 'string' || !contentTypeRegex.test(value.contentType)) {
|
|
204
|
+
throw new Error(`${labelArg}.contentType is invalid.`);
|
|
205
|
+
}
|
|
206
|
+
const sha256 = plugins.serveZoneInterfaces.data.normalizeCoreMailSha256(value.sha256);
|
|
207
|
+
if (!Number.isSafeInteger(value.lengthBytes) || Number(value.lengthBytes) < 0) {
|
|
208
|
+
throw new Error(`${labelArg}.lengthBytes is invalid.`);
|
|
209
|
+
}
|
|
210
|
+
const lengthBytes = Number(value.lengthBytes);
|
|
211
|
+
const maximum = value.kind === 'text'
|
|
212
|
+
? plugins.serveZoneInterfaces.data.coreMailLimits.textPartBytes
|
|
213
|
+
: value.kind === 'html'
|
|
214
|
+
? plugins.serveZoneInterfaces.data.coreMailLimits.htmlPartBytes
|
|
215
|
+
: plugins.serveZoneInterfaces.data.coreMailLimits.attachmentBytes;
|
|
216
|
+
if (lengthBytes > maximum) {
|
|
217
|
+
throw new Error(`${labelArg} exceeds its content budget.`);
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
partId: value.partId,
|
|
221
|
+
kind: value.kind,
|
|
222
|
+
contentType: value.contentType,
|
|
223
|
+
sha256,
|
|
224
|
+
lengthBytes,
|
|
225
|
+
...(value.filename === undefined
|
|
226
|
+
? {}
|
|
227
|
+
: {
|
|
228
|
+
filename: normalizeDisplayText(value.filename, `${labelArg}.filename`, 512),
|
|
229
|
+
}),
|
|
230
|
+
...(value.contentId === undefined
|
|
231
|
+
? {}
|
|
232
|
+
: {
|
|
233
|
+
contentId: normalizeDisplayText(value.contentId, `${labelArg}.contentId`, 256),
|
|
234
|
+
}),
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
export const normalizeCoreMailOutboundMessage = (valueArg, bindingArg) => {
|
|
238
|
+
const value = requirePlainRecord(valueArg, 'message');
|
|
239
|
+
requireExactKeys(value, ['sender', 'recipients', 'subject', 'parts'], ['replyTo', 'headers'], 'message');
|
|
240
|
+
const sender = normalizeMailbox(value.sender, 'message.sender');
|
|
241
|
+
if (!bindingArg.allowedSenders.includes(sender.address)) {
|
|
242
|
+
throw new Error('CoreMail sender is not authorized by the binding.');
|
|
243
|
+
}
|
|
244
|
+
const recipientsRecord = requirePlainRecord(value.recipients, 'message.recipients');
|
|
245
|
+
requireExactKeys(recipientsRecord, ['to'], ['cc', 'bcc'], 'message.recipients');
|
|
246
|
+
const to = normalizeMailboxArray(recipientsRecord.to, 'message.recipients.to');
|
|
247
|
+
const cc = recipientsRecord.cc === undefined
|
|
248
|
+
? undefined
|
|
249
|
+
: normalizeMailboxArray(recipientsRecord.cc, 'message.recipients.cc', true);
|
|
250
|
+
const bcc = recipientsRecord.bcc === undefined
|
|
251
|
+
? undefined
|
|
252
|
+
: normalizeMailboxArray(recipientsRecord.bcc, 'message.recipients.bcc', true);
|
|
253
|
+
const allRecipientAddresses = [...to, ...(cc ?? []), ...(bcc ?? [])]
|
|
254
|
+
.map((entryArg) => entryArg.address);
|
|
255
|
+
if (allRecipientAddresses.length === 0
|
|
256
|
+
|| new Set(allRecipientAddresses).size !== allRecipientAddresses.length) {
|
|
257
|
+
throw new Error('CoreMail recipients must be globally unique and non-empty.');
|
|
258
|
+
}
|
|
259
|
+
const partsValue = value.parts;
|
|
260
|
+
if (!Array.isArray(partsValue) || partsValue.length === 0) {
|
|
261
|
+
throw new Error('CoreMail message requires at least one part.');
|
|
262
|
+
}
|
|
263
|
+
const parts = partsValue.map((entryArg, indexArg) => normalizePart(entryArg, `message.parts[${indexArg}]`));
|
|
264
|
+
if (new Set(parts.map((partArg) => partArg.partId)).size !== parts.length
|
|
265
|
+
|| parts.filter((partArg) => partArg.kind === 'text').length > 1
|
|
266
|
+
|| parts.filter((partArg) => partArg.kind === 'html').length > 1
|
|
267
|
+
|| parts.filter((partArg) => partArg.kind === 'attachment').length >
|
|
268
|
+
plugins.serveZoneInterfaces.data.coreMailLimits.attachmentCount
|
|
269
|
+
|| parts
|
|
270
|
+
.filter((partArg) => partArg.kind === 'attachment')
|
|
271
|
+
.reduce((totalArg, partArg) => totalArg + partArg.lengthBytes, 0) >
|
|
272
|
+
plugins.serveZoneInterfaces.data.coreMailLimits.aggregateAttachmentBytes) {
|
|
273
|
+
throw new Error('CoreMail message part set is invalid.');
|
|
274
|
+
}
|
|
275
|
+
const headers = value.headers === undefined
|
|
276
|
+
? undefined
|
|
277
|
+
: (() => {
|
|
278
|
+
if (!Array.isArray(value.headers) || value.headers.length > 32) {
|
|
279
|
+
throw new Error('CoreMail custom headers are invalid.');
|
|
280
|
+
}
|
|
281
|
+
const seen = new Set();
|
|
282
|
+
return value.headers.map((entryArg, indexArg) => {
|
|
283
|
+
const record = requirePlainRecord(entryArg, `message.headers[${indexArg}]`);
|
|
284
|
+
requireExactKeys(record, ['name', 'value'], [], `message.headers[${indexArg}]`);
|
|
285
|
+
if (typeof record.name !== 'string'
|
|
286
|
+
|| !/^[A-Za-z][A-Za-z0-9-]{0,62}$/.test(record.name)) {
|
|
287
|
+
throw new Error('CoreMail header name is invalid.');
|
|
288
|
+
}
|
|
289
|
+
const lowerName = record.name.toLowerCase();
|
|
290
|
+
if (forbiddenHeaderNames.has(lowerName) || seen.has(lowerName)) {
|
|
291
|
+
throw new Error('CoreMail header is transport-owned or duplicated.');
|
|
292
|
+
}
|
|
293
|
+
seen.add(lowerName);
|
|
294
|
+
return {
|
|
295
|
+
name: record.name,
|
|
296
|
+
value: normalizeDisplayText(record.value, `message.headers[${indexArg}].value`, 768, true),
|
|
297
|
+
};
|
|
298
|
+
});
|
|
299
|
+
})();
|
|
300
|
+
return {
|
|
301
|
+
sender,
|
|
302
|
+
recipients: {
|
|
303
|
+
to,
|
|
304
|
+
...(cc ? { cc } : {}),
|
|
305
|
+
...(bcc ? { bcc } : {}),
|
|
306
|
+
},
|
|
307
|
+
...(value.replyTo === undefined
|
|
308
|
+
? {}
|
|
309
|
+
: { replyTo: normalizeMailbox(value.replyTo, 'message.replyTo') }),
|
|
310
|
+
subject: normalizeDisplayText(value.subject, 'message.subject', 768, true),
|
|
311
|
+
...(headers ? { headers } : {}),
|
|
312
|
+
parts,
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
export const createCoreMailSubmissionDigest = (idempotencyKeyArg, messageArg) => {
|
|
316
|
+
if (!idRegex.test(idempotencyKeyArg)) {
|
|
317
|
+
throw new Error('CoreMail idempotency key is invalid.');
|
|
318
|
+
}
|
|
319
|
+
return createSha256(JSON.stringify({
|
|
320
|
+
schemaVersion: 1,
|
|
321
|
+
idempotencyKey: idempotencyKeyArg,
|
|
322
|
+
message: messageArg,
|
|
323
|
+
}));
|
|
324
|
+
};
|
|
325
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZW1haWwudmFsaWRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NvcmVtYWlsLnZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBTXBELE1BQU0scUJBQXFCLEdBQUcsaUNBQWlDLENBQUM7QUFDaEUsTUFBTSx1QkFBdUIsR0FBRyx3Q0FBd0MsQ0FBQztBQUN6RSxNQUFNLE9BQU8sR0FBRyxxQ0FBcUMsQ0FBQztBQUN0RCxNQUFNLGdCQUFnQixHQUNwQiw4R0FBOEcsQ0FBQztBQUVqSCxNQUFNLGtCQUFrQixHQUFHLENBQ3pCLFFBQWlCLEVBQ2pCLFFBQWdCLEVBQ1MsRUFBRTtJQUMzQixJQUNFLENBQUMsUUFBUTtXQUNOLE9BQU8sUUFBUSxLQUFLLFFBQVE7V0FDNUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7V0FDdkIsQ0FDRCxNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTO2VBQ2pELE1BQU0sQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxDQUM1QyxFQUNELENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSwwQkFBMEIsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFDRCxPQUFPLFFBQW1DLENBQUM7QUFDN0MsQ0FBQyxDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FBRyxDQUN2QixTQUFrQyxFQUNsQyxXQUFxQixFQUNyQixXQUFxQixFQUNyQixRQUFnQixFQUNWLEVBQUU7SUFDUixNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsV0FBVyxFQUFFLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUMxRCxJQUNFLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7V0FDNUQsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUNoRSxDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsc0NBQXNDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQUcsQ0FBQyxRQUFpQixFQUFVLEVBQUU7SUFDM0UsSUFDRSxPQUFPLFFBQVEsS0FBSyxRQUFRO1dBQ3pCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUNuQixNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsR0FBRyxHQUFHO1dBQ3pDLFFBQVEsS0FBSyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQ3RDLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNoRSxNQUFNLE1BQU0sR0FBRyxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzlELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFDRSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUM7V0FDbkIsU0FBUyxDQUFDLE1BQU0sR0FBRyxFQUFFO1dBQ3JCLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztXQUN0QyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQztXQUN6QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQztXQUN2QixTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztXQUN4QixNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7V0FDbkIsTUFBTSxDQUFDLE1BQU0sR0FBRyxHQUFHO1dBQ25CLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUNqQixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUNyRSxDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxRQUFpQixFQUNtQyxFQUFFO0lBQ3RELE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN2RCxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2hFLElBQ0UsT0FBTyxLQUFLLENBQUMsUUFBUSxLQUFLLFFBQVE7V0FDL0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7V0FDNUIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztXQUN6QixLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQzVCLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLEtBQUssRUFBRTtRQUNwQyxDQUFDLENBQUMsRUFBRTtRQUNKLENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUNqRSxJQUFJLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0MsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFDRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQzlCLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLCtCQUErQixHQUFHLENBQzdDLFFBQWlCLEVBQ3FDLEVBQUU7SUFDeEQsTUFBTSxLQUFLLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDN0QsZ0JBQWdCLENBQ2QsS0FBSyxFQUNMLENBQUMsVUFBVSxDQUFDLEVBQ1o7UUFDRSxlQUFlO1FBQ2YsY0FBYztRQUNkLFVBQVU7UUFDVixLQUFLO1FBQ0wsY0FBYztRQUNkLDJCQUEyQjtLQUM1QixFQUNELGdCQUFnQixDQUNqQixDQUFDO0lBQ0YsSUFDRSxLQUFLLENBQUMsUUFBUSxLQUFLLE1BQU07V0FDdEIsS0FBSyxDQUFDLFFBQVEsS0FBSyxZQUFZO1dBQy9CLEtBQUssQ0FBQyxRQUFRLEtBQUssS0FBSyxFQUMzQixDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7SUFDRCxLQUFLLE1BQU0sR0FBRyxJQUFJO1FBQ2hCLGVBQWU7UUFDZixjQUFjO1FBQ2QsVUFBVTtRQUNWLGNBQWM7UUFDZCwyQkFBMkI7S0FDbkIsRUFBRSxDQUFDO1FBQ1gsSUFDRSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssU0FBUztlQUNyQixDQUNELE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLFFBQVE7bUJBQzNCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQzttQkFDdkIsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDLEdBQUcsR0FBRzttQkFDM0MsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FDcEMsRUFDRCxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsR0FBRyxjQUFjLENBQUMsQ0FBQztRQUNwRSxDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxTQUFTLElBQUksT0FBTyxLQUFLLENBQUMsR0FBRyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzlELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsT0FBTztRQUNMLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUTtRQUN4QixHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsS0FBSyxTQUFTO1lBQ25DLENBQUMsQ0FBQyxFQUFFO1lBQ0osQ0FBQyxDQUFDLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxhQUF1QixFQUFFLENBQUM7UUFDckQsR0FBRyxDQUFDLEtBQUssQ0FBQyxZQUFZLEtBQUssU0FBUztZQUNsQyxDQUFDLENBQUMsRUFBRTtZQUNKLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBc0IsRUFBRSxDQUFDO1FBQ25ELEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLFNBQVM7WUFDOUIsQ0FBQyxDQUFDLEVBQUU7WUFDSixDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQWtCLEVBQUUsQ0FBQztRQUMzQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3RELEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxLQUFLLFNBQVM7WUFDbEMsQ0FBQyxDQUFDLEVBQUU7WUFDSixDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQXNCLEVBQUUsQ0FBQztRQUNuRCxHQUFHLENBQUMsS0FBSyxDQUFDLHlCQUF5QixLQUFLLFNBQVM7WUFDL0MsQ0FBQyxDQUFDLEVBQUU7WUFDSixDQUFDLENBQUM7Z0JBQ0UseUJBQXlCLEVBQ3ZCLEtBQUssQ0FBQyx5QkFBbUM7YUFDNUMsQ0FBQztLQUNQLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSwrQkFBK0IsR0FBRyxDQUM3QyxRQUFpQixFQUNtRCxFQUFFO0lBQ3RFLE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzdELGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUN2RSxNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLHdCQUF3QixDQUFDLENBQUM7SUFDNUUsZ0JBQWdCLENBQ2QsT0FBTyxFQUNQLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxhQUFhLENBQUMsRUFDeEMsRUFBRSxFQUNGLHdCQUF3QixDQUN6QixDQUFDO0lBQ0YsSUFDRSxPQUFPLENBQUMsV0FBVyxLQUFLLGdCQUFnQjtXQUNyQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztXQUMxQyxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUM7V0FDL0IsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUM7Y0FDMUIsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsbUJBQW1CLEVBQ3ZFLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUNELE9BQU87UUFDTCxRQUFRLEVBQUUseUJBQXlCLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQztRQUNuRCxPQUFPLEVBQUU7WUFDUCxNQUFNLEVBQUUsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FDOUQsT0FBTyxDQUFDLE1BQU0sQ0FDZjtZQUNELFdBQVcsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztZQUN4QyxXQUFXLEVBQUUsZ0JBQWdCO1NBQzlCO0tBQ0YsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGLE1BQU0sb0JBQW9CLEdBQUcsQ0FDM0IsUUFBaUIsRUFDakIsUUFBZ0IsRUFDaEIsZUFBdUIsRUFDdkIsYUFBYSxHQUFHLEtBQUssRUFDYixFQUFFO0lBQ1YsSUFDRSxPQUFPLFFBQVEsS0FBSyxRQUFRO1dBQ3pCLENBQUMsQ0FBQyxhQUFhLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7V0FDekMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLFFBQVE7V0FDNUIsdUJBQXVCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztXQUN0QyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsR0FBRyxlQUFlLEVBQ3hELENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSxjQUFjLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLFFBQWlCLEVBQUUsUUFBZ0IsRUFBWSxFQUFFO0lBQ3pFLE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2hFLE9BQU87UUFDTCxPQUFPLEVBQUUsK0JBQStCLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUN2RCxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsS0FBSyxTQUFTO1lBQ2pDLENBQUMsQ0FBQyxFQUFFO1lBQ0osQ0FBQyxDQUFDO2dCQUNFLFdBQVcsRUFBRSxvQkFBb0IsQ0FDL0IsS0FBSyxDQUFDLFdBQVcsRUFDakIsR0FBRyxRQUFRLGNBQWMsRUFDekIsR0FBRyxDQUNKO2FBQ0YsQ0FBQztLQUNQLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLHFCQUFxQixHQUFHLENBQzVCLFFBQWlCLEVBQ2pCLFFBQWdCLEVBQ2hCLGFBQWEsR0FBRyxLQUFLLEVBQ1QsRUFBRTtJQUNkLElBQ0UsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztXQUNyQixDQUFDLENBQUMsYUFBYSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDO1dBQ3pDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUN4QixDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsbUNBQW1DLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUNyRCxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsR0FBRyxRQUFRLElBQUksUUFBUSxHQUFHLENBQUMsQ0FDdkQsQ0FBQztJQUNGLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqRSxJQUFJLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsZ0NBQWdDLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBQ0QsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNuQyxLQUFLO0lBQ0wsSUFBSTtJQUNKLDJCQUEyQjtJQUMzQixjQUFjO0lBQ2QsTUFBTTtJQUNOLGdCQUFnQjtJQUNoQixNQUFNO0lBQ04sWUFBWTtJQUNaLGNBQWM7SUFDZCxVQUFVO0lBQ1YsVUFBVTtJQUNWLGFBQWE7SUFDYixTQUFTO0lBQ1QsSUFBSTtDQUNMLENBQUMsQ0FBQztBQUVILE1BQU0sYUFBYSxHQUFHLENBQUMsUUFBaUIsRUFBRSxRQUFnQixFQUFTLEVBQUU7SUFDbkUsTUFBTSxLQUFLLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELGdCQUFnQixDQUNkLEtBQUssRUFDTCxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxhQUFhLENBQUMsRUFDMUQsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLEVBQ3pCLFFBQVEsQ0FDVCxDQUFDO0lBQ0YsSUFBSSxPQUFPLEtBQUssQ0FBQyxNQUFNLEtBQUssUUFBUSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUNwRSxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSxxQkFBcUIsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDbEYsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsbUJBQW1CLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ3ZGLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxRQUFRLDBCQUEwQixDQUFDLENBQUM7SUFDekQsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3RGLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzlFLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxRQUFRLDBCQUEwQixDQUFDLENBQUM7SUFDekQsQ0FBQztJQUNELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDOUMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNO1FBQ25DLENBQUMsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhO1FBQy9ELENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU07WUFDckIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGFBQWE7WUFDL0QsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQztJQUN0RSxJQUFJLFdBQVcsR0FBRyxPQUFPLEVBQUUsQ0FBQztRQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSw4QkFBOEIsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxPQUFPO1FBQ0wsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ3BCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtRQUNoQixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7UUFDOUIsTUFBTTtRQUNOLFdBQVc7UUFDWCxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsS0FBSyxTQUFTO1lBQzlCLENBQUMsQ0FBQyxFQUFFO1lBQ0osQ0FBQyxDQUFDO2dCQUNFLFFBQVEsRUFBRSxvQkFBb0IsQ0FDNUIsS0FBSyxDQUFDLFFBQVEsRUFDZCxHQUFHLFFBQVEsV0FBVyxFQUN0QixHQUFHLENBQ0o7YUFDRixDQUFDO1FBQ04sR0FBRyxDQUFDLEtBQUssQ0FBQyxTQUFTLEtBQUssU0FBUztZQUMvQixDQUFDLENBQUMsRUFBRTtZQUNKLENBQUMsQ0FBQztnQkFDRSxTQUFTLEVBQUUsb0JBQW9CLENBQzdCLEtBQUssQ0FBQyxTQUFTLEVBQ2YsR0FBRyxRQUFRLFlBQVksRUFDdkIsR0FBRyxDQUNKO2FBQ0YsQ0FBQztLQUNQLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxnQ0FBZ0MsR0FBRyxDQUM5QyxRQUFpQixFQUNqQixVQUF5RSxFQUMvRCxFQUFFO0lBQ1osTUFBTSxLQUFLLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3RELGdCQUFnQixDQUNkLEtBQUssRUFDTCxDQUFDLFFBQVEsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUM1QyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsRUFDdEIsU0FBUyxDQUNWLENBQUM7SUFDRixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDaEUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3hELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDcEYsZ0JBQWdCLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sRUFBRSxHQUFHLHFCQUFxQixDQUFDLGdCQUFnQixDQUFDLEVBQUUsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO0lBQy9FLE1BQU0sRUFBRSxHQUFHLGdCQUFnQixDQUFDLEVBQUUsS0FBSyxTQUFTO1FBQzFDLENBQUMsQ0FBQyxTQUFTO1FBQ1gsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLGdCQUFnQixDQUFDLEVBQUUsRUFBRSx1QkFBdUIsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM5RSxNQUFNLEdBQUcsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLEtBQUssU0FBUztRQUM1QyxDQUFDLENBQUMsU0FBUztRQUNYLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEYsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUNqRSxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QyxJQUNFLHFCQUFxQixDQUFDLE1BQU0sS0FBSyxDQUFDO1dBQy9CLElBQUksR0FBRyxDQUFDLHFCQUFxQixDQUFDLENBQUMsSUFBSSxLQUFLLHFCQUFxQixDQUFDLE1BQU0sRUFDdkUsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztJQUNoRixDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztJQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUNsRCxhQUFhLENBQUMsUUFBUSxFQUFFLGlCQUFpQixRQUFRLEdBQUcsQ0FBQyxDQUN0RCxDQUFDO0lBQ0YsSUFDRSxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssS0FBSyxDQUFDLE1BQU07V0FDbEUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQztXQUM3RCxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDO1dBQzdELEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssWUFBWSxDQUFDLENBQUMsTUFBTTtZQUNoRSxPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlO1dBQzlELEtBQUs7YUFDTCxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssWUFBWSxDQUFDO2FBQ2xELE1BQU0sQ0FBQyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUMvRCxPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyx3QkFBd0IsRUFDNUUsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQ0QsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sS0FBSyxTQUFTO1FBQ3pDLENBQUMsQ0FBQyxTQUFTO1FBQ1gsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFO1lBQ0osSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRSxDQUFDO2dCQUMvRCxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7WUFDMUQsQ0FBQztZQUNELE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7WUFDL0IsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRTtnQkFDOUMsTUFBTSxNQUFNLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxFQUFFLG1CQUFtQixRQUFRLEdBQUcsQ0FBQyxDQUFDO2dCQUM1RSxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixRQUFRLEdBQUcsQ0FBQyxDQUFDO2dCQUNoRixJQUNFLE9BQU8sTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRO3VCQUM1QixDQUFDLDhCQUE4QixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQ3BELENBQUM7b0JBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO2dCQUN0RCxDQUFDO2dCQUNELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQzVDLElBQUksb0JBQW9CLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztvQkFDL0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO2dCQUN2RSxDQUFDO2dCQUNELElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3BCLE9BQU87b0JBQ0wsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO29CQUNqQixLQUFLLEVBQUUsb0JBQW9CLENBQ3pCLE1BQU0sQ0FBQyxLQUFLLEVBQ1osbUJBQW1CLFFBQVEsU0FBUyxFQUNwQyxHQUFHLEVBQ0gsSUFBSSxDQUNMO2lCQUNGLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDVCxPQUFPO1FBQ0wsTUFBTTtRQUNOLFVBQVUsRUFBRTtZQUNWLEVBQUU7WUFDRixHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDckIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3hCO1FBQ0QsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssU0FBUztZQUM3QixDQUFDLENBQUMsRUFBRTtZQUNKLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztRQUNwRSxPQUFPLEVBQUUsb0JBQW9CLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDO1FBQzFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvQixLQUFLO0tBQ04sQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHLENBQzVDLGlCQUF5QixFQUN6QixVQUFvQixFQUM4QixFQUFFO0lBQ3BELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUNELE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDakMsYUFBYSxFQUFFLENBQUM7UUFDaEIsY0FBYyxFQUFFLGlCQUFpQjtRQUNqQyxPQUFPLEVBQUUsVUFBVTtLQUNwQixDQUFDLENBQUMsQ0FBQztBQUNOLENBQUMsQ0FBQyJ9
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CoreMail } from './classes.coremail.js';
|
|
2
|
+
export { CoreMail } from './classes.coremail.js';
|
|
3
|
+
export { readCoreMailConfig } from './classes.config.js';
|
|
4
|
+
export const runCli = async () => {
|
|
5
|
+
const coreMail = new CoreMail();
|
|
6
|
+
let stopping = false;
|
|
7
|
+
const stop = async () => {
|
|
8
|
+
if (stopping)
|
|
9
|
+
return;
|
|
10
|
+
stopping = true;
|
|
11
|
+
process.off('SIGINT', onSigint);
|
|
12
|
+
process.off('SIGTERM', onSigterm);
|
|
13
|
+
try {
|
|
14
|
+
await coreMail.stop();
|
|
15
|
+
process.exitCode = 0;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const onSigint = () => {
|
|
22
|
+
void stop();
|
|
23
|
+
};
|
|
24
|
+
const onSigterm = () => {
|
|
25
|
+
void stop();
|
|
26
|
+
};
|
|
27
|
+
process.on('SIGINT', onSigint);
|
|
28
|
+
process.on('SIGTERM', onSigterm);
|
|
29
|
+
try {
|
|
30
|
+
await coreMail.start();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
process.off('SIGINT', onSigint);
|
|
34
|
+
process.off('SIGTERM', onSigterm);
|
|
35
|
+
await coreMail.stop().catch(() => undefined);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFakQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBR3pELE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQW1CLEVBQUU7SUFDOUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztJQUNoQyxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDckIsTUFBTSxJQUFJLEdBQUcsS0FBSyxJQUFtQixFQUFFO1FBQ3JDLElBQUksUUFBUTtZQUFFLE9BQU87UUFDckIsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNoQixPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN0QixPQUFPLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztRQUN2QixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUMsQ0FBQztJQUNGLE1BQU0sUUFBUSxHQUFHLEdBQUcsRUFBRTtRQUNwQixLQUFLLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQyxDQUFDO0lBQ0YsTUFBTSxTQUFTLEdBQUcsR0FBRyxFQUFFO1FBQ3JCLEtBQUssSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDLENBQUM7SUFDRixPQUFPLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMvQixPQUFPLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNqQyxJQUFJLENBQUM7UUFDSCxNQUFNLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QyxNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDLENBQUMifQ==
|