UNPKG

@deepkit/app

Version:

Deepkit App, CLI framework and service container

668 lines 29.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.__ΩCommandWriter = exports.__ΩParsedCliControllerConfig = exports.__ΩCommand = exports.cli = exports.__ΩFlag = void 0; exports.isCommand = isCommand; exports.getBinFromEnvironment = getBinFromEnvironment; exports.getArgsFromEnvironment = getArgsFromEnvironment; exports.parseCliArgs = parseCliArgs; exports.parseControllerConfig = parseControllerConfig; exports.executeCommand = executeCommand; exports.runCommand = runCommand; /*@ts-ignore*/ const { __ΩClassType } = require('@deepkit/core'); /*@ts-ignore*/ const { __ΩTypeParameter } = require('@deepkit/type'); /*@ts-ignore*/ const { __ΩTypeProperty } = require('@deepkit/type'); /*@ts-ignore*/ const { __ΩTypePropertySignature } = require('@deepkit/type'); /*@ts-ignore*/ const { __ΩLoggerInterface } = require('@deepkit/logger'); /*@ts-ignore*/ const { __ΩTypeAnnotation } = require('@deepkit/core'); function __assignType(fn, args) { fn.__type = args; return fn; } /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ const core_1 = require("@deepkit/core"); const type_1 = require("@deepkit/type"); const event_1 = require("@deepkit/event"); const injector_1 = require("@deepkit/injector"); const app_js_1 = require("./app.js"); const stopwatch_1 = require("@deepkit/stopwatch"); const __ΩFlag = ['Options', () => __ΩTypeAnnotation, "cli:flag", 'Flag', 'PMc!.#e!!o"#w$y']; exports.__ΩFlag = __ΩFlag; class CommandDecoratorDefinition { constructor() { this.name = ''; this.description = ''; } } CommandDecoratorDefinition.__type = ['name', function () { return ''; }, 'description', function () { return ''; }, 'CommandDecoratorDefinition', '&3!>"&3#>$5w%']; class CommandDecorator { constructor() { this.t = new CommandDecoratorDefinition; } controller(name, options) { this.t.name = name; if (options) { if (options.description) this.t.description = options.description; } } } CommandDecorator.__type = ['t', function () { return new CommandDecoratorDefinition; }, 'name', 'description', 'options', 'controller', 'CommandDecorator', '!3!>"P&2#P&4$8M2%8"0&5w\'']; exports.cli = (0, type_1.createClassDecoratorContext)(CommandDecorator); const __ΩCommand = ['args', 'execute', 'Command', 'PP"@2!PP\'$J`\'$J1"Mw#y']; exports.__ΩCommand = __ΩCommand; function isCommand(classType) { return !!exports.cli._fetch(classType); } isCommand.__type = [() => __ΩClassType, () => __ΩCommand, 'classType', 'isCommand', 'Pn"o!"2#"/$']; function convert(parameter, value) { if (value === undefined) { if (parameter.optional) return undefined; throw new Error(`Value is required`); } if (parameter.type.kind === type_1.ReflectionKind.array && !Array.isArray(value)) { value = [value]; } value = (0, type_1.deserialize)(value, undefined, undefined, undefined, parameter.type); const errors = (0, type_1.validate)(value, parameter.type); if (errors.length) { throw errors[0]; } return value; } convert.__type = [() => __ΩCommandParameter, 'parameter', 'value', 'convert', 'Pn!2""2#"/$']; /** * Auto-detect some types as flag. */ function isFlagForced(type) { if (supportedAsArgument(type)) return false; return type.kind === type_1.ReflectionKind.boolean; } isFlagForced.__type = ['Type', 'type', 'isFlagForced', 'P"w!2")/#']; function supportedFlags(type) { return supportedAsArgument(type) || isFlagForced(type); } supportedFlags.__type = ['Type', 'type', 'supportedFlags', 'P"w!2")/#']; function supportedAsArgument(type) { if (type.kind === type_1.ReflectionKind.string || type.kind === type_1.ReflectionKind.number || type.kind === type_1.ReflectionKind.any || type.kind === type_1.ReflectionKind.unknown || (0, type_1.isDateType)(type) || type.kind === type_1.ReflectionKind.bigint || type.kind === type_1.ReflectionKind.literal) return true; if (type.kind === type_1.ReflectionKind.union) return type.types.every(__assignType(v => supportedAsArgument(v), ['v', '', 'P"2!"/"'])); if (type.kind === type_1.ReflectionKind.array) return supportedAsArgument(type.type); if ((0, type_1.isReferenceType)(type)) return true; return false; } supportedAsArgument.__type = ['Type', 'type', 'supportedAsArgument', 'P"w!2")/#']; function getBinFromEnvironment() { if ('undefined' !== typeof process && process.argv) { return process.argv.slice(0, 2); } if ('undefined' !== typeof Deno && Deno.args) { return ['deno', 'run', Deno.main?.filename || '']; } if ('undefined' !== typeof Bun && Bun.argv) { return Bun.argv.slice(0, 2); } return []; } getBinFromEnvironment.__type = ['getBinFromEnvironment', 'P&F/!']; function getArgsFromEnvironment() { if ('undefined' !== typeof process && process.argv) { return process.argv.slice(2); } if ('undefined' !== typeof Deno && Deno.args) { return Deno.args; } if ('undefined' !== typeof Bun && Bun.argv) { return Bun.argv.slice(2); } return []; } getArgsFromEnvironment.__type = ['getArgsFromEnvironment', 'P&F/!']; function parseCliArgs(args, aliases = {}) { const result = {}; let current = undefined; function append(name, value) { name = aliases[name] || name; const existing = result[name]; if ('string' === typeof existing) { result[name] = [existing]; } if (Array.isArray(result[name])) { result[name].push(value); } else { result[name] = value; } } append.__type = ['name', 'value', 'append', 'P&2!P&)J2""/#']; for (const arg of args) { if (arg.startsWith('--')) { if (current) { append(current, true); } current = arg.substr(2); if (current.includes(' ')) { const [name, value] = current.split(' '); append(name, value); current = undefined; } } else if (arg.startsWith('-')) { if (current) { append(current, true); } current = arg.substr(1); } else { if (current) { append(current, arg); } else { //no current flag, so it's a positional argument if (!result['@']) result['@'] = []; result['@'].push(arg); } current = undefined; } } if (current) { result[current] = true; } return result; } parseCliArgs.__type = ['args', 'aliases', () => ({}), 'parseCliArgs', 'P&F2!P&&LM2">#P&P)&&FJLM/$']; /** * Returns the longest string length of all names. */ function getSpacing(names) { return names.reduce(__assignType((max, name) => Math.max(max, name.length), ['max', 'name', '', 'P"2!"2""/#']), 0) + 1; } getSpacing.__type = ['names', 'getSpacing', 'P&F2!\'/"']; const __ΩParsedCliControllerConfig = [() => __ΩClassType, 'controller', () => Function, 'callback', 'description', 'name', () => injector_1.InjectorModule, 'module', 'ParsedCliControllerConfig', 'Pn!4"8Pu#4$8&4%8&4&P7\'4(Mw)y']; exports.__ΩParsedCliControllerConfig = __ΩParsedCliControllerConfig; /** * Tries to create a command name from a class name or function name. * //test => test * //testCommand => test-command * //TestCommand => test-command * //Test => test * //TestSomething => test-something * //system_crazyCommand => system:crazy-command * //system_crazy => system:crazy * //system_crazyCommandSomething => system:crazy-command-something * //system_subSystem_test => system:sub-system:test */ function commandNameFromSymbol(symbolName) { return symbolName.replace(/_+/g, ':') .replace(/([A-Z])/g, '-$1').replace(/^-/, '').toLowerCase() .replace(/-command$/, '').replace(/-controller/, '-'); } commandNameFromSymbol.__type = ['symbolName', 'commandNameFromSymbol', 'P&2!"/"']; function parseControllerConfig(config) { let name = config.name || ''; let description = ''; if (!name && config.controller) { name = commandNameFromSymbol((0, core_1.getClassName)(config.controller)); } else if (!name && config.callback) { name = commandNameFromSymbol(config.callback.name); } const decoratorConfig = config.controller ? exports.cli._fetch(config.controller) : undefined; if (decoratorConfig) { if (decoratorConfig.description) description = decoratorConfig.description; if (decoratorConfig.name) name = decoratorConfig.name; } if (!description) { const type = (0, type_1.reflect)(config.controller || config.callback); if (type.kind === type_1.ReflectionKind.function && type.description) description = type.description || ''; if (type.kind === type_1.ReflectionKind.class && type.description) description = type.description || ''; } return { controller: config.controller, callback: config.callback, description, name, module: config.module }; } parseControllerConfig.__type = ['ControllerConfig', 'config', () => __ΩParsedCliControllerConfig, 'parseControllerConfig', 'P"w!2"n#/$']; function printTopics(script, forTopic, commands, writer) { writer('<yellow>USAGE</yellow>'); writer(` $ ${script} ${forTopic ? forTopic + ':' : ''}[COMMAND]`); writer(''); writer('<yellow>COMMANDS</yellow>'); const descriptionSpacing = getSpacing(commands.map(__assignType(cmd => cmd.name, ['cmd', '', 'P"2!"/"']))); let lastTopic = ''; for (const cmd of commands) { const topic = cmd.name.lastIndexOf(':') ? cmd.name.substr(0, cmd.name.lastIndexOf(':')) : ''; if (lastTopic !== topic) { lastTopic = topic; writer(topic); } if (cmd.description) { const nameWithSpacing = `<green>${cmd.name}</green>` + ' '.repeat(descriptionSpacing - cmd.name.length); writer(' ' + nameWithSpacing + ' ' + cmd.description); } else { writer(` <green>${cmd.name}</green>`); } } writer(''); writer(`For more information on a specific command or topic, type '[command/topic] --help'`); } printTopics.__type = ['script', 'forTopic', () => __ΩParsedCliControllerConfig, 'commands', () => __ΩCommandWriter, 'writer', 'printTopics', 'P&2!&2"n#F2$n%2&"/\'']; function getParamFlags(parameter) { const flags = []; if (!parameter.optional) flags.push('required'); if (parameter.type.kind === type_1.ReflectionKind.array) { flags.push('multiple'); } if (parameter.defaultValue !== undefined) flags.push('default=' + parameter.defaultValue); return flags.length ? `[${flags.join(', ')}]` : ''; } getParamFlags.__type = [() => __ΩCommandParameter, 'parameter', 'getParamFlags', 'Pn!2"&/#']; function getParamIdentifier(parameter) { const elementType = parameter.type.kind === type_1.ReflectionKind.array ? parameter.type.type : parameter.type; if (parameter.kind === 'flag' || parameter.kind === 'flag-property') { let name = `--${parameter.name}`; if (parameter.char) name = `-${parameter.char}, ${name}`; if (parameter.type.kind === type_1.ReflectionKind.boolean) { return `<green>${name}</green>`; } let type = (0, type_1.isReferenceType)(elementType) ? (0, type_1.stringifyType)(type_1.ReflectionClass.from(elementType).getPrimary().type) : (0, type_1.stringifyType)(elementType); return `<green>${name} ${type}</green>`; } return `<green>${parameter.name}</green>`; } getParamIdentifier.__type = [() => __ΩCommandParameter, 'parameter', 'getParamIdentifier', 'Pn!2"&/#']; function printHelp(script, command, writer) { const commandParameters = collectCommandParameter(command); const args = commandParameters.filter(__assignType(v => v.kind === 'argument', ['v', '', 'P"2!"/"'])); writer(`<yellow>Usage:</yellow> ${script} ${command.name} [OPTIONS] ${args.map(__assignType(v => `[${v.name}]`, ['v', '', 'P"2!"/"'])).join(' ')}`); writer(''); if (command.description) { writer(`${command.description || ''}`); writer(''); } if (args.length) { writer('<yellow>Arguments:</yellow>'); for (const parameter of args) { writer(` ${parameter.name}</green>\t${parameter.description || ''}<yellow>${getParamFlags(parameter)}</yellow>`); } } writer('<yellow>Options:</yellow>'); const descriptionSpacing = getSpacing(commandParameters.map(getParamIdentifier)); for (const parameter of commandParameters) { if (parameter.kind === 'argument' || parameter.kind === 'service') continue; if (parameter.hidden) continue; const label = getParamIdentifier(parameter); const nameWithSpacing = label + ' '.repeat(descriptionSpacing - label.length); writer(` ${nameWithSpacing}${parameter.description || ''}<yellow>${getParamFlags(parameter)}</yellow>`); } } printHelp.__type = ['script', () => __ΩParsedCliControllerConfig, 'command', () => __ΩCommandWriter, 'writer', 'printHelp', 'P&2!n"2#n$2%"/&']; const __ΩCommandWriter = ['message', '', 'CommandWriter', 'P"@2!$/"w#y']; exports.__ΩCommandWriter = __ΩCommandWriter; const __ΩParameterMeta = ['flag', 'char', 'hidden', 'description', 'prefix', 'ParameterMeta', 'P)4!&4")4#&4$&4%8Mw&y']; function getParameterMeta(parameter) { const metaFlag = type_1.typeAnnotation.getOption(parameter.type, 'cli:flag'); const flagOptions = metaFlag || {}; return { flag: !!metaFlag, char: flagOptions.char || '', hidden: flagOptions.hidden === true, prefix: flagOptions.prefix, description: flagOptions.description || '', }; } getParameterMeta.__type = [() => __ΩTypeParameter, () => __ΩTypeProperty, () => __ΩTypePropertySignature, 'parameter', () => __ΩParameterMeta, 'getParameterMeta', 'PPn!n"n#J2$n%/&']; /** * bin: the binary name, e.g. ['node', 'app.ts'] * argv: the arguments, e.g. ['command', '--help'] * writer: a function used to write the output. Defaults to console.log. */ async function executeCommand(script, argv, eventDispatcher, logger, injector, commandsConfigs, writer) { let commands = commandsConfigs.map(__assignType(v => parseControllerConfig(v), ['v', '', 'P"2!"/"'])); if (!writer) { writer = __assignType((...message) => logger.log(...message), ['message', '', 'P&@2!"/"']); } const help = argv.some(__assignType(v => v === '--help', ['v', '', 'P"2!"/"'])) || argv[0] === 'help'; const first = argv[0] === 'help' || argv[0] === '--help' ? '' : argv[0]; const command = commands.find(__assignType(cmd => cmd.name === first, ['cmd', '', 'P"2!"/"'])); if (argv.length === 0 || (argv.length === 1) || help) { const topicPrefix = argv.length === 1 && first ? first + ':' : ''; if (command && help) { printHelp(script, command, writer); return 0; } else if (!command) { //print topics commands = commands.filter(__assignType(cmd => cmd.name?.startsWith(topicPrefix), ['cmd', '', 'P"2!"/"'])); //sort so that the ones without topics ( no ':' ) are first, then by name commands.sort(__assignType((a, b) => { if (a.name?.includes(':') && !b.name?.includes(':')) return 1; if (!a.name?.includes(':') && b.name?.includes(':')) return -1; return a.name?.localeCompare(b.name || '') || 0; }, ['a', 'b', '', 'P"2!"2""/#'])); printTopics(script, topicPrefix.slice(0, -1), commands, writer); return 0; } } if (!command) { writer(`Command "${first}" not found.`); return 1; } try { return await runCommand(command, argv.slice(1), injector, eventDispatcher, logger); } catch (e) { writer(`The command "${command.name}" failed.`); writer(e); return 1; } } executeCommand.__type = ['script', 'argv', () => event_1.EventDispatcher, 'eventDispatcher', () => __ΩLoggerInterface, 'logger', () => injector_1.InjectorContext, 'injector', 'ControllerConfig', 'commandsConfigs', () => __ΩCommandWriter, 'writer', 'executeCommand', 'P&2!&F2"P7#2$n%2&P7\'2("w)F2*n+2,8\'`/-']; function handleConvertError(logger, parameter, value, error) { let group = parameter.kind === 'argument' ? 'argument' : 'property'; let name = getActualCliParameterName(parameter); if (parameter.kind === 'flag' || parameter.kind === 'flag-property') { name = '--' + name; group = 'option'; } if (error instanceof type_1.ValidationError) { logger.log(`<red>Invalid value for ${group} ${name}: ${value}.</red> ${error.errors[0].message} [${error.errors[0].code}]`); return; } logger.log(`<red>Invalid value for ${group} ${name}: ${value}.</red> ${String(error.message)}`); } handleConvertError.__type = [() => __ΩLoggerInterface, 'logger', () => __ΩCommandParameter, 'parameter', 'value', 'error', 'handleConvertError', 'Pn!2"n#2$"2%"2&"/\'']; const __ΩCommandParameter = ['name', 'char', 'hidden', 'flag', 'optional', 'description', "argument", "flag", "flag-property", "service", 'kind', 'defaultValue', 'Type', 'type', 'prefix', 'collectInto', 'CommandParameter', 'P&4!&4")4#)4$)4%&4&P.\'.(.).*J4+"4,8"w-4.&4/&408Mw1y']; function collectCommandParameter(config) { const parameters = config.callback ? type_1.ReflectionFunction.from(config.callback).getParameters() : config.controller ? type_1.ReflectionClass.from(config.controller).getMethod('execute').getParameters() : []; const result = []; let objectLiterals = 0; for (const reflection of parameters) { if (reflection.parameter.type.kind === type_1.ReflectionKind.objectLiteral || reflection.parameter.type.kind === type_1.ReflectionKind.class) { objectLiterals++; } } const names = (Set.Ω = [['&']], new Set()); function add(parameter, prefixIn, collectInto, forceFlag) { const meta = getParameterMeta(parameter); const injectToken = (0, injector_1.getInjectOptions)(parameter.type); const isSimple = supportedAsArgument(parameter.type); const char = meta.char || ''; const hidden = meta.hidden || false; const prefix = prefixIn || meta.prefix || ''; const optional = (0, type_1.isOptional)(parameter) || (0, type_1.hasDefaultValue)(parameter); const description = meta.description || parameter.description || ''; const name = String(parameter.name); let defaultValue = undefined; try { defaultValue = parameter.kind === type_1.ReflectionKind.property || parameter.kind === type_1.ReflectionKind.parameter ? parameter.default?.() : undefined; } catch { } if (forceFlag || (meta.flag || isFlagForced(parameter.type)) && !injectToken) { // check if parameter.type is an object, e.g. { name: string, age: number } // split it into multiple flags, e.g. --name --age if (parameter.type.kind === type_1.ReflectionKind.objectLiteral || (0, type_1.isCustomTypeClass)(parameter.type)) { if ((0, type_1.isReferenceType)(parameter.type)) { result.push({ name, defaultValue, char, hidden, optional, description, prefix, collectInto, kind: 'flag', flag: true, type: parameter.type, }); return; } for (const property of parameter.type.types) { if (property.kind !== type_1.ReflectionKind.property && property.kind !== type_1.ReflectionKind.propertySignature) continue; if (!supportedFlags(property.type)) continue; const subName = String(property.name); if (names.has(prefix + '.' + subName)) { throw new Error(`Duplicate CLI argument/flag name ${subName} in object literal. Try setting a prefix via ${name}: ${(0, type_1.stringifyType)(parameter.type)} & Flag<{prefix: '${name}'}> `); } names.add(prefix + '.' + subName); add(property, prefix, name, true); } } else { names.add(name); result.push({ name, defaultValue, char, hidden, optional, description, prefix, collectInto, kind: 'flag', flag: true, type: parameter.type, }); } } else { names.add(name); //it's either a simple string|number positional argument or a service if (isSimple && !injectToken) { result.push({ name, defaultValue, flag: false, char, optional, description, hidden, collectInto, prefix, kind: 'argument', type: parameter.type, }); } else { result.push({ name, defaultValue, flag: false, char, optional, description, hidden, collectInto, prefix, kind: 'service', type: parameter.type, }); } } } add.__type = [() => __ΩTypeParameter, () => __ΩTypeProperty, () => __ΩTypePropertySignature, 'parameter', 'prefixIn', 'collectInto', 'forceFlag', 'add', 'PPn!n"n#J2$&2%&2&8)2\'8"/(']; for (const reflection of parameters) { add(reflection.parameter, ''); } if (config.controller) { const classSchema = type_1.ReflectionClass.from(config.controller); for (const reflection of classSchema.getProperties()) { const meta = getParameterMeta(reflection.property); const optional = reflection.isOptional() || reflection.hasDefault(); const description = meta.description || reflection.property.description || ''; if (!meta.flag) continue; result.push({ name: reflection.name, hidden: meta.hidden || false, prefix: meta.prefix || '', char: meta.char || '', kind: 'flag-property', flag: true, description, optional, type: reflection.property.type, }); } } return result; } collectCommandParameter.__type = [() => __ΩParsedCliControllerConfig, 'config', 'collectCommandParameter', 'Pn!2""/#']; function getActualCliParameterName(parameter) { return parameter.prefix ? parameter.prefix + '.' + parameter.name : parameter.name; } getActualCliParameterName.__type = ['prefix', 'name', 'parameter', 'getActualCliParameterName', 'PP&4!&4"M2#"/$']; async function runCommand(config, argv, injector, eventDispatcher, logger) { const parameters = config.callback ? type_1.ReflectionFunction.from(config.callback).getParameters() : config.controller ? type_1.ReflectionClass.from(config.controller).getMethod('execute').getParameters() : []; const stopwatch = injector.get(stopwatch_1.Stopwatch); const aliases = {}; const parameterValues = {}; for (const parameter of parameters) { const meta = getParameterMeta(parameter.parameter); if (meta.char) { aliases[meta.char] = parameter.name; } } const parsedArgs = parseCliArgs(argv, aliases); const args = []; let positionalIndex = 0; const positionalArguments = Array.isArray(parsedArgs['@']) ? parsedArgs['@'] : []; const commandParameters = collectCommandParameter(config); for (const parameter of commandParameters) { if (parameter.kind === 'service') { const injectToken = (0, injector_1.getInjectOptions)(parameter.type); try { args.push(injector.get(injectToken || parameter.type)); } catch (error) { if (parameter.optional && error instanceof injector_1.ServiceNotFoundError) { continue; } handleConvertError(logger, parameter, parsedArgs[parameter.name], error); return 1; } continue; } const id = getActualCliParameterName(parameter); let raw = parsedArgs[id]; if (parameter.kind === 'argument') { raw = positionalArguments[positionalIndex]; positionalIndex++; } try { const v = convert(parameter, raw) ?? parameter.defaultValue; if (parameter.collectInto) { if (!parameterValues[parameter.collectInto]) { parameterValues[parameter.collectInto] = {}; if (parameter.kind !== 'flag-property') { args.push(parameterValues[parameter.collectInto]); } } if (v !== undefined) { // Important to not have undefined properties in the object parameterValues[parameter.collectInto][parameter.name] = v; } } else { parameterValues[parameter.name] = v; if (parameter.kind !== 'flag-property') { args.push(v); } } } catch (error) { handleConvertError(logger, parameter, raw, error); return 1; } } const label = config.controller ? (0, core_1.getClassName)(config.controller) : config.callback ? config.callback.name : ''; await eventDispatcher.dispatch(app_js_1.onAppExecute, { command: config.name, parameters: parameterValues, injector }); const frame = stopwatch.active ? stopwatch.start(config.name + '(' + label + ')', stopwatch_1.FrameCategory.cli, true) : undefined; let exitCode = 1; try { //property injection possible, too if (config.controller) { const instance = injector.get(config.controller, config.module); for (const parameter of commandParameters) { if (parameter.kind !== 'flag-property') continue; instance[parameter.name] = parameterValues[parameter.name]; } if (frame) { exitCode = await frame.run(() => instance.execute(...args)); } else { exitCode = await instance.execute(...args); } } else if (config.callback) { if (frame) { exitCode = await frame.run(() => config.callback(...args)); } else { exitCode = await config.callback(...args); } } exitCode = 'number' === typeof exitCode ? exitCode : 0; await eventDispatcher.dispatch(app_js_1.onAppExecuted, { exitCode, command: config.name, parameters: parameterValues, injector, }); return exitCode; } catch (error) { await eventDispatcher.dispatch(app_js_1.onAppError, { command: config.name, parameters: parameterValues, injector, error: error instanceof Error ? error : new Error(String(error)), }); throw error; } finally { if (frame) frame.end(); await eventDispatcher.dispatch(app_js_1.onAppShutdown, { command: config.name, parameters: parameterValues, injector }); } } runCommand.__type = [() => __ΩParsedCliControllerConfig, 'config', 'argv', () => injector_1.InjectorContext, 'injector', () => event_1.EventDispatcher, 'eventDispatcher', () => __ΩLoggerInterface, 'logger', 'runCommand', 'Pn!2"&F2#P7$2%P7&2\'n(2)"`/*']; //# sourceMappingURL=command.js.map