diff --git a/packages/mail/.gitignore b/packages/mail/.gitignore new file mode 100644 index 00000000..5216f472 --- /dev/null +++ b/packages/mail/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/coverage +*.log +.DS_Store +clear_history.sh diff --git a/packages/mail/.npmignore b/packages/mail/.npmignore new file mode 100644 index 00000000..ed0792ba --- /dev/null +++ b/packages/mail/.npmignore @@ -0,0 +1,3 @@ +docs +scripts +tests \ No newline at end of file diff --git a/packages/mail/.vscode/launch.json b/packages/mail/.vscode/launch.json new file mode 100644 index 00000000..aa215f69 --- /dev/null +++ b/packages/mail/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "CLI:Test Send Email - Single", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}\\main.js", + "preLaunchTask": "tsc: build - tsconfig.json", + "args": [ + "test", + "--debug=true" + ], + "outFiles": [ + "${workspaceFolder}/**/*.js" + ], + "outputCapture": "std" + } + ] +} \ No newline at end of file diff --git a/packages/mail/README.md b/packages/mail/README.md new file mode 100644 index 00000000..b7d7b91e --- /dev/null +++ b/packages/mail/README.md @@ -0,0 +1,71 @@ +# OSR CAD Tools + +This is a CLI(CommandLineInterface) toolset to convert media files + +## Requirements + +1. [Node-JS](https://nodejs.org/en/download/) +2. Optional: install [Git](https://git-scm.com/downloads) (Make sure you enable Linux tools on Windows console) + +## Installation + +```sh +git clone https://gitlab.com/plastichub/osr/osr-media.git +cd osr-media +npm i +``` + +or globally (recommended) + +``` +npm i @plastichub/osr-media -g +``` + +## Usage + +Open a terminal and run this: + +```sh +osr-media --help +``` + +See more in [./docs/Examples.md](./docs/Examples.md) + +### Commands - Todos - 2D/Pictures + +- [ ] web formats (https://sharp.pixelplumbing.com/api-constructor) +- [ ] vector formats: pdf|svg +- [ ] meta exchange (from JSON, to Exif) + +### Commands - Todos - Pixels + +- [ ] RAW formats + +### Commands - Video + +- [ ] sub titles ? +- [ ] ffmpg + - [ ] split + - [ ] merge + - [ ] server/transcode ? + +## References + +- [pixelmatch](https://github.com/mapbox/pixelmatch) +- [lib content](https://git.osr-plastic.org/osr-plastic/osr-lib-content) +- [image diff](https://www.npmjs.com/package/img-diff-js) +- [ARW spec](https://github.com/WeTransfer/format_parser/blob/master/lib/parsers/arw_parser.rb) +- [ARW format notes - wiki](http://fileformats.archiveteam.org/wiki/Sony_ARW) +- [RAW View - NodeJS](https://github.com/catdad/raw-viewer/releases) +- [DCRaw - Github](https://github.com/zfedoran/dcraw.js) +- [DCRaw Vendored - NPM](https://www.npmjs.com/package/dcraw-vendored-win32) +- [Exif Data Reader](https://github.com/mattiasw/ExifReader) +- + +## AI Tools + +- [Object Replace](https://novita.ai/product/replace-object) + +## Video + +- [https://github.com/fluent-ffmpeg/node-fluent-ffmpeg.git](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg.git) diff --git a/packages/mail/commands/convert.d.ts b/packages/mail/commands/convert.d.ts new file mode 100644 index 00000000..88b52997 --- /dev/null +++ b/packages/mail/commands/convert.d.ts @@ -0,0 +1,15 @@ +import * as CLI from 'yargs'; +export declare const defaultOptions: (yargs: CLI.Argv) => CLI.Argv<{ + src: unknown; +} & { + dst: unknown; +} & { + debug: boolean; +} & { + alt: boolean; +} & { + dry: boolean; +} & { + verbose: boolean; +}>; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/convert.js b/packages/mail/commands/convert.js new file mode 100644 index 00000000..b655d24b --- /dev/null +++ b/packages/mail/commands/convert.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = exports.defaultOptions = void 0; +const __1 = require("../"); +const images_1 = require("../lib/media/images"); +const _cli_1 = require("../_cli"); +const defaultOptions = (yargs) => { + return yargs.option('src', { + describe: 'FILE|FOLDER|GLOB', + demandOption: true + }).option('dst', { + describe: 'FILE|FOLDER|GLOB' + }).option('debug', { + default: false, + describe: 'Enable internal debug messages', + type: 'boolean' + }).option('alt', { + default: false, + describe: 'Use alternate tokenizer, & instead of $', + type: 'boolean' + }).option('dry', { + default: false, + describe: 'Run without conversion', + type: 'boolean' + }).option('verbose', { + default: false, + describe: 'Show internal messages', + type: 'boolean' + }); +}; +exports.defaultOptions = defaultOptions; +let options = (yargs) => (0, exports.defaultOptions)(yargs); +const register = (cli) => { + return cli.command('convert', 'Convert files', options, (argv) => { + (0, _cli_1.defaults)(); + const options = (0, _cli_1.sanitize)(argv); + options.debug && __1.logger.info("options " + argv.dst, options); + return (0, images_1.convert)(options); + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9jb252ZXJ0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLDJCQUE0QjtBQUU1QixnREFFNEI7QUFFNUIsa0NBR2dCO0FBT1QsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRTtJQUM5QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ3ZCLFFBQVEsRUFBRSxrQkFBa0I7UUFDNUIsWUFBWSxFQUFFLElBQUk7S0FDckIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixRQUFRLEVBQUUsa0JBQWtCO0tBQy9CLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ2YsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsZ0NBQWdDO1FBQzFDLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUseUNBQXlDO1FBQ25ELElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsd0JBQXdCO1FBQ2xDLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLHdCQUF3QjtRQUNsQyxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUF2QlksUUFBQSxjQUFjLGtCQXVCMUI7QUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFLENBQUMsSUFBQSxzQkFBYyxFQUFDLEtBQUssQ0FBQyxDQUFBO0FBRWpELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLENBQUMsSUFBbUIsRUFBRSxFQUFFO1FBQzVFLElBQUEsZUFBUSxHQUFFLENBQUE7UUFDVixNQUFNLE9BQU8sR0FBRyxJQUFBLGVBQVEsRUFBQyxJQUFJLENBQWEsQ0FBQTtRQUMxQyxPQUFPLENBQUMsS0FBSyxJQUFJLFVBQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDNUQsT0FBTyxJQUFBLGdCQUFPLEVBQUMsT0FBTyxDQUFDLENBQUE7SUFDM0IsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFQWSxRQUFBLFFBQVEsWUFPcEIifQ== \ No newline at end of file diff --git a/packages/mail/commands/pdf2jpg.d.ts b/packages/mail/commands/pdf2jpg.d.ts new file mode 100644 index 00000000..443f33e5 --- /dev/null +++ b/packages/mail/commands/pdf2jpg.d.ts @@ -0,0 +1,2 @@ +import * as CLI from 'yargs'; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/pdf2jpg.js b/packages/mail/commands/pdf2jpg.js new file mode 100644 index 00000000..8a56f54b --- /dev/null +++ b/packages/mail/commands/pdf2jpg.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = void 0; +const __1 = require("../"); +const path = require("path"); +const index_1 = require("../lib/process/index"); +const bluebird = require("bluebird"); +const fg = require('fast-glob'); +const defaultOptions = (yargs) => { + return yargs.option('input', { + default: './', + describe: 'The sources' + }).option('debug', { + default: 'false', + describe: 'Enable internal debug message' + }); +}; +let options = (yargs) => defaultOptions(yargs); +async function convertFiles(files) { + return bluebird.resolve(files).map((file) => { + const inParts = path.parse(file); + // magick convert leg.pdf -quality 100 -density 250 -trim -flatten -resize 200% -sharpen 0x1.0 leg.jpg + const promise = index_1.Helper.run(inParts.dir, 'convert', [ + `"${inParts.base}[0]"`, + '-quality 80', + '-density 250', + '-trim', + '-flatten', + '-sharpen 0x1.0', + `"${inParts.name}.jpg"` + ]); + return promise; + }, { concurrency: 1 }); +} +// node ./build/main.js pdf2jpg --input=../drawings +const register = (cli) => { + return cli.command('pdf2jpg', '', options, async (argv) => { + if (argv.help) { + return; + } + const src = path.resolve('' + argv.input); + if (argv.debug) { + __1.logger.debug(`Begin convert PDF files${src}`); + } + const files = fg.sync('*.pdf|*.PDF', { dot: true, cwd: src, absolute: true }); + await convertFiles(files); + if (argv.debug) { + __1.logger.debug(`Converted ${files.length} files`); + } + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmMmpwZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9wZGYyanBnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLDJCQUE2QjtBQUM3Qiw2QkFBNkI7QUFDN0IsZ0RBQThDO0FBQzlDLHFDQUFxQztBQUVyQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFFaEMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRTtJQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ3pCLE9BQU8sRUFBRSxJQUFJO1FBQ2IsUUFBUSxFQUFFLGFBQWE7S0FDMUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDZixPQUFPLEVBQUUsT0FBTztRQUNoQixRQUFRLEVBQUUsK0JBQStCO0tBQzVDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQztBQUVGLElBQUksT0FBTyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7QUFFekQsS0FBSyxVQUFVLFlBQVksQ0FBQyxLQUFLO0lBQzdCLE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRTtRQUM3QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLHNHQUFzRztRQUN0RyxNQUFNLE9BQU8sR0FBRyxjQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUNqRDtZQUNJLElBQUksT0FBTyxDQUFDLElBQUksTUFBTTtZQUN0QixhQUFhO1lBQ2IsY0FBYztZQUNkLE9BQU87WUFDUCxVQUFVO1lBQ1YsZ0JBQWdCO1lBQ2hCLElBQUksT0FBTyxDQUFDLElBQUksT0FBTztTQUMxQixDQUFDLENBQUM7UUFDSCxPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDLEVBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBRUQsbURBQW1EO0FBQzVDLE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFtQixFQUFFLEVBQUU7UUFDckUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQUUsT0FBTztTQUFFO1FBQzFCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMxQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDWixVQUFNLENBQUMsS0FBSyxDQUFDLDBCQUEwQixHQUFHLEVBQUUsQ0FBQyxDQUFDO1NBQ2pEO1FBQ0QsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUUsTUFBTSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1osVUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLEtBQUssQ0FBQyxNQUFNLFFBQVEsQ0FBQyxDQUFDO1NBQ25EO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDLENBQUM7QUFiVyxRQUFBLFFBQVEsWUFhbkIifQ== \ No newline at end of file diff --git a/packages/mail/commands/resize.d.ts b/packages/mail/commands/resize.d.ts new file mode 100644 index 00000000..08480565 --- /dev/null +++ b/packages/mail/commands/resize.d.ts @@ -0,0 +1,31 @@ +import * as CLI from 'yargs'; +export declare const defaultOptions: (yargs: CLI.Argv) => CLI.Argv & { + percent: number; +} & { + logLevel: string; +}>; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/resize.js b/packages/mail/commands/resize.js new file mode 100644 index 00000000..2ddb1546 --- /dev/null +++ b/packages/mail/commands/resize.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = exports.defaultOptions = void 0; +const index_1 = require("../index"); +const resize_1 = require("../lib/media/images/resize"); +const _cli_1 = require("../_cli"); +const defaultOptions = (yargs) => { + return yargs.option('src', { + describe: 'FILE|FOLDER|GLOB', + demandOption: true + }).option('dst', { + describe: 'FILE|FOLDER|GLOB' + }).option('debug', { + default: false, + describe: 'Enable internal debug messages', + type: 'boolean' + }).option('alt', { + default: false, + describe: 'Use alternate tokenizer, & instead of $', + type: 'boolean' + }).option('dry', { + default: false, + describe: 'Run without conversion', + type: 'boolean' + }).option('verbose', { + default: false, + describe: 'Show internal messages', + type: 'boolean' + }).option('percent', { + default: false, + describe: 'Resize image with percent', + type: 'number' + }).option('width', { + default: false, + describe: 'Resize image with', + type: 'number' + }).option('height', { + default: false, + describe: 'Resize image height', + type: 'number' + }).option('minHeight', { + describe: 'Resize image minimum height', + type: 'number' + }).option('minWidth', { + describe: 'Resize image minimum width', + type: 'number' + }).option('minSize', { + describe: 'Resize image size (bytes)', + type: 'number' + }).option('percent', { + describe: 'Resize image in percent (width)', + type: 'number' + }).option('logLevel', { + describe: 'Log level : warn, info, debug, error', + type: 'string', + default: 'info' + }); +}; +exports.defaultOptions = defaultOptions; +let options = (yargs) => (0, exports.defaultOptions)(yargs); +const register = (cli) => { + return cli.command('resize', 'Resizes files', options, async (argv) => { + (0, _cli_1.defaults)(); + const options = (0, _cli_1.sanitize)(argv); + index_1.logger.setSettings({ + minLevel: options.logLevel + }); + index_1.logger.info("options " + argv.dst, options); + await (0, resize_1.resize)(options); + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL3Jlc2l6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxvQ0FBaUM7QUFDakMsdURBRW1DO0FBRW5DLGtDQUdnQjtBQU1ULE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUU7SUFDOUMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUN2QixRQUFRLEVBQUUsa0JBQWtCO1FBQzVCLFlBQVksRUFBRSxJQUFJO0tBQ3JCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsUUFBUSxFQUFFLGtCQUFrQjtLQUMvQixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUNmLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLGdDQUFnQztRQUMxQyxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNiLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLHlDQUF5QztRQUNuRCxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNiLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLHdCQUF3QjtRQUNsQyxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNqQixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSx3QkFBd0I7UUFDbEMsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7UUFDakIsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsMkJBQTJCO1FBQ3JDLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ2YsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsbUJBQW1CO1FBQzdCLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2hCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLHFCQUFxQjtRQUMvQixJQUFJLEVBQUUsUUFBUTtLQUNqQixDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRTtRQUNuQixRQUFRLEVBQUUsNkJBQTZCO1FBQ3ZDLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFO1FBQ2xCLFFBQVEsRUFBRSw0QkFBNEI7UUFDdEMsSUFBSSxFQUFFLFFBQVE7S0FDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7UUFDakIsUUFBUSxFQUFFLDJCQUEyQjtRQUNyQyxJQUFJLEVBQUUsUUFBUTtLQUNqQixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNqQixRQUFRLEVBQUUsaUNBQWlDO1FBQzNDLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFO1FBQ2xCLFFBQVEsRUFBRSxzQ0FBc0M7UUFDaEQsSUFBSSxFQUFFLFFBQVE7UUFDZCxPQUFPLEVBQUUsTUFBTTtLQUNsQixDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFuRFksUUFBQSxjQUFjLGtCQW1EMUI7QUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFLENBQUMsSUFBQSxzQkFBYyxFQUFDLEtBQUssQ0FBQyxDQUFBO0FBRWpELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFtQixFQUFFLEVBQUU7UUFDakYsSUFBQSxlQUFRLEdBQUUsQ0FBQTtRQUNWLE1BQU0sT0FBTyxHQUFHLElBQUEsZUFBUSxFQUFDLElBQUksQ0FBYSxDQUFBO1FBQzFDLGNBQU0sQ0FBQyxXQUFXLENBQUM7WUFDZixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQWU7U0FDcEMsQ0FBQyxDQUFBO1FBQ0YsY0FBTSxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUMzQyxNQUFNLElBQUEsZUFBTSxFQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3pCLENBQUMsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFBO0FBVlksUUFBQSxRQUFRLFlBVXBCIn0= \ No newline at end of file diff --git a/packages/mail/commands/svg2jpg.d.ts b/packages/mail/commands/svg2jpg.d.ts new file mode 100644 index 00000000..443f33e5 --- /dev/null +++ b/packages/mail/commands/svg2jpg.d.ts @@ -0,0 +1,2 @@ +import * as CLI from 'yargs'; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/svg2jpg.js b/packages/mail/commands/svg2jpg.js new file mode 100644 index 00000000..015da15c --- /dev/null +++ b/packages/mail/commands/svg2jpg.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = void 0; +const debug_1 = require("@plastichub/core/debug"); +const path = require("path"); +const index_1 = require("../lib/process/index"); +const bluebird = require("bluebird"); +const fg = require('fast-glob'); +const defaultOptions = (yargs) => { + return yargs.option('input', { + default: './', + describe: 'The sources' + }).option('debug', { + default: 'false', + describe: 'Enable internal debug message' + }); +}; +let options = (yargs) => defaultOptions(yargs); +async function convertFiles(files) { + return bluebird.mapSeries(files, (file) => { + const inParts = path.parse(file); + const promise = index_1.Helper.run(inParts.dir, 'convert', [ + `"${inParts.base}"`, + '-quality 40', + '-sharpen 0x1.0', + `"${inParts.name}.jpg"` + ]); + return promise; + }); +} +//node ./build/main.js svg2jpg --input=../tests/svg/ +const register = (cli) => { + return cli.command('svg2jpg', '', options, async (argv) => { + if (argv.help) { + return; + } + const src = path.resolve('' + argv.input); + const files = fg.sync('*.svg|*.SVG', { dot: true, cwd: src, absolute: true }); + if (argv.debug) { + (0, debug_1.debug)(`Begin convert SVG files at ${src} ${files}`); + } + await convertFiles(files); + if (argv.debug) { + (0, debug_1.debug)(`Converted ${files.length} files`); + } + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ZnMmpwZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9zdmcyanBnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGtEQUE4QztBQUM5Qyw2QkFBNkI7QUFDN0IsZ0RBQThDO0FBQzlDLHFDQUFxQztBQUVyQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFFaEMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRTtJQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ3pCLE9BQU8sRUFBRSxJQUFJO1FBQ2IsUUFBUSxFQUFFLGFBQWE7S0FDMUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDZixPQUFPLEVBQUUsT0FBTztRQUNoQixRQUFRLEVBQUUsK0JBQStCO0tBQzVDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQztBQUVGLElBQUksT0FBTyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7QUFFekQsS0FBSyxVQUFVLFlBQVksQ0FBQyxLQUFLO0lBQzdCLE9BQU8sUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRTtRQUM5QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLE1BQU0sT0FBTyxHQUFHLGNBQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQ2pEO1lBQ0ksSUFBSSxPQUFPLENBQUMsSUFBSSxHQUFHO1lBQ25CLGFBQWE7WUFDYixnQkFBZ0I7WUFDaEIsSUFBSSxPQUFPLENBQUMsSUFBSSxPQUFPO1NBQzFCLENBQUMsQ0FBQztRQUNILE9BQU8sT0FBTyxDQUFDO0lBQ25CLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUNELG9EQUFvRDtBQUU3QyxNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQWEsRUFBRSxFQUFFO0lBQ3RDLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBbUIsRUFBRSxFQUFFO1FBQ3JFLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtZQUFFLE9BQU87U0FBRTtRQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUUsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1osSUFBQSxhQUFLLEVBQUMsOEJBQThCLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1NBQ3ZEO1FBQ0QsTUFBTSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1osSUFBQSxhQUFLLEVBQUMsYUFBYSxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUMsQ0FBQztTQUM1QztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDO0FBYlcsUUFBQSxRQUFRLFlBYW5CIn0= \ No newline at end of file diff --git a/packages/mail/commands/test.d.ts b/packages/mail/commands/test.d.ts new file mode 100644 index 00000000..b3aa222d --- /dev/null +++ b/packages/mail/commands/test.d.ts @@ -0,0 +1,19 @@ +import * as CLI from 'yargs'; +export declare const defaultOptions: (yargs: CLI.Argv) => CLI.Argv<{ + src: string; +} & { + transport: string; +} & { + from: string; +} & { + to: string; +} & { + subject: string; +} & { + alt: boolean; +} & { + dry: boolean; +} & { + logLevel: string; +}>; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/test.js b/packages/mail/commands/test.js new file mode 100644 index 00000000..8259c628 --- /dev/null +++ b/packages/mail/commands/test.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = exports.defaultOptions = void 0; +const write_1 = require("@plastichub/fs/write"); +const index_1 = require("../index"); +const nodemailer_1 = require("../lib/nodemailer"); +const _cli_1 = require("../_cli"); +const defaultOptions = (yargs) => { + return yargs.option('src', { + describe: 'FILE|FOLDER|GLOB', + type: 'string', + default: './tests/email/test.html' + }).option('transport', { + default: 'newsletter', + describe: 'select the transport options with the OSR configuration', + type: 'string' + }).option('from', { + default: 'newsletter@osr-plastic.org', + describe: 'from email address', + type: 'string' + }).option('to', { + default: 'cgoflyn@gmail.com', + describe: 'to email address', + type: 'string' + }).option('subject', { + default: 'Schwarzer Kater Weisser Kater', + describe: 'the subject', + type: 'string' + }).option('alt', { + default: false, + describe: 'Use alternate tokenizer, & instead of $', + type: 'boolean' + }).option('dry', { + default: false, + describe: 'Run without conversion', + type: 'boolean' + }).option('logLevel', { + describe: 'Log level : warn, info, debug, error', + type: 'string', + default: 'info' + }); +}; +exports.defaultOptions = defaultOptions; +let options = (yargs) => (0, exports.defaultOptions)(yargs); +const register = (cli) => { + return cli.command('test', 'Send Test EMail', options, async (argv) => { + (0, _cli_1.defaults)(); + const options = (0, _cli_1.sanitize)(argv); + index_1.logger.setSettings({ + minLevel: options.logLevel + }); + index_1.logger.info("options " + argv.dst, options); + const ret = await (0, nodemailer_1.test)(options); + (0, write_1.sync)('./tests/email/log.json', ret); + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGdEQUFvRDtBQUVwRCxvQ0FBaUM7QUFFakMsa0RBRTBCO0FBRTFCLGtDQUdnQjtBQU1ULE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUU7SUFDOUMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUN2QixRQUFRLEVBQUUsa0JBQWtCO1FBQzVCLElBQUksRUFBRSxRQUFRO1FBQ2QsT0FBTyxFQUFFLHlCQUF5QjtLQUNyQyxDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRTtRQUNuQixPQUFPLEVBQUUsWUFBWTtRQUNyQixRQUFRLEVBQUUseURBQXlEO1FBQ25FLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ2QsT0FBTyxFQUFFLDRCQUE0QjtRQUNyQyxRQUFRLEVBQUUsb0JBQW9CO1FBQzlCLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFO1FBQ1osT0FBTyxFQUFFLG1CQUFtQjtRQUM1QixRQUFRLEVBQUUsa0JBQWtCO1FBQzVCLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSwrQkFBK0I7UUFDeEMsUUFBUSxFQUFFLGFBQWE7UUFDdkIsSUFBSSxFQUFFLFFBQVE7S0FDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSx5Q0FBeUM7UUFDbkQsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSx3QkFBd0I7UUFDbEMsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7UUFDbEIsUUFBUSxFQUFFLHNDQUFzQztRQUNoRCxJQUFJLEVBQUUsUUFBUTtRQUNkLE9BQU8sRUFBRSxNQUFNO0tBQ2xCLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQWxDWSxRQUFBLGNBQWMsa0JBa0MxQjtBQUVELElBQUksT0FBTyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUUsQ0FBQyxJQUFBLHNCQUFjLEVBQUMsS0FBSyxDQUFDLENBQUE7QUFFakQsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFhLEVBQUUsRUFBRTtJQUN0QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBbUIsRUFBRSxFQUFFO1FBQ2pGLElBQUEsZUFBUSxHQUFFLENBQUE7UUFDVixNQUFNLE9BQU8sR0FBRyxJQUFBLGVBQVEsRUFBQyxJQUFJLENBQWEsQ0FBQTtRQUMxQyxjQUFNLENBQUMsV0FBVyxDQUFDO1lBQ2YsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFlO1NBQ3BDLENBQUMsQ0FBQTtRQUNGLGNBQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDM0MsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFBLGlCQUFJLEVBQUMsT0FBTyxDQUFDLENBQUE7UUFDL0IsSUFBQSxZQUFLLEVBQUMsd0JBQXdCLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDeEMsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFYWSxRQUFBLFFBQVEsWUFXcEIifQ== \ No newline at end of file diff --git a/packages/mail/commands/watermark.d.ts b/packages/mail/commands/watermark.d.ts new file mode 100644 index 00000000..dac15219 --- /dev/null +++ b/packages/mail/commands/watermark.d.ts @@ -0,0 +1,31 @@ +import * as CLI from 'yargs'; +export declare const defaultOptions: (yargs: CLI.Argv) => CLI.Argv & { + percent: number; +} & { + key: string; +}>; +export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>; diff --git a/packages/mail/commands/watermark.js b/packages/mail/commands/watermark.js new file mode 100644 index 00000000..b54b86fc --- /dev/null +++ b/packages/mail/commands/watermark.js @@ -0,0 +1,75 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.register = exports.defaultOptions = void 0; +const osr_cli_commons_1 = require("@plastichub/osr-cli-commons"); +const index_1 = require("../index"); +const images_1 = require("../lib/media/images"); +const _cli_1 = require("../_cli"); +const defaultOptions = (yargs) => { + return yargs.option('src', { + describe: 'FILE|FOLDER|GLOB', + demandOption: true + }).option('dst', { + describe: 'FILE|FOLDER|GLOB' + }).option('debug', { + default: false, + describe: 'Enable internal debug messages', + type: 'boolean' + }).option('alt', { + default: false, + describe: 'Use alternate tokenizer, & instead of $', + type: 'boolean' + }).option('dry', { + default: false, + describe: 'Run without conversion', + type: 'boolean' + }).option('verbose', { + default: false, + describe: 'Show internal messages', + type: 'boolean' + }).option('percent', { + default: false, + describe: 'Resize image with percent', + type: 'number' + }).option('width', { + default: false, + describe: 'Resize image with', + type: 'number' + }).option('height', { + default: false, + describe: 'Resize image height', + type: 'number' + }).option('minHeight', { + describe: 'Resize image minimum height', + type: 'number' + }).option('minWidth', { + describe: 'Resize image minimum width', + type: 'number' + }).option('minSize', { + describe: 'Resize image size (bytes)', + type: 'number' + }).option('percent', { + describe: 'Resize image in percent (width)', + type: 'number' + }).option('key', { + describe: 'API Key', + type: 'string' + }); +}; +exports.defaultOptions = defaultOptions; +const options = (yargs) => (0, exports.defaultOptions)(yargs); +const register = (cli) => { + return cli.command('watermark', 'Remove watermark : FILE|GLOB', options, async (argv) => { + (0, _cli_1.defaults)(); + const options = (0, _cli_1.sanitize)(argv); + const config = (0, osr_cli_commons_1.CONFIG_DEFAULT)(); + if (!config.novita) { + index_1.logger.error("Novita key not found"); + return; + } + options.debug && index_1.logger.info("Watermark Options " + argv.dst, options); + return (0, images_1.watermark)({ ...options, key: config.novita.key }); + }); +}; +exports.register = register; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0ZXJtYXJrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL3dhdGVybWFyay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpRUFBNEQ7QUFHNUQsb0NBQWlDO0FBQ2pDLGdEQUc0QjtBQUU1QixrQ0FHZ0I7QUFNVCxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFO0lBQ2hELE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDekIsUUFBUSxFQUFFLGtCQUFrQjtRQUM1QixZQUFZLEVBQUUsSUFBSTtLQUNuQixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNmLFFBQVEsRUFBRSxrQkFBa0I7S0FDN0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDakIsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsZ0NBQWdDO1FBQzFDLElBQUksRUFBRSxTQUFTO0tBQ2hCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2YsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUseUNBQXlDO1FBQ25ELElBQUksRUFBRSxTQUFTO0tBQ2hCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2YsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsd0JBQXdCO1FBQ2xDLElBQUksRUFBRSxTQUFTO0tBQ2hCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ25CLE9BQU8sRUFBRSxLQUFLO1FBQ2QsUUFBUSxFQUFFLHdCQUF3QjtRQUNsQyxJQUFJLEVBQUUsU0FBUztLQUNoQixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNuQixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSwyQkFBMkI7UUFDckMsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUNqQixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSxtQkFBbUI7UUFDN0IsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtRQUNsQixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSxxQkFBcUI7UUFDL0IsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRTtRQUNyQixRQUFRLEVBQUUsNkJBQTZCO1FBQ3ZDLElBQUksRUFBRSxRQUFRO0tBQ2YsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7UUFDcEIsUUFBUSxFQUFFLDRCQUE0QjtRQUN0QyxJQUFJLEVBQUUsUUFBUTtLQUNmLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ25CLFFBQVEsRUFBRSwyQkFBMkI7UUFDckMsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNuQixRQUFRLEVBQUUsaUNBQWlDO1FBQzNDLElBQUksRUFBRSxRQUFRO0tBQ2YsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDZixRQUFRLEVBQUUsU0FBUztRQUNuQixJQUFJLEVBQUUsUUFBUTtLQUNmLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQTtBQWxEWSxRQUFBLGNBQWMsa0JBa0QxQjtBQUVELE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUUsQ0FBQyxJQUFBLHNCQUFjLEVBQUMsS0FBSyxDQUFDLENBQUE7QUFFbkQsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFhLEVBQUUsRUFBRTtJQUN4QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLDhCQUE4QixFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBbUIsRUFBRSxFQUFFO1FBQ3JHLElBQUEsZUFBUSxHQUFFLENBQUE7UUFDVixNQUFNLE9BQU8sR0FBRyxJQUFBLGVBQVEsRUFBQyxJQUFJLENBQWEsQ0FBQTtRQUMxQyxNQUFNLE1BQU0sR0FBUSxJQUFBLGdDQUFjLEdBQUUsQ0FBQTtRQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUNsQixjQUFNLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7WUFDckMsT0FBTTtTQUNQO1FBQ0QsT0FBTyxDQUFDLEtBQUssSUFBSSxjQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDdEUsT0FBTyxJQUFBLGtCQUFTLEVBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO0lBQzFELENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBWlksUUFBQSxRQUFRLFlBWXBCIn0= \ No newline at end of file diff --git a/packages/mail/dist-in/constants.d.ts b/packages/mail/dist-in/constants.d.ts new file mode 100644 index 00000000..56d9ad31 --- /dev/null +++ b/packages/mail/dist-in/constants.d.ts @@ -0,0 +1,5 @@ +export declare const GIT_REPO = "https://git.osr-plastic.org/osr-plastic/"; +export declare const MODULE_NAME = "Polymech-Mail"; +export declare const PACKAGE_NAME = "pm-mail"; +export declare const ERR_PERM_RETRY_DELAY = 500; +export declare const ERR_PERM_RETRY_MAX = 5; diff --git a/packages/mail/dist-in/constants.js b/packages/mail/dist-in/constants.js new file mode 100644 index 00000000..aca8db12 --- /dev/null +++ b/packages/mail/dist-in/constants.js @@ -0,0 +1,6 @@ +export const GIT_REPO = 'https://git.osr-plastic.org/osr-plastic/'; +export const MODULE_NAME = `Polymech-Mail`; +export const PACKAGE_NAME = 'pm-mail'; +export const ERR_PERM_RETRY_DELAY = 500; +export const ERR_PERM_RETRY_MAX = 5; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsMENBQTBDLENBQUE7QUFDbEUsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQztBQUMzQyxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsU0FBUyxDQUFDO0FBRXRDLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQTtBQUN2QyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUEifQ== \ No newline at end of file diff --git a/packages/mail/dist-in/index.d.ts b/packages/mail/dist-in/index.d.ts new file mode 100644 index 00000000..abac2e2c --- /dev/null +++ b/packages/mail/dist-in/index.d.ts @@ -0,0 +1,5 @@ +export * from './constants.js'; +export * from './types.js'; +export * from './lib/index.js'; +import { Logger, ILogObj } from 'tslog'; +export declare const logger: Logger; diff --git a/packages/mail/dist-in/index.js b/packages/mail/dist-in/index.js new file mode 100644 index 00000000..2daf4508 --- /dev/null +++ b/packages/mail/dist-in/index.js @@ -0,0 +1,7 @@ +export * from './constants.js'; +export * from './types.js'; +export * from './lib/index.js'; +import { createLogger } from '@polymech/log'; +import { MODULE_NAME } from './constants.js'; +export const logger = createLogger(MODULE_NAME); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxnQkFBZ0IsQ0FBQTtBQUM5QixjQUFjLFlBQVksQ0FBQTtBQUMxQixjQUFjLGdCQUFnQixDQUFBO0FBRzlCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDNUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRTVDLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsV0FBVyxDQUErQixDQUFBIn0= \ No newline at end of file diff --git a/packages/mail/dist-in/lib/imap/index.d.ts b/packages/mail/dist-in/lib/imap/index.d.ts new file mode 100644 index 00000000..a3c86c8d --- /dev/null +++ b/packages/mail/dist-in/lib/imap/index.d.ts @@ -0,0 +1 @@ +export declare const draft: (subject: string, html: string, options: any) => Promise; diff --git a/packages/mail/dist-in/lib/imap/index.js b/packages/mail/dist-in/lib/imap/index.js new file mode 100644 index 00000000..54d06738 --- /dev/null +++ b/packages/mail/dist-in/lib/imap/index.js @@ -0,0 +1,106 @@ +import { ImapFlow } from 'imapflow'; +async function getMessagesFromInboxWithFilter(imapConfig, fromAddress, toAddress) { + const client = new ImapFlow({ + host: imapConfig.host, + port: imapConfig.port, + secure: imapConfig.tls, + auth: { + user: imapConfig.user, + pass: imapConfig.password + } + }); + try { + // Connect to the IMAP server + await client.connect(); + // Select and lock the INBOX + let lock = await client.getMailboxLock('INBOX'); + try { + // Search for messages where the 'from' address and 'to' address match the specified filters + const searchCriteria = { + from: fromAddress, + to: toAddress + }; + // Search for messages matching the criteria + const messages = client.fetch({ from: fromAddress, to: toAddress }, { envelope: true, source: true }); + // Iterate through each filtered message and print details + for await (let message of messages) { + console.log('Message ID:', message.uid); + console.log('From:', message.envelope?.from?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('To:', message.envelope?.to?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('Subject:', message.envelope?.subject); + console.log('Date:', message.envelope?.date); + // If you need the message body, you can access it from message.source + console.log('Raw message source:', message.source.toString()); + } + } + finally { + // Always release the lock + lock.release(); + } + // Log out and close the connection + await client.logout(); + } + catch (err) { + console.error('Error fetching messages:', err); + throw err; + } +} +// Configuration for IMAP +const imapConfig = { + host: 'imap.example.com', + port: 993, + auth: { + user: 'your_email@example.com', + pass: 'your_password' + }, + secure: true +}; +// Create a draft email +export const draft = async (subject, html, options) => { + const client = new ImapFlow(options); + try { + await client.connect(); + await client.mailboxOpen('Drafts'); + const draftMessage = { + envelope: { + from: 'Your Name ', + subject: subject + }, + content: html, + ...options + }; + // Append the draft to the 'Drafts' folder + await client.append('Drafts', draftMessage, { flags: ['\Draft'] }); + console.log('Draft created successfully.'); + } + catch (err) { + console.error('Error:', err); + } + finally { + // Close the connection + await client.logout(); + console.log('Connection ended.'); + } +}; +/* +// Example usage +const config: ImapConfig = { + user: 'your-email@example.com', + password: 'your-password', + host: 'imap.your-email-provider.com', + port: 993, + tls: true +}; + +const fromAddress = 'sender@example.com'; +const toAddress = 'recipient@example.com'; + +getMessagesFromInboxWithFilter(config, fromAddress, toAddress) + .then(() => { + console.log('Finished fetching filtered messages.'); + }) + .catch(err => { + console.error('Error:', err); + }); +*/ +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2ltYXAvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQVVuQyxLQUFLLFVBQVUsOEJBQThCLENBQUMsVUFBc0IsRUFBRSxXQUFtQixFQUFFLFNBQWlCO0lBQ3hHLE1BQU0sTUFBTSxHQUFHLElBQUksUUFBUSxDQUFDO1FBQ3hCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtRQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUk7UUFDckIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxHQUFHO1FBQ3RCLElBQUksRUFBRTtZQUNGLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtZQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVE7U0FDNUI7S0FDSixDQUFDLENBQUM7SUFFSCxJQUFJLENBQUM7UUFDRCw2QkFBNkI7UUFDN0IsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFdkIsNEJBQTRCO1FBQzVCLElBQUksSUFBSSxHQUFHLE1BQU0sTUFBTSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVoRCxJQUFJLENBQUM7WUFDRCw0RkFBNEY7WUFDNUYsTUFBTSxjQUFjLEdBQUc7Z0JBQ25CLElBQUksRUFBRSxXQUFXO2dCQUNqQixFQUFFLEVBQUUsU0FBUzthQUNoQixDQUFDO1lBRUYsNENBQTRDO1lBQzVDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFFdEcsMERBQTBEO1lBQzFELElBQUksS0FBSyxFQUFFLElBQUksT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFD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 \ No newline at end of file diff --git a/packages/mail/dist-in/lib/index.d.ts b/packages/mail/dist-in/lib/index.d.ts new file mode 100644 index 00000000..020a6974 --- /dev/null +++ b/packages/mail/dist-in/lib/index.d.ts @@ -0,0 +1,2 @@ +export * from './nodemailer/index.js'; +export * from './imap/index.js'; diff --git a/packages/mail/dist-in/lib/index.js b/packages/mail/dist-in/lib/index.js new file mode 100644 index 00000000..99eac593 --- /dev/null +++ b/packages/mail/dist-in/lib/index.js @@ -0,0 +1,3 @@ +export * from './nodemailer/index.js'; +export * from './imap/index.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsdUJBQXVCLENBQUE7QUFDckMsY0FBYyxpQkFBaUIsQ0FBQSJ9 \ No newline at end of file diff --git a/packages/mail/dist-in/lib/nodemailer/index.d.ts b/packages/mail/dist-in/lib/nodemailer/index.d.ts new file mode 100644 index 00000000..cd8d10df --- /dev/null +++ b/packages/mail/dist-in/lib/nodemailer/index.d.ts @@ -0,0 +1,2 @@ +import { IOptions } from '../../types.js'; +export declare const test: (options: IOptions) => Promise; diff --git a/packages/mail/dist-in/lib/nodemailer/index.js b/packages/mail/dist-in/lib/nodemailer/index.js new file mode 100644 index 00000000..a2d0329b --- /dev/null +++ b/packages/mail/dist-in/lib/nodemailer/index.js @@ -0,0 +1,45 @@ +import { logger } from '../../index.js'; +import { createTransport } from 'nodemailer'; +import { CONFIG_DEFAULT } from '@polymech/commons'; +import { sync as read } from '@polymech/fs/read'; +const sendHtmlEmail = async ({ from, to, subject, html, attachments }, transport) => { + try { + const transporter = createTransport({ + ...transport + }); + const info = await transporter.sendMail({ + from, + to, // list of receivers + subject, // Subject line + html, + attachments + }); + logger.info(`Message sent: ${info.messageId}`); + return info; + } + catch (error) { + logger.error(`Error occurred: ${error.message}`); + logger.trace(error); + } +}; +export const test = async (options) => { + const config = CONFIG_DEFAULT(); + logger.setSettings({ minLevel: options.logLevel || 'info' }); + const transport = config?.email[options.transport]; + if (!transport) { + logger.error(`No email transport configuration found : ${options.transport}`); + return false; + } + if (!options.html && options.src && options.srcInfo) { + options.html = read(options.src, 'string') || '

