mail esm 2/2

This commit is contained in:
babayaga 2026-01-28 12:12:46 +01:00
parent 1f4df47e07
commit b73843bdc5
4 changed files with 152 additions and 0 deletions

3
packages/mail/dist-in/_cli.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import { IOptions } from './types.js';
export declare const defaults: () => void;
export declare const sanitize: (argv: any) => IOptions | boolean;

View File

@ -0,0 +1,67 @@
import { forward_slash, pathInfo, substitute, globBase } from "@polymech/commons";
import { isFile, resolve } from "@polymech/commons";
import { sync as exists } from "@polymech/fs/exists";
export const defaults = () => {
const DefaultCommand = 'info';
if (process.argv.length === 2) {
process.argv.push(DefaultCommand);
}
process.on('unhandledRejection', (reason) => {
console.error('Unhandled rejection, reason: ', reason);
});
};
export const sanitize = (argv) => {
const options = {
src: argv.src,
dry: argv.dry,
alt: argv.alt,
logLevel: argv.logLevel,
transport: argv.transport,
...argv
};
let srcInfo;
let variables = {
...options.variables
};
if (options.src) {
const srcIn = resolve(options.src, options.alt, variables);
options.src = forward_slash(substitute(options.alt, srcIn, variables));
// in case a file with a glob pattern is provided, strip the glob
// this is a special case, enabling shared scripts in Alt-Tap Salamand
const glob_base = globBase(options.src);
const file = options.src.replace(glob_base.glob, '').replace(/\/$/, '');
if (exists(file) && isFile(file)) {
options.src = file;
}
srcInfo = pathInfo(resolve(options.src, options.alt, variables));
if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
options.srcInfo = srcInfo;
for (const key in srcInfo) {
if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
variables['SRC_' + key] = srcInfo[key];
}
}
}
else {
options.src = resolve(options.src, options.alt, variables);
}
}
const out = resolve(options.dst || "", options.alt, variables);
options.dstInfo = pathInfo(out);
if (options.dst) {
if (options.srcInfo && options.dstInfo) {
options.dstInfo.PATH = options.dst;
for (const key in options.dstInfo) {
if (Object.prototype.hasOwnProperty.call(options.dstInfo, key)) {
variables['DST_' + key] = options.dstInfo[key];
}
}
}
else {
options.dst = resolve(options.dst || '', options.alt, variables);
}
}
options.variables = variables;
return options;
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2NsaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9fY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUNqRixPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ25ELE9BQU8sRUFBRSxJQUFJLElBQUksTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFFcEQsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHLEdBQUcsRUFBRTtJQUN6QixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUM7SUFDOUIsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM1QixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsT0FBTyxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLE1BQWMsRUFBRSxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDMUQsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFTLEVBQXNCLEVBQUU7SUFFdEQsTUFBTSxPQUFPLEdBQWE7UUFDdEIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1FBQ2IsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1FBQ2IsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1FBQ2IsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1FBQ3ZCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztRQUN6QixHQUFHLElBQUk7S0FDRSxDQUFBO0lBRWIsSUFBSSxPQUFPLENBQUE7SUFFWCxJQUFJLFNBQVMsR0FB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

View File

@ -0,0 +1,74 @@
import { describe, it, expect, beforeAll, vi } from 'vitest'
import nodemailer from 'nodemailer'
import { test as sendTestEmail } from '../lib/nodemailer/index.js'
import { IOptions, ITransportOptions } from '../types.js'
// Mock dependencies
vi.mock('@polymech/commons', async () => {
return {
CONFIG_DEFAULT: vi.fn(),
forward_slash: (s: string) => s,
pathInfo: () => ({}),
substitute: (_: any, s: string) => s,
resolve: (_: any, s: string) => s,
globBase: () => ({ glob: '', base: '' }),
isFile: () => true,
exists: () => true
}
})
// We need to import the mocked module to control the mock
import { CONFIG_DEFAULT } from '@polymech/commons'
describe('Mail E2E Tests', () => {
let testAccount: nodemailer.TestAccount
beforeAll(async () => {
// Create a real SMTP account on Ethereal for testing
testAccount = await nodemailer.createTestAccount()
})
it('should send a test email using ethereal account', async () => {
const transportConfig: ITransportOptions = {
host: testAccount.smtp.host,
port: testAccount.smtp.port,
secure: testAccount.smtp.secure,
auth: {
user: testAccount.user,
pass: testAccount.pass
}
}
// Setup the mock to return our test transport configuration
vi.mocked(CONFIG_DEFAULT).mockReturnValue({
email: {
'ethereal': transportConfig
}
})
const options: IOptions = {
transport: 'ethereal',
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Vitest E2E Test',
html: '<p>Hello from Vitest!</p>',
logLevel: 'error' // suppress logs during test
}
const info = await sendTestEmail(options)
if (!info) {
throw new Error('Email sending failed, info is undefined')
}
expect(info).toBeDefined()
expect(info.messageId).toBeDefined()
expect(info.accepted).toContain('recipient@example.com')
// Ethereal allows us to preview the email
const previewUrl = nodemailer.getTestMessageUrl(info)
console.log('Preview URL: %s', previewUrl)
expect(previewUrl).toBeTruthy()
})
})

View File

@ -0,0 +1,8 @@
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
environment: 'node',
},
})