@runium/cli 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{lib/commands → commands}/index.js +0 -0
- package/{lib/constants → constants}/index.js +0 -0
- package/{lib/macros → macros}/index.js +0 -0
- package/package.json +6 -31
- package/{lib/services → services}/index.js +0 -0
- package/{lib/utils → utils}/index.js +0 -0
- package/{lib/validation → validation}/index.js +0 -0
- package/.eslintrc.json +0 -31
- package/.prettierrc.json +0 -10
- package/README.md +0 -3
- package/build.js +0 -125
- package/lib/package.json +0 -22
- package/src/app.ts +0 -190
- package/src/commands/index.ts +0 -2
- package/src/commands/plugin/plugin-add.ts +0 -48
- package/src/commands/plugin/plugin-command.ts +0 -36
- package/src/commands/plugin/plugin-disable.ts +0 -46
- package/src/commands/plugin/plugin-enable.ts +0 -50
- package/src/commands/plugin/plugin-list.ts +0 -61
- package/src/commands/plugin/plugin-remove.ts +0 -42
- package/src/commands/plugin/plugin.ts +0 -36
- package/src/commands/project/project-add.ts +0 -64
- package/src/commands/project/project-command.ts +0 -43
- package/src/commands/project/project-list.ts +0 -32
- package/src/commands/project/project-remove.ts +0 -41
- package/src/commands/project/project-start.ts +0 -158
- package/src/commands/project/project-state-command.ts +0 -53
- package/src/commands/project/project-status.ts +0 -116
- package/src/commands/project/project-stop.ts +0 -59
- package/src/commands/project/project-validate.ts +0 -56
- package/src/commands/project/project.ts +0 -40
- package/src/commands/runium-command.ts +0 -52
- package/src/constants/error-code.ts +0 -28
- package/src/constants/index.ts +0 -1
- package/src/global.d.ts +0 -6
- package/src/index.ts +0 -24
- package/src/macros/conditional.ts +0 -31
- package/src/macros/date.ts +0 -15
- package/src/macros/empty.ts +0 -6
- package/src/macros/env.ts +0 -8
- package/src/macros/index.ts +0 -17
- package/src/macros/path.ts +0 -24
- package/src/services/command.ts +0 -171
- package/src/services/config.ts +0 -119
- package/src/services/file.ts +0 -272
- package/src/services/index.ts +0 -9
- package/src/services/output.ts +0 -205
- package/src/services/plugin-context.ts +0 -140
- package/src/services/plugin.ts +0 -248
- package/src/services/profile.ts +0 -199
- package/src/services/project.ts +0 -142
- package/src/services/shutdown.ts +0 -147
- package/src/utils/convert-path-to-valid-file-name.ts +0 -39
- package/src/utils/debounce.ts +0 -23
- package/src/utils/format-timestamp.ts +0 -17
- package/src/utils/get-version.ts +0 -13
- package/src/utils/index.ts +0 -4
- package/src/validation/create-validator.ts +0 -27
- package/src/validation/get-config-schema.ts +0 -59
- package/src/validation/get-error-messages.ts +0 -35
- package/src/validation/get-plugin-schema.ts +0 -137
- package/src/validation/index.ts +0 -4
- package/tsconfig.json +0 -38
- /package/{lib/app.js → app.js} +0 -0
- /package/{lib/commands → commands}/plugin/plugin-add.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin-command.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin-disable.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin-enable.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin-list.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin-remove.js +0 -0
- /package/{lib/commands → commands}/plugin/plugin.js +0 -0
- /package/{lib/commands → commands}/project/project-add.js +0 -0
- /package/{lib/commands → commands}/project/project-command.js +0 -0
- /package/{lib/commands → commands}/project/project-list.js +0 -0
- /package/{lib/commands → commands}/project/project-remove.js +0 -0
- /package/{lib/commands → commands}/project/project-start.js +0 -0
- /package/{lib/commands → commands}/project/project-state-command.js +0 -0
- /package/{lib/commands → commands}/project/project-status.js +0 -0
- /package/{lib/commands → commands}/project/project-stop.js +0 -0
- /package/{lib/commands → commands}/project/project-validate.js +0 -0
- /package/{lib/commands → commands}/project/project.js +0 -0
- /package/{lib/commands → commands}/runium-command.js +0 -0
- /package/{lib/constants → constants}/error-code.js +0 -0
- /package/{lib/index.js → index.js} +0 -0
- /package/{lib/macros → macros}/conditional.js +0 -0
- /package/{lib/macros → macros}/date.js +0 -0
- /package/{lib/macros → macros}/empty.js +0 -0
- /package/{lib/macros → macros}/env.js +0 -0
- /package/{lib/macros → macros}/path.js +0 -0
- /package/{lib/services → services}/command.js +0 -0
- /package/{lib/services → services}/config.js +0 -0
- /package/{lib/services → services}/file.js +0 -0
- /package/{lib/services → services}/output.js +0 -0
- /package/{lib/services → services}/plugin-context.js +0 -0
- /package/{lib/services → services}/plugin.js +0 -0
- /package/{lib/services → services}/profile.js +0 -0
- /package/{lib/services → services}/project.js +0 -0
- /package/{lib/services → services}/shutdown.js +0 -0
- /package/{lib/utils → utils}/convert-path-to-valid-file-name.js +0 -0
- /package/{lib/utils → utils}/debounce.js +0 -0
- /package/{lib/utils → utils}/format-timestamp.js +0 -0
- /package/{lib/utils → utils}/get-version.js +0 -0
- /package/{lib/validation → validation}/create-validator.js +0 -0
- /package/{lib/validation → validation}/get-config-schema.js +0 -0
- /package/{lib/validation → validation}/get-error-messages.js +0 -0
- /package/{lib/validation → validation}/get-plugin-schema.js +0 -0
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { RuniumError } from '@runium/core';
|
|
2
|
-
import { ErrorCode } from '@constants';
|
|
3
|
-
import { ProjectStateCommand } from './project-state-command.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Project stop command
|
|
7
|
-
*/
|
|
8
|
-
export class ProjectStopCommand extends ProjectStateCommand {
|
|
9
|
-
/**
|
|
10
|
-
* Config command
|
|
11
|
-
*/
|
|
12
|
-
protected config(): void {
|
|
13
|
-
this.command
|
|
14
|
-
.name('stop')
|
|
15
|
-
.description('stop project')
|
|
16
|
-
.option('-f, --file', 'use file path instead of project name')
|
|
17
|
-
.argument('<name>', 'project name');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Handle command
|
|
22
|
-
* @param name
|
|
23
|
-
* @param file
|
|
24
|
-
*/
|
|
25
|
-
protected async handle(
|
|
26
|
-
name: string,
|
|
27
|
-
{ file }: { file: boolean }
|
|
28
|
-
): Promise<void> {
|
|
29
|
-
const path = file
|
|
30
|
-
? this.projectService.resolvePath(name)
|
|
31
|
-
: this.ensureProfileProject(name).path;
|
|
32
|
-
|
|
33
|
-
const projectDataFileName = this.getProjectDataFileName(file ? path : name);
|
|
34
|
-
const projectDataFilePath = this.profileService.getPath(
|
|
35
|
-
'projects',
|
|
36
|
-
projectDataFileName
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// check if project is started
|
|
40
|
-
const projectData = await this.readProjectData(projectDataFilePath);
|
|
41
|
-
if (!projectData || !this.isProjectProcessStarted(projectData.pid)) {
|
|
42
|
-
throw new RuniumError(
|
|
43
|
-
`Project "${name}" is not started`,
|
|
44
|
-
ErrorCode.PROJECT_NOT_STARTED,
|
|
45
|
-
{ name }
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
process.kill(projectData.pid, 'SIGTERM');
|
|
51
|
-
} catch (ex) {
|
|
52
|
-
throw new RuniumError(
|
|
53
|
-
`Failed to stop project "${name}"`,
|
|
54
|
-
ErrorCode.PROJECT_STOP_ERROR,
|
|
55
|
-
{ name, original: ex }
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import * as ajv from 'ajv';
|
|
2
|
-
import { ProjectCommand } from './project-command.js';
|
|
3
|
-
import { getErrorMessages } from '@validation';
|
|
4
|
-
|
|
5
|
-
interface ValidationError {
|
|
6
|
-
code: string;
|
|
7
|
-
payload: { errors: ajv.ErrorObject[] };
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Project validate command
|
|
12
|
-
*/
|
|
13
|
-
export class ProjectValidateCommand extends ProjectCommand {
|
|
14
|
-
/**
|
|
15
|
-
* Config command
|
|
16
|
-
*/
|
|
17
|
-
protected config(): void {
|
|
18
|
-
this.command
|
|
19
|
-
.name('validate')
|
|
20
|
-
.description('validate project')
|
|
21
|
-
.option('-f, --file', 'use file path instead of project name')
|
|
22
|
-
.argument('<name>', 'project name');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Handle command
|
|
27
|
-
* @param name
|
|
28
|
-
* @param file
|
|
29
|
-
*/
|
|
30
|
-
protected async handle(
|
|
31
|
-
name: string,
|
|
32
|
-
{ file }: { file: boolean }
|
|
33
|
-
): Promise<void> {
|
|
34
|
-
const path = file
|
|
35
|
-
? this.projectService.resolvePath(name)
|
|
36
|
-
: this.ensureProfileProject(name).path;
|
|
37
|
-
const projectInstance = await this.projectService.initProject(path);
|
|
38
|
-
try {
|
|
39
|
-
await projectInstance.validate();
|
|
40
|
-
this.outputService.success(`Project "%s" is valid`, name);
|
|
41
|
-
} catch (error) {
|
|
42
|
-
const errorMessages = getErrorMessages(
|
|
43
|
-
(error as ValidationError).payload.errors,
|
|
44
|
-
{
|
|
45
|
-
filter: error => error.original?.keyword !== 'oneOf',
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
this.outputService.error(
|
|
50
|
-
`Project "%s" validation failed:\n\n%s`,
|
|
51
|
-
name,
|
|
52
|
-
errorMessages.join('\n')
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { RuniumCommand } from '@commands/runium-command.js';
|
|
2
|
-
import { ProjectAddCommand } from './project-add.js';
|
|
3
|
-
import { ProjectListCommand } from './project-list.js';
|
|
4
|
-
import { ProjectRemoveCommand } from './project-remove.js';
|
|
5
|
-
import { ProjectStartCommand } from './project-start.js';
|
|
6
|
-
import { ProjectStopCommand } from './project-stop.js';
|
|
7
|
-
import { ProjectStatusCommand } from './project-status.js';
|
|
8
|
-
import { ProjectValidateCommand } from './project-validate.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Project group command
|
|
12
|
-
*/
|
|
13
|
-
export class ProjectCommand extends RuniumCommand {
|
|
14
|
-
/**
|
|
15
|
-
* Subcommands
|
|
16
|
-
*/
|
|
17
|
-
subcommands = [
|
|
18
|
-
ProjectListCommand,
|
|
19
|
-
ProjectAddCommand,
|
|
20
|
-
ProjectRemoveCommand,
|
|
21
|
-
ProjectStartCommand,
|
|
22
|
-
ProjectStopCommand,
|
|
23
|
-
ProjectStatusCommand,
|
|
24
|
-
ProjectValidateCommand,
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Config command
|
|
29
|
-
*/
|
|
30
|
-
protected config(): void {
|
|
31
|
-
this.command.name('project').description('manage projects');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Handle command
|
|
36
|
-
*/
|
|
37
|
-
protected async handle(): Promise<void> {
|
|
38
|
-
this.command.help();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { Container } from 'typedi';
|
|
3
|
-
import { CommandService, OutputService } from '@services';
|
|
4
|
-
|
|
5
|
-
export type RuniumCommandConstructor = new (program: Command) => RuniumCommand;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Base runium command
|
|
9
|
-
*/
|
|
10
|
-
export abstract class RuniumCommand {
|
|
11
|
-
/**
|
|
12
|
-
* Output service
|
|
13
|
-
*/
|
|
14
|
-
protected outputService: OutputService;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Current command
|
|
18
|
-
*/
|
|
19
|
-
command: Command;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Subcommands
|
|
23
|
-
*/
|
|
24
|
-
subcommands: RuniumCommandConstructor[] = [];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Run command
|
|
28
|
-
*/
|
|
29
|
-
run: (...args: unknown[]) => Promise<void>;
|
|
30
|
-
|
|
31
|
-
constructor(parent: Command) {
|
|
32
|
-
const commandService = Container.get(CommandService);
|
|
33
|
-
this.run = commandService.createRunCommand(this.handle, this);
|
|
34
|
-
|
|
35
|
-
this.outputService = Container.get(OutputService);
|
|
36
|
-
this.command = new Command();
|
|
37
|
-
this.config();
|
|
38
|
-
this.command.action(this.run.bind(this));
|
|
39
|
-
|
|
40
|
-
parent.addCommand(this.command);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Config command
|
|
45
|
-
*/
|
|
46
|
-
protected abstract config(): void;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Handle command
|
|
50
|
-
*/
|
|
51
|
-
protected abstract handle(...args: unknown[]): Promise<void>;
|
|
52
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export enum ErrorCode {
|
|
2
|
-
FILE_READ_JSON_ERROR = 'file-read-json-error',
|
|
3
|
-
FILE_WRITE_JSON_ERROR = 'file-write-json-error',
|
|
4
|
-
FILE_READ_ERROR = 'file-read-error',
|
|
5
|
-
FILE_WRITE_ERROR = 'file-write-error',
|
|
6
|
-
FILE_CREATE_DIR_ERROR = 'file-create-dir-error',
|
|
7
|
-
PLUGIN_NOT_FOUND = 'plugin-not-found',
|
|
8
|
-
PLUGIN_FILE_NOT_FOUND = 'plugin-file-not-found',
|
|
9
|
-
PLUGIN_INCORRECT_MODULE = 'plugin-incorrect-module',
|
|
10
|
-
PLUGIN_INVALID = 'plugin-invalid',
|
|
11
|
-
PLUGIN_PATH_RESOLVE_ERROR = 'plugin-path-resolve-error',
|
|
12
|
-
PLUGIN_LOAD_ERROR = 'plugin-load-error',
|
|
13
|
-
PLUGIN_HOOK_ERROR = 'plugin-hook-error',
|
|
14
|
-
PROJECT_ALREADY_STARTED = 'project-already-started',
|
|
15
|
-
PROJECT_NOT_STARTED = 'project-not-started',
|
|
16
|
-
PROJECT_STOP_ERROR = 'project-stop-error',
|
|
17
|
-
PROJECT_NOT_FOUND = 'project-not-found',
|
|
18
|
-
PROJECT_FILE_NOT_FOUND = 'project-file-not-found',
|
|
19
|
-
PROJECT_FILE_CAN_NOT_READ = 'project-file-can-not-read',
|
|
20
|
-
PROJECT_JSON_PARSE_ERROR = 'project-json-parse-error',
|
|
21
|
-
INVALID_ARGUMENT = 'invalid-argument',
|
|
22
|
-
INVALID_PATH = 'invalid-path',
|
|
23
|
-
CONFIG_INVALID_DATA = 'config-invalid-data',
|
|
24
|
-
COMMAND_REGISTRATION_ERROR = 'command-registration-error',
|
|
25
|
-
COMMAND_INCORRECT = 'command-incorrect',
|
|
26
|
-
COMMAND_NOT_FOUND = 'command-not-found',
|
|
27
|
-
COMMAND_RUN_ERROR = 'command-run-error',
|
|
28
|
-
}
|
package/src/constants/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './error-code.js';
|
package/src/global.d.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import 'reflect-metadata';
|
|
4
|
-
import { Container } from 'typedi';
|
|
5
|
-
import { RuniumCliApp } from './app.js';
|
|
6
|
-
import { OutputService, ShutdownService } from '@services';
|
|
7
|
-
|
|
8
|
-
async function main() {
|
|
9
|
-
const app = new RuniumCliApp();
|
|
10
|
-
await app.start();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
main().catch(error => {
|
|
14
|
-
const outputService = Container.get(OutputService);
|
|
15
|
-
outputService.error('Error: %s', error.message);
|
|
16
|
-
outputService.debug('Error details:', {
|
|
17
|
-
code: error.code,
|
|
18
|
-
payload: error.payload,
|
|
19
|
-
});
|
|
20
|
-
const shutdownService = Container.get(ShutdownService);
|
|
21
|
-
shutdownService.shutdown('error').catch(() => {
|
|
22
|
-
process.exit(1);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Equal
|
|
3
|
-
* @param value1
|
|
4
|
-
* @param value2
|
|
5
|
-
* @param trueValue
|
|
6
|
-
* @param falseValue
|
|
7
|
-
*/
|
|
8
|
-
export function eqMacro(
|
|
9
|
-
value1: string,
|
|
10
|
-
value2: string,
|
|
11
|
-
trueValue?: string,
|
|
12
|
-
falseValue?: string
|
|
13
|
-
): string {
|
|
14
|
-
return value1 === value2 ? (trueValue ?? '') : (falseValue ?? '');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Not equal
|
|
19
|
-
* @param value1
|
|
20
|
-
* @param value2
|
|
21
|
-
* @param trueValue
|
|
22
|
-
* @param falseValue
|
|
23
|
-
*/
|
|
24
|
-
export function neMacro(
|
|
25
|
-
value1: string,
|
|
26
|
-
value2: string,
|
|
27
|
-
trueValue?: string,
|
|
28
|
-
falseValue?: string
|
|
29
|
-
): string {
|
|
30
|
-
return value1 !== value2 ? (trueValue ?? '') : (falseValue ?? '');
|
|
31
|
-
}
|
package/src/macros/date.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { formatTimestamp } from '@utils/format-timestamp.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Date
|
|
5
|
-
*/
|
|
6
|
-
export function dateMacro(): string {
|
|
7
|
-
return formatTimestamp(Date.now());
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Timestamp
|
|
12
|
-
*/
|
|
13
|
-
export function timestampMacro(): string {
|
|
14
|
-
return Date.now().toString();
|
|
15
|
-
}
|
package/src/macros/empty.ts
DELETED
package/src/macros/env.ts
DELETED
package/src/macros/index.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { eqMacro, neMacro } from './conditional.js';
|
|
2
|
-
import { dateMacro, timestampMacro } from './date.js';
|
|
3
|
-
import { emptyMacro } from './empty.js';
|
|
4
|
-
import { envMacro } from './env.js';
|
|
5
|
-
import { homeDirMacro, pathMacro, tmpDirMacro } from './path.js';
|
|
6
|
-
|
|
7
|
-
export const macros = {
|
|
8
|
-
date: dateMacro,
|
|
9
|
-
homedir: homeDirMacro,
|
|
10
|
-
env: envMacro,
|
|
11
|
-
empty: emptyMacro,
|
|
12
|
-
eq: eqMacro,
|
|
13
|
-
ne: neMacro,
|
|
14
|
-
path: pathMacro,
|
|
15
|
-
tmpdir: tmpDirMacro,
|
|
16
|
-
timestamp: timestampMacro,
|
|
17
|
-
};
|
package/src/macros/path.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { homedir, tmpdir } from 'node:os';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolve path
|
|
6
|
-
* @param path
|
|
7
|
-
*/
|
|
8
|
-
export function pathMacro(...path: string[]): string {
|
|
9
|
-
return resolve(...path);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Tmpdir path
|
|
14
|
-
*/
|
|
15
|
-
export function tmpDirMacro(): string {
|
|
16
|
-
return tmpdir();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Home directory path
|
|
21
|
-
*/
|
|
22
|
-
export function homeDirMacro(): string {
|
|
23
|
-
return homedir();
|
|
24
|
-
}
|
package/src/services/command.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { Container, Service } from 'typedi';
|
|
3
|
-
import { isRuniumError, RuniumError } from '@runium/core';
|
|
4
|
-
import { ErrorCode } from '@constants';
|
|
5
|
-
import { PluginService } from '@services';
|
|
6
|
-
import {
|
|
7
|
-
RuniumCommand,
|
|
8
|
-
RuniumCommandConstructor,
|
|
9
|
-
} from '@commands/runium-command.js';
|
|
10
|
-
|
|
11
|
-
const PROGRAM_NAME = 'runium';
|
|
12
|
-
|
|
13
|
-
@Service()
|
|
14
|
-
export class CommandService {
|
|
15
|
-
/**
|
|
16
|
-
* Full path commands
|
|
17
|
-
*/
|
|
18
|
-
private fullPathCommands: Map<string, RuniumCommand> = new Map();
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get command full path recursively
|
|
22
|
-
* @param command
|
|
23
|
-
*/
|
|
24
|
-
private getCommandFullPath(command: RuniumCommand): string {
|
|
25
|
-
const commandName = command.command?.name();
|
|
26
|
-
|
|
27
|
-
if (commandName === PROGRAM_NAME || !command.command.parent) {
|
|
28
|
-
return '';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// find the parent command instance
|
|
32
|
-
const parentCommand = Array.from(this.fullPathCommands.values()).find(
|
|
33
|
-
cmd => cmd.command === command.command.parent
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (parentCommand) {
|
|
37
|
-
// recursively get parent's full path
|
|
38
|
-
const parentPath = this.getCommandFullPath(parentCommand);
|
|
39
|
-
return [parentPath, commandName].filter(Boolean).join(' ').trim();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// fallback: if parent not found in map, check if parent is the program
|
|
43
|
-
const parentName = command.command.parent.name();
|
|
44
|
-
if (parentName === PROGRAM_NAME) {
|
|
45
|
-
return commandName;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return [parentName, commandName].join(' ').trim();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Register command
|
|
53
|
-
* @param command
|
|
54
|
-
* @param program
|
|
55
|
-
* @param context
|
|
56
|
-
*/
|
|
57
|
-
registerCommand(
|
|
58
|
-
command: RuniumCommandConstructor,
|
|
59
|
-
program: Command,
|
|
60
|
-
context: string = 'app'
|
|
61
|
-
): void {
|
|
62
|
-
const addCommand = (
|
|
63
|
-
CommandConstructor: RuniumCommandConstructor,
|
|
64
|
-
parent: Command
|
|
65
|
-
) => {
|
|
66
|
-
try {
|
|
67
|
-
if (!(CommandConstructor.prototype instanceof RuniumCommand)) {
|
|
68
|
-
throw new RuniumError(
|
|
69
|
-
`Command "${CommandConstructor.name}" for "${context}" must be a subclass of "RuniumCommand"`,
|
|
70
|
-
ErrorCode.COMMAND_INCORRECT,
|
|
71
|
-
{
|
|
72
|
-
context,
|
|
73
|
-
CommandConstructor,
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const commandInstance: RuniumCommand = new CommandConstructor(parent);
|
|
79
|
-
|
|
80
|
-
const commandPath = this.getCommandFullPath(commandInstance);
|
|
81
|
-
this.fullPathCommands.set(commandPath, commandInstance);
|
|
82
|
-
|
|
83
|
-
if (commandInstance.subcommands.length > 0) {
|
|
84
|
-
commandInstance.subcommands.forEach(subcommand => {
|
|
85
|
-
addCommand(subcommand, commandInstance.command);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
} catch (error) {
|
|
89
|
-
if (isRuniumError(error)) {
|
|
90
|
-
throw error;
|
|
91
|
-
}
|
|
92
|
-
throw new RuniumError(
|
|
93
|
-
`Failed to register command "${CommandConstructor.name}" for "${context}"`,
|
|
94
|
-
ErrorCode.COMMAND_REGISTRATION_ERROR,
|
|
95
|
-
{ original: error }
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
addCommand(command, program);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create run command
|
|
105
|
-
* @param handle
|
|
106
|
-
* @param command
|
|
107
|
-
*/
|
|
108
|
-
createRunCommand(
|
|
109
|
-
handle: (...args: unknown[]) => Promise<void>,
|
|
110
|
-
command: RuniumCommand
|
|
111
|
-
): (...args: unknown[]) => Promise<void> {
|
|
112
|
-
const pluginService = Container.get(PluginService);
|
|
113
|
-
return async (...args: unknown[]): Promise<void> => {
|
|
114
|
-
// run from command action contains command
|
|
115
|
-
// run from plugin context does not contain command
|
|
116
|
-
if (args?.length > 0 && args[args.length - 1] instanceof Command) {
|
|
117
|
-
args.pop();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const commandPath = this.getCommandFullPath(command);
|
|
121
|
-
|
|
122
|
-
await pluginService.runHook('app.beforeCommandRun', {
|
|
123
|
-
command: commandPath,
|
|
124
|
-
args,
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
await handle.call(command, ...args);
|
|
128
|
-
|
|
129
|
-
await pluginService.runHook('app.afterCommandRun', {
|
|
130
|
-
command: commandPath,
|
|
131
|
-
args,
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Check if command exists
|
|
138
|
-
* @param path
|
|
139
|
-
*/
|
|
140
|
-
hasCommand(path: string): boolean {
|
|
141
|
-
return this.fullPathCommands.has(path);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Run command
|
|
146
|
-
* @param path
|
|
147
|
-
* @param args
|
|
148
|
-
*/
|
|
149
|
-
async runCommand(path: string, ...args: unknown[]): Promise<void> {
|
|
150
|
-
const command = this.fullPathCommands.get(path);
|
|
151
|
-
if (!command) {
|
|
152
|
-
throw new RuniumError(
|
|
153
|
-
`Command "${path}" not found`,
|
|
154
|
-
ErrorCode.COMMAND_NOT_FOUND,
|
|
155
|
-
{ path }
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
try {
|
|
159
|
-
await command.run(...args);
|
|
160
|
-
} catch (error) {
|
|
161
|
-
if (isRuniumError(error)) {
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
throw new RuniumError(
|
|
165
|
-
`Failed to run command "${path}"`,
|
|
166
|
-
ErrorCode.COMMAND_RUN_ERROR,
|
|
167
|
-
{ original: error }
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
package/src/services/config.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
4
|
-
import { Service } from 'typedi';
|
|
5
|
-
import { readJsonFile, RuniumError } from '@runium/core';
|
|
6
|
-
import { ErrorCode } from '@constants';
|
|
7
|
-
import {
|
|
8
|
-
createValidator,
|
|
9
|
-
getConfigSchema,
|
|
10
|
-
getErrorMessages,
|
|
11
|
-
} from '@validation';
|
|
12
|
-
|
|
13
|
-
interface ConfigEnv {
|
|
14
|
-
path: string[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ConfigOutput {
|
|
18
|
-
debug: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface ConfigProfile {
|
|
22
|
-
path: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface ConfigPlugin {
|
|
26
|
-
disabled: boolean;
|
|
27
|
-
options: Record<string, unknown>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface ConfigPlugins {
|
|
31
|
-
[name: string]: ConfigPlugin;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface ConfigData {
|
|
35
|
-
env: ConfigEnv;
|
|
36
|
-
output: ConfigOutput;
|
|
37
|
-
profile: ConfigProfile;
|
|
38
|
-
plugins: ConfigPlugins;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const CONFIG_FILE_NAME = '.runiumrc.json';
|
|
42
|
-
const CONFIG_FILE_PATH = join(process.cwd(), CONFIG_FILE_NAME);
|
|
43
|
-
const PROFILE_DIR_NAME = '.runium';
|
|
44
|
-
const HOME_PROFILE_PATH = join(homedir(), PROFILE_DIR_NAME);
|
|
45
|
-
const CWD_PROFILE_PATH = join(process.cwd(), PROFILE_DIR_NAME);
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Validate config data
|
|
49
|
-
* @param data
|
|
50
|
-
*/
|
|
51
|
-
function validateConfigData(data: unknown): void {
|
|
52
|
-
const schema = getConfigSchema();
|
|
53
|
-
const validate = createValidator(schema);
|
|
54
|
-
const result = validate(data);
|
|
55
|
-
|
|
56
|
-
if (!result && validate.errors) {
|
|
57
|
-
const errorMessages = getErrorMessages(validate.errors);
|
|
58
|
-
|
|
59
|
-
throw new RuniumError(
|
|
60
|
-
`Invalid "${CONFIG_FILE_PATH}" configuration data`,
|
|
61
|
-
ErrorCode.CONFIG_INVALID_DATA,
|
|
62
|
-
errorMessages
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@Service()
|
|
68
|
-
export class ConfigService {
|
|
69
|
-
private data: ConfigData = {
|
|
70
|
-
profile: { path: HOME_PROFILE_PATH },
|
|
71
|
-
plugins: {},
|
|
72
|
-
output: { debug: false },
|
|
73
|
-
env: { path: [] },
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Initialize the config service
|
|
78
|
-
*/
|
|
79
|
-
async init(): Promise<void> {
|
|
80
|
-
if (existsSync(CWD_PROFILE_PATH)) {
|
|
81
|
-
this.data.profile.path = CWD_PROFILE_PATH;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (existsSync(CONFIG_FILE_PATH)) {
|
|
85
|
-
const configData: Partial<ConfigData> =
|
|
86
|
-
await readJsonFile<Partial<ConfigData>>(CONFIG_FILE_PATH);
|
|
87
|
-
if (configData) {
|
|
88
|
-
validateConfigData(configData);
|
|
89
|
-
|
|
90
|
-
const data = {
|
|
91
|
-
env: Object.assign({}, this.data.env, configData.env ?? {}),
|
|
92
|
-
output: Object.assign({}, this.data.output, configData.output ?? {}),
|
|
93
|
-
profile: Object.assign(
|
|
94
|
-
{},
|
|
95
|
-
this.data.profile,
|
|
96
|
-
configData.profile ?? {}
|
|
97
|
-
),
|
|
98
|
-
plugins: Object.assign(
|
|
99
|
-
{},
|
|
100
|
-
this.data.plugins,
|
|
101
|
-
configData.plugins ?? {}
|
|
102
|
-
),
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
data.env.path = data.env.path.map(envPath => resolve(envPath));
|
|
106
|
-
data.profile.path = resolve(data.profile.path);
|
|
107
|
-
this.data = data;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Get a configuration value
|
|
114
|
-
* @param key
|
|
115
|
-
*/
|
|
116
|
-
get<T extends keyof ConfigData>(key: T): ConfigData[T] {
|
|
117
|
-
return this.data[key];
|
|
118
|
-
}
|
|
119
|
-
}
|