Test Email

'; + } + logger.info(`Sending email from ${options.from} to ${options.to}`); + return sendHtmlEmail({ + from: options.from, + to: options.to, + subject: options.subject || 'Test Email', + html: options.html || '

Test Email

', + attachments: options.attachments + }, transport); +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL25vZGVtYWlsZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQ3ZDLE9BQU8sRUFBbUIsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQzdELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUNsRCxPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRWhELE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQW1CLEVBQUUsU0FBNEIsRUFBRSxFQUFFO0lBQ3BILElBQUksQ0FBQztRQUNELE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQztZQUNoQyxHQUFHLFNBQVM7U0FDZixDQUFDLENBQUE7UUFDRixNQUFNLElBQUksR0FBRyxNQUFNLFdBQVcsQ0FBQyxRQUFRLENBQUM7WUFDcEMsSUFBSTtZQUNKLEVBQUUsRUFBRSxvQkFBb0I7WUFDeEIsT0FBTyxFQUFFLGVBQWU7WUFDeEIsSUFBSTtZQUNKLFdBQVc7U0FDZCxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQTtRQUM5QyxPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDaEQsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUN2QixDQUFDO0FBQ0wsQ0FBQyxDQUFBO0FBRUQsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxPQUFpQixFQUFFLEVBQUU7SUFDNUMsTUFBTSxNQUFNLEdBQVEsY0FBYyxFQUFFLENBQUE7SUFDcEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBZSxJQUFJLE1BQU0sRUFBRSxDQUFDLENBQUE7SUFDbkUsTUFBTSxTQUFTLEdBQUcsTUFBTSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFzQixDQUFBO0lBQ3ZFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsNENBQTRDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO1FBQzdFLE9BQU8sS0FBSyxDQUFBO0lBQ2hCLENBQUM7SUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNsRCxPQUFPLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBVyxJQUFJLHFCQUFxQixDQUFBO0lBQ2pGLENBQUM7SUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixPQUFPLENBQUMsSUFBSSxPQUFPLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBQ2xFLE9BQU8sYUFBYSxDQUFDO1FBQ2pCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtRQUNsQixFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUU7UUFDZCxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sSUFBSSxZQUFZO1FBQ3hDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLHFCQUFxQjtRQUMzQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7S0FDbkMsRUFBRSxTQUFTLENBQUMsQ0FBQTtBQUNqQixDQUFDLENBQUEifQ== \ No newline at end of file diff --git a/packages/mail/dist-in/main.d.ts b/packages/mail/dist-in/main.d.ts new file mode 100644 index 00000000..b7988016 --- /dev/null +++ b/packages/mail/dist-in/main.d.ts @@ -0,0 +1,2 @@ +#!/usr/bin/env node +export {}; diff --git a/packages/mail/dist-in/main.js b/packages/mail/dist-in/main.js new file mode 100644 index 00000000..35c3962c --- /dev/null +++ b/packages/mail/dist-in/main.js @@ -0,0 +1,14 @@ +#!/usr/bin/env node +import { defaults } from './_cli'; +defaults(); +import * as CLI from 'yargs'; +//import { register as registerTest } from './commands/test'; registerTest(CLI) +const argv = CLI.argv; +if (argv.h || argv.help) { + CLI.showHelp(); + process.exit(); +} +else if (argv.v || argv.version) { + process.exit(); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQUMsUUFBUSxFQUFFLENBQUE7QUFDN0MsT0FBTyxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUE7QUFFNUIsK0VBQStFO0FBRS9FLE1BQU0sSUFBSSxHQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUE7QUFDMUIsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN0QixHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDZixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDbkIsQ0FBQztLQUFNLElBQUksSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDaEMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ25CLENBQUMifQ== \ No newline at end of file diff --git a/packages/mail/dist-in/types.d.ts b/packages/mail/dist-in/types.d.ts new file mode 100644 index 00000000..550f071e --- /dev/null +++ b/packages/mail/dist-in/types.d.ts @@ -0,0 +1,38 @@ +import { Hash } from '@polymech/core'; +import { PATH_INFO } from '@polymech/commons'; +import { Attachment } from 'nodemailer'; +export interface ITransportOptions { + host: string; + port: number; + secure: boolean; + auth: { + user: string; + pass: string; + }; +} +export type IOptions = { + alt?: boolean; + config?: any; + cwd?: string; + root?: string; + debug?: boolean; + verbose?: boolean; + dry?: boolean; + dst?: string; + dstInfo?: PATH_INFO; + env?: string; + cache?: boolean; + src?: string; + srcInfo?: PATH_INFO; + stdout?: boolean; + variables?: Hash; + key?: string; + logLevel?: string; + transport?: string; + from?: string; + subject?: string; + html?: string; + to?: string; + attachments?: Attachment[]; +}; +export type INodeMailer = IOptions & {}; diff --git a/packages/mail/dist-in/types.js b/packages/mail/dist-in/types.js new file mode 100644 index 00000000..a0dabde2 --- /dev/null +++ b/packages/mail/dist-in/types.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9 \ No newline at end of file diff --git a/packages/mail/lib/common/platform.d.ts b/packages/mail/lib/common/platform.d.ts new file mode 100644 index 00000000..2c5ed37f --- /dev/null +++ b/packages/mail/lib/common/platform.d.ts @@ -0,0 +1 @@ +export declare const os: () => "linux" | "arm" | "windows" | "osx"; diff --git a/packages/mail/lib/common/platform.js b/packages/mail/lib/common/platform.js new file mode 100644 index 00000000..e4124560 --- /dev/null +++ b/packages/mail/lib/common/platform.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.os = void 0; +const os_1 = require("os"); +const os = () => { + if ((0, os_1.platform)() === 'win32') { + return 'windows'; + } + else if ((0, os_1.platform)() === 'darwin') { + return 'osx'; + } + else if ((0, os_1.arch)() === 'arm') { + return 'arm'; + } + return 'linux'; +}; +exports.os = os; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2NvbW1vbi9wbGF0Zm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQkFBb0M7QUFFN0IsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFO0lBQ3JCLElBQUksSUFBQSxhQUFRLEdBQUUsS0FBSyxPQUFPLEVBQUU7UUFDMUIsT0FBTyxTQUFTLENBQUM7S0FDbEI7U0FBTSxJQUFJLElBQUEsYUFBUSxHQUFFLEtBQUssUUFBUSxFQUFFO1FBQ2xDLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7U0FBTSxJQUFJLElBQUEsU0FBSSxHQUFFLEtBQUssS0FBSyxFQUFFO1FBQzNCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDLENBQUE7QUFUWSxRQUFBLEVBQUUsTUFTZCJ9 \ No newline at end of file diff --git a/packages/mail/lib/imap/index.d.ts b/packages/mail/lib/imap/index.d.ts new file mode 100644 index 00000000..a3c86c8d --- /dev/null +++ b/packages/mail/lib/imap/index.d.ts @@ -0,0 +1 @@ +export declare const draft: (subject: string, html: string, options: any) => Promise; diff --git a/packages/mail/lib/imap/index.js b/packages/mail/lib/imap/index.js new file mode 100644 index 00000000..aee2a3ce --- /dev/null +++ b/packages/mail/lib/imap/index.js @@ -0,0 +1,110 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.draft = void 0; +const imapflow_1 = require("imapflow"); +async function getMessagesFromInboxWithFilter(imapConfig, fromAddress, toAddress) { + const client = new imapflow_1.ImapFlow({ + host: imapConfig.host, + port: imapConfig.port, + secure: imapConfig.tls, + auth: { + user: imapConfig.user, + pass: imapConfig.password + } + }); + try { + // Connect to the IMAP server + await client.connect(); + // Select and lock the INBOX + let lock = await client.getMailboxLock('INBOX'); + try { + // Search for messages where the 'from' address and 'to' address match the specified filters + const searchCriteria = { + from: fromAddress, + to: toAddress + }; + // Search for messages matching the criteria + const messages = client.fetch({ from: fromAddress, to: toAddress }, { envelope: true, source: true }); + // Iterate through each filtered message and print details + for await (let message of messages) { + console.log('Message ID:', message.uid); + console.log('From:', message.envelope?.from?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('To:', message.envelope?.to?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('Subject:', message.envelope?.subject); + console.log('Date:', message.envelope?.date); + // If you need the message body, you can access it from message.source + console.log('Raw message source:', message.source.toString()); + } + } + finally { + // Always release the lock + lock.release(); + } + // Log out and close the connection + await client.logout(); + } + catch (err) { + console.error('Error fetching messages:', err); + throw err; + } +} +// Configuration for IMAP +const imapConfig = { + host: 'imap.example.com', + port: 993, + auth: { + user: 'your_email@example.com', + pass: 'your_password' + }, + secure: true +}; +// Create a draft email +const draft = async (subject, html, options) => { + const client = new imapflow_1.ImapFlow(options); + try { + await client.connect(); + await client.mailboxOpen('Drafts'); + const draftMessage = { + envelope: { + from: 'Your Name ', + subject: subject + }, + content: html, + ...options + }; + // Append the draft to the 'Drafts' folder + await client.append('Drafts', draftMessage, { flags: ['\Draft'] }); + console.log('Draft created successfully.'); + } + catch (err) { + console.error('Error:', err); + } + finally { + // Close the connection + await client.logout(); + console.log('Connection ended.'); + } +}; +exports.draft = draft; +/* +// Example usage +const config: ImapConfig = { + user: 'your-email@example.com', + password: 'your-password', + host: 'imap.your-email-provider.com', + port: 993, + tls: true +}; + +const fromAddress = 'sender@example.com'; +const toAddress = 'recipient@example.com'; + +getMessagesFromInboxWithFilter(config, fromAddress, toAddress) + .then(() => { + console.log('Finished fetching filtered messages.'); + }) + .catch(err => { + console.error('Error:', err); + }); +*/ +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2ltYXAvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQW1DO0FBVW5DLEtBQUssVUFBVSw4QkFBOEIsQ0FBQyxVQUFzQixFQUFFLFdBQW1CLEVBQUUsU0FBaUI7SUFDeEcsTUFBTSxNQUFNLEdBQUcsSUFBSSxtQkFBUSxDQUFDO1FBQ3hCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtRQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLElBQUk7UUFDckIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxHQUFHO1FBQ3RCLElBQUksRUFBRTtZQUNGLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtZQUNyQixJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVE7U0FDNUI7S0FDSixDQUFDLENBQUM7SUFFSCxJQUFJO1FBQ0EsNkJBQTZCO1FBQzdCLE1BQU0sTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRXZCLDRCQUE0QjtRQUM1QixJQUFJLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFaEQsSUFBSTtZQUNBLDRGQUE0RjtZQUM1RixNQUFNLGNBQWMsR0FBRztnQkFDbkIsSUFBSSxFQUFFLFdBQVc7Z0JBQ2pCLEVBQUUsRUFBRSxTQUFTO2FBQ2hCLENBQUM7WUFFRiw0Q0FBNEM7WUFDNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUV0RywwREFBMEQ7WUFDMUQsSUFBSSxLQUFLLEVBQUUsSUFBSSxPQUFPLElBQUksUUFBUSxFQUFFO2dCQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxPQUFP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 \ No newline at end of file diff --git a/packages/mail/lib/index.d.ts b/packages/mail/lib/index.d.ts new file mode 100644 index 00000000..80bed9e2 --- /dev/null +++ b/packages/mail/lib/index.d.ts @@ -0,0 +1,2 @@ +export * from './nodemailer'; +export * from './imap'; diff --git a/packages/mail/lib/index.js b/packages/mail/lib/index.js new file mode 100644 index 00000000..93374142 --- /dev/null +++ b/packages/mail/lib/index.js @@ -0,0 +1,19 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./nodemailer"), exports); +__exportStar(require("./imap"), exports); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbGliL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBNEI7QUFDNUIseUNBQXNCIn0= \ No newline at end of file diff --git a/packages/mail/lib/media/images/convert.d.ts b/packages/mail/lib/media/images/convert.d.ts new file mode 100644 index 00000000..2ef3d53a --- /dev/null +++ b/packages/mail/lib/media/images/convert.d.ts @@ -0,0 +1,5 @@ +import * as sharp from 'sharp'; +import { IOptions, IResizeOptions } from '../../../types'; +export declare const convertFile: (file: any, target: any, onNode: (data: any) => void, options: IResizeOptions) => Promise; +export declare function _convert(file: any, targets: string[], onNode: (data: any) => void, options: IOptions): Promise; +export declare const convert: (options: IOptions) => Promise; diff --git a/packages/mail/lib/media/images/convert.js b/packages/mail/lib/media/images/convert.js new file mode 100644 index 00000000..d455cf4d --- /dev/null +++ b/packages/mail/lib/media/images/convert.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.convert = exports._convert = exports.convertFile = void 0; +const path = require("path"); +const bluebird = require("bluebird"); +const bluebird_1 = require("bluebird"); +const pMap = require("p-map"); +const sharp = require("sharp"); +const index_1 = require("../../../index"); +const osr_cli_commons_1 = require("@plastichub/osr-cli-commons"); +const exists_1 = require("@plastichub/fs/exists"); +const dir_1 = require("@plastichub/fs/dir"); +const lib_1 = require("@plastichub/osr-cache/lib"); +const lib_2 = require("./lib"); +const constants_1 = require("../../../constants"); +const convertFile = async (file, target, onNode = () => { }, options) => { + const osr_cache = (0, osr_cli_commons_1.OSR_CACHE)(); + const ca_options = JSON.parse(JSON.stringify({ ...options, target, skip: null })); + const cached = await (0, lib_1.get_cached)(file, ca_options, constants_1.MODULE_NAME); + let image = sharp(file); + const srcParts = path.parse(file); + const dstParts = path.parse(target); + if (!(0, exists_1.sync)(dstParts.dir)) { + (0, dir_1.sync)(dstParts.dir); + } + let ret = await image.withMetadata().toFile(target); + return ret; +}; +exports.convertFile = convertFile; +async function _convert(file, targets, onNode = () => { }, options) { + return pMap(targets, async (target) => { + index_1.logger.debug(`Convert ${file} to ${target}`); + if (options.dry) { + return bluebird.resolve(); + } + return (0, exports.convertFile)(file, target, onNode, options); + }, { concurrency: 1 }); +} +exports._convert = _convert; +const convert = async (options) => { + let reports = []; + const onNode = (data) => { reports.push(data); }; + index_1.logger.info(`Convert ${options.srcInfo.FILES.length} files `); + await bluebird_1.Promise.resolve(options.srcInfo.FILES).map((f) => { + const outputs = (0, lib_2.targets)(f, options); + options.verbose && index_1.logger.info(`Convert ${f} to `, outputs); + return _convert(f, outputs, onNode, options); + }, { concurrency: 1 }); +}; +exports.convert = convert; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvbWVkaWEvaW1hZ2VzL2NvbnZlcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTRCO0FBQzVCLHFDQUFvQztBQUNwQyx1Q0FBOEM7QUFHOUMsOEJBQTZCO0FBQzdCLCtCQUE4QjtBQUM5QiwwQ0FBdUM7QUFFdkMsaUVBQXVEO0FBQ3ZELGtEQUFzRDtBQUN0RCw0Q0FBZ0Q7QUFDaEQsbURBRWtDO0FBRWxDLCtCQUVjO0FBQ2Qsa0RBRTJCO0FBS3BCLE1BQU0sV0FBVyxHQUFHLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQThCLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxPQUF1QixFQUFFLEVBQUU7SUFFaEgsTUFBTSxTQUFTLEdBQUcsSUFBQSwyQkFBUyxHQUFFLENBQUE7SUFDN0IsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDakYsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFBLGdCQUFVLEVBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSx1QkFBVyxDQUFDLENBQUE7SUFDOUQsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3ZCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNuQyxJQUFHLENBQUMsSUFBQSxhQUFNLEVBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFDO1FBQ3JCLElBQUEsVUFBRyxFQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQTtLQUNwQjtJQUNELElBQUksR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNuRCxPQUFPLEdBQUcsQ0FBQTtBQUNkLENBQUMsQ0FBQTtBQWJZLFFBQUEsV0FBVyxlQWF2QjtBQUNNLEtBQUssVUFBVSxRQUFRLENBQUMsSUFBSSxFQUFFLE9BQWlCLEVBQUUsU0FBOEIsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLE9BQWlCO0lBQzlHLE9BQU8sSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDbEMsY0FBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLElBQUksT0FBTyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUNiLE9BQU8sUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQzdCO1FBQ0QsT0FBTyxJQUFBLG1CQUFXLEVBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEQsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQVJELDRCQVFDO0FBRU0sTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLE9BQWlCLEVBQUUsRUFBRTtJQUMvQyxJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUE7SUFDaEIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUEsQ0FBQyxDQUFDLENBQUE7SUFDL0MsY0FBTSxDQUFDLElBQUksQ0FBQyxXQUFXLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sU0FBUyxDQUFDLENBQUE7SUFDN0QsTUFBTSxrQkFBUSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3BELE1BQU0sT0FBTyxHQUFHLElBQUEsYUFBTyxFQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUNuQyxPQUFPLENBQUMsT0FBTyxJQUFJLGNBQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUMzRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUNoRCxDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUMxQixDQUFDLENBQUE7QUFUWSxRQUFBLE9BQU8sV0FTbkIifQ== \ No newline at end of file diff --git a/packages/mail/lib/media/images/index.d.ts b/packages/mail/lib/media/images/index.d.ts new file mode 100644 index 00000000..14d9024d --- /dev/null +++ b/packages/mail/lib/media/images/index.d.ts @@ -0,0 +1,24 @@ +export * from './resize'; +export * from './convert'; +export * from './watermark'; +import * as sharp from 'sharp'; +export declare const GLOB_BASIC = "png|jpg|tiff|jpeg|webp"; +export declare const GLOB_MIN = "*.{png,jpg,jpeg,PNG,JPG,JPEG}"; +export declare const files: (dir: any, glob: any) => any; +export declare const getFormats: (product: any, folder: any) => { + src: string; + dist: string; + format: string; +}[]; +export declare const meta: (file: any) => Promise; +export declare const format: (formats: any, options?: { + cache: boolean; + png: boolean; +}) => Promise; +export declare const getResizePatterns: (product: any, folder: any) => { + src: string; + dist: string; + percent: number; +}[]; +export declare const resize: (patterns: any) => Promise; +export declare const resizeSharp: (patterns: any) => Promise; diff --git a/packages/mail/lib/media/images/index.js b/packages/mail/lib/media/images/index.js new file mode 100644 index 00000000..e5fdf967 --- /dev/null +++ b/packages/mail/lib/media/images/index.js @@ -0,0 +1,151 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resizeSharp = exports.resize = exports.getResizePatterns = exports.format = exports.meta = exports.getFormats = exports.files = exports.GLOB_MIN = exports.GLOB_BASIC = void 0; +__exportStar(require("./resize"), exports); +__exportStar(require("./convert"), exports); +__exportStar(require("./watermark"), exports); +const pMap = require("p-map"); +const path = require("path"); +const fs = require("fs"); +const sharp = require("sharp"); +const exists_1 = require("@plastichub/fs/exists"); +const dir_1 = require("@plastichub/fs/dir"); +const fg = require('fast-glob'); +const glob = require('glob'); +const index_1 = require("../../../index"); +//https://www.lightgalleryjs.com/demos/responsive/ +exports.GLOB_BASIC = 'png|jpg|tiff|jpeg|webp'; +exports.GLOB_MIN = '*.{png,jpg,jpeg,PNG,JPG,JPEG}'; +const files = (dir, glob) => fg.sync(glob, { + dot: true, + cwd: dir, + absolute: true +}); +exports.files = files; +const getFormats = (product, folder) => { + return [{ + src: `${product}/${folder}/${exports.GLOB_MIN}`, + dist: `${product}/${folder}/webp`, + format: 'webp', + }]; +}; +exports.getFormats = getFormats; +const meta = async (file) => { + try { + return await sharp(file).metadata(); + } + catch (err) { + index_1.logger.error(`Error retrieving meta data for ${file}`, err); + } +}; +exports.meta = meta; +const format = async (formats, options = { + cache: true, + png: false +}) => { + return await pMap(formats, async (format) => { + (0, dir_1.sync)(format.dist); + let files = glob.sync(format.src); + return await pMap(files, async (file) => { + let fileParts = path.parse(file); + const target = path.resolve(`${format.dist}/${fileParts.name}.${format.format}`); + if (options.cache !== false && (0, exists_1.sync)(target)) { + return; + } + const image = sharp(file).keepExif(); + const metadata = await image.metadata(); + if (options.png) { + await image + .withMetadata() + .png() + .toFile(target) + .catch(index_1.logger.error); + } + else { + await image + .withMetadata() + .toFile(target) + .catch(index_1.logger.error); + } + return metadata; + }); + }); +}; +exports.format = format; +const getResizePatterns = (product, folder) => { + return [ + { + src: `${product}/${folder}/${exports.GLOB_MIN}`, + dist: `${product}/${folder}/20`, + percent: 20 + } + ]; +}; +exports.getResizePatterns = getResizePatterns; +const resize = async (patterns) => { + return pMap(patterns, async (resize) => { + if (!fs.existsSync(resize.dist)) { + (0, dir_1.sync)(resize.dist); + } + let files = glob.sync(resize.src); + return await pMap(files, async (file) => { + let filename = path.basename(file); + if ((0, exists_1.sync)(`${resize.dist}/${filename}`)) { + return; + } + try { + const image = sharp(file).keepExif().withMetadata(); + const metadata = await image.metadata(); + await image + .resize(Math.round(metadata.width * (resize.percent / 100))) + .keepExif() + .withMetadata() + .toFile(`${resize.dist}/${filename}`); + } + catch (err) { + index_1.logger.error(err); + } + }); + }); +}; +exports.resize = resize; +const resizeSharp = async (patterns) => { + return await pMap(patterns, async (resize) => { + (0, dir_1.sync)(resize.dist); + let files = glob.sync(resize.src); + return await pMap(files, async (file) => { + let filename = path.basename(file); + const image = sharp(file); + const metadata = await image.metadata(); + if ((0, exists_1.sync)(`${resize.dist}/${filename}`)) { + return metadata; + } + try { + const metadata = await image.metadata(); + await image + .resize(Math.round(metadata.width * (resize.percent / 100))) + .toFile(`${resize.dist}/${filename}`); + return metadata; + } + catch (err) { + console.error(err); + } + }); + }); +}; +exports.resizeSharp = resizeSharp; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL21lZGlhL2ltYWdlcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLDJDQUF3QjtBQUN4Qiw0Q0FBeUI7QUFDekIsOENBQTJCO0FBRTNCLDhCQUE2QjtBQUM3Qiw2QkFBNEI7QUFDNUIseUJBQXdCO0FBQ3hCLCtCQUE4QjtBQUU5QixrREFBc0Q7QUFDdEQsNENBQWtEO0FBRWxELE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNoQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7QUFFNUIsMENBQXVDO0FBRXZDLGtEQUFrRDtBQUNyQyxRQUFBLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQTtBQUVyQyxRQUFBLFFBQVEsR0FBRywrQkFBK0IsQ0FBQTtBQUVoRCxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO0lBQzlDLEdBQUcsRUFBRSxJQUFJO0lBQ1QsR0FBRyxFQUFFLEdBQUc7SUFDUixRQUFRLEVBQUUsSUFBSTtDQUNqQixDQUFDLENBQUE7QUFKVyxRQUFBLEtBQUssU0FJaEI7QUFFSyxNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtJQUMxQyxPQUFPLENBQUM7WUFDSixHQUFHLEVBQUUsR0FBRyxPQUFPLElBQUksTUFBTSxJQUFJLGdCQUFRLEVBQUU7WUFDdkMsSUFBSSxFQUFFLEdBQUcsT0FBTyxJQUFJLE1BQU0sT0FBTztZQUNqQyxNQUFNLEVBQUUsTUFBTTtTQUNqQixDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFOWSxRQUFBLFVBQVUsY0FNdEI7QUFFTSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7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 \ No newline at end of file diff --git a/packages/mail/lib/media/images/lib.d.ts b/packages/mail/lib/media/images/lib.d.ts new file mode 100644 index 00000000..fdc0eec5 --- /dev/null +++ b/packages/mail/lib/media/images/lib.d.ts @@ -0,0 +1,9 @@ +/// +/// +import { IResizeOptions } from '../../../types'; +import * as sharp from 'sharp'; +export declare const fileAsBuffer: (path: string) => Buffer; +export declare const targets: (f: string, options: IResizeOptions) => string[]; +export declare const base64ToBuffer: (b64string: string) => Promise; +export declare const imageToBase64: (imagePath: string) => Promise; +export declare const meta: (file: any, image: sharp.Sharp) => Promise; diff --git a/packages/mail/lib/media/images/lib.js b/packages/mail/lib/media/images/lib.js new file mode 100644 index 00000000..a35a8485 --- /dev/null +++ b/packages/mail/lib/media/images/lib.js @@ -0,0 +1,107 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.meta = exports.imageToBase64 = exports.base64ToBuffer = exports.targets = exports.fileAsBuffer = void 0; +const path = require("path"); +const fs = require("fs"); +const index_1 = require("../../../index"); +const exists_1 = require("@plastichub/fs/exists"); +const read_1 = require("@plastichub/fs/read"); +const fs_1 = require("@plastichub/osr-commons"); +const fileAsBuffer = (path) => (0, read_1.sync)(path, 'buffer') || Buffer.from("-"); +exports.fileAsBuffer = fileAsBuffer; +const clone = (obj) => { + if (null == obj || "object" != typeof obj) + return obj; + var copy = obj.constructor(); + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) + copy[attr] = obj[attr]; + } + return copy; +}; +const targets = (f, options) => { + const srcParts = path.parse(f); + const variables = clone(options.variables || {}); + const targets = []; + const rel = path.relative(options.srcInfo.DIR, srcParts.dir); + if (options.dstInfo.IS_GLOB) { + options.dstInfo.GLOB_EXTENSIONS.forEach((e) => { + variables.SRC_NAME = srcParts.name; + variables.SRC_DIR = srcParts.dir; + let targetPath = (0, index_1.substitute)(options.alt, variables.DST_PATH, variables); + targetPath = targetPath.replace(variables.DST_GLOB, ''); + if (variables.DST_FILE_EXT) { + targetPath = targetPath.replace('.' + variables.DST_FILE_EXT, ''); + } + const parts = path.parse(targetPath); + //back compat + if (variables.DST_NAME === '*') { + variables.DST_NAME = ''; + } + if (!parts.ext) { + if (variables.DST_PATH.indexOf(`{SRC_NAME}`) === -1) { + targetPath = path.join(targetPath, rel, srcParts.name + variables.DST_NAME.replace(variables.DST_GLOB, '') + '.' + e); + } + else { + targetPath = targetPath + variables.DST_NAME.replace(variables.DST_GLOB, '') + '.' + e; + } + } + //src.base contains dots + if (!targetPath.endsWith('.' + e)) { + targetPath += '.' + e; + } + targets.push(path.resolve(targetPath)); + }); + } + else { + let targetPath = ''; + if (!variables.DST_PATH) { + targetPath = path.join(srcParts.dir, srcParts.base); + } + else { + targetPath = (0, index_1.substitute)(options.alt, variables.DST_PATH, variables); + if ((0, fs_1.isFile)(f) && (0, exists_1.sync)(f)) { + // targetPath = path.join(targetPath, srcParts.base) + } + else { + targetPath = path.join(targetPath, srcParts.base); + } + const targetParts = path.parse(targetPath); + if (!targetParts.ext) { + targetPath = path.join(targetPath, srcParts.base); + } + } + targets.push(path.resolve((0, fs_1.resolve)(targetPath, options.alt, variables))); + } + return targets; +}; +exports.targets = targets; +const base64ToBuffer = async (b64string) => { + return Buffer.from(b64string, 'base64'); +}; +exports.base64ToBuffer = base64ToBuffer; +const imageToBase64 = async (imagePath) => { + try { + const imageBuffer = await fs.promises.readFile(imagePath); + const imageBase64 = imageBuffer.toString('base64'); + const mimeType = path.extname(imagePath).slice(1); + const dataUri = `data:image/${mimeType};base64,${imageBase64}`; + return dataUri; + } + catch (error) { + throw new Error(`Failed to convert image to base64: ${error}`); + } +}; +exports.imageToBase64 = imageToBase64; +const meta = (file, image) => { + return new Promise((resolve, reject) => { + image.metadata().then((meta) => { + resolve(meta); + }).catch((e) => { + console.error(`Error creating meta data ${file}`); + resolve(null); + }); + }); +}; +exports.meta = meta; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9tZWRpYS9pbWFnZXMvbGliLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE0QjtBQUM1Qix5QkFBd0I7QUFDeEIsMENBQTJDO0FBRzNDLGtEQUFzRDtBQUN0RCw4Q0FBa0Q7QUFDbEQsdURBQWdFO0FBTXpELE1BQU0sWUFBWSxHQUFHLENBQUMsSUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFBLFdBQUksRUFBQyxJQUFJLEVBQUUsUUFBUSxDQUFXLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtBQUFuRixRQUFBLFlBQVksZ0JBQXVFO0FBRWhHLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUU7SUFDbEIsSUFBSSxJQUFJLElBQUksR0FBRyxJQUFJLFFBQVEsSUFBSSxPQUFPLEdBQUc7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUN0RCxJQUFJLElBQUksR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDN0IsS0FBSyxJQUFJLElBQUksSUFBSSxHQUFHLEVBQUU7UUFDbEIsSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQztZQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDeEQ7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNoQixDQUFDLENBQUE7QUFFTSxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQVMsRUFBRSxPQUF1QixFQUFFLEVBQUU7SUFDMUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUM5QixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUNoRCxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUE7SUFDNUIsTUFBTSxHQUFHLEdBQUcs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 \ No newline at end of file diff --git a/packages/mail/lib/media/images/resize.d.ts b/packages/mail/lib/media/images/resize.d.ts new file mode 100644 index 00000000..11b571ed --- /dev/null +++ b/packages/mail/lib/media/images/resize.d.ts @@ -0,0 +1,5 @@ +import * as sharp from 'sharp'; +import { IOptions, IResizeOptions } from '../../../index'; +export declare const resizeFile: (source: any, target: any, onNode: (data: any) => void, options: IResizeOptions) => Promise; +export declare const _resize: (file: any, targets: string[], onNode: (data: any) => void, options: IOptions) => Promise<(void | sharp.Sharp)[]>; +export declare const resize: (options: IOptions) => Promise<(void | sharp.Sharp)[][]>; diff --git a/packages/mail/lib/media/images/resize.js b/packages/mail/lib/media/images/resize.js new file mode 100644 index 00000000..792f264f --- /dev/null +++ b/packages/mail/lib/media/images/resize.js @@ -0,0 +1,148 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.resize = exports._resize = exports.resizeFile = void 0; +const path = require("path"); +const pMap = require("p-map"); +const sharp = require("sharp"); +const exists_1 = require("@plastichub/fs/exists"); +const move_1 = require("@plastichub/fs/move"); +const dir_1 = require("@plastichub/fs/dir"); +const inspect_1 = require("@plastichub/fs/inspect"); +const index_1 = require("../../../index"); +const lib_1 = require("./lib"); +const resizeFile = async (source, target, onNode = () => { }, options) => { + //const osr_cache = OSR_CACHE() + //const ca_options = JSON.parse(JSON.stringify({ ...options, target, skip: null })) + //const cached = await get_cached(file, ca_options, MODULE_NAME) + const targetOri = '' + target; + let inPlace = false; + if (path.resolve(source) === path.resolve(target)) { + const parts = path.parse(target); + target = path.join(parts.dir, parts.name + '_tmp' + parts.ext); + inPlace = true; + } + let image; + try { + image = sharp(source); + } + catch (e) { + index_1.logger.error(`Error reading file, ${source}`, e); + return; + } + onNode(image); + let metaData = await (0, lib_1.meta)(source, image) || {}; + const percent = options.percent; + const srcParts = path.parse(source); + const dstParts = path.parse(target); + const node = (0, inspect_1.createItem)(source, { + size: true, + mime: true + }); + if (!(0, exists_1.sync)(dstParts.dir)) { + (0, dir_1.sync)(dstParts.dir); + } + if (options.width && options.minWidth && options.width <= options.minWidth) { + index_1.logger.error(`Error resizing : options.width <= options.minWidth`); + return; + } + if (metaData.width && options.width && options.minWidth) { + if (metaData.width <= options.minWidth) { + return image; + } + } + if (metaData.height && options.height && options.minHeight) { + if (metaData.height <= options.minHeight) { + return image; + } + } + if (options.minSize && node.size && options.minSize >= node.size) { + return image; + } + if (percent && metaData.width) { + image = image.resize({ + width: Math.round(metaData.width * (percent / 100)), + fastShrinkOnLoad: options.fastShrinkOnLoad, + withoutEnlargement: options.withoutEnlargement, + withoutReduction: options.withoutReduction, + fit: options.fit, + position: options.position + }); + } + else if (options.width || options.height) { + image = image.resize({ + width: options.width, + height: options.height, + fastShrinkOnLoad: options.fastShrinkOnLoad, + withoutEnlargement: options.withoutEnlargement, + withoutReduction: options.withoutReduction, + fit: options.fit, + position: options.position + }); + } + else { + index_1.logger.error(`Error resizing, invalid options for ${source} - no width, height or percent`); + return image; + } + if (metaData.width) { + await image.withMetadata().toFile(target); + } + else { + try { + await image.toFile(target); + } + catch (e) { + index_1.logger.error(`Error writing file out, ${source}`, e); + return; + } + } + if (inPlace) { + const timeout = async (retry) => new Promise((resolve) => setTimeout(resolve, index_1.ERR_PERM_RETRY_DELAY * retry)); + const moveRetry = async (src, dst, retry = 0) => { + if (retry > index_1.ERR_PERM_RETRY_MAX) { + index_1.logger.error(`Error moving file failed, max retries reached ${src}`); + return; + } + try { + await (0, move_1.async)(target, targetOri); + } + catch (e) { + if (e.code === 'EPERM') { + index_1.logger.warn(`Error moving file out, retry ${source}`, e); + await timeout(retry); + moveRetry(src, dst, retry + 1); + } + } + }; + await moveRetry(source, targetOri); + } + index_1.logger.debug(`Resized Image ${source} to ${targetOri}`); + return image; +}; +exports.resizeFile = resizeFile; +const _resize = async (file, targets, onNode = () => { }, options) => { + return pMap(targets, async (target) => { + index_1.logger.debug(`Resizing ${file} to ${target}`); + if (options.dry) { + return Promise.resolve(); + } + return (0, exports.resizeFile)(file, target, onNode, options); + }, { concurrency: 1 }); +}; +exports._resize = _resize; +const resize = async (options) => { + let reports = []; + const onNode = (data) => reports.push(data); + if (options.srcInfo) { + options.verbose && index_1.logger.info(`Convert ${options.srcInfo.FILES.length} files`); + return await pMap(options.srcInfo.FILES, async (f) => { + const outputs = (0, lib_1.targets)(f, options); + index_1.logger.info(`Convert ${f} to `, outputs); + return (0, exports._resize)(f, outputs, onNode, options); + }, { concurrency: 1 }); + } + else { + index_1.logger.error(`Invalid source info`); + } +}; +exports.resize = resize; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXplLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9tZWRpYS9pbWFnZXMvcmVzaXplLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE0QjtBQUM1Qiw4QkFBNkI7QUFDN0IsK0JBQThCO0FBRTlCLGtEQUFzRDtBQUN0RCw4Q0FBbUQ7QUFDbkQsNENBQWdEO0FBRWhELG9EQUE2RDtBQUU3RCwwQ0FNdUI7QUFFdkIsK0JBR2M7QUFHUCxNQUFNLFVBQVUsR0FBRyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUE4QixHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsT0FBdUIsRUFBb0MsRUFBRTtJQUVuSiwrQkFBK0I7SUFDL0IsbUZBQW1GO0lBQ25GLGdFQUFnRTtJQUVoRSxNQUFNLFNBQVMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFBO0lBRTdCLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQTtJQUVuQixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUMvQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ2hDLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksR0FBRyxNQUFNLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQzlELE9BQU8sR0FBRyxJQUFJLENBQUE7S0FDakI7SUFFRCxJQUFJLEtBQUssQ0FBQTtJQUNULElBQUk7UUFDQSxLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0tBQ3hCO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDUixjQUFNLENBQUMsS0FBSyxDQUFDLHVCQUF1QixNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNoRCxPQUFNO0tBQ1Q7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFYixJQUFJLFFBQVEsR0FBUSxNQUFNLElBQUEsVUFBSSxFQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUE7SUFFbkQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQTtJQUMvQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ25DLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFbkMsTUFBTSxJQUFJLEdBQUcsSUFBQSxvQkFBTSxFQUFDLE1BQU0sRUFBRTtRQUN4QixJQUFJLEVBQUUsSUFBSTtRQUNWLElBQUksRUFBRSxJQUFJO0tBQ2IsQ0FBQyxDQUFBO0lBR0YsSUFBSSxDQUFDLElBQUEsYUFBTSxFQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUN2QixJQUFBLFVBQUcsRUFBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUE7S0FDcEI7SUFFRCxJQUFJLE9BQU8sQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUU7UUFDeEUsY0FBTSxDQUFDLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFBO1FBQ2xFLE9BQU07S0FDVDtJQUVELElBQUksUUFBUSxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUU7UUFDckQsSUFBSSxRQUFRLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUU7WUFDcEMsT0FBTyxLQUFLLENBQUE7U0FDZjtLQUNKO0lBRUQsSUFBSSxRQUFRLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRTtRQUN4RCxJQUFJLFFBQVEsQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRTtZQUN0QyxPQUFPLEtBQUssQ0FBQTtTQUNmO0tBQ0o7SUFFRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7UUFDOUQsT0FBTyxLQUFLLENBQUE7S0FDZjtJQUVELElBQUksT0FBTyxJQUFJLFFBQVEsQ0FBQyxLQUFLLEVBQUU7UUFDM0IsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDakIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNuRCxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCO1lBQzFDLGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0I7WUFDOUMsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQjtZQUMxQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1NBQzdCLENBQUMsQ0FBQTtLQUVMO1NBQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUU7UUFDeEMsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDakIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1lBQ3BCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCO1lBQzFDLGtCQUFrQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0I7WUFDOUMsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQjtZQUMxQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1NBQzdCLENBQUMsQ0FBQTtLQUNMO1NBQU07UUFDSCxjQUFNLENBQUMsS0FBSyxDQUFDLHVDQUF1QyxNQUFNLGdDQUFnQyxDQUFDLENBQUE7UUFDM0YsT0FBTyxLQUFLLENBQUE7S0FDZjtJQUVELElBQUksUUFBUSxDQUFDLEtBQUssRUFBRTtRQUNoQixNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7S0FDNUM7U0FBTTtRQUNILElBQUk7WUFDQSxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7U0FDN0I7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLGNBQU0sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBQ3BELE9BQU07U0FDVDtLQUNKO0lBRUQsSUFBSSxPQUFPLEVBQUU7UUFFVCxNQUFNLE9BQU8sR0FBRyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQ3JELFVBQVUsQ0FBQyxPQUFPLEVBQUUsNEJBQW9CLEdBQUcsS0FBSyxDQUFDLENBQ3BELENBQUE7UUFFRCxNQUFNLFNBQVMsR0FBRyxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUU7WUFDNUMsSUFBSSxLQUFLLEdBQUcsMEJBQWtCLEVBQUU7Z0JBQzVCLGNBQU0sQ0FBQyxLQUFLLENBQUMsaURBQWlELEdBQUcsRUFBRSxDQUFDLENBQUE7Z0JBQ3BFLE9BQU07YUFDVDtZQUNELElBQUk7Z0JBQ0EsTUFBTSxJQUFBLFlBQUksRUFBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUE7YUFDaEM7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDUixJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFO29CQUNwQixjQUFNLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQTtvQkFDeEQsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7b0JBQ3BCLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQTtpQkFDakM7YUFDSjtRQUNMLENBQUMsQ0FBQTtRQUNELE1BQU0sU0FBUyxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQTtLQUNyQztJQUNELGNBQU0sQ0FBQyxLQUFLLENBQUMsaUJBQWlCLE1BQU0sT0FBTyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQ3ZELE9BQU8sS0FBSyxDQUFBO0FBQ2hCLENBQUMsQ0FBQTtBQTVIWSxRQUFBLFVBQVUsY0E0SHRCO0FBQ00sTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFpQixFQUFFLFNBQThCLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxPQUFpQixFQUFFLEVBQUU7SUFDakgsT0FBTyxJQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNsQyxjQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksSUFBSSxPQUFPLE1BQU0sRUFBRSxDQUFDLENBQUE7UUFDN0MsSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFO1lBQ2IsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUE7U0FDM0I7UUFDRCxPQUFPLElBQUEsa0JBQVUsRUFBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNyRCxDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUMxQixDQUFDLENBQUE7QUFSWSxRQUFBLE9BQU8sV0FRbkI7QUFDTSxNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsT0FBaUIsRUFBRSxFQUFFO0lBQzlDLElBQUksT0FBTyxHQUFRLEVBQUUsQ0FBQTtJQUNyQixNQUFNLE1BQU0sR0FBRyxDQUFDLElBQVMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNoRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUU7UUFDakIsT0FBTyxDQUFDLE9BQU8sSUFBSSxjQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUMsQ0FBQTtRQUMvRSxPQUFPLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNqRCxNQUFNLE9BQU8sR0FBRyxJQUFBLGFBQU8sRUFBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDcEMsY0FBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sSUFBQSxlQUFPLEVBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEQsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDMUI7U0FBTTtRQUNILGNBQU0sQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQTtLQUN0QztBQUNMLENBQUMsQ0FBQTtBQWJZLFFBQUEsTUFBTSxVQWFsQiJ9 \ No newline at end of file diff --git a/packages/mail/lib/media/images/watermark.d.ts b/packages/mail/lib/media/images/watermark.d.ts new file mode 100644 index 00000000..a3adeaf4 --- /dev/null +++ b/packages/mail/lib/media/images/watermark.d.ts @@ -0,0 +1,2 @@ +import { IOptions } from '../../../types'; +export declare const watermark: (options: IOptions) => Promise; diff --git a/packages/mail/lib/media/images/watermark.js b/packages/mail/lib/media/images/watermark.js new file mode 100644 index 00000000..adc4a164 --- /dev/null +++ b/packages/mail/lib/media/images/watermark.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.watermark = void 0; +const bluebird = require("bluebird"); +const bluebird_1 = require("bluebird"); +const write_1 = require("@plastichub/fs/write"); +const index_1 = require("../../../index"); +const lib_1 = require("./lib"); +const novita_sdk_1 = require("novita-sdk"); +const removeWatermark = async (file, target, onNode = () => { }, options) => { + const novitaClient = new novita_sdk_1.NovitaSDK(options.key); + const params = { + image_file: await (0, lib_1.imageToBase64)(file) + //"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD", + }; + try { + const wMark = await novitaClient.removeWatermark(params); + index_1.logger.info(`Watermark removed: ${file} to ${target}`); + (0, write_1.async)(target, (0, lib_1.base64ToBuffer)(wMark.image_file)); + } + catch (error) { + index_1.logger.error(`Failed to remove watermark: ${error.msg}`); + } +}; +const _watermark = async (file, targets, onNode = () => { }, options) => { + return bluebird_1.Promise.resolve(targets).map((target) => { + options.verbose && index_1.logger.debug(`Removing Watermark ${file} to ${target}`); + if (options.dry) { + return bluebird.resolve(); + } + return removeWatermark(file, target, onNode, options); + }, { concurrency: 1 }); +}; +const watermark = async (options) => { + // reporting, stub + let reports = []; + const onNode = (data) => reports.push(data); + if (options.srcInfo) { + options.verbose && index_1.logger.info(`Convert ${options.srcInfo.FILES.length} files`); + return await bluebird_1.Promise.resolve(options.srcInfo.FILES).map((f) => { + const outputs = (0, lib_1.targets)(f, options); + options.verbose && index_1.logger.info(`Convert ${f} to `, outputs); + return _watermark(f, outputs, onNode, options); + }, { concurrency: 1 }); + } + else { + options.debug && index_1.logger.error(`Invalid source info`); + } +}; +exports.watermark = watermark; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0ZXJtYXJrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9tZWRpYS9pbWFnZXMvd2F0ZXJtYXJrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUdBLHFDQUFvQztBQUNwQyx1Q0FBOEM7QUFLOUMsZ0RBQXFEO0FBS3JELDBDQUl1QjtBQU92QiwrQkFJYztBQU1kLDJDQUFzQztBQUV0QyxNQUFNLGVBQWUsR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUE4QixHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsT0FBdUIsRUFBRSxFQUFFO0lBQzdHLE1BQU0sWUFBWSxHQUFHLElBQUksc0JBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDL0MsTUFBTSxNQUFNLEdBQUc7UUFDWCxVQUFVLEVBQUUsTUFBTSxJQUFBLG1CQUFhLEVBQUMsSUFBSSxDQUFDO1FBQ3JDLHVEQUF1RDtLQUMxRCxDQUFBO0lBQ0QsSUFBSTtRQUNBLE1BQU0sS0FBSyxHQUFHLE1BQU0sWUFBWSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUN4RCxjQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixJQUFJLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQTtRQUN0RCxJQUFBLGFBQUssRUFBQyxNQUFNLEVBQUMsSUFBQSxvQkFBYyxFQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFBO0tBQ2pEO0lBQUMsT0FBTyxLQUFLLEVBQUU7UUFDWixjQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQTtLQUMzRDtBQUNMLENBQUMsQ0FBQTtBQUVELE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBaUIsRUFBRSxTQUE4QixHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsT0FBaUIsRUFBRSxFQUFFO0lBQzdHLE9BQU8sa0JBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7UUFDNUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxjQUFNLENBQUMsS0FBSyxDQUFDLHNCQUFzQixJQUFJLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQTtRQUMxRSxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDYixPQUFPLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQTtTQUM1QjtRQUNELE9BQU8sZUFBZSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzFELENBQUMsRUFBRSxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0FBQzFCLENBQUMsQ0FBQTtBQUVNLE1BQU0sU0FBUyxHQUFHLEtBQUssRUFBRSxPQUFpQixFQUFFLEVBQUU7SUFFakQsa0JBQWtCO0lBQ2xCLElBQUksT0FBTyxHQUFRLEVBQUUsQ0FBQTtJQUNyQixNQUFNLE1BQU0sR0FBRyxDQUFDLElBQVMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNoRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUU7UUFDakIsT0FBTyxDQUFDLE9BQU8sSUFBSSxjQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUMsQ0FBQTtRQUMvRSxPQUFPLE1BQU0sa0JBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMzRCxNQUFNLE9BQU8sR0FBRyxJQUFBLGFBQU8sRUFBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDbkMsT0FBTyxDQUFDLE9BQU8sSUFBSSxjQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDM0QsT0FBTyxVQUFVLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDbEQsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7S0FDekI7U0FBTTtRQUNILE9BQU8sQ0FBQyxLQUFLLElBQUksY0FBTSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBO0tBQ3ZEO0FBQ0wsQ0FBQyxDQUFBO0FBZlksUUFBQSxTQUFTLGFBZXJCIn0= \ No newline at end of file diff --git a/packages/mail/lib/nodemailer/index.d.ts b/packages/mail/lib/nodemailer/index.d.ts new file mode 100644 index 00000000..3e140e3d --- /dev/null +++ b/packages/mail/lib/nodemailer/index.d.ts @@ -0,0 +1,2 @@ +import { IOptions } from '../../types'; +export declare const test: (options: IOptions) => Promise; diff --git a/packages/mail/lib/nodemailer/index.js b/packages/mail/lib/nodemailer/index.js new file mode 100644 index 00000000..3afdd464 --- /dev/null +++ b/packages/mail/lib/nodemailer/index.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.test = void 0; +const index_1 = require("../../index"); +const nodemailer_1 = require("nodemailer"); +const osr_commons_1 = require("@plastichub/osr-commons"); +const read_1 = require("@plastichub/fs/read"); +const sendHtmlEmail = async ({ from, to, subject, html, attachments }, transport) => { + try { + const transporter = (0, nodemailer_1.createTransport)({ + ...transport + }); + const info = await transporter.sendMail({ + from, + to, + subject, + html, + attachments + }); + index_1.logger.info(`Message sent: ${info.messageId}`); + return info; + } + catch (error) { + index_1.logger.error(`Error occurred: ${error.message}`); + index_1.logger.trace(error); + } +}; +const test = async (options) => { + const config = (0, osr_commons_1.CONFIG_DEFAULT)(); + index_1.logger.setSettings({ minLevel: options.logLevel || 'info' }); + const transport = config?.email[options.transport]; + if (!transport) { + index_1.logger.error(`No email transport configuration found : ${options.transport}`); + return false; + } + if (!options.html && options.src && options.srcInfo) { + options.html = (0, read_1.sync)(options.src, 'string') || '

