@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.
Files changed (106) hide show
  1. package/{lib/commands → commands}/index.js +0 -0
  2. package/{lib/constants → constants}/index.js +0 -0
  3. package/{lib/macros → macros}/index.js +0 -0
  4. package/package.json +6 -31
  5. package/{lib/services → services}/index.js +0 -0
  6. package/{lib/utils → utils}/index.js +0 -0
  7. package/{lib/validation → validation}/index.js +0 -0
  8. package/.eslintrc.json +0 -31
  9. package/.prettierrc.json +0 -10
  10. package/README.md +0 -3
  11. package/build.js +0 -125
  12. package/lib/package.json +0 -22
  13. package/src/app.ts +0 -190
  14. package/src/commands/index.ts +0 -2
  15. package/src/commands/plugin/plugin-add.ts +0 -48
  16. package/src/commands/plugin/plugin-command.ts +0 -36
  17. package/src/commands/plugin/plugin-disable.ts +0 -46
  18. package/src/commands/plugin/plugin-enable.ts +0 -50
  19. package/src/commands/plugin/plugin-list.ts +0 -61
  20. package/src/commands/plugin/plugin-remove.ts +0 -42
  21. package/src/commands/plugin/plugin.ts +0 -36
  22. package/src/commands/project/project-add.ts +0 -64
  23. package/src/commands/project/project-command.ts +0 -43
  24. package/src/commands/project/project-list.ts +0 -32
  25. package/src/commands/project/project-remove.ts +0 -41
  26. package/src/commands/project/project-start.ts +0 -158
  27. package/src/commands/project/project-state-command.ts +0 -53
  28. package/src/commands/project/project-status.ts +0 -116
  29. package/src/commands/project/project-stop.ts +0 -59
  30. package/src/commands/project/project-validate.ts +0 -56
  31. package/src/commands/project/project.ts +0 -40
  32. package/src/commands/runium-command.ts +0 -52
  33. package/src/constants/error-code.ts +0 -28
  34. package/src/constants/index.ts +0 -1
  35. package/src/global.d.ts +0 -6
  36. package/src/index.ts +0 -24
  37. package/src/macros/conditional.ts +0 -31
  38. package/src/macros/date.ts +0 -15
  39. package/src/macros/empty.ts +0 -6
  40. package/src/macros/env.ts +0 -8
  41. package/src/macros/index.ts +0 -17
  42. package/src/macros/path.ts +0 -24
  43. package/src/services/command.ts +0 -171
  44. package/src/services/config.ts +0 -119
  45. package/src/services/file.ts +0 -272
  46. package/src/services/index.ts +0 -9
  47. package/src/services/output.ts +0 -205
  48. package/src/services/plugin-context.ts +0 -140
  49. package/src/services/plugin.ts +0 -248
  50. package/src/services/profile.ts +0 -199
  51. package/src/services/project.ts +0 -142
  52. package/src/services/shutdown.ts +0 -147
  53. package/src/utils/convert-path-to-valid-file-name.ts +0 -39
  54. package/src/utils/debounce.ts +0 -23
  55. package/src/utils/format-timestamp.ts +0 -17
  56. package/src/utils/get-version.ts +0 -13
  57. package/src/utils/index.ts +0 -4
  58. package/src/validation/create-validator.ts +0 -27
  59. package/src/validation/get-config-schema.ts +0 -59
  60. package/src/validation/get-error-messages.ts +0 -35
  61. package/src/validation/get-plugin-schema.ts +0 -137
  62. package/src/validation/index.ts +0 -4
  63. package/tsconfig.json +0 -38
  64. /package/{lib/app.js → app.js} +0 -0
  65. /package/{lib/commands → commands}/plugin/plugin-add.js +0 -0
  66. /package/{lib/commands → commands}/plugin/plugin-command.js +0 -0
  67. /package/{lib/commands → commands}/plugin/plugin-disable.js +0 -0
  68. /package/{lib/commands → commands}/plugin/plugin-enable.js +0 -0
  69. /package/{lib/commands → commands}/plugin/plugin-list.js +0 -0
  70. /package/{lib/commands → commands}/plugin/plugin-remove.js +0 -0
  71. /package/{lib/commands → commands}/plugin/plugin.js +0 -0
  72. /package/{lib/commands → commands}/project/project-add.js +0 -0
  73. /package/{lib/commands → commands}/project/project-command.js +0 -0
  74. /package/{lib/commands → commands}/project/project-list.js +0 -0
  75. /package/{lib/commands → commands}/project/project-remove.js +0 -0
  76. /package/{lib/commands → commands}/project/project-start.js +0 -0
  77. /package/{lib/commands → commands}/project/project-state-command.js +0 -0
  78. /package/{lib/commands → commands}/project/project-status.js +0 -0
  79. /package/{lib/commands → commands}/project/project-stop.js +0 -0
  80. /package/{lib/commands → commands}/project/project-validate.js +0 -0
  81. /package/{lib/commands → commands}/project/project.js +0 -0
  82. /package/{lib/commands → commands}/runium-command.js +0 -0
  83. /package/{lib/constants → constants}/error-code.js +0 -0
  84. /package/{lib/index.js → index.js} +0 -0
  85. /package/{lib/macros → macros}/conditional.js +0 -0
  86. /package/{lib/macros → macros}/date.js +0 -0
  87. /package/{lib/macros → macros}/empty.js +0 -0
  88. /package/{lib/macros → macros}/env.js +0 -0
  89. /package/{lib/macros → macros}/path.js +0 -0
  90. /package/{lib/services → services}/command.js +0 -0
  91. /package/{lib/services → services}/config.js +0 -0
  92. /package/{lib/services → services}/file.js +0 -0
  93. /package/{lib/services → services}/output.js +0 -0
  94. /package/{lib/services → services}/plugin-context.js +0 -0
  95. /package/{lib/services → services}/plugin.js +0 -0
  96. /package/{lib/services → services}/profile.js +0 -0
  97. /package/{lib/services → services}/project.js +0 -0
  98. /package/{lib/services → services}/shutdown.js +0 -0
  99. /package/{lib/utils → utils}/convert-path-to-valid-file-name.js +0 -0
  100. /package/{lib/utils → utils}/debounce.js +0 -0
  101. /package/{lib/utils → utils}/format-timestamp.js +0 -0
  102. /package/{lib/utils → utils}/get-version.js +0 -0
  103. /package/{lib/validation → validation}/create-validator.js +0 -0
  104. /package/{lib/validation → validation}/get-config-schema.js +0 -0
  105. /package/{lib/validation → validation}/get-error-messages.js +0 -0
  106. /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
- }
@@ -1 +0,0 @@
1
- export * from './error-code.js';
package/src/global.d.ts DELETED
@@ -1,6 +0,0 @@
1
- declare global {
2
- // eslint-disable-next-line
3
- var runium: unknown;
4
- }
5
-
6
- export {};
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
- }
@@ -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
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Empty string
3
- */
4
- export function emptyMacro(): string {
5
- return '';
6
- }
package/src/macros/env.ts DELETED
@@ -1,8 +0,0 @@
1
- /**
2
- * Get environment variable
3
- * @param name
4
- * @param defaultValue
5
- */
6
- export function envMacro(name: string, defaultValue?: string): string {
7
- return process.env[name] ?? defaultValue ?? '';
8
- }
@@ -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
- };
@@ -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
- }
@@ -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
- }
@@ -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
- }