UNPKG

mcdev

Version:

Accenture Salesforce Marketing Cloud DevTools

1,224 lines (1,213 loc) 58.6 kB
#!/usr/bin/env node /** * CLI entry for SFMC DevTools */ import { Util } from './util/util.js'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import Mcdev from './index.js'; // use this instead of setting "true" directly to more easily find deprecated commands in this file const isDeprecated = true; /** * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo */ yargs(hideBin(process.argv)) .scriptName('mcdev') .usage('$0 <command> [options]') .command( ['retrieve [BU] [TYPE] [KEY]', 'r'], 'retrieves metadata of a business unit', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to retrieve from (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type that shall be exclusively downloaded', }) .positional('KEY', { type: 'string', describe: 'metadata keys that shall be exclusively downloaded', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for retrieve:', describe: 'type or type:key or type:i:id or type:n:name to retrieve; if not provided, all metadata will be retrieved', }) .option('like', { type: 'string', group: 'Options for retrieve:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .option('skipValidation', { alias: 'sv', group: 'Options for retrieve:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('fix', { group: 'Options for retrieve:', describe: 'should ONLY be used to identify what items would be filtered out or changed during build/deploy. This does not actually change anything on the server.', }) .option('format', { type: 'boolean', alias: 'f', group: 'Options for retrieve:', describe: 'allows overwriting options.formatOnSave from the config file. Disable formatting via --no-format', }) .option('purge', { type: 'boolean', group: 'Options for retrieve:', describe: 'deletes the relevant retrieve folder before retrieving', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.retrieve(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.retrieve(argv.BU, typeKeyCombo); } } ) .command( ['deploy [BU] [TYPE] [KEY]', 'd'], 'deploys local metadata to a business unit', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to deploy to (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type that shall be exclusively uploaded', }) .positional('KEY', { type: 'string', describe: 'metadata key that shall be exclusively uploaded', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for deploy:', describe: 'type or type:key or type:i:id or type:n:name to deploy; if not provided, all metadata will be deploy', }) .option('keySuffix', { type: 'string', alias: 'ks', group: 'Options for deploy:', describe: 'allows you to add a suffix to the key of the metadata to be deployed', }) .option('autoMidSuffix', { type: 'boolean', group: 'Options for deploy:', describe: 'for asset: enables the automatic addition of the MID to the key of the deployed metadata when deploying cross-BU. Alternatively, use --keySuffix or templating-based suffixes', }) .option('changeKeyField', { type: 'string', alias: 'ckf', group: 'Options for deploy:', describe: 'enables updating the key of the deployed metadata with the value in provided field (e.g. c__newKey). Can be used to sync name and key fields.', }) .option('changeKeyValue', { type: 'string', alias: 'ckv', group: 'Options for deploy:', describe: 'allows updating the key of the metadata to the provided value. Only available if a single type and key is deployed', }) .option('fromRetrieve', { type: 'boolean', alias: 'fr', group: 'Options for deploy:', describe: 'deploy from retrieve folder', }) .option('refresh', { type: 'boolean', alias: 'r', group: 'Options for deploy:', describe: 'for asset-message: runs refresh command for related triggeredSends after deploy', }) .option('execute', { type: 'boolean', alias: 'e', group: 'Options for deploy:', describe: 'executes item after deploy; this will run the item once immediately', }) .option('schedule', { type: 'boolean', alias: 's', group: 'Options for deploy:', describe: 'start existing schedule instead of running item once immediately (only works for automations)', }) .option('fixShared', { group: 'Options for deploy:', describe: "ensure that updates to shared DataExtensions become visible in child BU's data designer (SF Known issue W-11031095)", }) .option('noUpdate', { group: 'Options for deploy:', describe: 'if set, no metadata will be updated, only new metadata will be created', }) .option('publish', { group: 'Options for deploy:', describe: 'publishes the entity after deploy (only works on journeys)', }) .option('validate', { group: 'Options for deploy:', describe: 'validate the entity after deploy (only works on journeys)', }) .option('skipStatusCheck', { group: 'Options for deploy:', describe: 'only relevant if used together with --publish. if you do not care if publishing actually worked you can skip the checks with this option.', }) .option('matchName', { group: 'Options for deploy:', describe: 'Some metadata types allow updating resources despite a key mismatch by matching the name. That avoids clean-ups on all BUs but instead allows you to continously get higher environmetns into a better shape.', }) .option('skipValidation', { alias: 'sv', group: 'Options for deploy:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('format', { type: 'boolean', alias: 'f', group: 'Options for deploy:', describe: 'allows overwriting options.formatOnSave from the config file. Disable formatting via --no-format', }) .option('ignoreFolder', { type: 'boolean', alias: 'if', group: 'Options for deploy:', describe: 'works with --matchName and allows skipping folder match if there is only 1 name match', }) .option('ignoreSfFields', { type: 'boolean', alias: 'isf', group: 'Options for deploy:', describe: 'relevant for Salesforce triggered journeys and events; allows ignoring errors on missing Salesforce fields in case the API returns other info than the GUI. CAUTION!', }) .option('fix', { group: 'Options for deploy:', describe: 'auto-fix validation issues if the rule is able to do it', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.deploy(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.deploy(argv.BU, typeKeyCombo); } } ) .command( ['init [credentialsName]'], `creates '${Util.configFileName}' in your root or adds additional credentials to the existing one`, (yargs) => yargs.positional('credentialsName', { type: 'string', describe: 'name of your installed package', }), (argv) => { Mcdev.setOptions(argv); Mcdev.initProject(argv.credentialsName); } ) .command(['join'], `clones an existing project from git`, {}, (argv) => { Mcdev.setOptions(argv); Mcdev.joinProject(); }) .command( ['reloadBUs [credentialsName]', 'rb', 'refreshBUs'], 'loads the list of available BUs from the server and saves it to your config', (yargs) => yargs.positional('credentialsName', { type: 'string', describe: 'name of your installed package', }), (argv) => { Mcdev.setOptions(argv); Mcdev.findBUs(argv.credentialsName); } ) .command( ['badKeys [BU]'], 'lists metadata with random API names in specified Business Unit directory', (yargs) => yargs.positional('BU', { type: 'string', describe: 'the business unit to deploy to', }), (argv) => { Mcdev.setOptions(argv); Mcdev.badKeys(argv.BU); } ) .command( ['document <BU> <TYPE>', 'doc'], 'Creates Markdown or HTML documentation for the selected type', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to generate docs for (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type to generate docs for; currently supported: dataExtension, role', }), (argv) => { Mcdev.setOptions(argv); Mcdev.document(argv.BU, argv.TYPE); } ) .command( ['delete <BU> [TYPE] [KEY]', 'del'], 'deletes metadata of selected type and external key', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to delete from (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type to delete from;', }) .positional('KEY', { type: 'string', describe: 'the key to delete', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for delete:', describe: 'type or type:key or type:i:id or type:n:name to delete', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata, ['key', 'id']); if ('undefined' === typeof typeKeyCombo) { if (argv.TYPE && argv.KEY) { Mcdev.deleteByKey(argv.BU, argv.TYPE, csvToArray(argv.KEY)); } } else { Mcdev.deleteByKey(argv.BU, typeKeyCombo, null); } } ) .command( ['resolveId <BU> <TYPE> <ID>', 'rid'], 'resolves metadata key by ID', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to search in (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type to search in; currently supported: asset', }) .positional('ID', { type: 'string', describe: 'the id to resolve', }) .option('json', { type: 'boolean', group: 'Options for resolveId:', describe: 'optionaly return info in json format', }), // TODO: add option --metadata (argv) => { Mcdev.setOptions(argv); Mcdev.resolveId(argv.BU, argv.TYPE, argv.ID); } ) .command( ['retrieveAsTemplate <BU> <TYPE> <NAME> <MARKET>', 'rt'], '[DEPRECATED] Retrieves a specific metadata file by name from the server for templating', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to deploy to (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('NAME', { type: 'string', describe: 'name of the metadata component', }) .positional('MARKET', { type: 'string', describe: 'market used for reverse building template', }), (argv) => { Mcdev.setOptions(argv); Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, csvToArray(argv.NAME), argv.MARKET); }, [], isDeprecated ) .command( ['clone'], 'clones items across BUs. Alias for: mcdev build --mf __clone__ --mt __clone__', (yargs) => yargs .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Required parameters for clone:', describe: 'type:key combos to clone', demandOption: true, }) .option('buFrom', { type: 'string', alias: 'bf', group: 'Required parameters for clone:', describe: 'the business unit to create the templates from (in format "credential name/BU name")', demandOption: true, }) .option('buTo', { type: 'string', alias: 'bt', group: 'Required parameters for clone:', describe: 'the business unit to deploy to; required unless --bulk is set', }) .option('dependencies', { type: 'boolean', alias: 'D', group: 'Options for clone:', describe: 'create templates for all dependencies of the metadata component', }) .option('retrieve', { type: 'boolean', alias: 'r', group: 'Options for clone:', describe: 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', }) .option('skipValidation', { alias: 'sv', group: 'Options for clone:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('purge', { group: 'Options for clone:', describe: 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' !== typeof typeKeyCombo) { Mcdev.clone(argv.buFrom, argv.buTo, typeKeyCombo); } } ) .command( ['build'], 'runs buildTemplate followed by buildDefinition', (yargs) => yargs .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Required parameters for build:', describe: 'type:key combos to build template for', demandOption: true, }) .option('buFrom', { type: 'string', alias: 'bf', group: 'Required parameters for build:', describe: 'the business unit to create the templates from (in format "credential name/BU name")', demandOption: true, }) .option('buTo', { type: 'string', alias: 'bt', group: 'Required parameters for build:', describe: 'the business unit to deploy to; required unless --bulk is set', }) .option('marketFrom', { type: 'string', array: true, alias: 'mf', group: 'Required parameters for build:', describe: 'market used for reverse building template', demandOption: true, }) .option('marketTo', { type: 'string', array: true, alias: 'mt', group: 'Required parameters for build:', describe: 'market used for building deployable definition', demandOption: true, }) .option('bulk', { type: 'boolean', group: 'Options for build:', describe: 'if defined, the marketTo parameter has to be a marketList and buildDefinitionBulk is executed', }) .option('dependencies', { type: 'boolean', alias: 'D', group: 'Options for build:', describe: 'create templates for all dependencies of the metadata component', }) .option('retrieve', { type: 'boolean', alias: 'r', group: 'Options for build:', describe: 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', }) .option('skipValidation', { alias: 'sv', group: 'Options for build:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('purge', { group: 'Options for build:', describe: 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', }) .option('fix', { group: 'Options for build:', describe: 'auto-fix validation issues if the rule is able to do it', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' !== typeof typeKeyCombo) { Mcdev.build( argv.buFrom, argv.buTo, typeKeyCombo, argv.marketFrom, argv.marketTo, argv.bulk ); } } ) .command( ['buildTemplate <BU> [TYPE] [KEY] [MARKET]', 'bt'], 'builds a template out of a specific metadata file already in your retrieve folder', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to create the templates from (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .positional('MARKET', { type: 'string', describe: 'market used for reverse building template', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for buildTemplate:', describe: 'type:key combos to build template for', }) .option('market', { type: 'string', array: true, group: 'Options for buildTemplate:', describe: 'market used for reverse building template', }) .option('dependencies', { type: 'boolean', alias: 'D', group: 'Options for buildTemplate:', describe: 'create templates for all dependencies of the metadata component', }) .option('retrieve', { type: 'boolean', alias: 'r', group: 'Options for buildTemplate:', describe: 're-retrieves potentially relevant metadata before building (all if --dependencies is used)', }) .check((argv) => { if (!argv.MARKET && !argv.market) { throw new Error( 'Error: You need to provide a market for reverse building the template' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.buildTemplate( argv.BU, argv.TYPE, csvToArray(argv.KEY), argv.MARKET ? [argv.MARKET] : argv.market ); } else { Mcdev.buildTemplate( argv.BU, typeKeyCombo, null, argv.MARKET ? [argv.MARKET] : argv.market ); } } ) .command( ['buildDefinition <BU> [TYPE] [FILENAME] [MARKET]', 'bd'], 'builds metadata definition based on template', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to deploy to', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('FILENAME', { type: 'string', describe: 'File name of the metadata template without the extension', }) .positional('MARKET', { type: 'string', describe: 'market used for building deployable definition', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for buildDefinition:', describe: 'type:templateName combos to build template for', }) .option('market', { type: 'string', array: true, group: 'Options for buildDefinition:', describe: 'market used for building deployable definition', }) .option('skipValidation', { alias: 'sv', group: 'Options for buildDefinition:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('purge', { group: 'Options for buildDefinition:', describe: 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', }) .option('fix', { group: 'Options for buildDefinition:', describe: 'auto-fix validation issues if the rule is able to do it', }) .check((argv) => { if (!argv.MARKET && !argv.market) { throw new Error( 'Error: You need to provide a market for reverse building the template' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.buildDefinition( argv.BU, argv.TYPE, csvToArray(argv.FILENAME), argv.MARKET ? [argv.MARKET] : argv.market ); } else { Mcdev.buildDefinition( argv.BU, typeKeyCombo, null, argv.MARKET ? [argv.MARKET] : argv.market ); } } ) .command( ['buildDefinitionBulk <LISTNAME> [TYPE] [FILENAME]', 'bdb'], 'builds metadata definition based on template en bulk', (yargs) => yargs .positional('LISTNAME', { type: 'string', describe: 'name of list of BU-market combos', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('FILENAME', { type: 'string', describe: 'File name of the metadata template without the extension', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for buildDefinitionBulk:', describe: 'type:templateName combos to build template for', }) .option('skipValidation', { alias: 'sv', group: 'Options for buildDefinitionBulk:', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('purge', { group: 'Options for buildDefinitionBulk:', describe: 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', }) .option('fix', { group: 'Options for buildDefinitionBulk:', describe: 'auto-fix validation issues if the rule is able to do it', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.buildDefinitionBulk(argv.LISTNAME, argv.TYPE, csvToArray(argv.FILENAME)); } else { Mcdev.buildDefinitionBulk(argv.LISTNAME, typeKeyCombo); } } ) .command( ['selectTypes', 'st'], 'lets you choose what metadata types to retrieve', {}, (argv) => { Mcdev.setOptions(argv); Mcdev.selectTypes(); } ) .command( ['explainTypes', 'et'], 'explains metadata types that can be retrieved', (yargs) => yargs.option('json', { type: 'boolean', group: 'Options for explainTypes:', describe: 'optionaly return info in json format', }), (argv) => { Mcdev.setOptions(argv); Mcdev.explainTypes(); } ) .command( ['createDeltaPkg [commitrange]', 'cdp'], 'Copies commit-based file delta into deploy folder', (yargs) => yargs .positional('commitrange', { type: 'string', describe: 'Pull Request target branch or git commit range', }) .option('range', { type: 'string', alias: ['branch', 'commit', 'R'], group: 'Options for createDeltaPkg:', describe: 'Pull Request target branch or git commit range', }) .option('filter', { type: 'string', group: 'Options for createDeltaPkg:', describe: 'Disable templating & instead filter by the specified BU path (comma separated), can include subtype, will be prefixed with "retrieve/"', }) .option('commitHistory', { type: 'number', group: 'Options for createDeltaPkg:', describe: 'Number of commits to look back for changes (supersedes config)', }) .option('dependencies', { type: 'boolean', alias: 'D', group: 'Options for build (run via createDeltaPkg):', describe: 'create templates for all dependencies of the metadata component', }) .option('retrieve', { type: 'boolean', alias: 'r', group: 'Options for build (run via createDeltaPkg):', describe: 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', }) .option('skipValidation', { alias: 'sv', group: 'Options for build (run via createDeltaPkg):', describe: 'allows reducing validation rules from error to warn to handle edge cases', }) .option('purge', { group: 'Options for build (run via createDeltaPkg):', describe: 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', }) .option('fix', { group: 'Options for build (run via createDeltaPkg)', describe: 'auto-fix validation issues if the rule is able to do it', }), (argv) => { Mcdev.setOptions(argv); Mcdev.createDeltaPkg(argv); } ) .command( ['getFilesToCommit <BU> <TYPE> <KEY>', 'fc'], 'returns a list of relative paths to files one needs to include in a commit', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to deploy to (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }), // TODO: add option --metadata (argv) => { Mcdev.setOptions(argv); Mcdev.getFilesToCommit(argv.BU, argv.TYPE, csvToArray(argv.KEY)); } ) .command( ['refresh <BU> [TYPE] [KEY]', 're'], 'ensures that updates are properly published', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit to execute the refresh on', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for execute:', describe: 'type or type:key or type:i:id or type:n:name to fix', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.refresh(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.refresh(argv.BU, typeKeyCombo); } } ) .command( ['execute <BU> [TYPE] [KEY]', 'exec', 'start', 'resume'], 'executes the entity', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for execute:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for execute:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .option('schedule', { type: 'boolean', group: 'Options for execute:', describe: 'optionally start existing schedule instead of running item once immediately (only works for automations)', }) .check((argv) => { if (!argv.TYPE && !argv.metadata) { throw new Error( 'Error: Either specify the metadata type after the BU or use --metadata' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.execute(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.execute(argv.BU, typeKeyCombo); } } ) .command( ['publish <BU> [TYPE] [KEY]', 'activate'], 'publishes the entity', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for publish:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for publish:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .option('skipStatusCheck', { group: 'Options for publish:', describe: 'if you don not care if publishing actually worked you can skip the checks', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.publish(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.publish(argv.BU, typeKeyCombo); } } ) .command( ['validate <BU> [TYPE] [KEY]'], 'validates the entity', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for validate:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for validate:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.validate(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.validate(argv.BU, typeKeyCombo); } } ) .command( ['schedule <BU> [TYPE] [KEY]', 'sched'], 'starts the predefined schedule of the item (shortcut for running execute --schedule)', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for schedule:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for schedule:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .check((argv) => { if (!argv.TYPE && !argv.metadata) { throw new Error( 'Error: Either specify the metadata type after the BU or use --metadata' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.schedule(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.schedule(argv.BU, typeKeyCombo); } } ) .command( ['pause <BU> [TYPE] [KEY]', 'p'], 'pauses the entity (automation etc.)', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for pause:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for pause:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .check((argv) => { if (!argv.TYPE && !argv.metadata) { throw new Error( 'Error: Either specify the metadata type after the BU or use --metadata' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.pause(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.pause(argv.BU, typeKeyCombo); } } ) .command( ['stop <BU> [TYPE] [KEY]'], 'stops the entity (journey etc.)', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for pause:', describe: 'type or type:key or type:i:id or type:n:name to fix', }) .option('like', { type: 'string', group: 'Options for pause:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }) .check((argv) => { if (!argv.TYPE && !argv.metadata) { throw new Error( 'Error: Either specify the metadata type after the BU or use --metadata' ); } return true; }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); if ('undefined' === typeof typeKeyCombo) { Mcdev.stop(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); } else { Mcdev.stop(argv.BU, typeKeyCombo); } } ) .command( ['audit <BU>'], 'shows audit log for the entity (journey etc.)', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to start an item', }) .option('metadata', { type: 'string', array: true, alias: 'm', group: 'Options for audit:', describe: 'type or type:key or type:i:id or type:n:name to fix', demandOption: true, }) .option('like', { type: 'string', group: 'Options for audit:', describe: 'filter metadata components (can include % as wildcard or _ for a single character)', }), (argv) => { Mcdev.setOptions(argv); const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); Mcdev.audit(argv.BU, typeKeyCombo); } ) .command( ['fixKeys <BU> [TYPE] [KEY]', 'fx'], 'changes the key of the items to match the name', (yargs) => yargs .positional('BU', { type: 'string', describe: 'the business unit where to fix keys', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) .positional('KEY', { type: 'string', describe: 'key(s) of the metadata component(s)', }) .option('metadata', { type: 'string', array: true, alias: 'm',