Test Email

'; + } + index_1.logger.info(`Sending email from ${options.from} to ${options.to}`); + return sendHtmlEmail({ + from: options.from, + to: options.to, + subject: options.subject || 'Test Email', + html: options.html || '

Test Email

', + attachments: options.attachments + }, transport); +}; +exports.test = test; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL25vZGVtYWlsZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsdUNBQW9DO0FBQ3BDLDJDQUE2RDtBQUM3RCx5REFBd0Q7QUFDeEQsOENBQWtEO0FBRWxELE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQW1CLEVBQUUsU0FBNEIsRUFBRSxFQUFFO0lBQ3BILElBQUk7UUFDQSxNQUFNLFdBQVcsR0FBRyxJQUFBLDRCQUFlLEVBQUM7WUFDaEMsR0FBRyxTQUFTO1NBQ2YsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxJQUFJLEdBQUcsTUFBTSxXQUFXLENBQUMsUUFBUSxDQUFDO1lBQ3BDLElBQUk7WUFDSixFQUFFO1lBQ0YsT0FBTztZQUNQLElBQUk7WUFDSixXQUFXO1NBQ2QsQ0FBQyxDQUFBO1FBQ0YsY0FBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUE7UUFDOUMsT0FBTyxJQUFJLENBQUE7S0FDZDtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osY0FBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDaEQsY0FBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtLQUN0QjtBQUNMLENBQUMsQ0FBQTtBQUVNLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxPQUFpQixFQUFFLEVBQUU7SUFDNUMsTUFBTSxNQUFNLEdBQVEsSUFBQSw0QkFBYyxHQUFFLENBQUE7SUFDcEMsY0FBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFFBQVEsRUFBQyxPQUFPLENBQUMsUUFBZSxJQUFJLE1BQU0sRUFBRSxDQUFDLENBQUE7SUFDbEUsTUFBTSxTQUFTLEdBQUcsTUFBTSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFzQixDQUFBO0lBQ3ZFLElBQUksQ0FBQyxTQUFTLEVBQUU7UUFDWixjQUFNLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQTtRQUM3RSxPQUFPLEtBQUssQ0FBQTtLQUNmO0lBQ0QsSUFBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxJQUFJLEdBQUcsSUFBQSxXQUFJLEVBQUMsT0FBTyxDQUFDLEdBQUcsRUFBQyxRQUFRLENBQVcsSUFBSSxxQkFBcUIsQ0FBQTtLQUMvRTtJQUNELGNBQU0sQ0FBQyxJQUFJLENBQUMsc0JBQXNCLE9BQU8sQ0FBQyxJQUFJLE9BQU8sT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDbEUsT0FBTyxhQUFhLENBQUM7UUFDakIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1FBQ2xCLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRTtRQUNkLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxJQUFJLFlBQVk7UUFDeEMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLElBQUkscUJBQXFCO1FBQzNDLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztLQUNuQyxFQUFFLFNBQVMsQ0FBQyxDQUFBO0FBQ2pCLENBQUMsQ0FBQTtBQW5CWSxRQUFBLElBQUksUUFtQmhCIn0= \ No newline at end of file diff --git a/packages/mail/lib/process/index.d.ts b/packages/mail/lib/process/index.d.ts new file mode 100644 index 00000000..a7b3285c --- /dev/null +++ b/packages/mail/lib/process/index.d.ts @@ -0,0 +1,18 @@ +export declare enum STATUS { + OK = 0, + ERROR = 1, + PENDING = 2 +} +export declare class Process { + binary: string; + cwd: string; + args: string; + constructor(options?: any); + optionsToString(options: any): string; + optionsToArray(options: any): string[]; + exec(command: string, options?: any, args?: any[]): Promise; +} +export declare class Helper { + static run(cwd: any, command: string, gitArgs: string[]): Promise; + static runBin(cwd: any, bin: any, command: string, gitArgs: string[]): Promise; +} diff --git a/packages/mail/lib/process/index.js b/packages/mail/lib/process/index.js new file mode 100644 index 00000000..44bb43e2 --- /dev/null +++ b/packages/mail/lib/process/index.js @@ -0,0 +1,149 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Helper = exports.Process = exports.STATUS = void 0; +const __1 = require("../.."); +const child_process_1 = require("child_process"); +const platform_1 = require("../common/platform"); +var STATUS; +(function (STATUS) { + STATUS[STATUS["OK"] = 0] = "OK"; + STATUS[STATUS["ERROR"] = 1] = "ERROR"; + STATUS[STATUS["PENDING"] = 2] = "PENDING"; +})(STATUS = exports.STATUS || (exports.STATUS = {})); +const fatalHandler = (message, fn) => { + if (message.startsWith('fatal:')) { + fn('\t\ ' + message); + return true; + } + return false; +}; +// tslint:disable-next-line:no-empty +const subscribe = (signal, collector = () => { }) => { + const buffer = []; + signal.on('message', (message) => __1.logger.debug('message', message)); + signal.on('error', (error) => __1.logger.error('std-error', error)); + signal.on('data', (data) => { + const message = data.toString(); + buffer.push(message); // .replace(/[\x00-\x1F\x7F-\x9F]/g, "") + collector(buffer); + }); +}; +const merge = (buffer, data) => buffer.concat(data); +const hook = (process, resolve, reject, cmd) => { + let buffer = []; + const collector = (data) => { buffer = buffer.concat(data); }; + const stdout = subscribe(process.stdout, collector); + const stderr = subscribe(process.stderr, collector); + process.on('exit', (code, signal) => { + if (code) { + resolve({ + code: STATUS.ERROR, + command: cmd, + error: code, + messages: buffer + }); + } + else { + resolve({ + code: STATUS.OK, + command: cmd, + messages: buffer + }); + } + }); + return process; +}; +class Process { + binary = 'magick'; + cwd = ''; + args = ''; + constructor(options = {}) { + this.binary = options.binary || this.binary; + //this.binary = path.resolve(which(this.binary)); + this.cwd = options.cwd || process.cwd(); + } + optionsToString(options) { + const args = []; + // tslint:disable-next-line:forin + for (const k in options) { + const val = options[k]; + if (k.length === 1) { + // val is true, add '-k' + if (val === true) { + args.push('-' + k); + } + else if (val !== false) { + // if val is not false, add '-k val' + args.push('-' + k + ' ' + val); + } + } + else { + if (val === true) { + args.push('--' + k); + } + else if (val !== false) { + args.push('--' + k + '=' + val); + } + } + } + return args.join(' '); + } + optionsToArray(options) { + const args = []; + // tslint:disable-next-line:forin + for (const k in options) { + const val = options[k]; + if (k.length === 1) { + // val is true, add '-k' + if (val === true) { + args.push('-' + k); + } + else if (val !== false) { + // if val is not false, add '-k val' + args.push('-' + k + ' ' + val); + } + } + else { + if (val === true) { + args.push('--' + k); + } + else if (val !== false) { + args.push('--' + k + '=' + val); + } + } + } + return args; + } + async exec(command, options = {}, args = []) { + args = [command].concat(args); + return new Promise((resolve, reject) => { + const p = (0, child_process_1.exec)(this.binary + ' ' + args.join(' '), { + cwd: this.cwd + }); + return hook(p, resolve, reject, this.binary + ' ' + args.join(' ')); + }); + } +} +exports.Process = Process; +class Helper { + static async run(cwd, command, gitArgs) { + const gitProcess = new Process({ + cwd: cwd, + binary: (0, platform_1.os)() == 'windows' ? 'magick' : '' + }); + const p = gitProcess.exec(command, {}, gitArgs); + p.catch((e) => __1.logger.error('Error git command : ' + command)); + return p; + } + static async runBin(cwd, bin, command, gitArgs) { + const gitProcess = new Process({ + cwd: cwd, + binary: bin + }); + const p = gitProcess.exec(command, {}, gitArgs); + p.catch((e) => __1.logger.error('Error git command : ' + command)); + return p; + } +} +exports.Helper = Helper; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3Byb2Nlc3MvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQStCO0FBRS9CLGlEQUFtRDtBQUNuRCxpREFBd0M7QUFFeEMsSUFBWSxNQUlYO0FBSkQsV0FBWSxNQUFNO0lBQ2QsK0JBQUUsQ0FBQTtJQUNGLHFDQUFLLENBQUE7SUFDTCx5Q0FBTyxDQUFBO0FBQ1gsQ0FBQyxFQUpXLE1BQU0sR0FBTixjQUFNLEtBQU4sY0FBTSxRQUlqQjtBQUVELE1BQU0sWUFBWSxHQUFHLENBQUMsT0FBZSxFQUFFLEVBQXlCLEVBQVcsRUFBRTtJQUN6RSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUU7UUFDOUIsRUFBRSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQztRQUNyQixPQUFPLElBQUksQ0FBQztLQUNmO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQyxDQUFDO0FBRUYsb0NBQW9DO0FBQ3BDLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBdUIsRUFBRSxZQUFpQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRTtJQUN0RixNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDcEUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFVBQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUN2QixNQUFNLE9BQU8sR0FBRyxJQUFJ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 \ No newline at end of file diff --git a/packages/mail/package-lock.json b/packages/mail/package-lock.json new file mode 100644 index 00000000..6699a891 --- /dev/null +++ b/packages/mail/package-lock.json @@ -0,0 +1,634 @@ +{ + "name": "@polymech/mail", + "version": "0.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@polymech/mail", + "version": "0.2.0", + "license": "BSD-3-Clause", + "dependencies": { + "@polymech/commons": "file:../commons", + "@polymech/core": "file:../core", + "@polymech/fs": "file:../fs", + "@polymech/log": "file:../log", + "@types/node": "^22.19.7", + "@types/nodemailer": "^7.0.9", + "@types/yargs": "^17.0.35", + "imapflow": "^1.2.7", + "nodemailer": "^7.0.13", + "tslog": "^4.10.2", + "yargs": "^18.0.0" + }, + "bin": { + "osr-mail": "main.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "../commons": { + "name": "@polymech/commons", + "version": "0.2.6", + "license": "BSD", + "dependencies": { + "@polymech/core": "file:../core", + "@polymech/fs": "file:../fs", + "@repo/typescript-config": "file:../typescript-config", + "@schemastore/package": "^0.0.10", + "ansi-regex": "^6.2.2", + "env-var": "^7.5.0", + "glob": "^10.4.5", + "js-yaml": "^4.1.0", + "jsonpath-plus": "^10.3.0", + "normalize-url": "^8.0.1", + "p-map": "^7.0.3", + "p-throttle": "^4.1.1", + "regedit": "^5.1.4", + "tslog": "^3.3.3", + "tsup": "^2.0.3", + "yargs": "^17.7.2", + "zod": "^3.24.3", + "zod-to-json-schema": "^3.24.5", + "zod-to-ts": "^1.2.0" + }, + "bin": { + "pm-cli": "dist/main.js" + }, + "devDependencies": { + "@types/node": "^22.12.0", + "typescript": "^5.7.3" + } + }, + "../core": { + "name": "@polymech/core", + "version": "0.2.6", + "license": "BSD", + "dependencies": { + "tslog": "^3.3.3", + "type-fest": "^4.37.0", + "zod": "^3.24.1" + }, + "devDependencies": { + "@repo/typescript-config": "../typescript-config", + "@types/node": "^22.12.0", + "typescript": "^5.7.3" + } + }, + "../fs": { + "name": "@polymech/fs", + "version": "0.13.41", + "license": "BSD-3-Clause", + "dependencies": { + "@polymech/core": "file:../core", + "@repo/typescript-config": "file:../typescript-config", + "denodeify": "^1.2.1", + "glob": "^10.4.1", + "mime": "^2.0.3", + "minimatch": "^10.0.1", + "mkdirp": "^3.0.1", + "q": "^1.4.1", + "rimraf": "^6.0.1", + "write-file-atomic": "^6.0.0", + "yargs": "^17.7.2" + }, + "devDependencies": { + "@types/denodeify": "^1.2.31", + "@types/mime": "^2.0.0", + "@types/node": "^22.10.2", + "fs-extra": "^4.0.2", + "globals": "^15.14.0", + "ts-node": "^10.9.1", + "typescript": "^5.7.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "../log": { + "name": "@polymech/log", + "version": "0.2.6", + "license": "BSD", + "dependencies": { + "@polymech/core": "file:../core", + "@repo/typescript-config": "file:../typescript-config", + "tslog": "^3.3.3", + "tsup": "^8.3.5", + "zod": "^3.24.1" + }, + "devDependencies": { + "@eslint/js": "^9.18.0", + "@types/node": "^22.10.9", + "eslint": "^8.57.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-regexp": "^2.7.0", + "ts-node": "^10.9.1", + "typescript": "^4.9.5", + "typescript-eslint": "^8.20.0" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, + "node_modules/@polymech/commons": { + "resolved": "../commons", + "link": true + }, + "node_modules/@polymech/core": { + "resolved": "../core", + "link": true + }, + "node_modules/@polymech/fs": { + "resolved": "../fs", + "link": true + }, + "node_modules/@polymech/log": { + "resolved": "../log", + "link": true + }, + "node_modules/@types/node": { + "version": "22.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/nodemailer": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.9.tgz", + "integrity": "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@zone-eu/mailsplit": { + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.8.tgz", + "integrity": "sha512-eEyACj4JZ7sjzRvy26QhLgKEMWwQbsw1+QZnlLX+/gihcNH07lVPOcnwf5U6UAL7gkc//J3jVd76o/WS+taUiA==", + "license": "(MIT OR EUPL-1.1+)", + "dependencies": { + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/encoding-japanese": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz", + "integrity": "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/imapflow": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/imapflow/-/imapflow-1.2.7.tgz", + "integrity": "sha512-x1UXswBXf4CQa577BVPp/2HMp1ILBPkzYePk0Fscgh7lO2QCSIUONKbjglrLSC/R0dQ3uYpe5ZRnU1szhmw62w==", + "license": "MIT", + "dependencies": { + "@zone-eu/mailsplit": "5.4.8", + "encoding-japanese": "2.2.0", + "iconv-lite": "0.7.2", + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1", + "nodemailer": "7.0.12", + "pino": "10.3.0", + "socks": "2.8.7" + } + }, + "node_modules/imapflow/node_modules/nodemailer": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.12.tgz", + "integrity": "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/libbase64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==", + "license": "MIT" + }, + "node_modules/libmime": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.7.tgz", + "integrity": "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==", + "license": "MIT", + "dependencies": { + "encoding-japanese": "2.2.0", + "iconv-lite": "0.6.3", + "libbase64": "1.3.0", + "libqp": "2.1.1" + } + }, + "node_modules/libmime/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/libqp": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz", + "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==", + "license": "MIT" + }, + "node_modules/nodemailer": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/pino": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.0.tgz", + "integrity": "sha512-0GNPNzHXBKw6U/InGe79A3Crzyk9bcSyObF9/Gfo9DLEf5qj5RF50RSjsu0W1rZ6ZqRGdzDFCRBQvi9/rSGPtA==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/thread-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tslog": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.10.2.tgz", + "integrity": "sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/fullstack-build/tslog?sponsor=1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + } + } +} diff --git a/packages/mail/package.json b/packages/mail/package.json new file mode 100644 index 00000000..2544e0d8 --- /dev/null +++ b/packages/mail/package.json @@ -0,0 +1,47 @@ +{ + "name": "@polymech/mail", + "version": "0.2.0", + "typings": "index.d.ts", + "type": "module", + "publishConfig": { + "access": "public" + }, + "bin": { + "osr-mail": "main.js" + }, + "dependencies": { + "@polymech/commons": "file:../commons", + "@polymech/core": "file:../core", + "@polymech/fs": "file:../fs", + "@polymech/log": "file:../log", + "@types/node": "^22.19.7", + "@types/nodemailer": "^7.0.9", + "@types/yargs": "^17.0.35", + "imapflow": "^1.2.7", + "nodemailer": "^7.0.13", + "tslog": "^4.10.2", + "yargs": "^18.0.0" + }, + "scripts": { + "test": "tsc; mocha --full-trace mocha \"spec/**/*.spec.js\"", + "test-with-coverage": "istanbul cover node_modules/.bin/_mocha -- 'spec/**/*.spec.js'", + "lint": "tslint --project=./tsconfig.json", + "build": "tsc -p .", + "dev": "tsc -p . --declaration -w", + "typings": "tsc --declaration", + "docs": "npx typedoc src/index.ts", + "dev-test-watch": "mocha-typescript-watch" + }, + "homepage": "https://git.osr-plastic.org/osr-plastic/osr-media", + "repository": { + "type": "git", + "url": "://git.osr-plastic.org/osr-plastic/osr-media.git" + }, + "engines": { + "node": ">= 14.0.0" + }, + "license": "BSD-3-Clause", + "keywords": [ + "typescript" + ] +} diff --git a/packages/mail/scripts/1.jpg b/packages/mail/scripts/1.jpg new file mode 100644 index 00000000..f627eb63 Binary files /dev/null and b/packages/mail/scripts/1.jpg differ diff --git a/packages/mail/scripts/2.jpg b/packages/mail/scripts/2.jpg new file mode 100644 index 00000000..14a51752 Binary files /dev/null and b/packages/mail/scripts/2.jpg differ diff --git a/packages/mail/scripts/combine-pics.sh b/packages/mail/scripts/combine-pics.sh new file mode 100644 index 00000000..9e201bab --- /dev/null +++ b/packages/mail/scripts/combine-pics.sh @@ -0,0 +1 @@ +convert 1.jpg 2.jpg -append result-sprite.jpg \ No newline at end of file diff --git a/packages/mail/scripts/createVideoPreview.sh b/packages/mail/scripts/createVideoPreview.sh new file mode 100644 index 00000000..1c7e4c1f --- /dev/null +++ b/packages/mail/scripts/createVideoPreview.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Bash script that generates film strip video preview using ffmpeg +# You can see live demo: http://jsfiddle.net/r6wz0nz6/2/ +# Tutorial on Binpress.com: http://www.binpress.com/tutorial/generating-nice-movie-previews-with-ffmpeg/138 + +if [ -z "$1" ]; then + echo "usage: ./movie_preview.sh VIDEO [HEIGHT=120] [COLS=100] [ROWS=1] [OUTPUT]" + exit +fi + +MOVIE=$1 +# get video name without the path and extension +MOVIE_NAME=`basename $MOVIE` +OUT_DIR=`pwd` + +HEIGHT=$2 +COLS=$3 +ROWS=$4 +OUT_FILENAME=$5 + +if [ -z "$HEIGHT" ]; then + HEIGHT=120 +fi +if [ -z "$COLS" ]; then + COLS=100 +fi +if [ -z "$ROWS" ]; then + ROWS=1 +fi +if [ -z "$OUT_FILENAME" ]; then + OUT_FILENAME=`echo ${MOVIE_NAME%.*}_preview.jpg` +fi + +OUT_FILEPATH=`echo $OUT_DIR/$OUT_FILENAME` + +TOTAL_IMAGES=`echo "$COLS*$ROWS" | bc` + +# get total number of frames in the video +# ffprobe is fast but not 100% reliable. It might not detect number of frames correctly! +NB_FRAMES=`ffprobe -show_streams "$MOVIE" 2> /dev/null | grep nb_frames | head -n1 | sed 's/.*=//'` +# `-show-streams` Show all streams found in the video. Each video has usualy two streams (video and audio). +# `head -n1` We care only about the video stream which comes first. +# `sed 's/.*=//'` Grab everything after `=`. + +if [ "$NB_FRAMES" = "N/A" ]; then + # as a fallback we'll use ffmpeg. This command basically copies this video to /dev/null and it counts + # frames in the process. It's slower (few seconds usually) than ffprobe but works everytime. + NB_FRAMES=`ffmpeg -nostats -i "$MOVIE" -vcodec copy -f rawvideo -y /dev/null 2>&1 | grep frame | awk '{split($0,a,"fps")}END{print a[1]}' | sed 's/.*= *//'` + # I know, that `awk` and `sed` parts look crazy but it has to be like this because ffmpeg can + # `-nostats` By default, `ffmpeg` prints progress information but that would be immediately caught by `grep` + # because it would contain word `frame` and therefore output of this entire command would be totally + # random. `-nostats` forces `ffmpeg` to print just the final result. + # `-i "$MOVIE"` Input file + # `-vcodec copy -f rawvideo` We don't want to do any reformating. Force `ffmpeg` to read and write the video as is. + # `-y /dev/null` Dump read video data. We just want it to count frames we don't care about the data. + # `awk ...` The line we're interested in has format might look like `frame= 42` or `frame=325`. Because of that + # extra space we can't just use `awk` to print the first column and we have to cut everything from the + # beggining of the line to the term `fps` (eg. `frame= 152`). + # `sed ...` Grab everything after `=` and ignore any spaces +fi + +# calculate offset between two screenshots, drop the floating point part +NTH_FRAME=`echo "$NB_FRAMES/$TOTAL_IMAGES" | bc` +echo "capture every ${NTH_FRAME}th frame out of $NB_FRAMES frames" + +# make sure output dir exists +mkdir -p $OUT_DIR + +FFMPEG_CMD="ffmpeg -loglevel panic -i \"$MOVIE\" -y -frames 1 -q:v 1 -vf \"select=not(mod(n\,$NTH_FRAME)),scale=-1:${HEIGHT},tile=${COLS}x${ROWS}\" \"$OUT_FILEPATH\"" +# `-loglevel panic` We don’t want to see any output. You can remove this option if you’re having any problem to see what went wrong +# `-i "$MOVIE"` Input file +# `-y` Override any existing output file +# `-frames 1` Tell `ffmpeg` that output from this command is just a single image (one frame). +# `-q:v 3` Output quality where `0` is the best. +# `-vf \"select=` That's where all the magic happens. Selector function for [video filter](https://trac.ffmpeg.org/wiki/FilteringGuide). +# # `not(mod(n\,58))` Select one frame every `58` frames [see the documentation](https://www.ffmpeg.org/ffmpeg-filters.html#Examples-34). +# # `scale=-1:120` Resize to fit `120px` height, width is adjusted automatically to keep correct aspect ration. +# # `tile=${COLS}x${ROWS}` Layout captured frames into this grid + +# print enire command for debugging purposes +# echo $FFMPEG_CMD + +echo $OUT_FILEPATH + +eval $FFMPEG_CMD \ No newline at end of file diff --git a/packages/mail/scripts/examples.sh b/packages/mail/scripts/examples.sh new file mode 100644 index 00000000..eeadbeab --- /dev/null +++ b/packages/mail/scripts/examples.sh @@ -0,0 +1,2 @@ +# Video preview +sh scripts\vid-preview.sh media\seedtray_promo_720.mp4 800 1 1 test.jpg diff --git a/packages/mail/scripts/link-dev.sh b/packages/mail/scripts/link-dev.sh new file mode 100644 index 00000000..8ba121ce --- /dev/null +++ b/packages/mail/scripts/link-dev.sh @@ -0,0 +1 @@ +npm i ../osr-cli-commons/ diff --git a/packages/mail/scripts/result-sprite.jpg b/packages/mail/scripts/result-sprite.jpg new file mode 100644 index 00000000..0254f684 Binary files /dev/null and b/packages/mail/scripts/result-sprite.jpg differ diff --git a/packages/mail/scripts/vid-preview.sh b/packages/mail/scripts/vid-preview.sh new file mode 100644 index 00000000..a059677f --- /dev/null +++ b/packages/mail/scripts/vid-preview.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Bash script that generates film strip video preview using ffmpeg +# You can see live demo: http://jsfiddle.net/r6wz0nz6/2/ +# Tutorial on Binpress.com: http://www.binpress.com/tutorial/generating-nice-movie-previews-with-ffmpeg/138 + +if [ -z "$1" ]; then + echo "usage: ./movie_preview.sh VIDEO [HEIGHT=120] [COLS=100] [ROWS=1] [OUTPUT]" + exit +fi + +MOVIE=$1 +# get video name without the path and extension +MOVIE_NAME=`basename $MOVIE` +OUT_DIR=`pwd` + +HEIGHT=$2 +COLS=$3 +ROWS=$4 +OUT_FILENAME=$5 + +if [ -z "$HEIGHT" ]; then + HEIGHT=120 +fi +if [ -z "$COLS" ]; then + COLS=100 +fi +if [ -z "$ROWS" ]; then + ROWS=1 +fi +if [ -z "$OUT_FILENAME" ]; then + OUT_FILENAME=`echo ${MOVIE_NAME%.*}_preview.jpg` +fi + +OUT_FILEPATH=`echo $OUT_DIR/$OUT_FILENAME` + +TOTAL_IMAGES=`echo "$COLS*$ROWS"` + +# get total number of frames in the video +# ffprobe is fast but not 100% reliable. It might not detect number of frames correctly! +NB_FRAMES=`ffprobe -show_streams "$MOVIE" 2> /dev/null | grep nb_frames | head -n1 | sed 's/.*=//'` +# `-show-streams` Show all streams found in the video. Each video has usualy two streams (video and audio). +# `head -n1` We care only about the video stream which comes first. +# `sed 's/.*=//'` Grab everything after `=`. + +if [ "$NB_FRAMES" = "N/A" ]; then + # as a fallback we'll use ffmpeg. This command basically copies this video to /dev/null and it counts + # frames in the process. It's slower (few seconds usually) than ffprobe but works everytime. + NB_FRAMES=`ffmpeg -nostats -i "$MOVIE" -vcodec copy -f rawvideo -y /dev/null 2>&1 | grep frame | awk '{split($0,a,"fps")}END{print a[1]}' | sed 's/.*= *//'` + # I know, that `awk` and `sed` parts look crazy but it has to be like this because ffmpeg can + # `-nostats` By default, `ffmpeg` prints progress information but that would be immediately caught by `grep` + # because it would contain word `frame` and therefore output of this entire command would be totally + # random. `-nostats` forces `ffmpeg` to print just the final result. + # `-i "$MOVIE"` Input file + # `-vcodec copy -f rawvideo` We don't want to do any reformating. Force `ffmpeg` to read and write the video as is. + # `-y /dev/null` Dump read video data. We just want it to count frames we don't care about the data. + # `awk ...` The line we're interested in has format might look like `frame= 42` or `frame=325`. Because of that + # extra space we can't just use `awk` to print the first column and we have to cut everything from the + # beggining of the line to the term `fps` (eg. `frame= 152`). + # `sed ...` Grab everything after `=` and ignore any spaces +fi + +# calculate offset between two screenshots, drop the floating point part +NTH_FRAME=`echo "$NB_FRAMES/$TOTAL_IMAGES" ` +echo "capture every ${NTH_FRAME}th frame out of $NB_FRAMES frames" + +# make sure output dir exists +mkdir -p $OUT_DIR + +FFMPEG_CMD="ffmpeg -loglevel panic -i \"$MOVIE\" -y -frames 1 -q:v 1 -vf \"select=not(mod(n\,$NTH_FRAME)),scale=-1:${HEIGHT},tile=${COLS}x${ROWS}\" \"$OUT_FILEPATH\"" +# `-loglevel panic` We don’t want to see any output. You can remove this option if you’re having any problem to see what went wrong +# `-i "$MOVIE"` Input file +# `-y` Override any existing output file +# `-frames 1` Tell `ffmpeg` that output from this command is just a single image (one frame). +# `-q:v 3` Output quality where `0` is the best. +# `-vf \"select=` That's where all the magic happens. Selector function for [video filter](https://trac.ffmpeg.org/wiki/FilteringGuide). +# # `not(mod(n\,58))` Select one frame every `58` frames [see the documentation](https://www.ffmpeg.org/ffmpeg-filters.html#Examples-34). +# # `scale=-1:120` Resize to fit `120px` height, width is adjusted automatically to keep correct aspect ration. +# # `tile=${COLS}x${ROWS}` Layout captured frames into this grid + +# print enire command for debugging purposes +# echo $FFMPEG_CMD + +echo $OUT_FILEPATH + +eval $FFMPEG_CMD \ No newline at end of file diff --git a/packages/mail/src/.gitignore b/packages/mail/src/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/packages/mail/src/_cli.ts b/packages/mail/src/_cli.ts new file mode 100644 index 00000000..87092cac --- /dev/null +++ b/packages/mail/src/_cli.ts @@ -0,0 +1,74 @@ +import { IOptions } from './types.js' +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: string) => { + console.error('Unhandled rejection, reason: ', reason) + }) +} + +export const sanitize = (argv: any): IOptions | boolean => { + + const options: IOptions = { + src: argv.src, + dry: argv.dry, + alt: argv.alt, + logLevel: argv.logLevel, + transport: argv.transport, + ...argv + } as IOptions + + 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 as string + 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 +} diff --git a/packages/mail/src/commands/test.ts b/packages/mail/src/commands/test.ts new file mode 100644 index 00000000..6999d6f3 --- /dev/null +++ b/packages/mail/src/commands/test.ts @@ -0,0 +1,68 @@ +import * as CLI from 'yargs' +import { sync as write } from '@polymech/fs/write' + +import { logger } from '../index' + +import { + test +} from '../lib/nodemailer' + +import { + sanitize, + defaults +} from '../_cli' + +import { + IOptions +} from '../types' + +export const defaultOptions = (yargs: CLI.Argv) => { + return yargs.option('src', { + describe: 'FILE|FOLDER|GLOB', + type: 'string', + default: './tests/email/test.html' + }).option('transport', { + default: 'newsletter', + describe: 'select the transport options with the OSR configuration', + type: 'string' + }).option('from', { + default: 'newsletter@osr-plastic.org', + describe: 'from email address', + type: 'string' + }).option('to', { + default: 'cgoflyn@gmail.com', + describe: 'to email address', + type: 'string' + }).option('subject', { + default: 'Schwarzer Kater Weisser Kater', + describe: 'the subject', + type: 'string' + }).option('alt', { + default: false, + describe: 'Use alternate tokenizer, & instead of $', + type: 'boolean' + }).option('dry', { + default: false, + describe: 'Run without conversion', + type: 'boolean' + }).option('logLevel', { + describe: 'Log level : warn, info, debug, error', + type: 'string', + default: 'info' + }) +} + +let options = (yargs: CLI.Argv) => defaultOptions(yargs) + +export const register = (cli: CLI.Argv) => { + return cli.command('test', 'Send Test EMail', options, async (argv: CLI.Arguments) => { + defaults() + const options = sanitize(argv) as IOptions + logger.setSettings({ + minLevel: options.logLevel as any + }) + logger.info("options " + argv.dst, options) + const ret = await test(options) + write('./tests/email/log.json', ret) + }) +} diff --git a/packages/mail/src/constants.ts b/packages/mail/src/constants.ts new file mode 100644 index 00000000..9d25e341 --- /dev/null +++ b/packages/mail/src/constants.ts @@ -0,0 +1,6 @@ +export const GIT_REPO = 'https://git.osr-plastic.org/osr-plastic/' +export const MODULE_NAME = `Polymech-Mail`; +export const PACKAGE_NAME = 'pm-mail'; + +export const ERR_PERM_RETRY_DELAY = 500 +export const ERR_PERM_RETRY_MAX = 5 diff --git a/packages/mail/src/index.ts b/packages/mail/src/index.ts new file mode 100644 index 00000000..f7de4d4c --- /dev/null +++ b/packages/mail/src/index.ts @@ -0,0 +1,9 @@ +export * from './constants.js' +export * from './types.js' +export * from './lib/index.js' + +import { Logger, ILogObj } from 'tslog' +import { createLogger } from '@polymech/log' +import { MODULE_NAME } from './constants.js' + +export const logger = createLogger(MODULE_NAME) as unknown as Logger diff --git a/packages/mail/src/lib/common/platform.ts b/packages/mail/src/lib/common/platform.ts new file mode 100644 index 00000000..440e33c8 --- /dev/null +++ b/packages/mail/src/lib/common/platform.ts @@ -0,0 +1,12 @@ +import { platform, arch } from 'os'; + +export const os = () => { + if (platform() === 'win32') { + return 'windows' + } else if (platform() === 'darwin') { + return 'osx' + } else if (arch() === 'arm') { + return 'arm' + } + return 'linux' +} \ No newline at end of file diff --git a/packages/mail/src/lib/imap/index.ts b/packages/mail/src/lib/imap/index.ts new file mode 100644 index 00000000..63794694 --- /dev/null +++ b/packages/mail/src/lib/imap/index.ts @@ -0,0 +1,125 @@ +import { ImapFlow } from 'imapflow' + +interface ImapConfig { + user: string; + password: string; + host: string; + port: number; + tls: boolean; +} + +async function getMessagesFromInboxWithFilter(imapConfig: ImapConfig, fromAddress: string, toAddress: string): Promise { + const client = new ImapFlow({ + host: imapConfig.host, + port: imapConfig.port, + secure: imapConfig.tls, + auth: { + user: imapConfig.user, + pass: imapConfig.password + } + }); + + try { + // Connect to the IMAP server + await client.connect(); + + // Select and lock the INBOX + let lock = await client.getMailboxLock('INBOX'); + + try { + // Search for messages where the 'from' address and 'to' address match the specified filters + const searchCriteria = { + from: fromAddress, + to: toAddress + }; + + // Search for messages matching the criteria + const messages = client.fetch({ from: fromAddress, to: toAddress }, { envelope: true, source: true }); + + // Iterate through each filtered message and print details + for await (let message of messages) { + console.log('Message ID:', message.uid); + console.log('From:', message.envelope?.from?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('To:', message.envelope?.to?.map(f => `${f.name} <${f.address}>`).join(', ')); + console.log('Subject:', message.envelope?.subject); + console.log('Date:', message.envelope?.date); + + // If you need the message body, you can access it from message.source + console.log('Raw message source:', message.source.toString()); + } + } finally { + // Always release the lock + lock.release(); + } + + // Log out and close the connection + await client.logout(); + + } catch (err) { + console.error('Error fetching messages:', err); + throw err; + } +} + +// Configuration for IMAP +const imapConfig = { + host: 'imap.example.com', + port: 993, + auth: { + user: 'your_email@example.com', + pass: 'your_password' + }, + secure: true +}; + +// Create a draft email +export const draft = async (subject: string, html: string, options) =>{ + const client = new ImapFlow(options) + + try { + await client.connect() + + await client.mailboxOpen('Drafts') + + const draftMessage = { + envelope: { + from: 'Your Name ', + subject: subject + }, + content: html, + ...options + } + + // Append the draft to the 'Drafts' folder + await client.append('Drafts', draftMessage, { flags: ['\Draft'] }); + console.log('Draft created successfully.'); + } catch (err) { + console.error('Error:', err); + } finally { + // Close the connection + await client.logout(); + console.log('Connection ended.'); + } +} + +/* +// Example usage +const config: ImapConfig = { + user: 'your-email@example.com', + password: 'your-password', + host: 'imap.your-email-provider.com', + port: 993, + tls: true +}; + +const fromAddress = 'sender@example.com'; +const toAddress = 'recipient@example.com'; + +getMessagesFromInboxWithFilter(config, fromAddress, toAddress) + .then(() => { + console.log('Finished fetching filtered messages.'); + }) + .catch(err => { + console.error('Error:', err); + }); +*/ \ No newline at end of file diff --git a/packages/mail/src/lib/index.ts b/packages/mail/src/lib/index.ts new file mode 100644 index 00000000..c94aa754 --- /dev/null +++ b/packages/mail/src/lib/index.ts @@ -0,0 +1,4 @@ +export * from './nodemailer/index.js' +export * from './imap/index.js' + + diff --git a/packages/mail/src/lib/nodemailer/index.ts b/packages/mail/src/lib/nodemailer/index.ts new file mode 100644 index 00000000..09b708a5 --- /dev/null +++ b/packages/mail/src/lib/nodemailer/index.ts @@ -0,0 +1,46 @@ +import { IOptions, ITransportOptions } from '../../types.js' +import { logger } from '../../index.js' +import { SendMailOptions, createTransport } from 'nodemailer' +import { CONFIG_DEFAULT } from '@polymech/commons' +import { sync as read } from '@polymech/fs/read' + +const sendHtmlEmail = async ({ from, to, subject, html, attachments }: SendMailOptions, transport: ITransportOptions) => { + try { + const transporter = createTransport({ + ...transport + }) + const info = await transporter.sendMail({ + from, + to, // list of receivers + subject, // Subject line + html, + attachments + }) + logger.info(`Message sent: ${info.messageId}`) + return info + } catch (error) { + logger.error(`Error occurred: ${error.message}`) + logger.trace(error) + } +} + +export const test = async (options: IOptions) => { + const config: any = CONFIG_DEFAULT() + logger.setSettings({ minLevel: options.logLevel as any || 'info' }) + const transport = config?.email[options.transport] as ITransportOptions + if (!transport) { + logger.error(`No email transport configuration found : ${options.transport}`) + return false + } + if (!options.html && options.src && options.srcInfo) { + options.html = read(options.src, 'string') as string || '

