diff --git a/email.esm.js b/email.esm.js deleted file mode 100644 index 49e3efe..0000000 --- a/email.esm.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as server from './smtp/client'; -import * as message from './smtp/message'; -import * as date from './smtp/date'; -import * as SMTP from './smtp/smtp'; -import * as error from './smtp/error'; - -export { server, message, date, SMTP, error }; diff --git a/email.js b/email.js deleted file mode 100644 index 76a4f60..0000000 --- a/email.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.server = require('./smtp/client'); -exports.message = require('./smtp/message'); -exports.date = require('./smtp/date'); -exports.SMTP = require('./smtp/smtp'); -exports.error = require('./smtp/error'); diff --git a/email.ts b/email.ts new file mode 100644 index 0000000..3cb00e8 --- /dev/null +++ b/email.ts @@ -0,0 +1,5 @@ +export * as client from './smtp/client'; +export * as message from './smtp/message'; +export * as date from './smtp/date'; +export * as SMTP from './smtp/smtp'; +export * as error from './smtp/error'; diff --git a/package.json b/package.json index a4a149b..5bac0e8 100644 --- a/package.json +++ b/package.json @@ -1,55 +1,73 @@ { - "name": "emailjs", - "description": "send text/html emails and attachments (files, streams and strings) from node.js to any smtp server", - "version": "2.2.0", - "author": "eleith", - "contributors": [ - "izuzak", - "Hiverness", - "mscdex", - "jimmybergman", - "zackschuster" - ], - "repository": { - "type": "git", - "url": "http://github.com/eleith/emailjs.git" - }, - "dependencies": { - "addressparser": "^0.3.2", - "emailjs-mime-codec": "^2.0.7" - }, - "devDependencies": { - "chai": "^4.1.2", - "eslint": "^5.1.0", - "eslint-config-prettier": "^2.9.0", - "eslint-plugin-mocha": "^5.1.0", - "eslint-plugin-prettier": "^2.6.2", - "mailparser": "^2.2.0", - "mocha": "^5.2.0", - "prettier": "^1.13.7", - "rollup": "^0.62.0", - "rollup-plugin-commonjs": "^9.1.3", - "rollup-plugin-node-resolve": "^3.3.0", - "smtp-server": "^3.4.6" - }, - "engine": [ - "node >= 6" - ], - "main": "email.js", - "scripts": { + "name": "emailjs", + "description": "send text/html emails and attachments (files, streams and strings) from node.js to any smtp server", + "version": "2.2.0", + "author": "eleith", + "contributors": [ + "izuzak", + "Hiverness", + "mscdex", + "jimmybergman", + "zackschuster" + ], + "repository": { + "type": "git", + "url": "http://github.com/eleith/emailjs.git" + }, + "dependencies": { + "addressparser": "^0.3.2", + "emailjs-mime-codec": "^2.0.7" + }, + "devDependencies": { + "@ledge/configs": "22.0.2", + "@ledge/types": "6.1.0", + "@types/addressparser": "2.7.2", + "@types/mailparser": "2.7.2", + "@types/smtp-server": "3.5.4", + "ava": "3.7.1", + "eslint": "^5.1.0", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-mocha": "^5.1.0", + "eslint-plugin-prettier": "^2.6.2", + "mailparser": "^2.2.0", + "prettier": "^1.13.7", + "rollup": "^0.62.0", + "rollup-plugin-commonjs": "^9.1.3", + "rollup-plugin-node-resolve": "^3.3.0", + "smtp-server": "^3.4.6", + "typescript": "3.8.3", + "ts-node": "8.9.0" + }, + "engine": [ + "node >= 10" + ], + "main": "email.js", + "type": "module", + "scripts": { "rollup": "rollup -c rollup.config.js && npm run rollup:test", "rollup:test": "npm run test -- --file rollup/email.bundle.test.js", - "test": "mocha" - }, - "license": "MIT", - "eslintIgnore": [ - "rollup.config.js", - "rollup/email.bundle.js", - "email.esm.js" - ], - "prettier": { - "singleQuote": true, - "trailingComma": "es5", - "useTabs": true - } + "test": "ava" + }, + "license": "MIT", + "ava": { + "files": [ + "test/*.ts" + ], + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register/transpile-only" + ] + }, + "eslintIgnore": [ + "rollup.config.js", + "rollup/email.bundle.js", + "email.esm.js" + ], + "prettier": { + "singleQuote": true, + "trailingComma": "es5", + "useTabs": true + } } diff --git a/rollup.config.js b/rollup.config.js index 18ce336..acd9018 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,15 +1,16 @@ +import { builtinModules as external } from 'module'; import commonjs from 'rollup-plugin-commonjs'; import resolve from 'rollup-plugin-node-resolve'; export default { - input: 'email.esm.js', + input: 'email.js', output: { file: 'rollup/email.bundle.js', format: 'cjs', interop: false, freeze: false, }, - external: require('module').builtinModules, + external, plugins: [ resolve(), commonjs(), diff --git a/smtp/client.js b/smtp/client.ts similarity index 74% rename from smtp/client.js rename to smtp/client.ts index f16a3fc..5aa36cb 100644 --- a/smtp/client.js +++ b/smtp/client.ts @@ -1,20 +1,29 @@ -const { SMTP, state } = require('./smtp'); -const { Message, create } = require('./message'); -const addressparser = require('addressparser'); +// @ts-ignore +import addressparser from 'addressparser'; +import { Message, MessageHeaders, MessageAttachment } from './message'; +import { SMTP, SMTPState, SMTPOptions } from './smtp'; + +export interface MessageStack { + callback: (error: Error | null, message: Message) => void; + message: Message; + attachment: MessageAttachment; + text: string; + returnPath: string; + from: string; + to: string | { address: string }[]; + cc: string[]; + bcc: string[]; +} + +export class Client { + public smtp: SMTP; + public queue: MessageStack[] = [] + public timer: any; + public sending: boolean; + public ready: boolean; -class Client { /** * @typedef {Object} MessageStack - * @property {function(Error, Message): void} [callback] - * @property {Message} [message] - * @property {string} [returnPath] - * @property {string} [from] - * @property {string} [subject] - * @property {string|Array} [to] - * @property {Array} [cc] - * @property {Array} [bcc] - * @property {string} [text] - * @property {*} [attachment] * * @typedef {Object} SMTPSocketOptions * @property {string} key @@ -36,15 +45,10 @@ class Client { * @constructor * @param {SMTPOptions} server smtp options */ - constructor(server) { + constructor(server: Partial) { this.smtp = new SMTP(server); //this.smtp.debug(1); - /** - * @type {MessageStack[]} - */ - this.queue = []; - /** * @type {NodeJS.Timer} */ @@ -61,27 +65,16 @@ class Client { this.ready = false; } - /** - * @param {Message|MessageStack} msg msg - * @param {function(Error, MessageStack): void} callback callback - * @returns {void} - */ - send(msg, callback) { - /** - * @type {Message} - */ - const message = + send(msg: Message, callback: (err: Error, msg: Message) => void): void { + const message: Message | null = msg instanceof Message ? msg : this._canMakeMessage(msg) - ? create(msg) + ? new Message(msg) : null; if (message == null) { - callback( - new Error('message is not a valid Message instance'), - /** @type {MessageStack} */ (msg) - ); + callback(new Error('message is not a valid Message instance'), msg); return; } @@ -92,7 +85,7 @@ class Client { to: addressparser(message.header.to), from: addressparser(message.header.from)[0].address, callback: (callback || function() {}).bind(this), - }; + } as MessageStack; if (message.header.cc) { stack.to = stack.to.concat(addressparser(message.header.cc)); @@ -123,23 +116,23 @@ class Client { * @private * @returns {void} */ - _poll() { + _poll(): void { clearTimeout(this.timer); - if (this.queue.length) { - if (this.smtp.state() == state.NOTCONNECTED) { + if (this.queue.length > 0) { + if (this.smtp.state == SMTPState.NOTCONNECTED) { this._connect(this.queue[0]); } else if ( - this.smtp.state() == state.CONNECTED && + this.smtp.state == SMTPState.CONNECTED && !this.sending && this.ready ) { - this._sendmail(this.queue.shift()); + this._sendmail(this.queue.shift() as MessageStack); } } // wait around 1 seconds in case something does come in, // otherwise close out SMTP connection if still open - else if (this.smtp.state() == state.CONNECTED) { + else if (this.smtp.state == SMTPState.CONNECTED) { this.timer = setTimeout(() => this.smtp.quit(), 1000); } } @@ -149,14 +142,14 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _connect(stack) { + _connect(stack: MessageStack): void { /** * @param {Error} err callback error * @returns {void} */ - const connect = err => { + const connect = (err: Error): void => { if (!err) { - const begin = err => { + const begin = (err: Error) => { if (!err) { this.ready = true; this._poll(); @@ -169,7 +162,7 @@ class Client { } }; - if (!this.smtp.authorized()) { + if (!this.smtp.isAuthorized) { this.smtp.login(begin); } else { this.smtp.ehlo_or_helo_if_needed(begin); @@ -192,11 +185,11 @@ class Client { * @param {MessageStack} msg message stack * @returns {boolean} can make message */ - _canMakeMessage(msg) { - return ( + _canMakeMessage(msg: MessageHeaders): boolean { + return !!( msg.from && (msg.to || msg.cc || msg.bcc) && - (msg.text !== undefined || this._containsInlinedHtml(msg.attachment)) + (msg.text != null || this._containsInlinedHtml(msg.attachment)) ); } @@ -205,7 +198,7 @@ class Client { * @param {*} attachment attachment * @returns {boolean} does contain */ - _containsInlinedHtml(attachment) { + _containsInlinedHtml(attachment: any): boolean { if (Array.isArray(attachment)) { return attachment.some(att => { return this._isAttachmentInlinedHtml(att); @@ -220,7 +213,7 @@ class Client { * @param {*} attachment attachment * @returns {boolean} is inlined */ - _isAttachmentInlinedHtml(attachment) { + _isAttachmentInlinedHtml(attachment: any): boolean { return ( attachment && (attachment.data || attachment.path) && @@ -234,7 +227,7 @@ class Client { * @param {function(MessageStack): void} next next * @returns {function(Error): void} callback */ - _sendsmtp(stack, next) { + _sendsmtp(stack: MessageStack, next: (msg: MessageStack) => void): (err: Error) => void { /** * @param {Error} [err] error * @returns {void} @@ -255,7 +248,7 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _sendmail(stack) { + _sendmail(stack: MessageStack): void { const from = stack.returnPath || stack.from; this.sending = true; this.smtp.mail(this._sendsmtp(stack, this._sendrcpt), '<' + from + '>'); @@ -266,12 +259,12 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _sendrcpt(stack) { + _sendrcpt(stack: MessageStack): void { if (stack.to == null || typeof stack.to === 'string') { throw new TypeError('stack.to must be array'); } - const to = stack.to.shift().address; + const { address: to } = stack.to.shift() ?? {}; this.smtp.rcpt( this._sendsmtp(stack, stack.to.length ? this._sendrcpt : this._senddata), `<${to}>` @@ -283,7 +276,7 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _senddata(stack) { + _senddata(stack: MessageStack): void { this.smtp.data(this._sendsmtp(stack, this._sendmessage)); } @@ -292,7 +285,7 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _sendmessage(stack) { + _sendmessage(stack: MessageStack): void { const stream = stack.message.stream(); stream.on('data', data => this.smtp.message(data)); @@ -316,17 +309,9 @@ class Client { * @param {MessageStack} stack stack * @returns {void} */ - _senddone(err, stack) { + _senddone(err: Error | null, stack: MessageStack): void { this.sending = false; stack.callback(err, stack.message); this._poll(); } } - -exports.Client = Client; - -/** - * @param {SMTPOptions} server smtp options - * @returns {Client} the client - */ -exports.connect = server => new Client(server); diff --git a/smtp/date.js b/smtp/date.js deleted file mode 100644 index 33d8245..0000000 --- a/smtp/date.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @param {Date} [date] an optional date to convert to RFC2822 format - * @param {boolean} [useUtc=false] whether to parse the date as UTC (default: false) - * @returns {string} the converted date - */ -function getRFC2822Date(date = new Date(), useUtc = false) { - if (useUtc) { - return getRFC2822DateUTC(date); - } - - const dates = date - .toString() - .replace('GMT', '') - .replace(/\s\(.*\)$/, '') - .split(' '); - - dates[0] = dates[0] + ','; - - const day = dates[1]; - dates[1] = dates[2]; - dates[2] = day; - - return dates.join(' '); -} - -/** - * @param {Date} [date] an optional date to convert to RFC2822 format (UTC) - * @returns {string} the converted date - */ -function getRFC2822DateUTC(date = new Date()) { - const dates = date.toUTCString().split(' '); - dates.pop(); // remove timezone - dates.push('+0000'); - return dates.join(' '); -} - -exports.getRFC2822Date = getRFC2822Date; -exports.getRFC2822DateUTC = getRFC2822DateUTC; diff --git a/smtp/date.ts b/smtp/date.ts new file mode 100644 index 0000000..be352b4 --- /dev/null +++ b/smtp/date.ts @@ -0,0 +1,35 @@ +/** + * @param [date] an optional date to convert to RFC2822 format + * @param [useUtc] whether to parse the date as UTC (default: false) + * @returns the converted date + */ +export function getRFC2822Date(date = new Date(), useUtc = false) { + if (useUtc) { + return getRFC2822DateUTC(date); + } + + const dates = date + .toString() + .replace('GMT', '') + .replace(/\s\(.*\)$/, '') + .split(' '); + + dates[0] = dates[0] + ','; + + const day = dates[1]; + dates[1] = dates[2]; + dates[2] = day; + + return dates.join(' '); +} + +/** + * @param [date] an optional date to convert to RFC2822 format (UTC) + * @returns the converted date + */ +export function getRFC2822DateUTC(date = new Date()) { + const dates = date.toUTCString().split(' '); + dates.pop(); // remove timezone + dates.push('+0000'); + return dates.join(' '); +} diff --git a/smtp/error.js b/smtp/error.js deleted file mode 100644 index a234062..0000000 --- a/smtp/error.js +++ /dev/null @@ -1,86 +0,0 @@ -class SMTPError extends Error { - /** - * @param {string} message the error message - */ - constructor(message) { - super(message); - - /** - * @type {number} - */ - this.code = null; - - /** - * @type {*} - */ - this.smtp = null; - - /** - * @type {Error} - */ - this.previous = null; - } -} - -/** - * @param {string} message the error message - * @param {number} code the error code - * @param {Error} [error] an error object - * @param {*} [smtp] smtp - * @returns {SMTPError} an smtp error object - */ -module.exports = function(message, code, error, smtp) { - const err = new SMTPError( - error != null && error.message ? `${message} (${error.message})` : message - ); - - err.code = code; - err.smtp = smtp; - - if (error) { - err.previous = error; - } - - return err; -}; - -/** - * @type {1} - */ -module.exports.COULDNOTCONNECT = 1; -/** - * @type {2} - */ -module.exports.BADRESPONSE = 2; -/** - * @type {3} - */ -module.exports.AUTHFAILED = 3; -/** - * @type {4} - */ -module.exports.TIMEDOUT = 4; -/** - * @type {5} - */ -module.exports.ERROR = 5; -/** - * @type {6} - */ -module.exports.NOCONNECTION = 6; -/** - * @type {7} - */ -module.exports.AUTHNOTSUPPORTED = 7; -/** - * @type {8} - */ -module.exports.CONNECTIONCLOSED = 8; -/** - * @type {9} - */ -module.exports.CONNECTIONENDED = 9; -/** - * @type {10} - */ -module.exports.CONNECTIONAUTH = 10; diff --git a/smtp/error.ts b/smtp/error.ts new file mode 100644 index 0000000..fc80d83 --- /dev/null +++ b/smtp/error.ts @@ -0,0 +1,32 @@ +class SMTPError extends Error { + public code: number | null = null; + public smtp: any = null; + public previous: Error | null = null; +} + +export function makeSMTPError(message: string, code: number, error?: Error, smtp?: any) { + const msg = error != null && error.message ? `${message} (${error.message})` : message; + const err = new SMTPError(msg); + + err.code = code; + err.smtp = smtp; + + if (error) { + err.previous = error; + } + + return err; +}; + +export const enum SMTPErrorStates { + COULDNOTCONNECT = 1, + BADRESPONSE = 2, + AUTHFAILED = 3, + TIMEDOUT = 4, + ERROR = 5, + NOCONNECTION = 6, + AUTHNOTSUPPORTED = 7, + CONNECTIONCLOSED = 8, + CONNECTIONENDED = 9, + CONNECTIONAUTH = 10, +} diff --git a/smtp/message.js b/smtp/message.ts similarity index 67% rename from smtp/message.js rename to smtp/message.ts index 373222b..622eea9 100644 --- a/smtp/message.js +++ b/smtp/message.ts @@ -1,38 +1,73 @@ -const fs = require('fs'); -const { hostname } = require('os'); -const { Stream } = require('stream'); -const addressparser = require('addressparser'); -const { mimeWordEncode } = require('emailjs-mime-codec'); -const { getRFC2822Date } = require('./date'); +import fs from 'fs'; +import { hostname } from 'os'; +import { Stream, Duplex } from 'stream'; + +// @ts-ignore +import addressparser from 'addressparser'; +// @ts-ignore +import { mimeWordEncode } from 'emailjs-mime-codec'; +import type { Indexed } from '@ledge/types'; + +import { getRFC2822Date } from './date'; const CRLF = '\r\n'; /** * MIME standard wants 76 char chunks when sending out. - * @type {76} */ -const MIMECHUNK = 76; +export const MIMECHUNK: 76 = 76; /** * meets both base64 and mime divisibility - * @type {456} */ -const MIME64CHUNK = /** @type {456} */ (MIMECHUNK * 6); +export const MIME64CHUNK: 456 = (MIMECHUNK * 6) as 456; /** * size of the message stream buffer - * @type {12768} */ -const BUFFERSIZE = /** @type {12768} */ (MIMECHUNK * 24 * 7); +export const BUFFERSIZE: 12768 = (MIMECHUNK * 24 * 7) as 12768; -/** - * @type {number} - */ -let counter = 0; -/** - * @returns {string} the generated boundary - */ +export interface MessageAttachmentHeaders extends Indexed { + 'content-type'?: string; + 'content-transfer-encoding'?: string; + 'content-disposition'?: string; +} + +export interface AlternateMessageAttachment extends Indexed { + headers: MessageAttachmentHeaders; + inline: boolean; + alternative?: MessageAttachment; + related?: MessageAttachment[]; + data: any; + encoded?: any; +} + +export interface MessageAttachment extends AlternateMessageAttachment { + name: string; + type: string; + charset: string; + method: string; + path: string; + stream: Duplex; +} + + +export interface MessageHeaders extends Indexed { + 'content-type': string; + 'message-id': string; + date: string; + from: string; + to: string; + cc: string; + bcc: string; + subject: string; + text: string | null; + attachment: MessageAttachment | MessageAttachment[]; +} + +let counter: number = 0; + function generate_boundary() { let text = ''; const possible = @@ -45,13 +80,9 @@ function generate_boundary() { return text; } -/** - * @param {string} l the person to parse into an address - * @returns {string} the parsed address - */ -function person2address(l) { - return addressparser(l) - .map(({ name, address }) => { +function convertPersonToAddress(person: string) { + return addressparser(person) + .map(({ name, address }: { name: string, address: string }) => { return name ? `${mimeWordEncode(name).replace(/,/g, '=2C')} <${address}>` : address; @@ -59,32 +90,21 @@ function person2address(l) { .join(', '); } -/** - * @param {string} header_name the header name to fix - * @returns {string} the fixed header name - */ -function fix_header_name_case(header_name) { - return header_name +function convertDashDelimitedTextToSnakeCase(text: string) { + return text .toLowerCase() .replace(/^(.)|-(.)/g, match => match.toUpperCase()); } -class Message { - /** - * @typedef {Object} MessageHeaders - * @property {string?} content-type - * @property {string} [subject] - * @property {string} [text] - * @property {MessageAttachment} [attachment] - * @param {MessageHeaders} headers hash of message headers - */ - constructor(headers) { - this.attachments = []; +export class Message { + attachments: any[] = []; + alternative: AlternateMessageAttachment | null = null; + header: Partial; + content: string; + text: any; + + constructor(headers: Partial) { - /** - * @type {MessageAttachment} - */ - this.alternative = null; this.header = { 'message-id': `<${new Date().getTime()}.${counter++}.${ process.pid @@ -99,22 +119,21 @@ class Message { this.content = headers[header]; } else if (header === 'text') { this.text = headers[header]; - } else if ( - header === 'attachment' && - typeof headers[header] === 'object' - ) { + } else if (header === 'attachment') { const attachment = headers[header]; - if (Array.isArray(attachment)) { - for (let i = 0; i < attachment.length; i++) { - this.attach(attachment[i]); + if (attachment != null) { + if (Array.isArray(attachment)) { + for (let i = 0; i < attachment.length; i++) { + this.attach(attachment[i]); + } + } else { + this.attach(attachment); } - } else { - this.attach(attachment); } } else if (header === 'subject') { this.header.subject = mimeWordEncode(headers.subject); } else if (/^(cc|bcc|to|from)/i.test(header)) { - this.header[header.toLowerCase()] = person2address(headers[header]); + this.header[header.toLowerCase()] = convertPersonToAddress(headers[header]); } else { // allow any headers the user wants to set?? // if(/cc|bcc|to|from|reply-to|sender|subject|date|message-id/i.test(header)) @@ -127,19 +146,7 @@ class Message { * @param {MessageAttachment} options attachment options * @returns {Message} the current instance for chaining */ - attach(options) { - /* - legacy support, will remove eventually... - arguments -> (path, type, name, headers) - */ - if (typeof options === 'string' && arguments.length > 1) { - options = { - path: options, - type: arguments[1], - name: arguments[2], - }; - } - + attach(options: MessageAttachment): Message { // sender can specify an attachment as an alternative if (options.alternative) { this.alternative = options; @@ -160,10 +167,13 @@ class Message { * @param {string} [charset='utf-8'] the charset to encode as * @returns {Message} the current Message instance */ - attach_alternative(html, charset) { + attach_alternative(html: string, charset = 'utf-8'): Message { this.alternative = { + headers: { + + }, data: html, - charset: charset || 'utf-8', + charset, type: 'text/html', inline: true, }; @@ -175,7 +185,7 @@ class Message { * @param {function(boolean, string): void} callback This callback is displayed as part of the Requester class. * @returns {void} */ - valid(callback) { + valid(callback: (arg0: boolean, arg1?: string) => void): void { if (!this.header.from) { callback(false, 'message does not have a valid sender'); } @@ -185,7 +195,7 @@ class Message { } else if (this.attachments.length === 0) { callback(true, undefined); } else { - const failed = []; + const failed: string[] = []; this.attachments.forEach(attachment => { if (attachment.path) { @@ -209,7 +219,7 @@ class Message { * returns a stream of the current message * @returns {MessageStream} a stream of the current message */ - stream() { + stream(): MessageStream { return new MessageStream(this); } @@ -217,7 +227,7 @@ class Message { * @param {function(Error, string): void} callback the function to call with the error and buffer * @returns {void} */ - read(callback) { + read(callback: (arg0: Error, arg1: string) => void): void { let buffer = ''; const str = this.stream(); str.on('data', data => (buffer += data)); @@ -226,34 +236,16 @@ class Message { } } -/** - * @typedef {Object} MessageAttachmentHeaders - * @property {string} content-type - * @property {string} content-transfer-encoding - * @property {string} content-disposition - */ - -/** - * @typedef {Object} MessageAttachment - * @property {string} [name] - * @property {string} [type] - * @property {string} [charset] - * @property {string} [method] - * @property {string} [path] - * @property {NodeJS.ReadWriteStream} [stream] - * @property {boolean} [inline] - * @property {MessageAttachment} [alternative] - * @property {MessageAttachment[]} [related] - * @property {*} [encoded] - * @property {*} [data] - * @property {MessageAttachmentHeaders} [headers] - */ - class MessageStream extends Stream { + message: Message; + readable: boolean; + paused: boolean; + buffer: Buffer | null; + bufferIndex: number; /** * @param {Message} message the message to stream */ - constructor(message) { + constructor(message: Message) { super(); /** @@ -284,7 +276,7 @@ class MessageStream extends Stream { /** * @returns {void} */ - const output_mixed = () => { + const output_mixed = (): void => { const boundary = generate_boundary(); output( `Content-Type: multipart/mixed; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}` @@ -294,9 +286,11 @@ class MessageStream extends Stream { output_text(this.message); output_message(boundary, this.message.attachments, 0, close); } else { - const cb = () => - output_message(boundary, this.message.attachments, 0, close); - output_alternative(this.message, cb); + output_alternative( + // typescript bug; should narrow to { alternative: AlternateMessageAttachment } + this.message as Parameters[0], + () => output_message(boundary, this.message.attachments, 0, close) + ); } }; @@ -307,7 +301,7 @@ class MessageStream extends Stream { * @param {function(): void} callback the function to call if index is greater than upper bound * @returns {void} */ - const output_message = (boundary, list, index, callback) => { + const output_message = (boundary: string, list: MessageAttachment[], index: number, callback: () => void): void => { if (index < list.length) { output(`--${boundary}${CRLF}`); if (list[index].related) { @@ -326,12 +320,11 @@ class MessageStream extends Stream { }; /** - * @param {MessageAttachment} attachment the metadata to use as headers * @returns {void} */ - const output_attachment_headers = attachment => { - let data = []; - const headers = { + const output_attachment_headers = (attachment: MessageAttachment | AlternateMessageAttachment): void => { + let data: string[] = []; + const headers: Partial = { 'content-type': attachment.type + (attachment.charset ? `; charset=${attachment.charset}` : '') + @@ -349,7 +342,7 @@ class MessageStream extends Stream { for (const header in headers) { data = data.concat([ - fix_header_name_case(header), + convertDashDelimitedTextToSnakeCase(header), ': ', headers[header], CRLF, @@ -359,12 +352,7 @@ class MessageStream extends Stream { output(data.concat([CRLF]).join('')); }; - /** - * @param {MessageAttachment} attachment the metadata to use as headers - * @param {function(): void} callback the function to call after output is finished - * @returns {void} - */ - const output_attachment = (attachment, callback) => { + const output_attachment = (attachment: MessageAttachment | AlternateMessageAttachment, callback: () => void): void => { const build = attachment.path ? output_file : attachment.stream @@ -379,7 +367,7 @@ class MessageStream extends Stream { * @param {function(): void} callback the function to call after output is finished * @returns {void} */ - const output_data = (attachment, callback) => { + const output_data = (attachment: MessageAttachment | AlternateMessageAttachment, callback: () => void): void => { output_base64( attachment.encoded ? attachment.data @@ -388,24 +376,19 @@ class MessageStream extends Stream { ); }; - /** - * @param {MessageAttachment} attachment the metadata to use as headers - * @param {function(NodeJS.ErrnoException): void} next the function to call when the file is closed - * @returns {void} - */ - const output_file = (attachment, next) => { + const output_file = (attachment: MessageAttachment | AlternateMessageAttachment, next: (err: NodeJS.ErrnoException) => void): void => { const chunk = MIME64CHUNK * 16; const buffer = Buffer.alloc(chunk); - const closed = fd => fs.closeSync(fd); + const closed = (fd: number) => fs.closeSync(fd); /** * @param {Error} err the error to emit * @param {number} fd the file descriptor * @returns {void} */ - const opened = (err, fd) => { + const opened = (err: Error, fd: number): void => { if (!err) { - const read = (err, bytes) => { + const read = (err: Error, bytes: number) => { if (!err && this.readable) { let encoding = attachment && attachment.headers @@ -452,20 +435,20 @@ class MessageStream extends Stream { * @param {function(): void} callback the function to call after output is finished * @returns {void} */ - const output_stream = (attachment, callback) => { + const output_stream = (attachment: MessageAttachment | AlternateMessageAttachment, callback: () => void): void => { if (attachment.stream.readable) { let previous = Buffer.alloc(0); attachment.stream.resume(); - attachment.stream.on('end', () => { + (attachment as MessageAttachment).on('end', () => { output_base64(previous.toString('base64'), callback); this.removeListener('pause', attachment.stream.pause); this.removeListener('resume', attachment.stream.resume); this.removeListener('error', attachment.stream.resume); }); - attachment.stream.on('data', buff => { + (attachment as MessageAttachment).stream.on('data', buff => { // do we have bytes from a previous stream data event? let buffer = Buffer.isBuffer(buff) ? buff : Buffer.from(buff); @@ -497,7 +480,7 @@ class MessageStream extends Stream { * @param {function(): void} [callback] the function to call after output is finished * @returns {void} */ - const output_base64 = (data, callback) => { + const output_base64 = (data: string, callback?: () => void): void => { const loops = Math.ceil(data.length / MIMECHUNK); let loop = 0; while (loop < loops) { @@ -513,8 +496,8 @@ class MessageStream extends Stream { * @param {Message} message the message to output * @returns {void} */ - const output_text = message => { - let data = []; + const output_text = (message: Message): void => { + let data: string[] = []; data = data.concat([ 'Content-Type:', @@ -534,7 +517,7 @@ class MessageStream extends Stream { * @param {function(): void} callback the function to call after output is finished * @returns {void} */ - const output_alternative = (message, callback) => { + const output_alternative = (message: Message & { alternative: AlternateMessageAttachment }, callback: () => void): void => { const boundary = generate_boundary(); output( `Content-Type: multipart/alternative; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}` @@ -545,7 +528,7 @@ class MessageStream extends Stream { /** * @returns {void} */ - const finish = () => { + const finish = (): void => { output([CRLF, '--', boundary, '--', CRLF, CRLF].join('')); callback(); }; @@ -562,13 +545,13 @@ class MessageStream extends Stream { * @param {function(): void} callback the function to call after output is finished * @returns {void} */ - const output_related = (message, callback) => { + const output_related = (message: AlternateMessageAttachment, callback: () => void): void => { const boundary = generate_boundary(); output( `Content-Type: multipart/related; boundary="${boundary}"${CRLF}${CRLF}--${boundary}${CRLF}` ); output_attachment(message, () => { - output_message(boundary, message.related, 0, () => { + output_message(boundary, message.related ?? [], 0, () => { output(`${CRLF}--${boundary}--${CRLF}${CRLF}`); callback(); }); @@ -578,7 +561,7 @@ class MessageStream extends Stream { /** * @returns {void} */ - const output_header_data = () => { + const output_header_data = (): void => { if (this.message.attachments.length || this.message.alternative) { output(`MIME-Version: 1.0${CRLF}`); output_mixed(); @@ -592,8 +575,8 @@ class MessageStream extends Stream { /** * @returns {void} */ - const output_header = () => { - let data = []; + const output_header = (): void => { + let data: string[] = []; for (const header in this.message.header) { // do not output BCC in the headers (regex) nor custom Object.prototype functions... @@ -602,7 +585,7 @@ class MessageStream extends Stream { this.message.header.hasOwnProperty(header) ) { data = data.concat([ - fix_header_name_case(header), + convertDashDelimitedTextToSnakeCase(header), ': ', this.message.header[header], CRLF, @@ -615,69 +598,69 @@ class MessageStream extends Stream { }; /** - * @param {string} data the data to output - * @param {function(...args): void} [callback] the function - * @param {*[]} [args] array of arguments to pass to the callback - * @returns {void} + * @param [data] the data to output + * @param [callback] the function + * @param [args] array of arguments to pass to the callback */ - const output = (data, callback, args) => { - const bytes = Buffer.byteLength(data); - + const output = (data: string, callback?: (...args: any[]) => void, args: any[] = []) => { // can we buffer the data? - if (bytes + this.bufferIndex < this.buffer.length) { - this.buffer.write(data, this.bufferIndex); - this.bufferIndex += bytes; - if (callback) { - callback.apply(null, args); - } - } - // we can't buffer the data, so ship it out! - else if (bytes > this.buffer.length) { - if (this.bufferIndex) { - this.emit('data', this.buffer.toString('utf-8', 0, this.bufferIndex)); - this.bufferIndex = 0; - } + if (this.buffer != null) { + const bytes = Buffer.byteLength(data); - const loops = Math.ceil(data.length / this.buffer.length); - let loop = 0; - while (loop < loops) { - this.emit( - 'data', - data.substring( - this.buffer.length * loop, - this.buffer.length * (loop + 1) - ) - ); - loop++; - } - } // we need to clean out the buffer, it is getting full - else { - if (!this.paused) { - this.emit('data', this.buffer.toString('utf-8', 0, this.bufferIndex)); - this.buffer.write(data, 0); - this.bufferIndex = bytes; - // we could get paused after emitting data... - if (this.paused) { - this.once('resume', () => callback.apply(null, args)); - } else if (callback) { + if ((bytes + this.bufferIndex) < this.buffer.length) { + this.buffer.write(data, this.bufferIndex); + this.bufferIndex += bytes; + if (callback) { callback.apply(null, args); } - } // we can't empty out the buffer, so let's wait till we resume before adding to it + } + // we can't buffer the data, so ship it out! + else if (bytes > this.buffer.length) { + if (this.bufferIndex) { + this.emit('data', this.buffer.toString('utf-8', 0, this.bufferIndex)); + this.bufferIndex = 0; + } + + const loops = Math.ceil(data.length / this.buffer.length); + let loop = 0; + while (loop < loops) { + this.emit( + 'data', + data.substring( + this.buffer.length * loop, + this.buffer.length * (loop + 1) + ) + ); + loop++; + } + } // we need to clean out the buffer, it is getting full else { - this.once('resume', () => output(data, callback, args)); + if (!this.paused) { + this.emit('data', this.buffer.toString('utf-8', 0, this.bufferIndex)); + this.buffer.write(data, 0); + this.bufferIndex = bytes; + // we could get paused after emitting data... + + if (typeof callback === 'function') { + if (this.paused) { + this.once('resume', () => callback.apply(null, args)); + } else { + callback.apply(null, args); + } + } + } // we can't empty out the buffer, so let's wait till we resume before adding to it + else { + this.once('resume', () => output(data, callback, args)); + } } } }; - /** - * @param {*} [err] the error to emit - * @returns {void} - */ - const close = err => { + const close = (err?: any): void => { if (err) { this.emit('error', err); } else { - this.emit('data', this.buffer.toString('utf-8', 0, this.bufferIndex)); + this.emit('data', this.buffer?.toString('utf-8', 0, this.bufferIndex) ?? ''); this.emit('end'); } this.buffer = null; @@ -698,7 +681,7 @@ class MessageStream extends Stream { * pause the stream * @returns {void} */ - pause() { + pause(): void { this.paused = true; this.emit('pause'); } @@ -707,7 +690,7 @@ class MessageStream extends Stream { * resume the stream * @returns {void} */ - resume() { + resume(): void { this.paused = false; this.emit('resume'); } @@ -716,7 +699,7 @@ class MessageStream extends Stream { * destroy the stream * @returns {void} */ - destroy() { + destroy(): void { this.emit( 'destroy', this.bufferIndex > 0 ? { message: 'message stream destroyed' } : null @@ -727,11 +710,7 @@ class MessageStream extends Stream { * destroy the stream at first opportunity * @returns {void} */ - destroySoon() { + destroySoon(): void { this.emit('destroy'); } } - -exports.Message = Message; -exports.BUFFERSIZE = BUFFERSIZE; -exports.create = headers => new Message(headers); diff --git a/smtp/response.js b/smtp/response.js deleted file mode 100644 index 0b73bfd..0000000 --- a/smtp/response.js +++ /dev/null @@ -1,139 +0,0 @@ -const SMTPError = require('./error'); - -/** - * @typedef {import('net').Socket} Socket - * @typedef {import('tls').TLSSocket} TLSSocket - */ - -class SMTPResponse { - /** - * @constructor - * @param {Socket | TLSSocket} stream the open socket to stream a response from - * @param {number} timeout the time to wait (in milliseconds) before closing the socket - * @param {function(Error): void} onerror the function to call on error - */ - constructor(stream, timeout, onerror) { - let buffer = ''; - - /** - * @returns {void} - */ - const notify = () => { - if (buffer.length) { - // parse buffer for response codes - const line = buffer.replace('\r', ''); - if ( - !line - .trim() - .split(/\n/) - .pop() - .match(/^(\d{3})\s/) - ) { - return; - } - - const match = line ? line.match(/(\d+)\s?(.*)/) : null; - const data = - match !== null - ? { code: match[1], message: match[2], data: line } - : { code: -1, data: line }; - - stream.emit('response', null, data); - buffer = ''; - } - }; - - /** - * @param {Error} err the error object - * @returns {void} - */ - const error = err => { - stream.emit( - 'response', - SMTPError('connection encountered an error', SMTPError.ERROR, err) - ); - }; - - /** - * @param {Error} err the error object - * @returns {void} - */ - const timedout = err => { - stream.end(); - stream.emit( - 'response', - SMTPError( - 'timedout while connecting to smtp server', - SMTPError.TIMEDOUT, - err - ) - ); - }; - - /** - * @param {string | Buffer} data the data - * @returns {void} - */ - const watch = data => { - if (data !== null) { - buffer += data.toString(); - notify(); - } - }; - - /** - * @param {Error} err the error object - * @returns {void} - */ - const close = err => { - stream.emit( - 'response', - SMTPError('connection has closed', SMTPError.CONNECTIONCLOSED, err) - ); - }; - - /** - * @param {Error} err the error object - * @returns {void} - */ - const end = err => { - stream.emit( - 'response', - SMTPError('connection has ended', SMTPError.CONNECTIONENDED, err) - ); - }; - - /** - * @param {Error} [err] the error object - * @returns {void} - */ - this.stop = err => { - stream.removeAllListeners('response'); - stream.removeListener('data', watch); - stream.removeListener('end', end); - stream.removeListener('close', close); - stream.removeListener('error', error); - - if (err != null && typeof onerror === 'function') { - onerror(err); - } - }; - - stream.on('data', watch); - stream.on('end', end); - stream.on('close', close); - stream.on('error', error); - stream.setTimeout(timeout, timedout); - } -} - -exports.SMTPResponse = SMTPResponse; - -/** - * @param {Socket | TLSSocket} stream the open socket to stream a response from - * @param {number} timeout the time to wait (in milliseconds) before closing the socket - * @param {function(Error): void} onerror the function to call on error - * @returns {SMTPResponse} the smtp response - */ -exports.monitor = (stream, timeout, onerror) => - new SMTPResponse(stream, timeout, onerror); diff --git a/smtp/response.ts b/smtp/response.ts new file mode 100644 index 0000000..b141811 --- /dev/null +++ b/smtp/response.ts @@ -0,0 +1,113 @@ +import { Socket } from 'net'; +import { TLSSocket } from 'tls'; + +import { makeSMTPError, SMTPErrorStates } from './error'; + +export class SMTPResponse { + private buffer = ''; + public stop: (err?: Error) => void; + + /** + * @param [stream] The open socket to stream a response from + * @param [timeout] The time to wait (in milliseconds) before closing the socket + * @param [onerror] The function to call on error + */ + constructor(private stream: Socket | TLSSocket, timeout: number, onerror: (err: Error) => void) { + const watch = (data: Parameters[0]) => this.watch(data); + const end = () => this.end(); + const close = () => this.close(); + const error = (data: Parameters[0]) => this.error(data); + const timedout = (data: Parameters[0]) => this.timedout(data); + + this.stream.on('data', watch); + this.stream.on('end', end); + this.stream.on('close', close); + this.stream.on('error', error); + this.stream.setTimeout(timeout, timedout); + + this.stop = err => { + this.stream.removeAllListeners('response'); + this.stream.removeListener('data', watch); + this.stream.removeListener('end', end); + this.stream.removeListener('close', close); + this.stream.removeListener('error', error); + + if (err != null && typeof onerror === 'function') { + onerror(err); + } + }; + } + + public notify() { + if (this.buffer.length) { + // parse buffer for response codes + const line = this.buffer.replace('\r', ''); + if ( + !line + .trim() + .split(/\n/) + .pop() + ?.match(/^(\d{3})\s/) ?? false + ) { + return; + } + + const match = line ? line.match(/(\d+)\s?(.*)/) : null; + const data = + match !== null + ? { code: match[1], message: match[2], data: line } + : { code: -1, data: line }; + + this.stream.emit('response', null, data); + this.buffer = ''; + } + } + + protected error(err: Error) { + this.stream.emit( + 'response', + makeSMTPError('connection encountered an error', SMTPErrorStates.ERROR, err) + ); + } + + protected watch(data: string | Buffer) { + if (data !== null) { + this.buffer += data.toString(); + this.notify(); + } + } + + protected timedout(err: Error) { + this.stream.end(); + this.stream.emit( + 'response', + makeSMTPError( + 'timedout while connecting to smtp server', + SMTPErrorStates.TIMEDOUT, + err + ) + ); + } + + protected close() { + this.stream.emit( + 'response', + makeSMTPError('connection has closed', SMTPErrorStates.CONNECTIONCLOSED) + ); + } + + protected end() { + this.stream.emit( + 'response', + makeSMTPError('connection has ended', SMTPErrorStates.CONNECTIONENDED) + ); + } +} + +/** + * @param [stream] the open socket to stream a response from + * @param [timeout] the time to wait (in milliseconds) before closing the socket + * @param [onerror] the function to call on error + */ +export const monitor = (stream: Socket | TLSSocket, timeout: number, onerror: (err: Error) => void) => + new SMTPResponse(stream, timeout, onerror); diff --git a/smtp/smtp.js b/smtp/smtp.ts similarity index 68% rename from smtp/smtp.js rename to smtp/smtp.ts index 791e7b5..39b625a 100644 --- a/smtp/smtp.js +++ b/smtp/smtp.ts @@ -1,73 +1,71 @@ -const { Socket } = require('net'); -const { createHmac } = require('crypto'); -const { hostname } = require('os'); -const { connect, createSecureContext, TLSSocket } = require('tls'); -const { EventEmitter } = require('events'); +import { Socket } from 'net'; +import { createHmac } from 'crypto'; +import { hostname } from 'os'; +import { connect, createSecureContext, TLSSocket } from 'tls'; +import { EventEmitter } from 'events'; -const SMTPResponse = require('./response'); -const SMTPError = require('./error'); +import { SMTPResponse, monitor } from './response'; +import { makeSMTPError, SMTPErrorStates } from './error'; +import { Indexed } from '@ledge/types'; /** * @readonly * @type {5000} */ -const TIMEOUT = 5000; +const TIMEOUT: 5000 = 5000; +export { TIMEOUT as DEFAULT_TIMEOUT }; /** * @readonly * @type {25} */ -const SMTP_PORT = 25; +const SMTP_PORT: 25 = 25; /** * @readonly * @type {465} */ -const SMTP_SSL_PORT = 465; +const SMTP_SSL_PORT: 465 = 465; /** * @readonly * @type {587} */ -const SMTP_TLS_PORT = 587; +const SMTP_TLS_PORT: 587 = 587; /** * @readonly * @type {'\r\n'} */ -const CRLF = '\r\n'; +const CRLF: '\r\n' = '\r\n'; -/** - * @readonly - * @enum - */ -const AUTH_METHODS = { - PLAIN: /** @type {'PLAIN'} */ ('PLAIN'), - CRAM_MD5: /** @type {'CRAM-MD5'} */ ('CRAM-MD5'), - LOGIN: /** @type {'LOGIN'} */ ('LOGIN'), - XOAUTH2: /** @type {'XOAUTH2'} */ ('XOAUTH2'), +export enum AUTH_METHODS { + PLAIN = 'PLAIN', + CRAM_MD5 = 'CRAM-MD5', + LOGIN = 'LOGIN', + XOAUTH2 = 'XOAUTH2', }; /** * @readonly * @enum */ -const SMTPState = { - NOTCONNECTED: /** @type {0} */ (0), - CONNECTING: /** @type {1} */ (1), - CONNECTED: /** @type {2} */ (2), -}; +export const SMTPState = { + NOTCONNECTED: 0, + CONNECTING: 1, + CONNECTED: 2, +} as const; /** * @type {0 | 1} */ -let DEBUG = 0; +let DEBUG: 0 | 1 = 0; /** * @param {...any} args the message(s) to log * @returns {void} */ -const log = (...args) => { +const log = (...args: any[]): void => { if (DEBUG === 1) { args.forEach(d => console.log( @@ -86,35 +84,80 @@ const log = (...args) => { * @param {...*} args the arguments to apply to the function * @returns {void} */ -const caller = (callback, ...args) => { +const caller = (callback?: (...rest: any[]) => void, ...args: any[]): void => { if (typeof callback === 'function') { callback.apply(null, args); } }; -class SMTP extends EventEmitter { +export interface SMTPSocketOptions { + key: string; + ca: string; + cert: string; +} + +export interface SMTPOptions { + timeout: number | null; + user: string; + password: string; + domain: string; + host: string; + port: number; + ssl: boolean | SMTPSocketOptions; + tls: boolean | SMTPSocketOptions; + authentication: string[]; + logger: (...args: any[]) => void; +} + +export interface ConnectOptions { + ssl?: boolean; +} + +export class SMTP extends EventEmitter { + private _state: 0 | 1 | 2 = SMTPState.NOTCONNECTED; + private _isAuthorized = false; + private _isSecure = false; + private _user?: string = ''; + private _password?: string = ''; + private _timeout: number = TIMEOUT; + + public set debug(level: 0 | 1) { + DEBUG = level; + } + + public get state() { + return this._state; + } + + public get timeout() { + return this._timeout; + } + + public get user() { + return this._user; + } + + public get password() { + return this._password; + } + + public get isAuthorized() { + return this._isAuthorized; + } + + protected sock: Socket | TLSSocket | null = null; + protected features: Indexed = {}; + protected monitor: SMTPResponse | null = null; + protected authentication: any[]; + protected domain = hostname(); + protected host = 'localhost'; + protected ssl: boolean | SMTPSocketOptions = false; + protected tls: boolean | SMTPSocketOptions = false; + protected port: any; + protected log = log; + /** * SMTP class written using python's (2.7) smtplib.py as a base - * - * @typedef {Object} SMTPSocketOptions - * @property {string} key - * @property {string} ca - * @property {string} cert - * - * @typedef {Object} SMTPOptions - * @property {number} [timeout] - * @property {string} [user] - * @property {string} [password] - * @property {string} [domain] - * @property {string} [host] - * @property {number} [port] - * @property {boolean|SMTPSocketOptions} [ssl] - * @property {boolean|SMTPSocketOptions} [tls] - * @property {string[]} [authentication] - * @property {function(...any): void} [logger] - * - * @constructor - * @param {SMTPOptions} [options] instance options */ constructor({ timeout, @@ -127,120 +170,50 @@ class SMTP extends EventEmitter { tls, logger, authentication, - } = {}) { + }: Partial = {}) { super(); - /** - * @private - * @type {0 | 1 | 2} - */ - this._state = SMTPState.NOTCONNECTED; - - /** - * @private - * @type {boolean} - */ - this._secure = false; - - /** - * @type {Socket|TLSSocket} - */ - this.sock = null; - - /** - * @type {{ [i: string]: string | boolean }} - */ - this.features = null; - - /** - * @type {SMTPResponse.SMTPResponse} - */ - this.monitor = null; + this._user = user; + this._password = password; - /** - * @type {string[]} - */ this.authentication = Array.isArray(authentication) ? authentication : [ - AUTH_METHODS.CRAM_MD5, - AUTH_METHODS.LOGIN, - AUTH_METHODS.PLAIN, - AUTH_METHODS.XOAUTH2, - ]; - - /** - * @type {number} } - */ - this.timeout = typeof timeout === 'number' ? timeout : TIMEOUT; - - /** - * @type {string} } - */ - this.domain = typeof domain === 'string' ? domain : hostname(); - - /** - * @type {string} } - */ - this.host = typeof host === 'string' ? host : 'localhost'; - - /** - * @type {boolean|SMTPSocketOptions} - */ - this.ssl = - ssl != null && - (typeof ssl === 'boolean' || - (typeof ssl === 'object' && Array.isArray(ssl) === false)) - ? ssl - : false; - - /** - * @type {boolean|SMTPSocketOptions} - */ - this.tls = - tls != null && - (typeof tls === 'boolean' || - (typeof tls === 'object' && Array.isArray(tls) === false)) - ? tls - : false; + AUTH_METHODS.CRAM_MD5, + AUTH_METHODS.LOGIN, + AUTH_METHODS.PLAIN, + AUTH_METHODS.XOAUTH2, + ]; + + if (typeof timeout === 'number') { + this._timeout = timeout; + } - /** - * @type {number} - */ - this.port = port || (ssl ? SMTP_SSL_PORT : tls ? SMTP_TLS_PORT : SMTP_PORT); + if (typeof domain === 'string') { + this.domain = domain; + } - /** - * @type {boolean} - */ - this.loggedin = user && password ? false : true; + if (typeof host === 'string') { + this.host = host; + } - // keep these strings hidden when quicky debugging/logging - this.user = /** @returns {string} */ () => user; - this.password = /** @returns {string} */ () => password; + if (typeof logger === 'function') { + this.log = log; + } - this.log = typeof logger === 'function' ? logger : log; - } + if (ssl != null && (typeof ssl === 'boolean' || (typeof ssl === 'object' && Array.isArray(ssl) === false))) { + this.ssl = ssl; + } - /** - * @param {0 | 1} level - - * @returns {void} - */ - debug(level) { - DEBUG = level; - } + if (tls != null && (typeof tls === 'boolean' || (typeof tls === 'object' && Array.isArray(tls) === false))) { + this.tls = tls; + } - /** - * @returns {number} the current state - */ - state() { - return this._state; - } + if (!port) { + this.port = this.ssl ? SMTP_SSL_PORT : this.tls ? SMTP_TLS_PORT : SMTP_PORT; + } - /** - * @returns {boolean} whether or not the instance is authorized - */ - authorized() { - return this.loggedin; + this._isAuthorized = user && password ? false : true; } /** @@ -253,7 +226,7 @@ class SMTP extends EventEmitter { * @param {ConnectOptions} [options={}] the options * @returns {void} */ - connect(callback, port = this.port, host = this.host, options = {}) { + connect(callback: (...rest: any[]) => void, port: number = this.port, host: string = this.host, options: ConnectOptions = {}): void { this.port = port; this.host = host; this.ssl = options.ssl || this.ssl; @@ -272,7 +245,7 @@ class SMTP extends EventEmitter { /** * @returns {void} */ - const connected = () => { + const connected = (): void => { this.log(`connected: ${this.host}:${this.port}`); if (this.ssl && !this.tls) { @@ -285,13 +258,13 @@ class SMTP extends EventEmitter { this.close(true); caller( callback, - SMTPError( + makeSMTPError( 'could not establish an ssl connection', - SMTPError.CONNECTIONAUTH + SMTPErrorStates.CONNECTIONAUTH ) ); } else { - this._secure = true; + this._isSecure = true; } } }; @@ -300,7 +273,7 @@ class SMTP extends EventEmitter { * @param {Error} err err * @returns {void} */ - const connectedErrBack = err => { + const connectedErrBack = (err: Error): void => { if (!err) { connected(); } else { @@ -308,12 +281,12 @@ class SMTP extends EventEmitter { this.log(err); caller( callback, - SMTPError('could not connect', SMTPError.COULDNOTCONNECT, err) + makeSMTPError('could not connect', SMTPErrorStates.COULDNOTCONNECT, err) ); } }; - const response = (err, msg) => { + const response = (err: Error, msg: { code: string | number, data: string }) => { if (err) { if (this._state === SMTPState.NOTCONNECTED && !this.sock) { return; @@ -331,9 +304,9 @@ class SMTP extends EventEmitter { this.quit(() => { caller( callback, - SMTPError( + makeSMTPError( 'bad response on connection', - SMTPError.BADRESPONSE, + SMTPErrorStates.BADRESPONSE, err, msg.data ) @@ -361,7 +334,7 @@ class SMTP extends EventEmitter { ); } - this.monitor = SMTPResponse.monitor(this.sock, this.timeout, () => + this.monitor = monitor(this.sock, this._timeout, () => this.close(true) ); this.sock.once('response', response); @@ -373,7 +346,7 @@ class SMTP extends EventEmitter { * @param {*} callback function to call after response * @returns {void} */ - send(str, callback) { + send(str: string, callback: any): void { if (this.sock && this._state === SMTPState.CONNECTED) { this.log(str); @@ -390,7 +363,7 @@ class SMTP extends EventEmitter { this.close(true); caller( callback, - SMTPError('no connection has been established', SMTPError.NOCONNECTION) + makeSMTPError('no connection has been established', SMTPErrorStates.NOCONNECTION) ); } } @@ -401,14 +374,14 @@ class SMTP extends EventEmitter { * @param {(number[] | number)} [codes=[250]] array codes * @returns {void} */ - command(cmd, callback, codes = [250]) { + command(cmd: string, callback: (...rest: any[]) => void, codes: (number[] | number) = [250]): void { const codesArray = Array.isArray(codes) ? codes : typeof codes === 'number' ? [codes] : [250]; - const response = (err, msg) => { + const response = (err: Error, msg: { code: string | number, data: string, message: string }) => { if (err) { caller(callback, err); } else { @@ -418,10 +391,10 @@ class SMTP extends EventEmitter { const suffix = msg.message ? `: ${msg.message}` : ''; const errorMessage = `bad response on command '${ cmd.split(' ')[0] - }'${suffix}`; + }'${suffix}`; caller( callback, - SMTPError(errorMessage, SMTPError.BADRESPONSE, null, msg.data) + makeSMTPError(errorMessage, SMTPErrorStates.BADRESPONSE, undefined, msg.data) ); } } @@ -440,7 +413,7 @@ class SMTP extends EventEmitter { * @param {string} domain the domain to associate with the 'helo' request * @returns {void} */ - helo(callback, domain) { + helo(callback: (...rest: any[]) => void, domain?: string): void { this.command(`helo ${domain || this.domain}`, (err, data) => { if (err) { caller(callback, err); @@ -455,8 +428,12 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - starttls(callback) { - const response = (err, msg) => { + starttls(callback: (...rest: any[]) => void): void { + const response = (err: Error, msg: { data: any }) => { + if (this.sock == null) { + throw new Error('null socket'); + } + if (err) { err.message += ' while establishing a starttls session'; caller(callback, err); @@ -466,15 +443,15 @@ class SMTP extends EventEmitter { ); const secureSocket = new TLSSocket(this.sock, { secureContext }); - secureSocket.on('error', err => { + secureSocket.on('error', (err: Error) => { this.close(true); caller(callback, err); }); - this._secure = true; + this._isSecure = true; this.sock = secureSocket; - SMTPResponse.monitor(this.sock, this.timeout, () => this.close(true)); + monitor(this.sock, this._timeout, () => this.close(true)); caller(callback, msg.data); } }; @@ -486,7 +463,7 @@ class SMTP extends EventEmitter { * @param {string} data the string to parse for features * @returns {void} */ - parse_smtp_features(data) { + parse_smtp_features(data: string): void { // According to RFC1869 some (badly written) // MTA's will disconnect on an ehlo. Toss an exception if // that happens -ddm @@ -516,7 +493,7 @@ class SMTP extends EventEmitter { * @param {string} domain the domain to associate with the 'ehlo' request * @returns {void} */ - ehlo(callback, domain) { + ehlo(callback: (...rest: any[]) => void, domain?: string): void { this.features = {}; this.command(`ehlo ${domain || this.domain}`, (err, data) => { if (err) { @@ -524,7 +501,7 @@ class SMTP extends EventEmitter { } else { this.parse_smtp_features(data); - if (this.tls && !this._secure) { + if (this.tls && !this._isSecure) { this.starttls(() => this.ehlo(callback, domain)); } else { caller(callback, err, data); @@ -537,7 +514,7 @@ class SMTP extends EventEmitter { * @param {string} opt the features keyname to check * @returns {boolean} whether the extension exists */ - has_extn(opt) { + has_extn(opt: string): boolean { return this.features[opt.toLowerCase()] === undefined; } @@ -547,7 +524,7 @@ class SMTP extends EventEmitter { * @param {string} domain the domain to associate with the 'help' request * @returns {void} */ - help(callback, domain) { + help(callback: (...rest: any[]) => void, domain: string): void { this.command(domain ? `help ${domain}` : 'help', callback, [211, 214]); } @@ -555,7 +532,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - rset(callback) { + rset(callback: (...rest: any[]) => void): void { this.command('rset', callback); } @@ -563,7 +540,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - noop(callback) { + noop(callback: (...rest: any[]) => void): void { this.send('noop', callback); } @@ -572,7 +549,7 @@ class SMTP extends EventEmitter { * @param {string} from the sender * @returns {void} */ - mail(callback, from) { + mail(callback: (...rest: any[]) => void, from: string): void { this.command(`mail FROM:${from}`, callback); } @@ -581,7 +558,7 @@ class SMTP extends EventEmitter { * @param {string} to the receiver * @returns {void} */ - rcpt(callback, to) { + rcpt(callback: (...rest: any[]) => void, to: string): void { this.command(`RCPT TO:${to}`, callback, [250, 251]); } @@ -589,7 +566,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - data(callback) { + data(callback: (...rest: any[]) => void): void { this.command('data', callback, [354]); } @@ -597,7 +574,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - data_end(callback) { + data_end(callback: (...rest: any[]) => void): void { this.command(`${CRLF}.`, callback); } @@ -605,9 +582,9 @@ class SMTP extends EventEmitter { * @param {string} data the message to send * @returns {void} */ - message(data) { + message(data: string): void { this.log(data); - this.sock.write(data); + this.sock?.write(data) ?? this.log('no socket to write to'); } /** @@ -617,7 +594,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - verify(address, callback) { + verify(address: string, callback: (...rest: any[]) => void): void { this.command(`vrfy ${address}`, callback, [250, 251, 252]); } @@ -628,7 +605,7 @@ class SMTP extends EventEmitter { * @param {function(...*): void} callback function to call after response * @returns {void} */ - expn(address, callback) { + expn(address: string, callback: (...rest: any[]) => void): void { this.command(`expn ${address}`, callback); } @@ -642,10 +619,10 @@ class SMTP extends EventEmitter { * @param {string} [domain] the domain to associate with the command * @returns {void} */ - ehlo_or_helo_if_needed(callback, domain) { + ehlo_or_helo_if_needed(callback: (...rest: any[]) => void, domain?: string): void { // is this code callable...? - if (!this.features) { - const response = (err, data) => caller(callback, err, data); + if (Object.keys(this.features).length === 0) { + const response = (err: Error, data: any) => caller(callback, err, data); this.ehlo((err, data) => { if (err) { this.helo(response, domain); @@ -670,28 +647,28 @@ class SMTP extends EventEmitter { * @param {{ method: string, domain: string }} [options] login options * @returns {void} */ - login(callback, user, password, options) { + login(callback: (...rest: any[]) => void, user = '', password = '', options: { method?: string; domain?: string; } = {}): void { const login = { - user: user ? () => user : this.user, - password: password ? () => password : this.password, + user: () => user || this.user || '', + password: () => password || this.password || '', method: options && options.method ? options.method.toUpperCase() : '', }; const domain = options && options.domain ? options.domain : this.domain; - const initiate = (err, data) => { + const initiate = (err: Error, data: any) => { if (err) { caller(callback, err); return; } - let method = null; + let method: AUTH_METHODS | null = null; /** * @param {string} challenge challenge * @returns {string} base64 cram hash */ - const encode_cram_md5 = challenge => { + const encode_cram_md5 = (challenge: string): string => { const hmac = createHmac('md5', login.password()); hmac.update(Buffer.from(challenge, 'base64').toString('ascii')); return Buffer.from(`${login.user()} ${hmac.digest('hex')}`).toString( @@ -702,7 +679,7 @@ class SMTP extends EventEmitter { /** * @returns {string} base64 login/password */ - const encode_plain = () => + const encode_plain = (): string => Buffer.from(`\u0000${login.user()}\u0000${login.password()}`).toString( 'base64' ); @@ -711,7 +688,7 @@ class SMTP extends EventEmitter { * @see https://developers.google.com/gmail/xoauth2_protocol * @returns {string} base64 xoauth2 auth token */ - const encode_xoauth2 = () => + const encode_xoauth2 = (): string => Buffer.from( `user=${login.user()}\u0001auth=Bearer ${login.password()}\u0001\u0001` ).toString('base64'); @@ -742,12 +719,12 @@ class SMTP extends EventEmitter { * @param {*} data data * @returns {void} */ - const failed = (err, data) => { - this.loggedin = false; + const failed = (err: Error, data: any): void => { + this._isAuthorized = false; this.close(); // if auth is bad, close the connection, it won't get better by itself caller( callback, - SMTPError('authorization.failed', SMTPError.AUTHFAILED, err, data) + makeSMTPError('authorization.failed', SMTPErrorStates.AUTHFAILED, err, data) ); }; @@ -756,11 +733,11 @@ class SMTP extends EventEmitter { * @param {*} data data * @returns {void} */ - const response = (err, data) => { + const response = (err: Error, data: any): void => { if (err) { failed(err, data); } else { - this.loggedin = true; + this._isAuthorized = true; caller(callback, err, data); } }; @@ -771,7 +748,7 @@ class SMTP extends EventEmitter { * @param {string} msg msg * @returns {void} */ - const attempt = (err, data, msg) => { + const attempt = (err: Error, data: any, msg: string): void => { if (err) { failed(err, data); } else { @@ -793,7 +770,7 @@ class SMTP extends EventEmitter { * @param {string} msg msg * @returns {void} */ - const attempt_user = (err, data, msg) => { + const attempt_user = (err: Error, data: any): void => { if (err) { failed(err, data); } else { @@ -830,7 +807,7 @@ class SMTP extends EventEmitter { break; default: const msg = 'no form of authorization supported'; - const err = SMTPError(msg, SMTPError.AUTHNOTSUPPORTED, null, data); + const err = makeSMTPError(msg, SMTPErrorStates.AUTHNOTSUPPORTED, undefined, data); caller(callback, err); break; } @@ -843,7 +820,7 @@ class SMTP extends EventEmitter { * @param {boolean} [force=false] whether or not to force destroy the connection * @returns {void} */ - close(force = false) { + close(force: boolean = false): void { if (this.sock) { if (force) { this.log('smtp connection destroyed!'); @@ -860,17 +837,17 @@ class SMTP extends EventEmitter { } this._state = SMTPState.NOTCONNECTED; - this._secure = false; + this._isSecure = false; this.sock = null; - this.features = null; - this.loggedin = !(this.user() && this.password()); + this.features = {}; + this._isAuthorized = !(this._user && this._password); } /** * @param {function(...*): void} [callback] function to call after response * @returns {void} */ - quit(callback) { + quit(callback?: (...rest: any[]) => void): void { this.command( 'quit', (err, data) => { @@ -881,8 +858,3 @@ class SMTP extends EventEmitter { ); } } - -exports.SMTP = SMTP; -exports.state = SMTPState; -exports.authentication = AUTH_METHODS; -exports.DEFAULT_TIMEOUT = TIMEOUT; diff --git a/test/authplain.js b/test/authplain.js deleted file mode 100644 index 0b5de2d..0000000 --- a/test/authplain.js +++ /dev/null @@ -1,74 +0,0 @@ -describe('authorize plain', function() { - const { simpleParser: parser } = require('mailparser'); - const { SMTPServer: smtpServer } = require('smtp-server'); - const { expect } = require('chai'); - const email = require('../email'); - const port = 2526; - - let server = null; - let smtp = null; - - const send = function(message, verify, done) { - smtp.onData = function(stream, session, callback) { - parser(stream) - .then(verify) - .then(done) - .catch(done); - stream.on('end', callback); - }; - - server.send(message, function(err) { - if (err) { - throw err; - } - }); - }; - - before(function(done) { - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors - - smtp = new smtpServer({ secure: true, authMethods: ['LOGIN'] }); - smtp.listen(port, function() { - smtp.onAuth = function(auth, session, callback) { - if (auth.username == 'pooh' && auth.password == 'honey') { - callback(null, { user: 'pooh' }); - } else { - return callback(new Error('invalid user / pass')); - } - }; - - server = email.server.connect({ - port: port, - user: 'pooh', - password: 'honey', - ssl: true, - }); - - done(); - }); - }); - - after(function(done) { - smtp.close(done); - }); - - it('login', function(done) { - const message = { - subject: 'this is a test TEXT message from emailjs', - from: 'piglet@gmail.com', - to: 'pooh@gmail.com', - text: "It is hard to be brave when you're only a Very Small Animal.", - }; - - const created = email.message.create(message); - - const callback = function(mail) { - expect(mail.text).to.equal(message.text + '\n\n\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }; - - send(created, callback, done); - }); -}); diff --git a/test/authplain.ts b/test/authplain.ts new file mode 100644 index 0000000..7f07009 --- /dev/null +++ b/test/authplain.ts @@ -0,0 +1,57 @@ +import test from 'ava'; +import { Readable } from 'stream'; +import { simpleParser } from 'mailparser'; +import { SMTPServer } from 'smtp-server'; + +import { client as c, message as m } from '../email'; + +type UnPromisify = T extends Promise ? U : T; + +const port = 2526; +const client = new c.Client({ port, user: 'pooh', password: 'honey', ssl: true }) +const smtp = new SMTPServer({ secure: true, authMethods: ['LOGIN'] }); + +const send = (message: m.Message, verify: (mail: UnPromisify>) => void) => { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors + + smtp.onData = (stream: Readable, _session, callback: () => void) => { + simpleParser(stream).then(verify); + stream.on('end', callback); + }; + client.send(message, err => { + if (err) { + throw err; + } + }); +}; + +test.before(() => { + smtp.listen(port, function() { + smtp.onAuth = function(auth, _session, callback) { + if (auth.username == 'pooh' && auth.password == 'honey') { + callback(null, { user: 'pooh' }); + } else { + return callback(new Error('invalid user / pass')); + } + }; + }); +}); + +test.after(() => smtp.close()); + +test.cb('authorize plain', t => { + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'piglet@gmail.com', + to: 'pooh@gmail.com', + text: "It is hard to be brave when you're only a Very Small Animal.", + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, msg.text + '\n\n\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); diff --git a/test/authssl.js b/test/authssl.js deleted file mode 100644 index f461aa8..0000000 --- a/test/authssl.js +++ /dev/null @@ -1,73 +0,0 @@ -describe('authorize ssl', function() { - const { simpleParser: parser } = require('mailparser'); - const { SMTPServer: smtpServer } = require('smtp-server'); - const { expect } = require('chai'); - const email = require('../email'); - const port = 2526; - - let server = null; - let smtp = null; - - const send = function(message, verify, done) { - smtp.onData = function(stream, session, callback) { - parser(stream) - .then(verify) - .then(done) - .catch(done); - stream.on('end', callback); - }; - - server.send(message, function(err) { - if (err) { - throw err; - } - }); - }; - - before(function(done) { - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors - - smtp = new smtpServer({ secure: true, authMethods: ['LOGIN'] }); - smtp.listen(port, function() { - smtp.onAuth = function(auth, session, callback) { - if (auth.username == 'pooh' && auth.password == 'honey') { - callback(null, { user: 'pooh' }); - } else { - return callback(new Error('invalid user / pass')); - } - }; - - server = email.server.connect({ - port: port, - user: 'pooh', - password: 'honey', - ssl: true, - }); - done(); - }); - }); - - after(function(done) { - smtp.close(done); - }); - - it('login', function(done) { - const message = { - subject: 'this is a test TEXT message from emailjs', - from: 'pooh@gmail.com', - to: 'rabbit@gmail.com', - text: 'hello friend, i hope this message finds you well.', - }; - - send( - email.message.create(message), - function(mail) { - expect(mail.text).to.equal(message.text + '\n\n\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }, - done - ); - }); -}); diff --git a/test/authssl.ts b/test/authssl.ts new file mode 100644 index 0000000..b724754 --- /dev/null +++ b/test/authssl.ts @@ -0,0 +1,57 @@ +import test from 'ava'; +import { Readable } from 'stream'; +import { simpleParser } from 'mailparser'; +import { SMTPServer } from 'smtp-server'; + +import { client as c, message as m } from '../email'; + +const port = 2526; + +const client = new c.Client({ port, user: 'pooh', password: 'honey', ssl: true }); +const smtp = new SMTPServer({ secure: true, authMethods: ['LOGIN'] }); + +type UnPromisify = T extends Promise ? U : T; +const send = (message: m.Message, verify: (mail: UnPromisify>) => void) => { + smtp.onData = (stream: Readable, _session, callback: () => void) => { + simpleParser(stream).then(verify); + stream.on('end', callback); + }; + client.send(message, err => { + if (err) { + throw err; + } + }); +}; + +test.before(() => { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors + + smtp.listen(port, function () { + smtp.onAuth = function (auth, _session, callback) { + if (auth.username == 'pooh' && auth.password == 'honey') { + callback(null, { user: 'pooh' }); + } else { + return callback(new Error('invalid user / pass')); + } + }; + }); +}); + +test.after(() => smtp.close()); + +test.cb('authorize ssl', t => { + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'pooh@gmail.com', + to: 'rabbit@gmail.com', + text: 'hello friend, i hope this message finds you well.', + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, msg.text + '\n\n\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); diff --git a/test/date.js b/test/date.js deleted file mode 100644 index ec2b6a5..0000000 --- a/test/date.js +++ /dev/null @@ -1,41 +0,0 @@ -describe('rfc2822 dates', function() { - const { expect } = require('chai'); - const { - date: { getRFC2822Date, getRFC2822DateUTC }, - } = require('../email'); - - var d_utc = dt => getRFC2822DateUTC(new Date(dt)); - var d = (dt, utc = false) => getRFC2822Date(new Date(dt), utc); - - it('should match standard regex', function(done) { - // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 - // thanks to moment.js for the listing: https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101 - var rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; - expect(d(0)).to.match(rfc2822re); - expect(d(329629726785)).to.match(rfc2822re); - expect(d(729629726785)).to.match(rfc2822re); - expect(d(1129629726785)).to.match(rfc2822re); - expect(d(1529629726785)).to.match(rfc2822re); - - done(); - }); - - it('should produce proper UTC dates', function(done) { - expect(d_utc(0)).to.equal('Thu, 01 Jan 1970 00:00:00 +0000'); - expect(d_utc(0)).to.equal(d(0, true)); - - expect(d_utc(329629726785)).to.equal('Thu, 12 Jun 1980 03:48:46 +0000'); - expect(d_utc(329629726785)).to.equal(d(329629726785, true)); - - expect(d_utc(729629726785)).to.equal('Sat, 13 Feb 1993 18:55:26 +0000'); - expect(d_utc(729629726785)).to.equal(d(729629726785, true)); - - expect(d_utc(1129629726785)).to.equal('Tue, 18 Oct 2005 10:02:06 +0000'); - expect(d_utc(1129629726785)).to.equal(d(1129629726785, true)); - - expect(d_utc(1529629726785)).to.equal('Fri, 22 Jun 2018 01:08:46 +0000'); - expect(d_utc(1529629726785)).to.equal(d(1529629726785, true)); - - done(); - }); -}); diff --git a/test/date.ts b/test/date.ts new file mode 100644 index 0000000..84564a0 --- /dev/null +++ b/test/date.ts @@ -0,0 +1,35 @@ +import test from 'ava'; + +import { date as d } from '../email'; + +const { getRFC2822Date, getRFC2822DateUTC } = d; +const toD_utc = (dt: number) => getRFC2822DateUTC(new Date(dt)); +const toD = (dt: number, utc = false) => getRFC2822Date(new Date(dt), utc); + +test('rfc2822 non-UTC', async t => { + // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 + // thanks to moment.js for the listing: https://github.com/moment/moment/blob/a831fc7e2694281ce31e4f090bbcf90a690f0277/src/lib/create/from-string.js#L101 + var rfc2822re = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; + t.regex(toD(0), rfc2822re); + t.regex(toD(329629726785), rfc2822re); + t.regex(toD(729629726785), rfc2822re); + t.regex(toD(1129629726785), rfc2822re); + t.regex(toD(1529629726785), rfc2822re); +}); + +test('rfc2822 UTC', async t => { + t.is(toD_utc(0), 'Thu, 01 Jan 1970 00:00:00 +0000'); + t.is(toD_utc(0), toD(0, true)); + + t.is(toD_utc(329629726785), 'Thu, 12 Jun 1980 03:48:46 +0000'); + t.is(toD_utc(329629726785), toD(329629726785, true)); + + t.is(toD_utc(729629726785), 'Sat, 13 Feb 1993 18:55:26 +0000'); + t.is(toD_utc(729629726785), toD(729629726785, true)); + + t.is(toD_utc(1129629726785), 'Tue, 18 Oct 2005 10:02:06 +0000'); + t.is(toD_utc(1129629726785), toD(1129629726785, true)); + + t.is(toD_utc(1529629726785), 'Fri, 22 Jun 2018 01:08:46 +0000'); + t.is(toD_utc(1529629726785), toD(1529629726785, true)); +}); diff --git a/test/message.js b/test/message.js deleted file mode 100644 index 1c0b275..0000000 --- a/test/message.js +++ /dev/null @@ -1,457 +0,0 @@ -describe('messages', function() { - const { simpleParser: parser } = require('mailparser'); - const { SMTPServer: smtpServer } = require('smtp-server'); - const { expect } = require('chai'); - const fs = require('fs'); - const path = require('path'); - const email = require('../email'); - const port = 2526; - - let server = null; - let smtp = null; - - const send = function(message, verify, done) { - smtp.onData = function(stream, session, callback) { - //stream.pipe(process.stdout); - parser(stream) - .then(verify) - .then(done) - .catch(done); - stream.on('end', callback); - }; - - server.send(message, function(err) { - if (err) { - throw err; - } - }); - }; - - before(function(done) { - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors - - smtp = new smtpServer({ secure: true, authMethods: ['LOGIN'] }); - smtp.listen(port, function() { - smtp.onAuth = function(auth, session, callback) { - if (auth.username == 'pooh' && auth.password == 'honey') { - callback(null, { user: 'pooh' }); - } else { - return callback(new Error('invalid user / pass')); - } - }; - - server = email.server.connect({ - port: port, - user: 'pooh', - password: 'honey', - ssl: true, - }); - done(); - }); - }); - - after(function(done) { - smtp.close(done); - }); - - it('simple text message', function(done) { - var message = { - subject: 'this is a test TEXT message from emailjs', - from: 'zelda@gmail.com', - to: 'gannon@gmail.com', - text: 'hello friend, i hope this message finds you well.', - 'message-id': 'this is a special id', - }; - - send( - email.message.create(message), - function(mail) { - expect(mail.text).to.equal(message.text + '\n\n\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - expect(mail.messageId).to.equal('<' + message['message-id'] + '>'); - }, - done - ); - }); - - it('null text', function(done) { - send( - { - subject: 'this is a test TEXT message from emailjs', - from: 'zelda@gmail.com', - to: 'gannon@gmail.com', - text: null, - 'message-id': 'this is a special id', - }, - function(mail) { - expect(mail.text).to.equal('\n\n\n'); - }, - done - ); - }); - - it('empty text', function(done) { - send( - { - subject: 'this is a test TEXT message from emailjs', - from: 'zelda@gmail.com', - to: 'gannon@gmail.com', - text: '', - 'message-id': 'this is a special id', - }, - function(mail) { - expect(mail.text).to.equal('\n\n\n'); - }, - done - ); - }); - - it('simple unicode text message', function(done) { - var message = { - subject: 'this ✓ is a test ✓ TEXT message from emailjs', - from: 'zelda✓ ', - to: 'gannon✓ ', - text: 'hello ✓ friend, i hope this message finds you well.', - }; - - send( - email.message.create(message), - function(mail) { - expect(mail.text).to.equal(message.text + '\n\n\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }, - done - ); - }); - - it('very large text message', function(done) { - this.timeout(20000); - // thanks to jart+loberstech for this one! - var message = { - subject: 'this is a test TEXT message from emailjs', - from: 'ninjas@gmail.com', - to: 'pirates@gmail.com', - text: fs.readFileSync( - path.join(__dirname, 'attachments/smtp.txt'), - 'utf-8' - ), - }; - - send( - email.message.create(message), - function(mail) { - expect(mail.text).to.equal(message.text.replace(/\r/g, '') + '\n\n\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }, - done - ); - }); - - it('very large text data', function(done) { - this.timeout(10000); - var text = - '
' +
-			fs.readFileSync(path.join(__dirname, 'attachments/smtp.txt'), 'utf-8') +
-			'
'; - var message = { - subject: 'this is a test TEXT+DATA message from emailjs', - from: 'lobsters@gmail.com', - to: 'lizards@gmail.com', - text: - 'hello friend if you are seeing this, you can not view html emails. it is attached inline.', - attachment: { data: text, alternative: true }, - }; - - send( - message, - function(mail) { - expect(mail.html).to.equal(text.replace(/\r/g, '')); - expect(mail.text).to.equal(message.text + '\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }, - done - ); - }); - - it('html data', function(done) { - var html = fs.readFileSync( - path.join(__dirname, 'attachments/smtp.html'), - 'utf-8' - ); - var message = { - subject: 'this is a test TEXT+HTML+DATA message from emailjs', - from: 'obama@gmail.com', - to: 'mitt@gmail.com', - attachment: { data: html, alternative: true }, - }; - - send( - message, - function(mail) { - expect(mail.html).to.equal(html.replace(/\r/g, '')); - expect(mail.text).to.equal('\n'); - expect(mail.subject).to.equal(message.subject); - expect(mail.from.text).to.equal(message.from); - expect(mail.to.text).to.equal(message.to); - }, - done - ); - }); - - it('html file', function(done) { - var html = fs.readFileSync( - path.join(__dirname, 'attachments/smtp.html'), - 'utf-8' - ); - var headers = { - subject: 'this is a test TEXT+HTML+FILE message from emailjs', - from: 'thomas@gmail.com', - to: 'nikolas@gmail.com', - attachment: { - path: path.join(__dirname, 'attachments/smtp.html'), - alternative: true, - }, - }; - - send( - headers, - function(mail) { - expect(mail.html).to.equal(html.replace(/\r/g, '')); - expect(mail.text).to.equal('\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('html with image embed', function(done) { - var html = fs.readFileSync( - path.join(__dirname, 'attachments/smtp2.html'), - 'utf-8' - ); - var image = fs.readFileSync(path.join(__dirname, 'attachments/smtp.gif')); - var headers = { - subject: 'this is a test TEXT+HTML+IMAGE message from emailjs', - from: 'ninja@gmail.com', - to: 'pirate@gmail.com', - attachment: { - path: path.join(__dirname, 'attachments/smtp2.html'), - alternative: true, - related: [ - { - path: path.join(__dirname, 'attachments/smtp.gif'), - type: 'image/gif', - name: 'smtp-diagram.gif', - headers: { 'Content-ID': '' }, - }, - ], - }, - }; - - send( - headers, - function(mail) { - expect(mail.attachments[0].content.toString('base64')).to.equal( - image.toString('base64') - ); - expect(mail.html).to.equal(html.replace(/\r/g, '')); - expect(mail.text).to.equal('\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('html data and attachment', function(done) { - var html = fs.readFileSync( - path.join(__dirname, 'attachments/smtp.html'), - 'utf-8' - ); - var headers = { - subject: 'this is a test TEXT+HTML+FILE message from emailjs', - from: 'thomas@gmail.com', - to: 'nikolas@gmail.com', - attachment: [ - { - path: path.join(__dirname, 'attachments/smtp.html'), - alternative: true, - }, - { path: path.join(__dirname, 'attachments/smtp.gif') }, - ], - }; - - send( - headers, - function(mail) { - expect(mail.html).to.equal(html.replace(/\r/g, '')); - expect(mail.text).to.equal('\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('attachment', function(done) { - var pdf = fs.readFileSync(path.join(__dirname, 'attachments/smtp.pdf')); - var headers = { - subject: 'this is a test TEXT+ATTACHMENT message from emailjs', - from: 'washing@gmail.com', - to: 'lincoln@gmail.com', - text: 'hello friend, i hope this message and pdf finds you well.', - attachment: { - path: path.join(__dirname, 'attachments/smtp.pdf'), - type: 'application/pdf', - name: 'smtp-info.pdf', - }, - }; - - send( - headers, - function(mail) { - expect(mail.attachments[0].content.toString('base64')).to.equal( - pdf.toString('base64') - ); - expect(mail.text).to.equal(headers.text + '\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('attachment sent with unicode filename', function(done) { - var pdf = fs.readFileSync(path.join(__dirname, 'attachments/smtp.pdf')); - var headers = { - subject: 'this is a test TEXT+ATTACHMENT message from emailjs', - from: 'washing@gmail.com', - to: 'lincoln@gmail.com', - text: 'hello friend, i hope this message and pdf finds you well.', - attachment: { - path: path.join(__dirname, 'attachments/smtp.pdf'), - type: 'application/pdf', - name: 'smtp-✓-info.pdf', - }, - }; - - send( - headers, - function(mail) { - expect(mail.attachments[0].content.toString('base64')).to.equal( - pdf.toString('base64') - ); - expect(mail.attachments[0].filename).to.equal('smtp-✓-info.pdf'); - expect(mail.text).to.equal(headers.text + '\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('attachments', function(done) { - var pdf = fs.readFileSync(path.join(__dirname, 'attachments/smtp.pdf')); - var tar = fs.readFileSync( - path.join(__dirname, 'attachments/postfix-2.8.7.tar.gz') - ); - var headers = { - subject: 'this is a test TEXT+2+ATTACHMENTS message from emailjs', - from: 'sergey@gmail.com', - to: 'jobs@gmail.com', - text: 'hello friend, i hope this message and attachments finds you well.', - attachment: [ - { - path: path.join(__dirname, 'attachments/smtp.pdf'), - type: 'application/pdf', - name: 'smtp-info.pdf', - }, - { - path: path.join(__dirname, 'attachments/postfix-2.8.7.tar.gz'), - type: 'application/tar-gz', - name: 'postfix.source.2.8.7.tar.gz', - }, - ], - }; - - send( - headers, - function(mail) { - expect(mail.attachments[0].content.toString('base64')).to.equal( - pdf.toString('base64') - ); - expect(mail.attachments[1].content.toString('base64')).to.equal( - tar.toString('base64') - ); - expect(mail.text).to.equal(headers.text + '\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); - - it('streams', function(done) { - var pdf = fs.readFileSync(path.join(__dirname, 'attachments/smtp.pdf')); - var tar = fs.readFileSync( - path.join(__dirname, 'attachments/postfix-2.8.7.tar.gz') - ); - var stream = fs.createReadStream( - path.join(__dirname, 'attachments/smtp.pdf') - ); - var stream2 = fs.createReadStream( - path.join(__dirname, 'attachments/postfix-2.8.7.tar.gz') - ); - var headers = { - subject: - 'this is a test TEXT+2+STREAMED+ATTACHMENTS message from emailjs', - from: 'stanford@gmail.com', - to: 'mit@gmail.com', - text: - 'hello friend, i hope this message and streamed attachments finds you well.', - attachment: [ - { stream: stream, type: 'application/pdf', name: 'smtp-info.pdf' }, - { - stream: stream2, - type: 'application/x-gzip', - name: 'postfix.source.2.8.7.tar.gz', - }, - ], - }; - - stream.pause(); - stream2.pause(); - - send( - headers, - function(mail) { - expect(mail.attachments[0].content.toString('base64')).to.equal( - pdf.toString('base64') - ); - expect(mail.attachments[1].content.toString('base64')).to.equal( - tar.toString('base64') - ); - expect(mail.text).to.equal(headers.text + '\n'); - expect(mail.subject).to.equal(headers.subject); - expect(mail.from.text).to.equal(headers.from); - expect(mail.to.text).to.equal(headers.to); - }, - done - ); - }); -}); diff --git a/test/message.ts b/test/message.ts new file mode 100644 index 0000000..4d0e2ca --- /dev/null +++ b/test/message.ts @@ -0,0 +1,375 @@ +import { readFileSync, createReadStream } from 'fs'; +import { join } from 'path'; + +import test from 'ava'; +import { Readable } from 'stream'; +import { simpleParser } from 'mailparser'; +import { SMTPServer } from 'smtp-server'; + +import { client as c, message as m } from '../email'; + +const port = 2526; +const client = new c.Client({ port, user: 'pooh', password: 'honey', ssl: true }); +const smtp = new SMTPServer({ secure: true, authMethods: ['LOGIN'] }); + +type UnPromisify = T extends Promise ? U : T; +const send = (message: m.Message, verify: (mail: UnPromisify>) => void) => { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors + + smtp.onData = (stream: Readable, _session, callback: () => void) => { + simpleParser(stream).then(verify); + stream.on('end', callback); + }; + client.send(message, err => { + if (err) { + throw err; + } + }); +}; + +test.before(() => { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // prevent CERT_HAS_EXPIRED errors + smtp.listen(port, function () { + smtp.onAuth = function (auth, _session, callback) { + if (auth.username == 'pooh' && auth.password == 'honey') { + callback(null, { user: 'pooh' }); + } else { + return callback(new Error('invalid user / pass')); + } + }; + }); +}); + +test.after(() => smtp.close()); + +test.cb('simple text message', t => { + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'zelda@gmail.com', + to: 'gannon@gmail.com', + text: 'hello friend, i hope this message finds you well.', + 'message-id': 'this is a special id', + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, msg.text + '\n\n\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.is(mail.messageId, '<' + msg['message-id'] + '>'); + t.end(); + }); +}); + +test.cb('null text message', t => { + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'zelda@gmail.com', + to: 'gannon@gmail.com', + text: null, + 'message-id': 'this is a special id', + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, '\n\n\n'); + t.end(); + }); +}); + +test.cb('empty text message', t => { + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'zelda@gmail.com', + to: 'gannon@gmail.com', + text: '', + 'message-id': 'this is a special id', + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, '\n\n\n'); + t.end(); + }); +}); + +test.cb('simple unicode text message', t => { + const msg = { + subject: 'this ✓ is a test ✓ TEXT message from emailjs', + from: 'zelda✓ ', + to: 'gannon✓ ', + text: 'hello ✓ friend, i hope this message finds you well.', + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, msg.text + '\n\n\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('very large text message', t => { + t.timeout(20000); + + // thanks to jart+loberstech for this one! + const msg = { + subject: 'this is a test TEXT message from emailjs', + from: 'ninjas@gmail.com', + to: 'pirates@gmail.com', + text: readFileSync( + join(__dirname, 'attachments/smtp.txt'), + 'utf-8' + ), + }; + + send(new m.Message(msg), mail => { + t.is(mail.text, msg.text.replace(/\r/g, '') + '\n\n\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('very large text data message', t => { + t.timeout(10000); + + const text = + '
' +
+		readFileSync(join(__dirname, 'attachments/smtp.txt'), 'utf-8') +
+		'
'; + + const msg = { + subject: 'this is a test TEXT+DATA message from emailjs', + from: 'lobsters@gmail.com', + to: 'lizards@gmail.com', + text: + 'hello friend if you are seeing this, you can not view html emails. it is attached inline.', + attachment: { data: text, alternative: true } as unknown as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.html, text.replace(/\r/g, '')); + t.is(mail.text, msg.text + '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('html data message', t => { + const html = readFileSync( + join(__dirname, 'attachments/smtp.html'), + 'utf-8' + ); + const msg = { + subject: 'this is a test TEXT+HTML+DATA message from emailjs', + from: 'obama@gmail.com', + to: 'mitt@gmail.com', + attachment: { data: html, alternative: true } as unknown as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.html, html.replace(/\r/g, '')); + t.is(mail.text, '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('html file message', t => { + const html = readFileSync( + join(__dirname, 'attachments/smtp.html'), + 'utf-8' + ); + const msg = { + subject: 'this is a test TEXT+HTML+FILE message from emailjs', + from: 'thomas@gmail.com', + to: 'nikolas@gmail.com', + attachment: { path: join(__dirname, 'attachments/smtp.html'), alternative: true } as unknown as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.html, html.replace(/\r/g, '')); + t.is(mail.text, '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('html with image embed message', t => { + const html = readFileSync( + join(__dirname, 'attachments/smtp2.html'), + 'utf-8' + ); + const image = readFileSync(join(__dirname, 'attachments/smtp.gif')); + const msg = { + subject: 'this is a test TEXT+HTML+IMAGE message from emailjs', + from: 'ninja@gmail.com', + to: 'pirate@gmail.com', + attachment: { + path: join(__dirname, 'attachments/smtp2.html'), + alternative: true, + related: [ + { + path: join(__dirname, 'attachments/smtp.gif'), + type: 'image/gif', + name: 'smtp-diagram.gif', + headers: { 'Content-ID': '' }, + }, + ], + } as unknown as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.attachments[0].content.toString('base64'), image.toString('base64')); + t.is(mail.html, html.replace(/\r/g, '')); + t.is(mail.text, '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('html data and attachment message', t => { + const html = readFileSync(join(__dirname, 'attachments/smtp.html'), 'utf-8'); + const msg = { + subject: 'this is a test TEXT+HTML+FILE message from emailjs', + from: 'thomas@gmail.com', + to: 'nikolas@gmail.com', + attachment: [ + { path: join(__dirname, 'attachments/smtp.html'), alternative: true }, + { path: join(__dirname, 'attachments/smtp.gif') }, + ] as m.MessageAttachment[], + }; + + send(new m.Message(msg), mail => { + t.is(mail.html, html.replace(/\r/g, '')); + t.is(mail.text, '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('attachment message', t => { + const pdf = readFileSync(join(__dirname, 'attachments/smtp.pdf')); + const msg = { + subject: 'this is a test TEXT+ATTACHMENT message from emailjs', + from: 'washing@gmail.com', + to: 'lincoln@gmail.com', + text: 'hello friend, i hope this message and pdf finds you well.', + attachment: { + path: join(__dirname, 'attachments/smtp.pdf'), + type: 'application/pdf', + name: 'smtp-info.pdf', + } as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.attachments[0].content.toString('base64'), pdf.toString('base64')); + t.is(mail.text, msg.text + '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('attachment sent with unicode filename message', t => { + const pdf = readFileSync(join(__dirname, 'attachments/smtp.pdf')); + const msg = { + subject: 'this is a test TEXT+ATTACHMENT message from emailjs', + from: 'washing@gmail.com', + to: 'lincoln@gmail.com', + text: 'hello friend, i hope this message and pdf finds you well.', + attachment: { + path: join(__dirname, 'attachments/smtp.pdf'), + type: 'application/pdf', + name: 'smtp-✓-info.pdf', + } as m.MessageAttachment, + }; + + send(new m.Message(msg), mail => { + t.is(mail.attachments[0].content.toString('base64'), pdf.toString('base64')); + t.is(mail.attachments[0].filename, 'smtp-✓-info.pdf'); + t.is(mail.text, msg.text + '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('attachments message', t => { + const pdf = readFileSync(join(__dirname, 'attachments/smtp.pdf')); + const tar = readFileSync(join(__dirname, 'attachments/postfix-2.8.7.tar.gz')); + const msg = { + subject: 'this is a test TEXT+2+ATTACHMENTS message from emailjs', + from: 'sergey@gmail.com', + to: 'jobs@gmail.com', + text: 'hello friend, i hope this message and attachments finds you well.', + attachment: [ + { + path: join(__dirname, 'attachments/smtp.pdf'), + type: 'application/pdf', + name: 'smtp-info.pdf', + }, + { + path: join(__dirname, 'attachments/postfix-2.8.7.tar.gz'), + type: 'application/tar-gz', + name: 'postfix.source.2.8.7.tar.gz', + }, + ] as m.MessageAttachment[], + }; + + send(new m.Message(msg), mail => { + t.is(mail.attachments[0].content.toString('base64'), pdf.toString('base64')); + t.is(mail.attachments[1].content.toString('base64'), tar.toString('base64')); + t.is(mail.text, msg.text + '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); + +test.cb('streams message', t => { + const pdf = readFileSync(join(__dirname, 'attachments/smtp.pdf')); + const tar = readFileSync(join(__dirname, 'attachments/postfix-2.8.7.tar.gz')); + const stream = createReadStream(join(__dirname, 'attachments/smtp.pdf')); + const stream2 = createReadStream(join(__dirname, 'attachments/postfix-2.8.7.tar.gz')); + + const msg = { + subject: + 'this is a test TEXT+2+STREAMED+ATTACHMENTS message from emailjs', + from: 'stanford@gmail.com', + to: 'mit@gmail.com', + text: + 'hello friend, i hope this message and streamed attachments finds you well.', + attachment: [ + { stream, type: 'application/pdf', name: 'smtp-info.pdf' }, + { stream: stream2, type: 'application/x-gzip', name: 'postfix.source.2.8.7.tar.gz' }, + ] as unknown as m.MessageAttachment[], + }; + + stream.pause(); + stream2.pause(); + + send(new m.Message(msg), mail => { + t.is(mail.attachments[0].content.toString('base64'), pdf.toString('base64')); + t.is(mail.attachments[1].content.toString('base64'), tar.toString('base64')); + t.is(mail.text, msg.text + '\n'); + t.is(mail.subject, msg.subject); + t.is(mail.from?.text, msg.from); + t.is(mail.to?.text, msg.to); + t.end(); + }); +}); diff --git a/test/server.js b/test/server.js deleted file mode 100644 index 0a85905..0000000 --- a/test/server.js +++ /dev/null @@ -1,63 +0,0 @@ -const assert = require('assert'); - -describe('Connect to wrong email server', function() { - const emailModulePath = require.resolve('../email.js'); - - /** - * @type {typeof import('../email.js')} - */ - let email = null; - - beforeEach(function() { - if (require.cache[emailModulePath]) { - delete require.cache[emailModulePath]; - } - email = require(emailModulePath); - }); - - it('Should not call callback multiple times with wrong server configuration', function(done) { - this.timeout(5000); - const server = email.server.connect({ host: 'bar.baz' }); - server.send( - { - from: 'foo@bar.baz', - to: 'foo@bar.baz', - subject: 'hello world', - text: 'hello world', - }, - function(err) { - assert.notEqual(err, null); - done(); - } - ); - }); - - it('should have a default timeout', function(done) { - const connectionOptions = { - user: 'username', - password: 'password', - host: '127.0.0.1', - port: 1234, - }; - - const email = require(emailModulePath); - assert.strictEqual( - email.server.connect(connectionOptions).smtp.timeout, - email.SMTP.DEFAULT_TIMEOUT - ); - - connectionOptions.timeout = null; - assert.strictEqual( - email.server.connect(connectionOptions).smtp.timeout, - email.SMTP.DEFAULT_TIMEOUT - ); - - connectionOptions.timeout = undefined; - assert.strictEqual( - email.server.connect(connectionOptions).smtp.timeout, - email.SMTP.DEFAULT_TIMEOUT - ); - - done(); - }); -}); diff --git a/test/server.ts b/test/server.ts new file mode 100644 index 0000000..756d460 --- /dev/null +++ b/test/server.ts @@ -0,0 +1,36 @@ +import test from 'ava'; + +import { client as c, message as m, SMTP } from '../email'; + +test.cb('connecting to wrong email server should not invoke callback multiple times', t => { + t.timeout(5000); + + const client = new c.Client({ host: 'bar.baz' }); + const msg = { + from: 'foo@bar.baz', + to: 'foo@bar.baz', + subject: 'hello world', + text: 'hello world', + }; + client.send(new m.Message(msg), err => { + t.not(err, null); + t.end(); + }); +}); + +test('should have a default timeout', async t => { + const connectionOptions = { + user: 'username', + password: 'password', + host: '127.0.0.1', + port: 1234, + timeout: undefined as number | null | undefined + }; + t.deepEqual(new c.Client(connectionOptions).smtp.timeout, SMTP.DEFAULT_TIMEOUT); + + connectionOptions.timeout = null; + t.deepEqual(new c.Client(connectionOptions).smtp.timeout, SMTP.DEFAULT_TIMEOUT); + + connectionOptions.timeout = undefined; + t.deepEqual(new c.Client(connectionOptions).smtp.timeout, SMTP.DEFAULT_TIMEOUT); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f919c1a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "@ledge/configs/tsconfig.json", + "include": [ + "email.ts", + "smtp/**/*.ts", + "test/**/*.ts", + "test/-register.js" + ], + "ts-node": { + "compilerOptions": { + "module": "commonjs" + } + } +} diff --git a/yarn.lock b/yarn.lock index 0490fbc..cc7a731 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,138 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/helper-validator-identifier@^7.9.0": + version "7.9.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + +"@babel/highlight@^7.8.3": + version "7.9.0" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" + integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@concordance/react@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@concordance/react/-/react-2.0.0.tgz#aef913f27474c53731f4fd79cc2f54897de90fde" + integrity sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA== + dependencies: + arrify "^1.0.1" + +"@ledge/configs@22.0.2": + version "22.0.2" + resolved "https://registry.npmjs.org/@ledge/configs/-/configs-22.0.2.tgz#969f53a0dd025c2a11f7594b1f7f6abafcd9b467" + integrity sha512-qmb2E3Js/Fcfmnr7tU+ldMYUWH47XoUHtxO2AAFoUK2Y1reoaZ0qZ5aAtLzkhCis6fnXeL16NLjLY/SxC2sQEA== + +"@ledge/types@6.1.0": + version "6.1.0" + resolved "https://registry.npmjs.org/@ledge/types/-/types-6.1.0.tgz#f142a36c57c37e241560439652d7615d47151727" + integrity sha512-v52fE43n/RmRH1DV7qUqWs71lE5sRO2+lret2rTvf0B85MUVoiifkKCD7U1SeGt/GUvSGNVGx6NUvXjTV73V0Q== + dependencies: + "@types/node" "*" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" +"@types/events@*": + version "3.0.0" + resolved "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/mailparser@2.7.2": + version "2.7.2" + resolved "https://registry.npmjs.org/@types/mailparser/-/mailparser-2.7.2.tgz#4c319f8f8ad770d055850d8f7d32d311d893dfa9" + integrity sha512-hGXNTyqKy5o6pLxeXKKNPVxDyML0kJcHgjVg/6STrtmVUwKXDYGT40HR/eGhXXZpiPAg9/8pVPCo9c5+IJ8s+A== + dependencies: + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + "@types/node@*": version "10.5.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707" +"@types/nodemailer@*": + version "6.4.0" + resolved "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.0.tgz#d8c039be3ed685c4719a026455555be82c124b74" + integrity sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA== + dependencies: + "@types/node" "*" + +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/smtp-server@3.5.4": + version "3.5.4" + resolved "https://registry.npmjs.org/@types/smtp-server/-/smtp-server-3.5.4.tgz#28ede421381c367d328dde496095d1ec4f17451a" + integrity sha512-HxPQdRNTTUZzTcwE5LwWL233eHFIfM9rS5TPufuBwQ2a6FdufUvnkBfb08VpMaodlFbls1o7s5VZG7ghxJKz3Q== + dependencies: + "@types/node" "*" + "@types/nodemailer" "*" + acorn-jsx@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" @@ -28,6 +152,14 @@ addressparser@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-0.3.2.tgz#59873f35e8fcf6c7361c10239261d76e15348bb2" +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-keywords@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" @@ -41,6 +173,13 @@ ajv@^6.0.1, ajv@^6.5.0: json-schema-traverse "^0.4.1" uri-js "^4.2.1" +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" @@ -53,6 +192,16 @@ ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -63,6 +212,27 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -79,12 +249,22 @@ arr-flatten@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -93,13 +273,84 @@ array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" -arrify@^1.0.0: +arrgv@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz#025ed55a6a433cad9b604f8112fc4292715a6ec0" + integrity sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw== + +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -assertion-error@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +ava@3.7.1: + version "3.7.1" + resolved "https://registry.npmjs.org/ava/-/ava-3.7.1.tgz#7baba69820242e0efcbfb4ab2060b500ec745421" + integrity sha512-UX7RSenUgFPhxe866doqOJy6tQZAXAVAU4yufYeBAcnEjnS/plIcG6lE2yGIqgjk5cIMpSi+sP4f6EsornlsuA== + dependencies: + "@concordance/react" "^2.0.0" + ansi-styles "^4.2.1" + arrgv "^1.0.2" + arrify "^2.0.1" + chalk "^4.0.0" + chokidar "^3.3.1" + chunkd "^2.0.1" + ci-info "^2.0.0" + ci-parallel-vars "^1.0.0" + clean-stack "^2.2.0" + clean-yaml-object "^0.1.0" + cli-cursor "^3.1.0" + cli-truncate "^2.1.0" + code-excerpt "^2.1.1" + common-path-prefix "^3.0.0" + concordance "^4.0.0" + convert-source-map "^1.7.0" + currently-unhandled "^0.4.1" + debug "^4.1.1" + del "^5.1.0" + emittery "^0.6.0" + equal-length "^1.0.0" + figures "^3.2.0" + globby "^11.0.0" + ignore-by-default "^1.0.0" + import-local "^3.0.2" + indent-string "^4.0.0" + is-error "^2.2.2" + is-plain-object "^3.0.0" + is-promise "^2.1.0" + lodash "^4.17.15" + matcher "^2.1.0" + md5-hex "^3.0.1" + mem "^6.1.0" + ms "^2.1.2" + ora "^4.0.3" + p-map "^4.0.0" + picomatch "^2.2.2" + pkg-conf "^3.1.0" + plur "^4.0.0" + pretty-ms "^6.0.1" + read-pkg "^5.2.0" + resolve-cwd "^3.0.0" + slash "^3.0.0" + source-map-support "^0.5.16" + stack-utils "^2.0.1" + strip-ansi "^6.0.0" + supertap "^1.0.0" + temp-dir "^2.0.0" + trim-off-newlines "^1.0.1" + update-notifier "^4.1.0" + write-file-atomic "^3.0.3" + yargs "^15.3.1" babel-code-frame@^6.26.0: version "6.26.0" @@ -117,6 +368,30 @@ base32.js@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/base32.js/-/base32.js-0.1.0.tgz#b582dec693c2f11e893cf064ee6ac5b6131a2202" +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + +blueimp-md5@^2.10.0: + version "2.13.0" + resolved "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.13.0.tgz#07314b0c64dda0bf1733f96ce40d5af94eb28965" + integrity sha512-lmp0m647R5e77ORduxLW5mISIDcvgJZa52vMBv5uVI3UmSWTQjkJsZVBfaFqQPw/QFogJwvY6e3Gl9nP+Loe+Q== + +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -132,14 +407,35 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== builtin-modules@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" @@ -150,16 +446,10 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" -chai@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" - dependencies: - assertion-error "^1.0.1" - check-error "^1.0.1" - deep-eql "^3.0.0" - get-func-name "^2.0.0" - pathval "^1.0.0" - type-detect "^4.0.0" +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== chalk@^1.1.3: version "1.1.3" @@ -179,46 +469,214 @@ chalk@^2.0.0, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" -check-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" +chokidar@^3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" + integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.3.0" + optionalDependencies: + fsevents "~2.1.2" + +chunkd@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz#49cd1d7b06992dc4f7fccd962fe2a101ee7da920" + integrity sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-parallel-vars@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz#af97729ed1c7381911ca37bcea263d62638701b3" + integrity sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g== circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" +clean-stack@^2.0.0, clean-stack@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +clean-yaml-object@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" + integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g= + +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" + integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +code-excerpt@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" + integrity sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw== + dependencies: + convert-to-spaces "^1.0.1" + color-convert@^1.9.0: version "1.9.2" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" dependencies: color-name "1.1.1" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concordance@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/concordance/-/concordance-4.0.0.tgz#5932fdee397d129bdbc3a1885fbe69839b1b7e15" + integrity sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ== + dependencies: + date-time "^2.1.0" + esutils "^2.0.2" + fast-diff "^1.1.2" + js-string-escape "^1.0.1" + lodash.clonedeep "^4.5.0" + lodash.flattendeep "^4.4.0" + lodash.islength "^4.0.1" + lodash.merge "^4.6.1" + md5-hex "^2.0.0" + semver "^5.5.1" + well-known-symbols "^2.0.0" + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +convert-to-spaces@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" + integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -233,22 +691,71 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -debug@3.1.0, debug@^3.1.0: +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +date-time@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" + integrity sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g== + dependencies: + time-zone "^1.0.0" + +debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" -deep-eql@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" +debug@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: - type-detect "^4.0.0" + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" @@ -268,9 +775,31 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" +del@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" + integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== + dependencies: + globby "^10.0.1" + graceful-fs "^4.2.2" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.1" + p-map "^3.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" doctrine@^2.1.0: version "2.1.0" @@ -306,6 +835,18 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + emailjs-base64@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/emailjs-base64/-/emailjs-base64-1.1.4.tgz#392fa38cb6aa35dccd3af3637ffc14c1c7ce9612" @@ -318,10 +859,44 @@ emailjs-mime-codec@^2.0.7: ramda "^0.25.0" text-encoding "^0.6.4" +emittery@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.6.0.tgz#e85312468d77c3ed9a6adf43bb57d34849e0c95a" + integrity sha512-6EMRGr9KzYWp8DzHFZsKVZBsMO6QhAeHMeHND8rhyBNCHKMLpgW9tZv40bwN3rAIKRS5CxcK8oLRKUJSB9h7yQ== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" +equal-length@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" + integrity sha1-IcoRLUirJLTh5//A5TOdMf38J0w= + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + es-abstract@^1.10.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" @@ -340,10 +915,20 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + eslint-config-prettier@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" @@ -491,6 +1076,23 @@ fast-diff@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.0.3, fast-glob@^3.1.1: + version "3.2.2" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -499,12 +1101,26 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" +fastq@^1.6.0: + version "1.7.0" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" + integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ== + dependencies: + reusify "^1.0.4" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" dependencies: escape-string-regexp "^1.0.5" +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" @@ -526,6 +1142,28 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" @@ -553,6 +1191,11 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -561,14 +1204,29 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -582,7 +1240,14 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: +glob-parent@^5.1.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -593,10 +1258,55 @@ glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" + integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== + dependencies: + ini "^1.3.5" + globals@^11.7.0: version "11.7.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" + integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -608,14 +1318,32 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.15, graceful-fs@^4.2.2: + version "4.2.3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -626,20 +1354,35 @@ has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: function-bind "^1.1.1" -he@1.1.1, he@^1.0.0, he@^1.1.1: +he@^1.0.0, he@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + html-to-text@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-3.3.0.tgz#6a9b63c699b885bb7ba84b1446bfe6876bbfcfb7" @@ -661,6 +1404,11 @@ htmlparser2@^3.9.2: inherits "^2.0.1" readable-stream "^2.0.2" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" @@ -675,14 +1423,47 @@ iconv-lite@^0.4.17: dependencies: safer-buffer ">= 2.1.2 < 3" +ignore-by-default@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + ignore@^3.3.3: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" +ignore@^5.1.1, ignore@^5.1.4: + version "5.1.4" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +indent-string@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -694,6 +1475,11 @@ inherits@2, inherits@^2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + inquirer@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" @@ -716,6 +1502,23 @@ ipv6-normalize@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz#1b3258290d365fa83239e89907dde4592e7620a8" +irregular-plurals@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz#b19c490a0723798db51b235d7e39add44dab0822" + integrity sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -724,8 +1527,15 @@ is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" -is-date-object@^1.0.1: - version "1.0.1" +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-date-object@^1.0.1: + version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" is-dotfile@^1.0.0: @@ -738,6 +1548,11 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" +is-error@^2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" + integrity sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg== + is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -746,20 +1561,55 @@ is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" dependencies: is-extglob "^1.0.0" +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -770,10 +1620,25 @@ is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" @@ -786,6 +1651,18 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + +is-plain-object@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" + integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== + dependencies: + isobject "^4.0.0" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -812,6 +1689,16 @@ is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -826,14 +1713,37 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + jest-docblock@^21.0.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.10.0: + version "3.13.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" @@ -841,6 +1751,16 @@ js-yaml@^3.11.0: argparse "^1.0.7" esprima "^4.0.0" +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -849,6 +1769,13 @@ json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -859,6 +1786,13 @@ kind-of@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -886,16 +1820,89 @@ libqp@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + linkify-it@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" dependencies: uc.micro "^1.0.1" +load-json-file@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" + integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw== + dependencies: + graceful-fs "^4.1.15" + parse-json "^4.0.0" + pify "^4.0.1" + strip-bom "^3.0.0" + type-fest "^0.3.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + +lodash.islength@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/lodash.islength/-/lodash.islength-4.0.1.tgz#4e9868d452575d750affd358c979543dc20ed577" + integrity sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc= + +lodash.merge@^4.6.1: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + magic-string@^0.22.4: version "0.22.5" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" @@ -923,10 +1930,68 @@ mailsplit@4.1.2: libmime "3.1.0" libqp "1.1.0" +make-dir@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392" + integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w== + dependencies: + semver "^6.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-age-cleaner@^0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +matcher@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/matcher/-/matcher-2.1.0.tgz#64e1041c15b993e23b786f93320a7474bf833c28" + integrity sha512-o+nZr+vtJtgPNklyeUKkkH42OsK8WAfdgaJE2FNxcjLPg+5QbeEoT6vRj8Xq/iv18JlQ9cmKsEu0b94ixWf1YQ== + dependencies: + escape-string-regexp "^2.0.0" + math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" +md5-hex@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" + integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= + dependencies: + md5-o-matic "^0.1.1" + +md5-hex@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" + integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw== + dependencies: + blueimp-md5 "^2.10.0" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= + +mem@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz#846eca0bd4708a8f04b9c3f3cd769e194ae63c5c" + integrity sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg== + dependencies: + map-age-cleaner "^0.1.3" + mimic-fn "^3.0.0" + +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -945,11 +2010,34 @@ micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -minimatch@3.0.4, minimatch@^3.0.4: +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b" + integrity sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -959,40 +2047,39 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" +minimist@^1.2.0: + version "1.2.5" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" -mkdirp@0.5.1, mkdirp@^0.5.1: +mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@^2.1.1, ms@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -1005,12 +2092,32 @@ nodemailer@4.6.7: version "4.6.7" resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.7.tgz#b68de7f36d65618bdeeeb76234e3547d51266373" +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -1026,7 +2133,7 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -1038,6 +2145,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -1056,10 +2170,84 @@ optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" +ora@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/ora/-/ora-4.0.3.tgz#752a1b7b4be4825546a7a3d59256fa523b6b6d05" + integrity sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg== + dependencies: + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-spinners "^2.2.0" + is-interactive "^1.0.0" + log-symbols "^3.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -1069,6 +2257,39 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1085,14 +2306,30 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" -pathval@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1, picomatch@^2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -1103,6 +2340,28 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" +pkg-conf@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae" + integrity sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ== + dependencies: + find-up "^3.0.0" + load-json-file "^5.2.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +plur@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + integrity sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg== + dependencies: + irregular-plurals "^3.2.0" + pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" @@ -1111,6 +2370,11 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -1119,6 +2383,13 @@ prettier@^1.13.7: version "1.13.7" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" +pretty-ms@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-6.0.1.tgz#03ec6cfee20329f142645e63efad96bb775d3da4" + integrity sha512-ke4njoVmlotekHlHyCZ3wI/c5AMT8peuHs8rKJqekj/oR5G8lND2dVpicFlUz5cbZgE290vvkMuDwfj/OcW1kw== + dependencies: + parse-ms "^2.1.0" + process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" @@ -1127,10 +2398,25 @@ progress@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" +pupa@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" + integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== + dependencies: + escape-goat "^2.0.0" + ramda@^0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" @@ -1143,6 +2429,26 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@^2.0.2: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -1155,6 +2461,13 @@ readable-stream@^2.0.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readdirp@~3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" + integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== + dependencies: + picomatch "^2.0.7" + regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -1171,6 +2484,20 @@ regexpp@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" +registry-auth-token@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" + integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -1183,6 +2510,16 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -1190,16 +2527,42 @@ require-uncached@^1.0.3: caller-path "^0.1.0" resolve-from "^1.0.0" +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve@^1.1.6, resolve@^1.5.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" +resolve@^1.10.0: + version "1.16.1" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" + integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== + dependencies: + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -1207,12 +2570,32 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@^2.2.8: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rollup-plugin-commonjs@^9.1.3: version "9.1.3" resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.3.tgz#37bfbf341292ea14f512438a56df8f9ca3ba4d67" @@ -1250,6 +2633,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + rxjs@^5.5.2: version "5.5.11" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" @@ -1264,10 +2652,37 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + +"semver@2 || 3 || 4 || 5", semver@^5.5.1: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -1282,12 +2697,26 @@ signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" dependencies: is-fullwidth-code-point "^2.0.0" +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + smtp-server@^3.4.6: version "3.4.6" resolved "https://registry.yarnpkg.com/smtp-server/-/smtp-server-3.4.6.tgz#0f2505158ae42846f55bf374cb1a3386cabcf700" @@ -1296,6 +2725,45 @@ smtp-server@^3.4.6: ipv6-normalize "1.0.1" nodemailer "4.6.7" +source-map-support@^0.5.16, source-map-support@^0.5.17: + version "0.5.17" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.17.tgz#29fe1b3c98b9dbd5064ada89052ee8ff070cb46c" + integrity sha512-bwdKOBZ5L0gFRh4KOxNap/J/MpvX9Yxsq9lFDx65s3o7F/NiHy7JRaGIS8MwW6tZPAq9UXE207Il0cfcb5yu/Q== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + sprintf-js@^1.0.3: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" @@ -1304,6 +2772,13 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" +stack-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.1.tgz#3df48345a3b92adc06038f0e95782df61beff742" + integrity sha512-BvBTnHGm8boe+HiJFqP19ywEsGlfQAKqW78pbfvUuzCbUuxPPUyLrH5dYFY+Xn9IpLY3b5ZmMcl8jAqXB4wddg== + dependencies: + escape-string-regexp "^2.0.0" + string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -1311,6 +2786,24 @@ string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.matchall@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz#2af8fe3d2d6dc53ca2a59bd376b089c3c152b3c8" @@ -1339,20 +2832,58 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-json-comments@^2.0.1: +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -supports-color@5.4.0, supports-color@^5.3.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" +supertap@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e" + integrity sha512-HZJ3geIMPgVwKk2VsmO5YHqnnJYl6bV5A9JW2uzqV43WmpgliNEYbuvukfor7URpaqpxuw3CfZ3ONdVbZjCgIA== dependencies: - has-flag "^3.0.0" + arrify "^1.0.1" + indent-string "^3.2.0" + js-yaml "^3.10.0" + serialize-error "^2.1.0" + strip-ansi "^4.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" @@ -1368,6 +2899,16 @@ table@^4.0.3: slice-ansi "1.0.0" string-width "^2.1.1" +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +term-size@^2.1.0: + version "2.2.0" + resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" + integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== + text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -1380,6 +2921,11 @@ through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= + tlds@1.199.0: version "1.199.0" resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.199.0.tgz#a4fc8c3058216488a80aaaebb427925007e55217" @@ -1390,15 +2936,66 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +trim-off-newlines@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + +ts-node@8.9.0: + version "8.9.0" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.9.0.tgz#d7bf7272dcbecd3a2aa18bd0b96c7d2f270c15d4" + integrity sha512-rwkXfOs9zmoHrV8xE++dmNd6ZIS+nmHHCxcV53ekGJrxFLMbp+pizpPS07ARvhwneCIECPppOwbZHvw9sQtU4w== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" -type-detect@^4.0.0: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@3.8.3: + version "3.8.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" + integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== uc.micro@^1.0.1: version "1.0.5" @@ -1415,26 +3012,91 @@ underscore@^1.8.3: version "1.9.1" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +update-notifier@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3" + integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + uri-js@^4.2.1: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" dependencies: punycode "^2.1.0" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vlq@^0.2.2: version "0.2.3" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +well-known-symbols@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" + integrity sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q== + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: isexe "^2.0.0" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" @@ -1443,12 +3105,71 @@ wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" dependencies: mkdirp "^0.5.1" + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==