fix: close durable queue and runtime gaps
This commit is contained in:
@@ -14,6 +14,39 @@ export interface MailDriver {
|
||||
test?(): Promise<{ ok: boolean; error?: string }>;
|
||||
}
|
||||
|
||||
export interface SealedMailDriverOptions {
|
||||
/** Ciphertext stored by the application; plaintext is never retained here. */
|
||||
sealedCredential: string;
|
||||
unseal(value: string): Promise<string>;
|
||||
create(credential: string): MailDriver | Promise<MailDriver>;
|
||||
/** Cache the initialized driver. Defaults to true. */
|
||||
cache?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily opens a sealed credential only at the transport boundary. This keeps
|
||||
* encryption policy and SMTP/vendor choice independent while preventing every
|
||||
* app from rebuilding the same decrypt-on-send lifecycle.
|
||||
*/
|
||||
export function sealedMailDriver(options: SealedMailDriverOptions): MailDriver {
|
||||
let cached: Promise<MailDriver> | undefined;
|
||||
const create = async () => options.create(await options.unseal(options.sealedCredential));
|
||||
const driver = () =>
|
||||
options.cache === false ? create() : (cached ??= create().catch((error) => {
|
||||
cached = undefined;
|
||||
throw error;
|
||||
}));
|
||||
return {
|
||||
async send(message) {
|
||||
return (await driver()).send(message);
|
||||
},
|
||||
async test() {
|
||||
const resolved = await driver();
|
||||
return resolved.test?.() ?? { ok: true };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export interface MailTemplate<T = Record<string, unknown>> {
|
||||
subject(data: T): string;
|
||||
html?(data: T): string;
|
||||
|
||||
Reference in New Issue
Block a user