Test Email

' + } + logger.info(`Sending email from ${options.from} to ${options.to}`) + return sendHtmlEmail({ + from: options.from, + to: options.to, + subject: options.subject || 'Test Email', + html: options.html || '

Test Email

', + attachments: options.attachments + }, transport) +} \ No newline at end of file diff --git a/packages/mail/src/lib/process/index.ts b/packages/mail/src/lib/process/index.ts new file mode 100644 index 00000000..38fdc880 --- /dev/null +++ b/packages/mail/src/lib/process/index.ts @@ -0,0 +1,142 @@ +import { logger } from '../../index.js'; +import * as stream from 'stream'; +import { ChildProcess, exec } from 'child_process'; +import { os } from '../common/platform.js'; + +export enum STATUS { + OK, + ERROR, + PENDING +} + +const fatalHandler = (message: string, fn: (msg: string) => void): boolean => { + if (message.startsWith('fatal:')) { + fn('\t\ ' + message); + return true; + } + return false; +}; + +// tslint:disable-next-line:no-empty +const subscribe = (signal: stream.Readable, collector: (data: any) => void = () => { }) => { + const buffer: string[] = []; + signal.on('message', (message) => logger.debug('message', message)); + signal.on('error', (error) => logger.error('std-error', error)); + signal.on('data', (data) => { + const message = data.toString(); + buffer.push(message); // .replace(/[\x00-\x1F\x7F-\x9F]/g, "") + collector(buffer); + }); +}; +const merge = (buffer: string[], data: any): string[] => buffer.concat(data); + +const hook = (process: ChildProcess, resolve: any, reject: any, cmd: string) => { + let buffer: string[] = []; + const collector = (data: any) => { buffer = buffer.concat(data); }; + const stdout = subscribe(process.stdout, collector); + const stderr = subscribe(process.stderr, collector); + process.on('exit', (code, signal) => { + if (code) { + resolve({ + code: STATUS.ERROR, + command: cmd, + error: code, + messages: buffer + }); + } else { + resolve({ + code: STATUS.OK, + command: cmd, + messages: buffer + }); + } + }); + return process; +}; + +export class Process { + public binary = 'magick'; + public cwd: string = ''; + public args: string = ''; + constructor(options: any = {}) { + this.binary = options.binary || this.binary; + //this.binary = path.resolve(which(this.binary)); + this.cwd = options.cwd || process.cwd(); + } + public optionsToString(options: any): string { + const args: any[] = []; + // tslint:disable-next-line:forin + for (const k in options) { + const val = options[k]; + if (k.length === 1) { + // val is true, add '-k' + if (val === true) { + args.push('-' + k); + } else if (val !== false) { + // if val is not false, add '-k val' + args.push('-' + k + ' ' + val); + } + } else { + if (val === true) { + args.push('--' + k); + } else if (val !== false) { + args.push('--' + k + '=' + val); + } + } + } + return args.join(' '); + } + public optionsToArray(options: any): string[] { + const args: any[] = []; + // tslint:disable-next-line:forin + for (const k in options) { + const val = options[k]; + if (k.length === 1) { + // val is true, add '-k' + if (val === true) { + args.push('-' + k); + } else if (val !== false) { + // if val is not false, add '-k val' + args.push('-' + k + ' ' + val); + } + } else { + if (val === true) { + args.push('--' + k); + } else if (val !== false) { + args.push('--' + k + '=' + val); + } + } + } + return args; + } + public async exec(command: string, options: any = {}, args: any[] = []): Promise { + args = [command].concat(args); + return new Promise((resolve, reject) => { + const p = exec(this.binary + ' ' + args.join(' '), { + cwd: this.cwd + }); + return hook(p, resolve, reject, this.binary + ' ' + args.join(' ')); + }); + } +} + +export class Helper { + public static async run(cwd, command: string, gitArgs: string[]): Promise { + const gitProcess = new Process({ + cwd: cwd, + binary: os() == 'windows' ? 'magick' : '' + }); + const p = gitProcess.exec(command, {}, gitArgs); + p.catch((e) => logger.error('Error git command : ' + command)); + return p; + } + public static async runBin(cwd, bin, command: string, gitArgs: string[]): Promise { + const gitProcess = new Process({ + cwd: cwd, + binary: bin + }); + const p = gitProcess.exec(command, {}, gitArgs); + p.catch((e) => logger.error('Error git command : ' + command)); + return p; + } +} \ No newline at end of file diff --git a/packages/mail/src/main.ts b/packages/mail/src/main.ts new file mode 100644 index 00000000..0a73deaa --- /dev/null +++ b/packages/mail/src/main.ts @@ -0,0 +1,13 @@ +#!/usr/bin/env node +import { defaults } from './_cli'; defaults() +import * as CLI from 'yargs' + +//import { register as registerTest } from './commands/test'; registerTest(CLI) + +const argv: any = CLI.argv +if (argv.h || argv.help) { + CLI.showHelp(); + process.exit(); +} else if (argv.v || argv.version) { + process.exit(); +} diff --git a/packages/mail/src/types.ts b/packages/mail/src/types.ts new file mode 100644 index 00000000..a5160873 --- /dev/null +++ b/packages/mail/src/types.ts @@ -0,0 +1,44 @@ +import { Hash } from '@polymech/core' +import { PATH_INFO } from '@polymech/commons' +import { Attachment } from 'nodemailer' + +export interface ITransportOptions { + host: string + port: number + secure: boolean + auth: { + user: string + pass: string + } +} +export type IOptions = { + alt?: boolean + config?: any + cwd?: string + root?: string + debug?: boolean + verbose?: boolean + dry?: boolean + dst?: string + dstInfo?: PATH_INFO + env?: string + cache?: boolean + src?: string + srcInfo?: PATH_INFO + stdout?: boolean + variables?: Hash + key?: string + logLevel?: string + transport?: string + from?: string + subject?: string + html?: string + to?: string + attachments?: Attachment[] +} + + +export type INodeMailer = IOptions & +{ + +} \ No newline at end of file diff --git a/packages/mail/tests/email/log.json b/packages/mail/tests/email/log.json new file mode 100644 index 00000000..caf1f10c --- /dev/null +++ b/packages/mail/tests/email/log.json @@ -0,0 +1,26 @@ +{ + "accepted": [ + "cgoflyn@gmail.com" + ], + "rejected": [], + "ehlo": [ + "PIPELINING", + "SIZE 10240000", + "ETRN", + "AUTH DIGEST-MD5 CRAM-MD5 PLAIN LOGIN", + "ENHANCEDSTATUSCODES", + "8BITMIME", + "DSN" + ], + "envelopeTime": 155, + "messageTime": 159, + "messageSize": 71747, + "response": "250 2.0.0 Ok: queued as E942F68402C5", + "envelope": { + "from": "newsletter@osr-plastic.org", + "to": [ + "cgoflyn@gmail.com" + ] + }, + "messageId": "<8fcfe99d-04d4-5c2f-1d4c-e1e31225173a@osr-plastic.org>" +} \ No newline at end of file diff --git a/packages/mail/tests/email/test.html b/packages/mail/tests/email/test.html new file mode 100644 index 00000000..15d6ea3a --- /dev/null +++ b/packages/mail/tests/email/test.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/mail/tsconfig.json b/packages/mail/tsconfig.json new file mode 100644 index 00000000..68a5cd90 --- /dev/null +++ b/packages/mail/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../typescript-config/base.json", + "compilerOptions": { + "outDir": "./dist-in", + "rootDir": "src", + "baseUrl": ".", + "allowJs": true, + "esModuleInterop": true, + "composite": false, + "importHelpers": false, + "inlineSourceMap": true, + "paths": { + "@/*": [ + "src/*" + ] + } + }, + "files": [ + "src/index.ts", + "src/main.ts" + ] +} \ No newline at end of file