Files
directus/packages/cli/src/core/output.ts
WoLfulus d8caf221ed CLI 2.0 (#5376)
* merge components

merge args, parser, docs, formatter, help and handlers

* change directus command and add auto debug

* output format fixes

* adds back some reformatted and documented commands

* better help output format

* refactor all output flow

* export cli types

* more formatting fixes and param rework

* fix table spacing

* add yaml formatting and fix string colors

* finished formatting docs

* remove log

* remove package-lock

* update dependency versions

* fix command description

* workaround typescript loading

* module loading fixes
added command error
rename human to table
fix disconnect usage

* add typescript loader

redirect execution to local package if installed locally
added command alias `directus-ctl`

* fix module load directories

* reimplement stdin pipe to work on linux

* fix sdk server info type

* info command

* Fix stdin bug
Disable community extensions to discourage use for now
Added template to config files
Added password stdin to connect to instances
Fixed typescript command load

* Added command suggestions and QOL features

* Linter fixes

* Add command hints

* Separate positional options

* Add back delete many, fix delete one location

* Change score logic

* Add whoami util command

* Add short online docs

* Fix typo

* Fix typo

* Update commands

* Param consistency fix and docs update

* Create commands

* Update package.json version

* Update package-lock

* Fixed several linting problems

* Update dependencies

* Update lock

* Remove locked dependencies

* Stop conflicts when in home directory

* Package lock update and npm audit fix

* Fix formatting errors

* Comment out extending cli section until we figure out cli ext

* Update readme

* Tweak dev/build/prebuild script naming

* Use up to date deps

* Fix dependency version in lock (fix build)

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
2021-05-12 20:38:30 +00:00

121 lines
3.0 KiB
TypeScript

import { defaults } from './utils';
import { Argv } from 'yargs';
import { IOptions } from '../options';
import { IOutput, IUIComposer, IOutputFormat } from '../output';
import { TableOutputFormat } from './output/formats/table';
import { UIBuilder } from './output/ui';
import { CLIError, CLIRuntimeError } from './exceptions';
import { CommandHelp, GeneralHelp } from '../help';
import { WriteStream } from 'fs';
export type OutputOptions = {
format: string;
};
export class Output implements IOutput {
private options: IOptions;
private formats: {
table: IOutputFormat;
[name: string]: IOutputFormat;
};
private _text: string[];
private _help?: GeneralHelp | CommandHelp;
private _value?: any;
private _errors: CLIError[];
constructor(options: IOptions) {
this.formats = {
table: new TableOutputFormat(),
};
this._text = [];
this._errors = [];
this.options = options;
this.options.feature('output', (builder: Argv, _, raw) => {
builder.option('format', {
description: 'The output format',
default: 'table',
choices: [...Object.keys(this.formats)],
});
const explicitFormat = raw.format ?? 'table';
Object.entries(this.formats).forEach(([name, format]) => {
if (name === explicitFormat) {
format.registerOptions(builder);
}
});
if (explicitFormat != 'table' && !(explicitFormat in this.formats)) {
this.formats['table']!.registerOptions(builder);
throw new CLIRuntimeError(`Unknown output format: ${explicitFormat}`);
}
});
}
async help(help: GeneralHelp | CommandHelp): Promise<void> {
this._help = help;
}
async text(text: string): Promise<void> {
this._text.push(text);
}
async value<T>(value: T): Promise<void> {
this._value = value;
}
async error(err: CLIError): Promise<void> {
this._errors.push({
code: err.code,
name: err.name,
message: err.message,
stack: err.stack,
});
}
async flush(stream: WriteStream): Promise<void> {
stream.write(
await this.getFormatter().format(
{
value: {
result: this._value,
help: this._help,
errors: this._errors.length > 0 ? this._errors : undefined,
},
help: this._help,
text: this._text,
errors: this._errors,
},
this.getOptions()
)
);
this._help = undefined;
this._value = undefined;
this._errors = [];
this._text = [];
}
registerFormat(name: string, format: IOutputFormat): void {
this.formats[name] = format;
}
async compose(builder: (builder: IUIComposer) => Promise<void>): Promise<void> {
const outputBuilder = new UIBuilder();
await builder(outputBuilder);
await this.text(await outputBuilder.get());
}
getFormatter(): IOutputFormat {
const { format } = this.getOptions();
return this.formats[format] ?? this.formats['table']!;
}
getOptions(options?: Partial<OutputOptions>): OutputOptions {
const opts = this.options.values() as OutputOptions & { [k: string]: any };
return defaults(options, {
...opts,
format: (opts.format as any) ?? 'table',
}) as OutputOptions;
}
}