UNPKG

@swell/cli

Version:

Swell's command line interface/utility

191 lines (190 loc) 7.55 kB
import { input, select } from '@inquirer/prompts'; import { Args, Flags } from '@oclif/core'; import { singularize } from 'inflection'; import { CreateConfigCommand } from '../../create-config-command.js'; import { ConfigType } from '../../lib/apps/index.js'; import { toFileName, toNotificationLabel } from '../../lib/create/index.js'; import { SCHEMAS } from '../../lib/create/schemas.js'; export default class CreateNotification extends CreateConfigCommand { static args = { name: Args.string({ default: '', description: 'Notification name (e.g., order-paid)', }), }; static description = 'Create notification files and configuration in the notifications folder.'; static examples = [ '$ swell create notification', '$ swell create notification order-paid -m orders -y', '$ swell create notification order-paid -m orders -e created -s "Order Paid" --admin --once -y', ]; static helpMeta = { usageDirect: '<name> -m <model> [...] -y', }; static flags = { model: Flags.string({ char: 'm', default: '', description: 'Triggering model (required with -y)', }), event: Flags.string({ char: 'e', default: '', description: 'Triggering event (default: created)', }), subject: Flags.string({ char: 's', default: '', description: 'Email subject', }), description: Flags.string({ char: 'd', default: '', description: 'Description', }), admin: Flags.boolean({ char: 'a', description: 'Send to store admins only', }), once: Flags.boolean({ char: 'o', description: 'Send only once when conditions met', }), overwrite: Flags.boolean({ default: false, description: 'Overwrite existing file', }), yes: Flags.boolean({ char: 'y', description: 'Skip prompts, require all arguments', }), }; static summary = 'Create notification files and configuration in the notifications folder.'; createType = ConfigType.NOTIFICATION; async run() { const { args, flags } = await this.parse(CreateNotification); const confirmYes = Boolean(flags.yes); // NON-INTERACTIVE PATH if (confirmYes) { // Validate NAME argument if (!args.name) { this.error('Missing required argument for non-interactive mode: NAME\n\nExample: swell create notification order-paid -m orders -y', { exit: 1 }); } // Validate --model flag if (!flags.model) { this.error('Missing required flag for non-interactive mode: --model\n\nExample: swell create notification order-paid -m orders -y', { exit: 1 }); } // Build with defaults const name = toFileName(args.name); const { model, event: eventFlag, subject: subjectFlag, description: descFlag, admin: adminFlag, once: onceFlag, overwrite, } = flags; const event = eventFlag || 'created'; const subject = subjectFlag || toNotificationLabel(name); const description = descFlag || ''; const admin = adminFlag || false; const once = onceFlag || false; await this.writeNotificationFile({ admin, description, event, model, name, once, subject }, overwrite, /* shouldConfirm */ false); return; } // INTERACTIVE PATH let name = args.name; let model = flags.model; const { event: eventFlag, description: descFlag, subject: subjectFlag, overwrite, } = flags; // Prompt for admin if not provided let { admin } = flags; if (admin === undefined) { const choice = await select({ choices: [ { name: 'Admins', value: 'admin' }, { name: 'Customers', value: 'customer' }, ], message: 'Who will be notified?', }); admin = choice === 'admin'; } // Prompt for model if not provided if (!model) { const collections = await this.getCollectionOptions(); model = await select({ choices: collections.map((collectionName) => ({ name: collectionName, value: collectionName, })), loop: false, message: 'Which model will trigger the notification?', pageSize: 25, }); } // Prompt for event if not provided const event = eventFlag || (await input({ default: 'created', message: 'Event to trigger the notification', })); // Prompt for name if not provided if (!name) { name = await input({ default: `${singularize(model)}-${event}`, message: 'Name of the notification', }); } name = toFileName(name); // Prompt for description if not provided const description = descFlag || (await input({ default: `Notify ${admin ? 'admin' : 'customer'} when ${singularize(model)}...`, message: 'Describe what the notification does', })); // Prompt for once if not provided let { once } = flags; if (once === undefined) { once = await select({ choices: [ { name: 'Every time conditions are met', value: false }, { name: 'Only the first time conditions are met', value: true }, ], message: 'When should we send this notification?', }); } // Prompt for subject if not provided const subject = subjectFlag || (await input({ default: toNotificationLabel(name), message: 'Subject of the notification email', })); await this.writeNotificationFile({ admin, description, event, model, name, once, subject }, overwrite, /* shouldConfirm */ true); } async writeNotificationFile({ admin, description, event, model, name, once, subject, }, overwrite, shouldConfirm = true) { const fileName = toFileName(name); const noteLabel = toNotificationLabel(name); const fileBody = { $schema: SCHEMAS.NOTIFICATION, collection: model, conditions: {}, event: event || 'created', label: noteLabel, method: 'email', subject: subject || `${noteLabel}...`, }; fileBody.description = description; if (admin) { fileBody.admin = true; } else { fileBody.contact = 'account.email'; } // Note since we are using events, we don't need 'new' option if (!once) { fileBody.repeat = true; } fileBody.query = { expand: [], }; fileBody.sample = {}; const jsonCreated = await this.createFile({ fileBody, fileName }, overwrite, shouldConfirm); if (jsonCreated) { await this.createFile({ extension: 'tpl', fileBody: '\n', fileName }, overwrite, false); } } }