@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,248 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
- import { Inject, Service } from 'typedi';
4
- import {
5
- isRuniumError,
6
- MacrosCollection,
7
- Project,
8
- ProjectConfig,
9
- ProjectSchemaExtension,
10
- RuniumError,
11
- RuniumTaskConstructor,
12
- RuniumTriggerConstructor,
13
- RuniumTriggerOptions,
14
- } from '@runium/core';
15
- import { RuniumCommandConstructor } from '@commands/runium-command.js';
16
- import { ErrorCode } from '@constants';
17
- import { OutputService } from '@services';
18
- import {
19
- createValidator,
20
- getErrorMessages,
21
- getPluginSchema,
22
- } from '@validation';
23
-
24
- type PluginModule = { default: (options?: PluginOptions) => Plugin };
25
-
26
- type PluginHookErrorHandler = (error: RuniumError) => void;
27
-
28
- type PluginHookName =
29
- | `app.${keyof PluginAppHooksDefinition}`
30
- | `project.${keyof PluginProjectHooksDefinition}`;
31
-
32
- interface PluginHookOptions<M extends boolean> {
33
- mutable?: M;
34
- onError?: PluginHookErrorHandler;
35
- }
36
-
37
- export interface PluginProjectDefinition {
38
- macros?: MacrosCollection;
39
- tasks?: Record<string, RuniumTaskConstructor>;
40
- actions?: Record<string, (payload: unknown) => void>;
41
- triggers?: Record<string, RuniumTriggerConstructor<RuniumTriggerOptions>>;
42
- validationSchema?: ProjectSchemaExtension;
43
- }
44
-
45
- export type PluginOptions = Record<string, unknown>;
46
-
47
- export interface PluginAppDefinition {
48
- commands?: RuniumCommandConstructor[];
49
- }
50
-
51
- export interface PluginProjectHooksDefinition {
52
- beforeConfigRead?(path: string): Promise<void>;
53
- afterConfigRead?(content: string): Promise<string>;
54
- afterConfigMacrosApply?(content: string): Promise<string>;
55
- afterConfigParse?<T extends ProjectConfig>(config: T): Promise<T>;
56
- beforeStart?(project: Project): Promise<void>;
57
- }
58
-
59
- export interface PluginAppHooksDefinition {
60
- afterInit?(params: { profilePath: string }): Promise<void>;
61
- beforeExit?(reason?: string): Promise<void>;
62
- beforeCommandRun?(params: {
63
- command: string;
64
- args: unknown[];
65
- }): Promise<void>;
66
- afterCommandRun?(params: { command: string; args: unknown[] }): Promise<void>;
67
- }
68
-
69
- export interface PluginHooksDefinition {
70
- app?: PluginAppHooksDefinition;
71
- project?: PluginProjectHooksDefinition;
72
- }
73
-
74
- export interface Plugin {
75
- name: string;
76
- project?: PluginProjectDefinition;
77
- options?: PluginOptions;
78
- app?: PluginAppDefinition;
79
- hooks?: PluginHooksDefinition;
80
- }
81
-
82
- @Service()
83
- export class PluginService {
84
- /**
85
- * Loaded plugins
86
- */
87
- private plugins: Map<string, Plugin> = new Map();
88
-
89
- /**
90
- * Validate plugin schema
91
- * @private
92
- */
93
- private validator: ReturnType<typeof createValidator> =
94
- createValidator(getPluginSchema());
95
-
96
- constructor(@Inject() private outputService: OutputService) {}
97
-
98
- /**
99
- * Get all plugins
100
- */
101
- getAllPlugins(): Plugin[] {
102
- return Array.from(this.plugins.values());
103
- }
104
-
105
- /**
106
- * Get plugin by name
107
- * @param name
108
- */
109
- getPluginByName(name: string): Plugin | undefined {
110
- return this.plugins.get(name);
111
- }
112
-
113
- /**
114
- * Load plugin
115
- * @param path
116
- * @param options
117
- */
118
- async loadPlugin(path: string, options?: PluginOptions): Promise<string> {
119
- if (!path || !existsSync(path)) {
120
- throw new RuniumError(
121
- `Plugin file "${path}" does not exist`,
122
- ErrorCode.PLUGIN_FILE_NOT_FOUND,
123
- { path }
124
- );
125
- }
126
-
127
- try {
128
- const pluginModule = (await import(path)) as PluginModule;
129
- const { default: getPlugin } = pluginModule;
130
- if (!getPlugin || typeof getPlugin !== 'function') {
131
- throw new RuniumError(
132
- 'Plugin module must have a default function',
133
- ErrorCode.PLUGIN_INCORRECT_MODULE,
134
- { path }
135
- );
136
- }
137
- const plugin = getPlugin(options);
138
-
139
- this.validate(plugin);
140
-
141
- this.plugins.set(plugin.name, plugin);
142
-
143
- return plugin.name;
144
- } catch (error) {
145
- if (isRuniumError(error)) {
146
- throw error;
147
- }
148
- throw new RuniumError(
149
- `Failed to load plugin "${path}"`,
150
- ErrorCode.PLUGIN_LOAD_ERROR,
151
- { path, original: error }
152
- );
153
- }
154
- }
155
-
156
- /**
157
- * Unload plugin
158
- * @param name
159
- */
160
- async unloadPlugin(name: string): Promise<boolean> {
161
- return this.plugins.delete(name);
162
- }
163
-
164
- /**
165
- * Resolve path
166
- * @param path
167
- * @param isFile
168
- */
169
- resolvePath(path: string, isFile: boolean = false): string {
170
- try {
171
- const resolvedPath = isFile ? resolve(path) : import.meta.resolve(path);
172
- return resolvedPath.replace('file://', '');
173
- } catch (error) {
174
- throw new RuniumError(
175
- `Failed to resolve plugin path "${path}"`,
176
- ErrorCode.PLUGIN_PATH_RESOLVE_ERROR,
177
- { path, original: error }
178
- );
179
- }
180
- }
181
-
182
- /**
183
- * Run plugin hook
184
- * @param name
185
- * @param params
186
- * @param options
187
- */
188
- async runHook<T, M extends boolean>(
189
- name: PluginHookName,
190
- params: T,
191
- { mutable, onError }: PluginHookOptions<M> = {}
192
- ): Promise<M extends true ? T : void> {
193
- const plugins = this.getAllPlugins();
194
-
195
- const [group, hookName] = name.split('.') as [
196
- keyof PluginHooksDefinition,
197
- keyof PluginHooksDefinition[keyof PluginHooksDefinition],
198
- ];
199
-
200
- for (const plugin of plugins) {
201
- const hook = plugin.hooks?.[group]?.[hookName] as
202
- | ((params: T) => Promise<T>)
203
- | undefined;
204
- if (hook) {
205
- try {
206
- if (!mutable) {
207
- await hook(params);
208
- } else {
209
- params = (await hook(params)) ?? params;
210
- }
211
- } catch (ex) {
212
- const error = new RuniumError(
213
- `Failed to run "${plugin.name}.${name}" hook`,
214
- ErrorCode.PLUGIN_HOOK_ERROR,
215
- { plugin: plugin.name, hook: name, original: ex }
216
- );
217
- if (onError) {
218
- onError(error);
219
- } else {
220
- this.outputService.error('Error: %s', error.message);
221
- this.outputService.debug('Error details:', {
222
- code: error.code,
223
- payload: error.payload,
224
- });
225
- }
226
- }
227
- }
228
- }
229
-
230
- return (mutable ? params : undefined) as M extends true ? T : void;
231
- }
232
-
233
- /**
234
- * Validate plugin
235
- * @param plugin
236
- */
237
- private validate(plugin: Plugin): void {
238
- const result = this.validator(plugin || {});
239
- if (!result && this.validator.errors) {
240
- const errorMessages = getErrorMessages(this.validator.errors);
241
- throw new RuniumError(
242
- 'Incorrect plugin format',
243
- ErrorCode.PLUGIN_INVALID,
244
- { errors: errorMessages }
245
- );
246
- }
247
- }
248
- }
@@ -1,199 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { mkdir } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import { Inject, Service } from 'typedi';
5
- import { ConfigService, FileService } from '@services';
6
-
7
- export interface ProfilePlugin {
8
- name: string;
9
- path: string;
10
- file?: boolean;
11
- disabled?: boolean;
12
- options?: Record<string, unknown>;
13
- }
14
-
15
- export interface ProfileProject {
16
- name: string;
17
- path: string;
18
- }
19
-
20
- const PLUGINS_FILE_NAME = 'plugins.json';
21
- const PROJECTS_FILE_NAME = 'projects.json';
22
-
23
- @Service()
24
- export class ProfileService {
25
- private path: string = process.cwd();
26
-
27
- private plugins: ProfilePlugin[] = [];
28
-
29
- private projects: ProfileProject[] = [];
30
-
31
- constructor(
32
- @Inject() private configService: ConfigService,
33
- @Inject() private fileService: FileService
34
- ) {}
35
-
36
- /**
37
- * Initialize the profile service
38
- */
39
- async init(): Promise<void> {
40
- this.path = this.configService.get('profile').path;
41
- if (!existsSync(this.path)) {
42
- await mkdir(this.path, { recursive: true });
43
- }
44
-
45
- await this.readPlugins();
46
- await this.patchPlugins();
47
- await this.readProjects();
48
- }
49
-
50
- /**
51
- * Get plugins
52
- */
53
- getPlugins(): ProfilePlugin[] {
54
- return this.plugins;
55
- }
56
-
57
- /**
58
- * Get plugin by name
59
- * @param name
60
- */
61
- getPluginByName(name: string): ProfilePlugin | undefined {
62
- return this.plugins.find(p => p.name === name);
63
- }
64
-
65
- /**
66
- * Add plugin
67
- * @param plugin
68
- */
69
- async addPlugin(plugin: ProfilePlugin): Promise<void> {
70
- this.plugins = this.plugins
71
- .filter(p => p.name !== plugin.name)
72
- .concat(plugin);
73
- await this.writePlugins();
74
- }
75
-
76
- /**
77
- * Update plugin
78
- * @param name
79
- */
80
- async removePlugin(name: string): Promise<void> {
81
- this.plugins = this.plugins.filter(plugin => plugin.name !== name);
82
- await this.writePlugins();
83
- }
84
-
85
- /**
86
- * Update plugin
87
- * @param name
88
- * @param data
89
- */
90
- async updatePlugin(
91
- name: string,
92
- data: Partial<Omit<ProfilePlugin, 'name'>>
93
- ): Promise<void> {
94
- const index = this.plugins.findIndex(plugin => plugin.name === name);
95
- if (index !== -1) {
96
- this.plugins[index] = {
97
- ...this.plugins[index],
98
- ...data,
99
- };
100
- await this.writePlugins();
101
- }
102
- }
103
-
104
- /**
105
- * Get projects
106
- */
107
- getProjects(): ProfileProject[] {
108
- return this.projects;
109
- }
110
-
111
- /**
112
- * Get project by name
113
- * @param name
114
- */
115
- getProjectByName(name: string): ProfileProject | undefined {
116
- return this.projects.find(p => p.name === name);
117
- }
118
-
119
- /**
120
- * Add project
121
- * @param project
122
- */
123
- async addProject(project: ProfileProject): Promise<void> {
124
- this.projects = this.projects
125
- .filter(p => p.name !== project.name)
126
- .concat(project);
127
- await this.writeProjects();
128
- }
129
-
130
- /**
131
- * Remove project
132
- * @param name
133
- */
134
- async removeProject(name: string): Promise<void> {
135
- this.projects = this.projects.filter(p => p.name !== name);
136
- await this.writeProjects();
137
- }
138
-
139
- /**
140
- * Get path for a file
141
- * @param parts
142
- */
143
- getPath(...parts: string[]): string {
144
- return join(this.path, ...parts);
145
- }
146
-
147
- /**
148
- * Read plugins from file
149
- */
150
- private async readPlugins(): Promise<void> {
151
- this.plugins =
152
- ((await this.fileService
153
- .readJson(this.getPath(PLUGINS_FILE_NAME))
154
- .catch(() => [])) as ProfilePlugin[]) || this.plugins;
155
- }
156
-
157
- /**
158
- * Write plugins to file
159
- */
160
- private async writePlugins(): Promise<void> {
161
- await this.fileService.writeJson(
162
- this.getPath(PLUGINS_FILE_NAME),
163
- this.plugins
164
- );
165
- }
166
-
167
- /**
168
- * Patch plugins
169
- */
170
- private async patchPlugins(): Promise<void> {
171
- const pluginsConfig = this.configService.get('plugins');
172
- for (const plugin of this.plugins) {
173
- const config = pluginsConfig[plugin.name];
174
- if (config) {
175
- Object.assign(plugin, config);
176
- }
177
- }
178
- }
179
-
180
- /**
181
- * Read projects from file
182
- */
183
- private async readProjects(): Promise<void> {
184
- this.projects =
185
- ((await this.fileService
186
- .readJson(this.getPath(PROJECTS_FILE_NAME))
187
- .catch(() => [])) as ProfileProject[]) || this.projects;
188
- }
189
-
190
- /**
191
- * Write projects to file
192
- */
193
- private async writeProjects(): Promise<void> {
194
- await this.fileService.writeJson(
195
- this.getPath(PROJECTS_FILE_NAME),
196
- this.projects
197
- );
198
- }
199
- }
@@ -1,142 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { readFile } from 'node:fs/promises';
3
- import { resolve } from 'node:path';
4
- import { Inject, Service } from 'typedi';
5
- import { applyMacros, Project, ProjectConfig, RuniumError } from '@runium/core';
6
- import { ErrorCode } from '@constants';
7
- import { macros } from '@macros';
8
- import { PluginProjectDefinition, PluginService } from '@services';
9
-
10
- @Service()
11
- export class ProjectService {
12
- constructor(@Inject() private pluginService: PluginService) {}
13
-
14
- /**
15
- * Init project
16
- * @param path
17
- */
18
- async initProject(path: string): Promise<Project> {
19
- await this.pluginService.runHook('project.beforeConfigRead', path);
20
-
21
- let content = await this.readFile(path);
22
- content = await this.pluginService.runHook(
23
- 'project.afterConfigRead',
24
- content,
25
- { mutable: true }
26
- );
27
- content = this.applyMacros(content);
28
- content = await this.pluginService.runHook(
29
- 'project.afterConfigMacrosApply',
30
- content,
31
- { mutable: true }
32
- );
33
-
34
- let projectData = this.parseProjectContent(content, path);
35
- projectData = await this.pluginService.runHook(
36
- 'project.afterConfigParse',
37
- projectData,
38
- { mutable: true }
39
- );
40
-
41
- const project = new Project(projectData);
42
- return this.extendProjectWithPlugins(project);
43
- }
44
-
45
- /**
46
- * Resolve path
47
- * @param path
48
- */
49
- resolvePath(path: string): string {
50
- return resolve(path);
51
- }
52
-
53
- /**
54
- * Run hook
55
- * @param args
56
- */
57
- runHook(
58
- ...args: Parameters<PluginService['runHook']>
59
- ): ReturnType<PluginService['runHook']> {
60
- return this.pluginService.runHook(...args);
61
- }
62
-
63
- /**
64
- * Read project file
65
- * @param path
66
- */
67
- private async readFile(path: string): Promise<string> {
68
- if (!existsSync(path)) {
69
- throw new RuniumError(
70
- `Project file "${path}" does not exist`,
71
- ErrorCode.PROJECT_FILE_NOT_FOUND,
72
- { path }
73
- );
74
- }
75
- try {
76
- return readFile(path, { encoding: 'utf-8' });
77
- } catch (error) {
78
- throw new RuniumError(
79
- `Failed to read project file "${path}"`,
80
- ErrorCode.PROJECT_FILE_CAN_NOT_READ,
81
- { path, original: error }
82
- );
83
- }
84
- }
85
-
86
- /**
87
- * Apply macros to text
88
- * @param text
89
- */
90
- private applyMacros(text: string): string {
91
- const plugins = this.pluginService.getAllPlugins();
92
- const pluginMacros = plugins.reduce(
93
- (acc, plugin) => ({ ...acc, ...(plugin.project?.macros || {}) }),
94
- {}
95
- );
96
- return applyMacros(text, { ...pluginMacros, ...macros });
97
- }
98
-
99
- /**
100
- * Parse project content
101
- * @param content
102
- * @param path
103
- */
104
- private parseProjectContent(content: string, path: string): ProjectConfig {
105
- try {
106
- return JSON.parse(content);
107
- } catch (error) {
108
- throw new RuniumError(
109
- `Failed to parse project "${path}"`,
110
- ErrorCode.PROJECT_JSON_PARSE_ERROR,
111
- { path, original: error }
112
- );
113
- }
114
- }
115
-
116
- /**
117
- * Extends the project with plugins
118
- * @param project
119
- */
120
- private extendProjectWithPlugins(project: Project): Project {
121
- const plugins = this.pluginService.getAllPlugins();
122
-
123
- plugins.forEach(plugin => {
124
- const { tasks, actions, triggers, validationSchema } = (plugin.project ||
125
- {}) as PluginProjectDefinition;
126
- Object.entries(actions || {}).forEach(([type, processor]) => {
127
- project.registerAction(type, processor);
128
- });
129
- Object.entries(tasks || {}).forEach(([type, processor]) => {
130
- project.registerTask(type, processor);
131
- });
132
- Object.entries(triggers || {}).forEach(([type, processor]) => {
133
- project.registerTrigger(type, processor);
134
- });
135
- if (validationSchema) {
136
- project.extendValidationSchema(validationSchema);
137
- }
138
- });
139
-
140
- return project;
141
- }
142
- }