Created
July 13, 2018 12:56
Example of nested commands for sywac/sywac#21
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
flags: 'schedule-delivery', | |
desc: 'Launch scheduled mail delivery, max of three days in advance.', | |
setup: sywac => { | |
sywac | |
.showHelpByDefault(false) // disable this here since schedule-delivery is a runnable command | |
.option('-l, --email-list <email-list>', { | |
type: 'string', | |
desc: 'The mailgun email list you would like to use.', | |
strinct: true, // this is misspelled, and strict does not apply to strings; use `required: true` to require this option | |
defaultValue: 'something' | |
}) | |
.option('-b, --email-body-file <email-body-file>', { | |
type: 'file', | |
desc: 'File containing the html for the body of the email. Relative to the emailBodyFileDir directory you set in the configuration.', | |
strinct: true // this is misspelled, and strict does not apply to files; use `mustExist: true` to guarantee the path given exists on the local filesystem and is a file. | |
}) | |
.option('-f, --from <sent-from-for-replies>', { | |
type: 'string', | |
desc: 'The value that the receiver will see that your emails appear to be sent from, in the form of "Kim <[email protected]>"', | |
strict: true // strict does not apply to strings; use `required: true` to require this option | |
}) | |
.option('-s, --subject <subject-for-email>', { | |
type: 'string', | |
desc: 'The subject for the email', | |
strict: true // strict does not apply to strings; use `required: true` to require this option | |
}) | |
.option('-t, --schedule-time <time-to-schedule-email-send-for>', { | |
type: 'mailgunDateTimeFormat', // since this custom type was registered at the top-level, it is safe to use everywhere in this app and does not need to be re-registered anywhere | |
desc: 'The time that all emails will be sent (in RFC 2822 time).', | |
strict: true // this will guarantee the validateValue method for the custom type is called | |
}) | |
.option('-tm, --test-mode', { // -tm is not valid, flags with more than one character must use double-hyphen on the command line; otherwise -tm is parsed as -t and -m | |
type: 'boolean', | |
desc: 'Whether or not to send in test mode "o:testmode".', | |
strict: true, // strict does not apply to booleans | |
defaultValue: false | |
}) | |
.command('list', { // could potentially replace the -o flag with a positional arg by using 'list [order=asc]' here, in which case you could remove the setup handler entirely | |
desc: 'List members in order based on latest or oldest mailgunMateScheduledSends datetimes.', | |
paramsDesc: 'The order to list the items in: "des" for descending, "asc" for ascending.', | |
setup: sywac => { // shadowing the existing sywac variable can lead to bugs and is thus discouraged | |
sywac | |
// no need to redefine this option since it is inherited from the parent command's configuration | |
// .option('-l, --email-list <email-list>', { | |
// type: 'string', | |
// desc: 'The mailgun email list you would like to use.', | |
// strinct: true, | |
// defaultValue: 'something' | |
// }) | |
.option('-o, --order [des|asc(default)]', { | |
type: 'string', // consider using 'enum' here and define a `choices` property as an array with all valid values | |
desc: 'The order you would like the items displayed in.', | |
defaultValue: 'asc' | |
}) | |
}, | |
run: async (parsedArgv, context) => { | |
// if this is called, then the run handler for schedule-delivery will not be called | |
// this artificial delay just demonstrates that it will be awaited | |
await new Promise(resolve => { | |
setTimeout(() => { | |
console.log('list:', parsedArgv) | |
resolve() | |
}, 500) | |
}) | |
} | |
}) | |
}, | |
run: (parsedArgv, context) => { | |
// this will not be called if any subcommands are run | |
console.log('schedule-delivery:', parsedArgv) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const moment = require('moment') | |
const Type = require('sywac/types/type') | |
const internals = {} | |
class mailgunDateTimeFormat extends Type { | |
get datatype () { | |
return 'mailgunDateTimeFormat' | |
} | |
// this is superfluous | |
// setValue (context, value) { | |
// context.assignValue(this.id, value) | |
// } | |
validateValue (value) { | |
// https://momentjs.com/docs/#/parsing/string-format/ | |
const scheduledTime = moment(value, 'YYYY-MM-DD') | |
internals.scheduleDateIsValid = scheduledTime.isValid() | |
if (!internals.scheduleDateIsValid) return false | |
internals.scheduleDateIsBeforeDeadline = scheduledTime.isBefore(moment().add(3, 'days')) | |
if (!internals.scheduleDateIsBeforeDeadline) return false | |
internals.scheduleDateIsAfterNow = scheduledTime.isAfter(moment()) | |
if (!internals.scheduleDateIsAfterNow) return false | |
internals.scheduledSendDateTime = value | |
return true | |
} | |
buildInvalidMessage (context, msgAndArgs) { | |
super.buildInvalidMessage(context, msgAndArgs) | |
let customMessage | |
if (!internals.scheduleDateIsValid) customMessage = `The datetime you entered was not valid according to mailgun\'s rules. RFC 2822, formatted as mailgun requires "YYYY-MM-DD", See (https://documentation.mailgun.com/en/latest/user_manual.html#scheduling-delivery) for more information.` | |
else if (!internals.scheduleDateIsBeforeDeadline) customMessage = `The datetime you entered was outside of the mailgun 3 days schedule linmmit.` | |
else if (!internals.scheduleDateIsAfterNow) customMessage = `The datetime you entered was in the past.` | |
msgAndArgs.msg += ` Please specify a valid schedule datetime. ${customMessage} Please try again.` | |
} | |
} | |
require('sywac') | |
.registerFactory('mailgunDateTimeFormat', opts => new mailgunDateTimeFormat(opts)) | |
.command(require('./issue21-schedule-delivery')) | |
.help('-h, --help') | |
.showHelpByDefault() // this is fine here and can be disabled at lower levels (commands) if necessary | |
.parseAndExit() // this initiates parsing of process.argv and will exit the process if any parsing/validation errors occur |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment