@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
package/src/services/plugin.ts
DELETED
|
@@ -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
|
-
}
|
package/src/services/profile.ts
DELETED
|
@@ -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
|
-
}
|
package/src/services/project.ts
DELETED
|
@@ -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
|
-
}
|