UNPKG

@black-flag/extensions

Version:

A collection of set-theoretic declarative-first APIs for yargs and Black Flag

782 lines (781 loc) 32.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getInvocableExtendedHandler = getInvocableExtendedHandler; exports.withBuilderExtensions = withBuilderExtensions; exports.withUsageExtensions = withUsageExtensions; require("core-js/modules/es.array.push.js"); require("core-js/modules/es.iterator.constructor.js"); require("core-js/modules/es.iterator.find.js"); require("core-js/modules/es.iterator.for-each.js"); require("core-js/modules/es.iterator.map.js"); require("core-js/modules/es.iterator.some.js"); require("core-js/modules/es.set.difference.v2.js"); require("core-js/modules/es.set.intersection.v2.js"); require("core-js/modules/es.set.is-disjoint-from.v2.js"); require("core-js/modules/es.set.is-subset-of.v2.js"); require("core-js/modules/es.set.is-superset-of.v2.js"); require("core-js/modules/es.set.symmetric-difference.v2.js"); require("core-js/modules/es.set.union.v2.js"); require("core-js/modules/esnext.array.group.js"); var _nodeUtil = require("node:util"); var _types = require("node:util/types"); var _js = require("@-xun/js"); var _core = require("@black-flag/core"); var _util = require("@black-flag/core/util"); var _lodash = _interopRequireDefault(require("lodash.camelcase")); var _rejoinder = require("rejoinder"); var _constant = require("./constant.js"); var _error = require("./error.js"); exports.BfeErrorMessage = _error.BfeErrorMessage; var _symbols = require("./symbols.js"); exports.$artificiallyInvoked = _symbols.$artificiallyInvoked; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const alphaSort = new Intl.Collator(undefined, { numeric: true }); function withBuilderExtensions(customBuilder, { commonOptions = ['help'], disableAutomaticGrouping = false, enableAutomaticSorting = false } = {}) { const xbuilderDebug = (0, _rejoinder.createDebugLogger)({ namespace: `${_constant.globalDebuggerNamespace}:withBuilderExtensions` }); xbuilderDebug('entered withBuilderExtensions function'); let optionsMetadata = undefined; let latestProgram = undefined; let latestBfBuilderObject = undefined; let latestBfParserConfiguration = undefined; xbuilderDebug('exited withBuilderExtensions function'); return [function builder(blackFlag, helpOrVersionSet, argv) { const builderDebug = xbuilderDebug.extend('builder'); const isFirstPass = !argv; const isSecondPass = !isFirstPass; builderDebug('entered withBuilderExtensions::builder wrapper function'); builderDebug('isFirstPass: %O', isFirstPass); builderDebug('isSecondPass: %O', isSecondPass); builderDebug('current argv: %O', argv); let defaultedOptions = undefined; if (isSecondPass) { defaultedOptions = latestProgram.parsed?.defaulted; hardAssert(defaultedOptions, _error.BfeErrorMessage.UnexpectedlyFalsyDetailedArguments()); deleteDefaultedArguments({ argv, defaultedOptions }); } latestProgram = blackFlag; builderDebug('calling customBuilder (if a function) and returning builder object'); let builderObject = (0, _js.safeDeepClone)((typeof customBuilder === 'function' ? customBuilder(blackFlag, helpOrVersionSet, argv) : customBuilder) || {}); Object.values(builderObject).forEach(builderObjectValue => { if (builderObjectValue.default === undefined) { delete builderObjectValue.default; } }); if (enableAutomaticSorting) { builderDebug(`commencing automatic options sorting (${isFirstPass ? 'first' : 'second'} pass)`); const keys = Object.keys(builderObject).sort((k1, k2) => alphaSort.compare(k1, k2)); builderObject = Object.fromEntries(keys.map(k => [k, builderObject[k]])); } builderDebug('builderObject (maybe auto-sorted; undefined defaults deleted): %O', builderObject); if (isSecondPass) { Object.entries(builderObject).forEach(([subOption, subOptionConfig]) => { const { subOptionOf } = subOptionConfig; if (subOptionOf) { builderDebug('evaluating suboption configuration for %O', subOption); Object.entries(subOptionOf).forEach(([superOption, updaters_]) => { const updaters = [updaters_].flat(); builderDebug('saw entry for super-option %O (%O potential updates)', superOption, updaters.length); updaters.forEach(({ when, update }, index) => { if (superOption in argv && when(argv[superOption], argv)) { subOptionConfig = typeof update === 'function' ? update(subOptionConfig, argv) : update; builderDebug('accepted configuration update #%o to suboption %O: %O', index + 1, subOption, subOptionConfig); } else { builderDebug('rejected configuration update #%o to suboption %O: when() returned falsy', index + 1, subOption); } }); }); builderObject[subOption] = subOptionConfig; builderDebug('applied suboption configuration for %O', builderObject[subOption]); } delete subOptionConfig.subOptionOf; }); } const parserConfiguration = getParserConfigurationFromBlackFlagInstance(blackFlag); const optionLocalMetadata = analyzeBuilderObject({ builderObject, commonOptions, parserConfiguration }); builderDebug('option local metadata: %O', optionLocalMetadata); if (!disableAutomaticGrouping) { builderDebug(`commencing automatic options grouping (${isFirstPass ? 'first' : 'second'} pass)`); const { demanded, demandedAtLeastOne, demandedMutuallyExclusive, optional, customGroups } = optionLocalMetadata; if (demanded.length) { blackFlag.group(demanded, 'Required Options:'); builderDebug('added "Required" grouping: %O', demanded); } demandedAtLeastOne.forEach((group, index) => { const count = index + 1; const options = Object.keys(group); blackFlag.group(options, `Required Options ${demandedAtLeastOne.length > 1 ? `${count} ` : ''}(at least one):`); builderDebug(`added "Required (at least one)" grouping #%O: %O`, count, options); }); demandedMutuallyExclusive.forEach((group, index) => { const count = index + 1; const options = Object.keys(group); blackFlag.group(options, `Required Options ${demandedAtLeastOne.length > 1 ? `${count} ` : ''}(mutually exclusive):`); builderDebug(`added "Required (mutually exclusive)" grouping #%O: %O`, count, options); }); for (const [groupName, options] of Object.entries(customGroups)) { blackFlag.group(options, groupName); builderDebug(`added custom "${groupName}" grouping: %O`, options); } if (optional.length) { blackFlag.group(optional, 'Optional Options:'); builderDebug('added "Optional" grouping: %O', optional); } if (commonOptions.length) { const commonOptions_ = commonOptions.map(o => String(o)); blackFlag.group(commonOptions_, 'Common Options:'); builderDebug('added "Common" grouping: %O', commonOptions_); } } else { builderDebug(`automatic options grouping disabled (at ${isFirstPass ? 'first' : 'second'} pass)`); } if (isSecondPass) { optionsMetadata = optionLocalMetadata; builderDebug('stored option local metadata => option metadata'); } latestBfBuilderObject = builderObject; latestBfParserConfiguration = parserConfiguration; builderDebug('stored latestBfBuilderObject and latestBfParserConfiguration'); builderDebug('transmuting BFE builder to BF builder'); const finalBuilderObject = transmuteBFEBuilderToBFBuilder({ builderObject, deleteGroupProps: !disableAutomaticGrouping, isGeneratingSecondPassHelpText: helpOrVersionSet && isSecondPass, optionsMetadata, argv }); builderDebug('final transmuted builderObject: %O', finalBuilderObject); builderDebug('exited withBuilderExtensions::builder wrapper function'); return finalBuilderObject; }, function withHandlerExtensions(customHandler) { return async function handler(realArgv) { const debug = (0, _rejoinder.createDebugLogger)({ namespace: `${_constant.globalDebuggerNamespace}:withHandlerExtensions` }); debug('entered withHandlerExtensions::handler wrapper function'); debug('option metadata: %O', optionsMetadata); hardAssert(optionsMetadata, _error.BfeErrorMessage.IllegalHandlerInvocation()); debug('real argv: %O', realArgv); const { [_symbols.$artificiallyInvoked]: wasInvokedArtificially } = realArgv; debug('wasInvokedArtificially: %O', wasInvokedArtificially); if (wasInvokedArtificially) { debug.warn('skipped bfe checks due to presence of $artificiallyInvoked'); } else { const defaultedOptions = latestProgram.parsed?.defaulted; debug('defaultedOptions: %O', defaultedOptions); hardAssert(defaultedOptions, _error.BfeErrorMessage.UnexpectedlyFalsyDetailedArguments()); deleteDefaultedArguments({ argv: realArgv, defaultedOptions }); debug('real argv with defaults deleted: %O', realArgv); const canonicalArgv = deriveCanonicalArgv(optionsMetadata, realArgv); debug('"canonical argv" used for checks: %O', canonicalArgv); optionsMetadata.required.forEach(({ [_symbols.$genesis]: requirer, ...requireds }) => { hardAssert(requirer !== undefined, _error.BfeErrorMessage.MetadataInvariantViolated('requires')); if (canonicalArgv.has(requirer)) { const missingRequiredKeyValues = []; Object.entries(requireds).forEach(required => { const [requiredKey, requiredValue] = required; const givenValue = canonicalArgv.get(requiredKey); const givenValueIsArray = Array.isArray(givenValue); if (!canonicalArgv.has(requiredKey) || requiredValue !== _symbols.$exists && (givenValueIsArray && !givenValue.some(value => (0, _nodeUtil.isDeepStrictEqual)(value, requiredValue)) || !givenValueIsArray && !(0, _nodeUtil.isDeepStrictEqual)(givenValue, requiredValue))) { missingRequiredKeyValues.push(required); } }); softAssert(!missingRequiredKeyValues.length, _error.BfeErrorMessage.RequiresViolation(requirer, missingRequiredKeyValues)); } }); optionsMetadata.conflicted.forEach(({ [_symbols.$genesis]: conflicter, ...conflicteds }) => { hardAssert(conflicter !== undefined, _error.BfeErrorMessage.MetadataInvariantViolated('conflicts')); if (canonicalArgv.has(conflicter)) { const seenConflictingKeyValues = []; Object.entries(conflicteds).forEach(keyValue => { const [conflictedKey, conflictedValue] = keyValue; const givenValue = canonicalArgv.get(conflictedKey); const givenValueIsArray = Array.isArray(givenValue); if (canonicalArgv.has(conflictedKey) && (conflictedValue === _symbols.$exists || givenValueIsArray && givenValue.some(value => (0, _nodeUtil.isDeepStrictEqual)(value, conflictedValue)) || !givenValueIsArray && (0, _nodeUtil.isDeepStrictEqual)(givenValue, conflictedValue))) { seenConflictingKeyValues.push(keyValue); } }); softAssert(!seenConflictingKeyValues.length, _error.BfeErrorMessage.ConflictsViolation(conflicter, seenConflictingKeyValues)); } }); optionsMetadata.demandedIf.forEach(({ [_symbols.$genesis]: demanded, ...demanders }) => { hardAssert(demanded !== undefined, _error.BfeErrorMessage.MetadataInvariantViolated('demandThisOptionIf')); const sawDemanded = canonicalArgv.has(demanded); Object.entries(demanders).forEach(demander => { const [demanderKey, demanderValue] = demander; const givenValue = canonicalArgv.get(demanderKey); const givenValueIsArray = Array.isArray(givenValue); const sawADemander = canonicalArgv.has(demanderKey) && (demanderValue === _symbols.$exists || givenValueIsArray && givenValue.some(value => (0, _nodeUtil.isDeepStrictEqual)(value, demanderValue)) || !givenValueIsArray && (0, _nodeUtil.isDeepStrictEqual)(givenValue, demanderValue)); softAssert(!sawADemander || sawDemanded, _error.BfeErrorMessage.DemandIfViolation(demanded, demander)); }); }); optionsMetadata.demandedAtLeastOne.forEach(group => { const groupEntries = Object.entries(group); const sawAtLeastOne = groupEntries.some(keyValue => { const [key, value] = keyValue; const givenValue = canonicalArgv.get(key); const givenValueIsArray = Array.isArray(givenValue); return canonicalArgv.has(key) && (value === _symbols.$exists || givenValueIsArray && givenValue.some(value_ => (0, _nodeUtil.isDeepStrictEqual)(value_, value)) || !givenValueIsArray && (0, _nodeUtil.isDeepStrictEqual)(givenValue, value)); }); softAssert(sawAtLeastOne, _error.BfeErrorMessage.DemandOrViolation(groupEntries)); }); optionsMetadata.demandedMutuallyExclusive.forEach(group => { const groupEntries = Object.entries(group); let sawAtLeastOne = undefined; groupEntries.forEach(keyValue => { const [key, value] = keyValue; const givenValue = canonicalArgv.get(key); const givenValueIsArray = Array.isArray(givenValue); if (canonicalArgv.has(key) && (value === _symbols.$exists || givenValueIsArray && givenValue.some(value_ => (0, _nodeUtil.isDeepStrictEqual)(value_, value)) || !givenValueIsArray && (0, _nodeUtil.isDeepStrictEqual)(givenValue, value))) { if (sawAtLeastOne !== undefined) { softAssert(false, _error.BfeErrorMessage.DemandSpecificXorViolation(sawAtLeastOne, keyValue)); } sawAtLeastOne = keyValue; } }); softAssert(sawAtLeastOne, _error.BfeErrorMessage.DemandGenericXorViolation(groupEntries)); }); const impliedKeyValues = {}; optionsMetadata.implied.forEach(({ [_symbols.$genesis]: implier, [_symbols.$canonical]: canonicalImplications, ...expandedImplications }) => { hardAssert(implier !== undefined, _error.BfeErrorMessage.MetadataInvariantViolated('implies')); if (canonicalArgv.has(implier) && (optionsMetadata.implyVacuously.includes(implier) || canonicalArgv.get(implier) !== false)) { Object.assign(impliedKeyValues, expandedImplications); if (!optionsMetadata.implyLoosely.includes(implier)) { const seenConflictingKeyValues = []; Object.entries(canonicalImplications).forEach(keyValue => { const [key, value] = keyValue; if (canonicalArgv.has(key) && !(0, _nodeUtil.isDeepStrictEqual)(canonicalArgv.get(key), value)) { seenConflictingKeyValues.push([key, canonicalArgv.get(key)]); } }); softAssert(!seenConflictingKeyValues.length, _error.BfeErrorMessage.ImpliesViolation(implier, seenConflictingKeyValues)); } } }); Object.assign(realArgv, { ...optionsMetadata.defaults, ...impliedKeyValues, ...realArgv }); debug('final argv (defaults and implies merged): %O', realArgv); for (const [currentArgument, checkFunctions_] of Object.entries(optionsMetadata.checks)) { if (currentArgument in realArgv) { const checkFunctions = [checkFunctions_].flat(); await Promise.all(checkFunctions.map(async checkFn => { let result; try { result = await checkFn(realArgv[currentArgument], realArgv); } catch (error) { result = error; } if (!result || typeof result === 'string' || (0, _types.isNativeError)(result)) { throw _core.CliError.isError(result) ? result : new _core.CliError(result || _error.BfeErrorMessage.CheckFailed(currentArgument)); } })); } } } debug('invoking customHandler (or defaultHandler if undefined)'); await (customHandler ?? defaultHandler)(realArgv); debug('exited withHandlerExtensions::handler wrapper function'); }; }]; function deleteDefaultedArguments({ argv, defaultedOptions }) { hardAssert(latestBfBuilderObject, _error.BfeErrorMessage.GuruMeditation()); hardAssert(latestBfParserConfiguration, _error.BfeErrorMessage.GuruMeditation()); Object.keys(defaultedOptions).forEach(defaultedOption => { expandOptionNameAndAliasesWithRespectToParserConfiguration({ option: defaultedOption, aliases: latestBfBuilderObject[defaultedOption].alias, parserConfiguration: latestBfParserConfiguration }).forEach(expandedName => delete argv[expandedName]); }); latestBfBuilderObject = undefined; latestBfParserConfiguration = undefined; } } function withUsageExtensions(config, moreConfig) { const { altDescription = '$1.', trim = true, appendPeriod = true, prependNewlines = true, includeOptions = prependNewlines, includeSubCommand = false } = typeof config === 'string' ? { altDescription: config, ...moreConfig } : { ...config, ...moreConfig }; return `Usage: $000${includeSubCommand === 'required' ? ' <subcommand>' : includeSubCommand ? ' [subcommand]' : ''}${includeOptions ? ' [...options]' : ''}${prependNewlines ? '\n\n' : ''}${altDescription[trim ? 'trim' : 'toString']()}${appendPeriod && !altDescription.endsWith('.') ? '.' : ''}`; } async function getInvocableExtendedHandler(maybeCommand, context) { const debug = (0, _rejoinder.createDebugLogger)({ namespace: `${_constant.globalDebuggerNamespace}:getInvocableExtendedHandler` }); debug('safely deep cloning context argument'); context = (0, _js.safeDeepClone)(context, context.state.extensions); debug('resolving maybePromisedCommand'); let command; try { command = await maybeCommand; } catch (error) { throw new _core.CliError(_error.BfeErrorMessage.FrameworkError(_error.BfeErrorMessage.FalsyCommandExport()), { cause: error, suggestedExitCode: _core.FrameworkExitCode.AssertionFailed }); } hardAssert(command, _error.BfeErrorMessage.FalsyCommandExport()); if (command.default !== undefined) { command = command.default; } if (command?.default !== undefined) { command = command.default; } let config; if (typeof command === 'function') { config = await command(context); } else { hardAssert(command && typeof command === 'object', _error.BfeErrorMessage.FalsyCommandExport()); config = command; } const { builder, handler } = config; hardAssert(handler, _error.BfeErrorMessage.CommandHandlerNotAFunction()); debug('returned immediately invocable handler function'); return async function (argv) { const fakeYargsWarning = '<this is a pseudo-yargs instance passed around by getInvocableExtendedHandler>'; const argv_ = (0, _js.safeDeepClone)({ [_symbols.$artificiallyInvoked]: true, $0: config.name || '???', _: [], ...argv, [_core.$executionContext]: context }, context.state.extensions); if (typeof builder === 'function') { const { default: makeVanillaYargs } = await import('yargs/yargs'); const dummyYargs = makeVanillaYargs(); const fakeBlackFlag = dummyYargs; dummyYargs.parsed = { '//': fakeYargsWarning, argv: argv_, defaulted: {}, aliases: {}, configuration: new Proxy({}, { get() { return true; } }), error: null, newAliases: {} }; debug('invoking builder (for the first time)'); builder(fakeBlackFlag, false, undefined); debug('invoking builder (for the second time)'); builder(fakeBlackFlag, false, { '//': fakeYargsWarning, ...argv_ }); } else { debug('warning: no callable builder function was returned!'); } debug('invoking handler'); return handler(argv_); }; } function transmuteBFEBuilderToBFBuilder({ builderObject, deleteGroupProps, isGeneratingSecondPassHelpText, optionsMetadata, argv }) { const vanillaYargsBuilderObject = {}; for (const [option, builderObjectValue] of Object.entries(builderObject)) { const [bfeBuilderObjectValue, vanillaYargsBuilderObjectValue] = separateExtensionsFromBuilderObjectValue({ builderObjectValue }); const { demandThisOption } = bfeBuilderObjectValue; const genericVanillaYargsBuilderObjectValue = vanillaYargsBuilderObjectValue; if (demandThisOption !== undefined) { genericVanillaYargsBuilderObjectValue.demandOption = demandThisOption; } if (bfeBuilderObjectValue.default !== undefined) { genericVanillaYargsBuilderObjectValue.default = bfeBuilderObjectValue.default; } if (genericVanillaYargsBuilderObjectValue.coerce !== undefined) { const coercer = genericVanillaYargsBuilderObjectValue.coerce; genericVanillaYargsBuilderObjectValue.coerce = parameter => { return coercer(vanillaYargsBuilderObjectValue.array ? [parameter].flat() : parameter); }; } if (deleteGroupProps) { delete vanillaYargsBuilderObjectValue.group; } vanillaYargsBuilderObject[option] = vanillaYargsBuilderObjectValue; } if (isGeneratingSecondPassHelpText) { hardAssert(optionsMetadata && argv, _error.BfeErrorMessage.GuruMeditation()); const canonicalArgv = deriveCanonicalArgv(optionsMetadata, argv); optionsMetadata.implied.forEach(({ [_symbols.$genesis]: implier, [_symbols.$canonical]: canonicalImplications }) => { hardAssert(implier !== undefined, _error.BfeErrorMessage.MetadataInvariantViolated('implies')); if (canonicalArgv.has(implier) && (optionsMetadata.implyVacuously.includes(implier) || canonicalArgv.get(implier) !== false)) { Object.entries(canonicalImplications).forEach(([impliedArg, impliedValue]) => { vanillaYargsBuilderObject[impliedArg].default = impliedValue; }); } }); } return vanillaYargsBuilderObject; } function analyzeBuilderObject({ builderObject, commonOptions, parserConfiguration }) { const metadata = { required: [], conflicted: [], implied: [], implyLoosely: [], implyVacuously: [], demandedIf: [], demanded: [], demandedAtLeastOne: [], demandedMutuallyExclusive: [], optional: [], defaults: {}, checks: {}, optionNames: new Set(), optionNamesAsSeenInArgv: {}, customGroups: {} }; for (const [option, builderObjectValue] of Object.entries(builderObject)) { const [{ requires, conflicts, check, default: default_, implies, looseImplications, vacuousImplications, demandThisOptionIf, demandThisOption, demandThisOptionOr, demandThisOptionXor }, { alias: optionAliases }] = separateExtensionsFromBuilderObjectValue({ builderObjectValue }); const allPossibleOptionNamesAndAliasesSet = expandOptionNameAndAliasesWithRespectToParserConfiguration({ option, aliases: optionAliases, parserConfiguration }); const conflictingNamesSet = metadata.optionNames.intersection(allPossibleOptionNamesAndAliasesSet); hardAssert(conflictingNamesSet.size === 0, _error.BfeErrorMessage.DuplicateOptionName(getFirstValueFromNonEmptySet(conflictingNamesSet))); metadata.optionNames = metadata.optionNames.union(allPossibleOptionNamesAndAliasesSet); allPossibleOptionNamesAndAliasesSet.forEach(expandedName => { metadata.optionNamesAsSeenInArgv[expandedName] = option; }); if (requires !== undefined) { const normalizedOption = validateAndFlattenExtensionValue(requires, builderObject, option); addToSet(metadata.required, { ...normalizedOption, [_symbols.$genesis]: option }); } if (conflicts !== undefined) { const normalizedOption = validateAndFlattenExtensionValue(conflicts, builderObject, option); addToSet(metadata.conflicted, { ...normalizedOption, [_symbols.$genesis]: option }); } if (check !== undefined) { metadata.checks[option] = check; } if (default_ !== undefined) { allPossibleOptionNamesAndAliasesSet.forEach(expandedName => { metadata.defaults[expandedName] = default_; }); } if (implies !== undefined) { const canonicalNormalizedImplications = validateAndFlattenExtensionValue(implies, builderObject, option); const expandedNormalizedImplications = {}; Object.entries(canonicalNormalizedImplications).forEach(([impliedOption, impliedValue]) => { const { alias: impliedOptionAliases } = builderObject[impliedOption]; expandOptionNameAndAliasesWithRespectToParserConfiguration({ option: impliedOption, aliases: impliedOptionAliases, parserConfiguration }).forEach(expandedName => { expandedNormalizedImplications[expandedName] = impliedValue; }); }); addToSet(metadata.implied, { ...expandedNormalizedImplications, [_symbols.$canonical]: canonicalNormalizedImplications, [_symbols.$genesis]: option }); } if (looseImplications) { metadata.implyLoosely.push(option); } if (vacuousImplications) { metadata.implyVacuously.push(option); } if (demandThisOption !== undefined) { metadata.demanded.push(option); } if (demandThisOptionIf !== undefined) { const normalizedOption = validateAndFlattenExtensionValue(demandThisOptionIf, builderObject, option); addToSet(metadata.demandedIf, { ...normalizedOption, [_symbols.$genesis]: option }); } if (demandThisOptionOr !== undefined) { const normalizedOption = validateAndFlattenExtensionValue(demandThisOptionOr, builderObject, option); addToSet(metadata.demandedAtLeastOne, { ...normalizedOption, [option]: _symbols.$exists }); } if (demandThisOptionXor !== undefined) { const normalizedOption = validateAndFlattenExtensionValue(demandThisOptionXor, builderObject, option); addToSet(metadata.demandedMutuallyExclusive, { ...normalizedOption, [option]: _symbols.$exists }); } } for (const [option, { group: groupOverride }] of Object.entries(builderObject)) { const isExplicitlyDemanded = !!(metadata.demanded.includes(option) || metadata.demandedAtLeastOne.some(record => option in record) || metadata.demandedMutuallyExclusive.some(record => option in record)); const hasExplicitGroupOverride = !!groupOverride; const commonOptionsIncludesOption = commonOptions.includes(option); if (hasExplicitGroupOverride) { (metadata.customGroups[groupOverride] ||= []).push(option); } else { if (!isExplicitlyDemanded && !commonOptionsIncludesOption) { metadata.optional.push(option); } } } return metadata; } function expandOptionNameAndAliasesWithRespectToParserConfiguration({ option, aliases, parserConfiguration }) { const { 'camel-case-expansion': camelCaseExpansion, 'strip-aliased': stripAliased, 'strip-dashed': stripDashed } = { 'camel-case-expansion': true, 'strip-aliased': false, 'strip-dashed': false, ...parserConfiguration }; const targetNames = [option, stripAliased ? [] : aliases ?? []].flat(); const expandedNamesSet = new Set(); targetNames.forEach(name => { if (camelCaseExpansion) { const camelCasedName = (0, _lodash.default)(name); if (camelCasedName !== name && (!stripDashed || !name.includes('-'))) { add(name); } add(camelCasedName); } else { add(name); } }); return expandedNamesSet; function add(name) { hardAssert(!expandedNamesSet.has(name), _error.BfeErrorMessage.DuplicateOptionName(name)); expandedNamesSet.add(name); } } function getParserConfigurationFromBlackFlagInstance(blackFlag) { hardAssert(typeof blackFlag.getInternalMethods === 'function', _error.BfeErrorMessage.UnexpectedValueFromInternalYargsMethod()); const yargsInternalMethods = blackFlag.getInternalMethods(); hardAssert(typeof yargsInternalMethods.getParserConfiguration === 'function', _error.BfeErrorMessage.UnexpectedValueFromInternalYargsMethod()); const parserConfiguration = yargsInternalMethods.getParserConfiguration(); hardAssert(parserConfiguration && typeof parserConfiguration === 'object', _error.BfeErrorMessage.UnexpectedValueFromInternalYargsMethod()); return parserConfiguration; } function separateExtensionsFromBuilderObjectValue({ builderObjectValue: builderObjectValue }) { const { check, conflicts, default: default_, demandThisOption, demandThisOptionIf, demandThisOptionOr, demandThisOptionXor, implies, looseImplications, vacuousImplications, requires, subOptionOf, ...vanillaYargsConfig } = builderObjectValue; const bfeConfig = { check, conflicts, demandThisOption, demandThisOptionIf, demandThisOptionOr, demandThisOptionXor, implies, looseImplications, vacuousImplications, requires, subOptionOf }; hardAssert(!('default' in builderObjectValue) || default_ !== undefined, _error.BfeErrorMessage.GuruMeditation()); return [{ ...bfeConfig, default: default_, coerce: undefined }, vanillaYargsConfig]; } function validateAndFlattenExtensionValue(extendedOption, builderObject, optionName) { const mergedConfig = {}; if (Array.isArray(extendedOption)) { extendedOption.forEach(option => { mergeInto(option); }); } else { mergeInto(extendedOption); } Object.keys(mergedConfig).forEach(referredOptionName => { hardAssert(referredOptionName in builderObject, _error.BfeErrorMessage.ReferencedNonExistentOption(optionName, referredOptionName)); }); return mergedConfig; function mergeInto(option) { if (typeof option === 'string') { mergedConfig[option] = _symbols.$exists; } else { Object.assign(mergedConfig, option); } } } function deriveCanonicalArgv(optionsMetadata, argv) { const canonicalArgv = new Map(); Object.entries(optionsMetadata.optionNamesAsSeenInArgv).forEach(([maybeNameInRealArgv, canonicalName]) => { const valueInRealArgv = argv[maybeNameInRealArgv]; if (valueInRealArgv !== undefined) { canonicalArgv.set(canonicalName, valueInRealArgv); } }); return canonicalArgv; } function addToSet(arrayAsSet, element) { const hasElement = arrayAsSet.find(item => (0, _nodeUtil.isDeepStrictEqual)(item, element)); if (!hasElement) { arrayAsSet.push(element); } } function defaultHandler() { throw new _util.CommandNotImplementedError(); } function getFirstValueFromNonEmptySet(set) { return set.values().next().value; } function softAssert(valueOrMessage, message) { let shouldThrow = true; if (typeof message === 'string') { const value = valueOrMessage; shouldThrow = !value; } else { message = String(valueOrMessage); } if (shouldThrow) { throw new _core.CliError(message, { suggestedExitCode: _core.FrameworkExitCode.DefaultError }); } } function hardAssert(valueOrMessage, message) { let shouldThrow = true; if (typeof message === 'string') { const value = valueOrMessage; shouldThrow = !value; } else { message = String(valueOrMessage); } if (shouldThrow) { throw new _core.CliError(_error.BfeErrorMessage.FrameworkError(message), { suggestedExitCode: _core.FrameworkExitCode.AssertionFailed }); } }