mirror of
https://github.com/directus/directus.git
synced 2026-02-01 15:34:57 -05:00
* 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>
226 lines
6.0 KiB
TypeScript
226 lines
6.0 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
// @ts-ignore
|
|
import amp = require('app-module-path');
|
|
amp.addPath(`${__dirname}/../node_modules`);
|
|
amp.addPath(`${process.cwd()}/node_modules`);
|
|
amp.addPath(process.cwd());
|
|
|
|
import { build } from 'gluegun';
|
|
import { command } from './core/command';
|
|
import { Toolbox } from './toolbox';
|
|
import { CommandResult } from './command';
|
|
import { CLIRuntimeError } from './core/exceptions';
|
|
|
|
export { command } from './core/command';
|
|
export type { Toolbox } from './toolbox';
|
|
|
|
import * as config from './core/extensions/config';
|
|
import { Output } from './core/output';
|
|
import { Options } from './core/options';
|
|
import { Events } from './core/events';
|
|
|
|
export * from './command';
|
|
export * from './config';
|
|
export * from './events';
|
|
export * from './help';
|
|
export * from './options';
|
|
export * from './output';
|
|
export * from './toolbox';
|
|
|
|
function hasTsNode(): boolean {
|
|
try {
|
|
if ((process as any)[Symbol.for('ts-node.register.instance')]) {
|
|
return true;
|
|
}
|
|
} catch {
|
|
//
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export default async function <T extends any>(argv: string[]): Promise<CommandResult<T>> {
|
|
// create a runtime
|
|
const brand = 'directusctl';
|
|
const runtime = build(brand)
|
|
.exclude([
|
|
'meta',
|
|
'strings',
|
|
'print',
|
|
'filesystem',
|
|
'semver',
|
|
'system',
|
|
'prompt',
|
|
'http',
|
|
'template',
|
|
'patching',
|
|
'package-manager',
|
|
])
|
|
.create();
|
|
|
|
const events = new Events();
|
|
const options = new Options(events, process.argv);
|
|
const output = new Output(options);
|
|
|
|
let extensionsPath = process.env.EXTENSIONS_PATH ?? './extensions';
|
|
|
|
if (config.project.data.experimental?.cli?.typescript?.enabled) {
|
|
const project = config.project.data.experimental?.cli?.typescript.tsconfig || './tsconfig.json';
|
|
if (fs.existsSync(project)) {
|
|
if (!hasTsNode()) {
|
|
if (!fs.existsSync('./node_modules/ts-node')) {
|
|
const error = new CLIRuntimeError(`
|
|
You're using experimental typescript support on the cli, but we couldn't find "ts-node" package installed.
|
|
Please make sure to install it before proceeding.
|
|
`);
|
|
await output.error(error);
|
|
return {
|
|
output,
|
|
error,
|
|
};
|
|
}
|
|
|
|
require('ts-node').register({
|
|
project: path.resolve(project),
|
|
});
|
|
}
|
|
} else {
|
|
throw new CLIRuntimeError(`
|
|
You're using experimental typescript support on the cli, but we couldn't find the typescript project file.
|
|
Please make sure to configure it properly. The current value is "${project}"
|
|
`);
|
|
}
|
|
|
|
extensionsPath = path.resolve(config.project.data.experimental?.cli?.typescript?.source || extensionsPath);
|
|
}
|
|
|
|
const loading = {
|
|
state: false,
|
|
};
|
|
|
|
// Workaround stupid bug in gluegun
|
|
// @ts-ignore
|
|
const list = require('fs-jetpack/lib/list');
|
|
const shimmer = require('shimmer');
|
|
shimmer.wrap(list, 'sync', (original: (...args: any[]) => any) => {
|
|
return function (this: any, ...args: any[]) {
|
|
const result = original.apply(this, args) as string[];
|
|
if (!loading.state) {
|
|
return result;
|
|
}
|
|
|
|
const folder = args[0] as string;
|
|
|
|
const ts = hasTsNode();
|
|
const files = result.filter((file: string) => {
|
|
if (fs.statSync(path.join(folder, file)).isDirectory()) {
|
|
return true;
|
|
}
|
|
|
|
if (!ts) {
|
|
return file.endsWith('.js');
|
|
}
|
|
|
|
if (file.endsWith('.ts')) {
|
|
if (file.endsWith('.d.ts')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (file.endsWith('.js')) {
|
|
// only allow .js if there's no matching .ts
|
|
return result.indexOf(`${file.substr(0, file.length - 3)}.ts`) < 0;
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
return files;
|
|
};
|
|
});
|
|
|
|
loading.state = true;
|
|
|
|
// no exclusions
|
|
runtime.addDefaultPlugin(path.join(__dirname, 'cli'), {
|
|
name: 'directus',
|
|
hidden: false,
|
|
});
|
|
|
|
runtime.addPlugin('./node_modules/directus/dist/cli/new', {
|
|
name: 'directus-server',
|
|
hidden: false,
|
|
required: false,
|
|
});
|
|
|
|
const extensions = ['config', 'events', 'options', 'output', 'query', 'stdin', 'instances', 'help'];
|
|
extensions.forEach((extension) =>
|
|
runtime.addExtension(extension, require(path.join(__dirname, `core/extensions/${extension}`)))
|
|
);
|
|
|
|
if (config.project.data.experimental?.cli?.community_extensions) {
|
|
// This isn't decided yet, please don't publish packages to npm until we have decided
|
|
// if we'll have a naming pattern and what it's going to be.
|
|
// TODO: Disabled to discourage usage/tests until final release and decision regarding this
|
|
// runtime.addPlugins('./node_modules', { matching: 'directus-cli-*', hidden: false });
|
|
// runtime.addPlugins('./node_modules', { matching: 'directus-*-cli', hidden: false });
|
|
// runtime.addPlugins('./node_modules', { matching: '@directus/*-cli', hidden: false });
|
|
// runtime.addPlugins('./node_modules', { matching: '@directus/cli-*', hidden: false });
|
|
}
|
|
|
|
const cliExtensionDir = path.resolve(extensionsPath, 'cli');
|
|
|
|
if (fs.existsSync(cliExtensionDir)) {
|
|
runtime.addPlugin(cliExtensionDir, {
|
|
name: 'directus-project',
|
|
hidden: false,
|
|
required: false,
|
|
});
|
|
}
|
|
|
|
loading.state = false;
|
|
|
|
// add a default command first
|
|
runtime.defaultCommand = command(
|
|
{
|
|
disableHelp: true,
|
|
},
|
|
async function ({ help, parameters: { array } }: Toolbox) {
|
|
if (array && array.length) {
|
|
let suggestion = [''];
|
|
const suggestions = (await help.suggest(array)).filter(({ score }) => score >= 0.8);
|
|
if (suggestions.length > 0) {
|
|
if (suggestions[0]!.score >= 1) {
|
|
suggestion = [`\nDid you mean "${brand} ${suggestions[0]?.suggestion}"?`];
|
|
} else {
|
|
suggestion = [
|
|
`\n\nDid you mean any of the following ones?\n`,
|
|
...suggestions.map(({ suggestion }) => `- ${brand} ${suggestion}`),
|
|
];
|
|
}
|
|
}
|
|
|
|
throw new CLIRuntimeError(`Unknown command: "${brand} ${array.join(' ')}"${suggestion.join('\n')}`);
|
|
}
|
|
|
|
await help.displayHelp();
|
|
}
|
|
) as any;
|
|
|
|
const commandResult: CommandResult<T> = {};
|
|
|
|
try {
|
|
const { result, output } = await runtime.run(argv);
|
|
commandResult.help = result.help;
|
|
commandResult.result = result.data;
|
|
commandResult.error = result.error;
|
|
commandResult.output = output;
|
|
} catch (err) {
|
|
//
|
|
}
|
|
|
|
return commandResult;
|
|
}
|