@runium/cli 0.0.3 → 0.0.5
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 +7 -32
- 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/file.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { PathLike } from 'node:fs';
|
|
2
|
-
import { basename, dirname, join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
access,
|
|
5
|
-
constants,
|
|
6
|
-
mkdir,
|
|
7
|
-
readFile,
|
|
8
|
-
rename,
|
|
9
|
-
writeFile,
|
|
10
|
-
} from 'node:fs/promises';
|
|
11
|
-
import { fileURLToPath } from 'node:url';
|
|
12
|
-
|
|
13
|
-
import { Service } from 'typedi';
|
|
14
|
-
import { JSONObject, RuniumError } from '@runium/core';
|
|
15
|
-
import { ErrorCode } from '@constants';
|
|
16
|
-
|
|
17
|
-
type Resolve = () => void;
|
|
18
|
-
type Reject = (error: Error) => void;
|
|
19
|
-
type Data = Parameters<typeof writeFile>[1];
|
|
20
|
-
|
|
21
|
-
@Service()
|
|
22
|
-
export class FileService {
|
|
23
|
-
/**
|
|
24
|
-
* Reads a file as text
|
|
25
|
-
* @param path
|
|
26
|
-
* @param options
|
|
27
|
-
*/
|
|
28
|
-
async read(
|
|
29
|
-
path: string,
|
|
30
|
-
options: { encoding?: BufferEncoding } = {}
|
|
31
|
-
): Promise<string> {
|
|
32
|
-
try {
|
|
33
|
-
return await readFile(path, { encoding: options.encoding || 'utf-8' });
|
|
34
|
-
} catch (ex) {
|
|
35
|
-
throw new RuniumError(
|
|
36
|
-
`Can not read file ${path}`,
|
|
37
|
-
ErrorCode.FILE_READ_ERROR,
|
|
38
|
-
{ path, options, original: ex }
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Writes data to a file
|
|
45
|
-
* @param path
|
|
46
|
-
* @param data
|
|
47
|
-
* @param options
|
|
48
|
-
*/
|
|
49
|
-
async write(
|
|
50
|
-
path: string,
|
|
51
|
-
data: string,
|
|
52
|
-
options: { encoding?: BufferEncoding } = {}
|
|
53
|
-
): Promise<void> {
|
|
54
|
-
try {
|
|
55
|
-
await writeFile(path, data, { encoding: options.encoding || 'utf-8' });
|
|
56
|
-
} catch (ex) {
|
|
57
|
-
throw new RuniumError(
|
|
58
|
-
`Can not write file ${path}`,
|
|
59
|
-
ErrorCode.FILE_WRITE_ERROR,
|
|
60
|
-
{ path, data, options, original: ex }
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Reads a JSON file
|
|
67
|
-
* @param path
|
|
68
|
-
*/
|
|
69
|
-
async readJson<T = JSONObject>(path: string): Promise<T> {
|
|
70
|
-
try {
|
|
71
|
-
const data = await readFile(path, { encoding: 'utf-8' });
|
|
72
|
-
return JSON.parse(data);
|
|
73
|
-
} catch (ex) {
|
|
74
|
-
throw new RuniumError(
|
|
75
|
-
`Can not read JSON file ${path}`,
|
|
76
|
-
ErrorCode.FILE_READ_JSON_ERROR,
|
|
77
|
-
{ path, original: ex }
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Writes a JSON file
|
|
84
|
-
* @param path
|
|
85
|
-
* @param data
|
|
86
|
-
*/
|
|
87
|
-
async writeJson<T = JSONObject>(path: string, data: T): Promise<void> {
|
|
88
|
-
try {
|
|
89
|
-
await writeFile(path, JSON.stringify(data, null, 2), {
|
|
90
|
-
encoding: 'utf-8',
|
|
91
|
-
});
|
|
92
|
-
} catch (ex) {
|
|
93
|
-
throw new RuniumError(
|
|
94
|
-
`Can not write JSON file ${path}`,
|
|
95
|
-
ErrorCode.FILE_WRITE_JSON_ERROR,
|
|
96
|
-
{ path, data, original: ex }
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Checks if a file or directory exists
|
|
103
|
-
* @param path
|
|
104
|
-
*/
|
|
105
|
-
async isExists(path: string): Promise<boolean> {
|
|
106
|
-
try {
|
|
107
|
-
await access(path, constants.F_OK);
|
|
108
|
-
return true;
|
|
109
|
-
} catch {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Create directory recursively if it does not exist
|
|
116
|
-
* @param path
|
|
117
|
-
*/
|
|
118
|
-
async ensureDirExists(path: string): Promise<void> {
|
|
119
|
-
try {
|
|
120
|
-
await mkdir(path, { recursive: true });
|
|
121
|
-
} catch (ex) {
|
|
122
|
-
throw new RuniumError(
|
|
123
|
-
`Can not create directory ${path}`,
|
|
124
|
-
ErrorCode.FILE_CREATE_DIR_ERROR,
|
|
125
|
-
{ path, original: ex }
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Create an atomic file writer
|
|
132
|
-
* @param path
|
|
133
|
-
*/
|
|
134
|
-
createAtomicWriter(path: PathLike): AtomicWriter {
|
|
135
|
-
return new AtomicWriter(path);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Creates a temporary file name for a given file
|
|
141
|
-
* @param file
|
|
142
|
-
*/
|
|
143
|
-
function getTempFilename(file: PathLike): string {
|
|
144
|
-
const f = file instanceof URL ? fileURLToPath(file) : file.toString();
|
|
145
|
-
return join(dirname(f), `.${basename(f)}.tmp`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Retries an asynchronous operation with a delay between retries and a maximum retry count
|
|
150
|
-
* @param fn
|
|
151
|
-
* @param maxRetries
|
|
152
|
-
* @param delayMs
|
|
153
|
-
*/
|
|
154
|
-
async function retryAsyncOperation(
|
|
155
|
-
fn: () => Promise<void>,
|
|
156
|
-
maxRetries: number,
|
|
157
|
-
delayMs: number
|
|
158
|
-
): Promise<void> {
|
|
159
|
-
for (let i = 0; i < maxRetries; i++) {
|
|
160
|
-
try {
|
|
161
|
-
return await fn();
|
|
162
|
-
} catch (error) {
|
|
163
|
-
if (i < maxRetries - 1) {
|
|
164
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
165
|
-
} else {
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Atomic file writer
|
|
174
|
-
*
|
|
175
|
-
* Allows writing to a file atomically
|
|
176
|
-
* based on https://github.com/typicode/steno
|
|
177
|
-
*/
|
|
178
|
-
export class AtomicWriter {
|
|
179
|
-
private readonly filename: PathLike;
|
|
180
|
-
private readonly tempFilename: PathLike;
|
|
181
|
-
private locked = false;
|
|
182
|
-
private prev: [Resolve, Reject] | null = null;
|
|
183
|
-
private next: [Resolve, Reject] | null = null;
|
|
184
|
-
private nextPromise: Promise<void> | null = null;
|
|
185
|
-
private nextData: Data | null = null;
|
|
186
|
-
|
|
187
|
-
constructor(filename: PathLike) {
|
|
188
|
-
this.filename = filename;
|
|
189
|
-
this.tempFilename = getTempFilename(filename);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Add data for later write
|
|
194
|
-
* @param data
|
|
195
|
-
*/
|
|
196
|
-
private addData(data: Data): Promise<void> {
|
|
197
|
-
// keep only most recent data
|
|
198
|
-
this.nextData = data;
|
|
199
|
-
|
|
200
|
-
// create a singleton promise to resolve all next promises once next data is written
|
|
201
|
-
this.nextPromise ||= new Promise((resolve, reject) => {
|
|
202
|
-
this.next = [resolve, reject];
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// return a promise that will resolve at the same time as next promise
|
|
206
|
-
return new Promise((resolve, reject) => {
|
|
207
|
-
this.nextPromise?.then(resolve).catch(reject);
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Write data to a file atomically
|
|
213
|
-
* @param data
|
|
214
|
-
*/
|
|
215
|
-
private async writeData(data: Data): Promise<void> {
|
|
216
|
-
this.locked = true;
|
|
217
|
-
try {
|
|
218
|
-
await writeFile(this.tempFilename, data, 'utf-8');
|
|
219
|
-
await retryAsyncOperation(
|
|
220
|
-
async () => {
|
|
221
|
-
await rename(this.tempFilename, this.filename);
|
|
222
|
-
},
|
|
223
|
-
10,
|
|
224
|
-
100
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
// resolve
|
|
228
|
-
this.prev?.[0]();
|
|
229
|
-
} catch (err) {
|
|
230
|
-
// reject
|
|
231
|
-
if (err instanceof Error) {
|
|
232
|
-
this.prev?.[1](err);
|
|
233
|
-
}
|
|
234
|
-
throw err;
|
|
235
|
-
} finally {
|
|
236
|
-
this.locked = false;
|
|
237
|
-
|
|
238
|
-
this.prev = this.next;
|
|
239
|
-
this.next = this.nextPromise = null;
|
|
240
|
-
|
|
241
|
-
if (this.nextData !== null) {
|
|
242
|
-
const nextData = this.nextData;
|
|
243
|
-
this.nextData = null;
|
|
244
|
-
await this.write(nextData);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Write data to a file atomically
|
|
251
|
-
* @param data
|
|
252
|
-
*/
|
|
253
|
-
async write(data: Data): Promise<void> {
|
|
254
|
-
try {
|
|
255
|
-
await (this.locked ? this.addData(data) : this.writeData(data));
|
|
256
|
-
} catch (ex) {
|
|
257
|
-
throw new RuniumError(
|
|
258
|
-
`Can not write file ${this.filename}`,
|
|
259
|
-
ErrorCode.FILE_WRITE_ERROR,
|
|
260
|
-
{ path: this.filename, data, original: ex }
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Writes a JSON file
|
|
267
|
-
* @param data
|
|
268
|
-
*/
|
|
269
|
-
async writeJson<T = JSONObject>(data: T): Promise<void> {
|
|
270
|
-
return this.write(JSON.stringify(data, null, 2));
|
|
271
|
-
}
|
|
272
|
-
}
|
package/src/services/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export * from './command.js';
|
|
2
|
-
export * from './config.js';
|
|
3
|
-
export * from './file.js';
|
|
4
|
-
export * from './output.js';
|
|
5
|
-
export * from './profile.js';
|
|
6
|
-
export * from './plugin.js';
|
|
7
|
-
export * from './project.js';
|
|
8
|
-
export * from './shutdown.js';
|
|
9
|
-
export * from './plugin-context.js';
|
package/src/services/output.ts
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { Console } from 'node:console';
|
|
2
|
-
import { Transform } from 'node:stream';
|
|
3
|
-
import { inspect } from 'node:util';
|
|
4
|
-
|
|
5
|
-
import { Service } from 'typedi';
|
|
6
|
-
|
|
7
|
-
export enum OutputLevel {
|
|
8
|
-
TRACE = 0,
|
|
9
|
-
DEBUG = 1,
|
|
10
|
-
INFO = 2,
|
|
11
|
-
WARN = 3,
|
|
12
|
-
ERROR = 4,
|
|
13
|
-
SILENT = 5,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Console dumper
|
|
18
|
-
* wrapper around node console with a transform stream
|
|
19
|
-
*/
|
|
20
|
-
class ConsoleDumper extends Console {
|
|
21
|
-
private readonly transform: Transform;
|
|
22
|
-
|
|
23
|
-
constructor() {
|
|
24
|
-
inspect.defaultOptions.depth = 5;
|
|
25
|
-
|
|
26
|
-
const transform = new Transform({
|
|
27
|
-
transform: (chunk, _, cb) => cb(null, chunk),
|
|
28
|
-
});
|
|
29
|
-
super({
|
|
30
|
-
stdout: transform,
|
|
31
|
-
stderr: transform,
|
|
32
|
-
colorMode: false,
|
|
33
|
-
});
|
|
34
|
-
this.transform = transform;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Get a table output with index column removed
|
|
39
|
-
* @param data
|
|
40
|
-
* @param columns
|
|
41
|
-
*/
|
|
42
|
-
getPatchedTable(data: unknown[], columns?: string[]): string {
|
|
43
|
-
this.table(data, columns);
|
|
44
|
-
|
|
45
|
-
const original = (this.transform.read() || '').toString();
|
|
46
|
-
|
|
47
|
-
// Tables should all start with roughly:
|
|
48
|
-
// ┌─────────┬──────
|
|
49
|
-
// │ (index) │
|
|
50
|
-
// ├─────────┼
|
|
51
|
-
const columnWidth = original.indexOf('┬') + 1;
|
|
52
|
-
|
|
53
|
-
return original
|
|
54
|
-
.split('\n')
|
|
55
|
-
.map((line: string) => line.charAt(0) + line.slice(columnWidth))
|
|
56
|
-
.join('\n')
|
|
57
|
-
.replace(/'([^']*)'/g, '$1 ');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const dumper = new ConsoleDumper();
|
|
62
|
-
|
|
63
|
-
@Service()
|
|
64
|
-
export class OutputService {
|
|
65
|
-
private outputLevel: OutputLevel = OutputLevel.INFO;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Set output level
|
|
69
|
-
* @param level
|
|
70
|
-
*/
|
|
71
|
-
setLevel(level: OutputLevel): void {
|
|
72
|
-
this.outputLevel = level;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get output level
|
|
77
|
-
*/
|
|
78
|
-
getLevel(): OutputLevel {
|
|
79
|
-
return this.outputLevel;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Log a trace message
|
|
84
|
-
* @param message
|
|
85
|
-
* @param args
|
|
86
|
-
*/
|
|
87
|
-
trace(message: string, ...args: unknown[]): void {
|
|
88
|
-
if (this.outputLevel <= OutputLevel.TRACE) {
|
|
89
|
-
// eslint-disable-next-line no-console
|
|
90
|
-
console.log(message, ...args);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Log a debug message
|
|
96
|
-
* @param message
|
|
97
|
-
* @param args
|
|
98
|
-
*/
|
|
99
|
-
debug(message: string, ...args: unknown[]): void {
|
|
100
|
-
if (this.outputLevel <= OutputLevel.DEBUG) {
|
|
101
|
-
// eslint-disable-next-line no-console
|
|
102
|
-
console.log(message, ...args);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Log an info message
|
|
108
|
-
* @param message
|
|
109
|
-
* @param args
|
|
110
|
-
*/
|
|
111
|
-
info(message: string, ...args: unknown[]): void {
|
|
112
|
-
if (this.outputLevel <= OutputLevel.INFO) {
|
|
113
|
-
// eslint-disable-next-line no-console
|
|
114
|
-
console.log(message, ...args);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Log a success message
|
|
120
|
-
* @param message
|
|
121
|
-
* @param args
|
|
122
|
-
*/
|
|
123
|
-
success(message: string, ...args: unknown[]): void {
|
|
124
|
-
if (this.outputLevel <= OutputLevel.INFO) {
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
console.log(message, ...args);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Log a warning message
|
|
132
|
-
* @param message
|
|
133
|
-
* @param args
|
|
134
|
-
*/
|
|
135
|
-
warn(message: string, ...args: unknown[]): void {
|
|
136
|
-
if (this.outputLevel <= OutputLevel.WARN) {
|
|
137
|
-
// eslint-disable-next-line no-console
|
|
138
|
-
console.warn(message, ...args);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Log an error message
|
|
144
|
-
* @param message
|
|
145
|
-
* @param args
|
|
146
|
-
*/
|
|
147
|
-
error(message: string, ...args: unknown[]): void {
|
|
148
|
-
if (this.outputLevel <= OutputLevel.ERROR) {
|
|
149
|
-
// eslint-disable-next-line no-console
|
|
150
|
-
console.error(message, ...args);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Log a message without level
|
|
156
|
-
* @param message
|
|
157
|
-
* @param args
|
|
158
|
-
*/
|
|
159
|
-
log(message: string, ...args: unknown[]): void {
|
|
160
|
-
if (this.outputLevel < OutputLevel.SILENT) {
|
|
161
|
-
// eslint-disable-next-line no-console
|
|
162
|
-
console.log(message, ...args);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Output a table
|
|
168
|
-
* @param data
|
|
169
|
-
* @param columns
|
|
170
|
-
*/
|
|
171
|
-
table(data: unknown[], columns?: string[]): void {
|
|
172
|
-
if (this.outputLevel < OutputLevel.SILENT) {
|
|
173
|
-
const patchedData = data.map((item, index) => ({
|
|
174
|
-
...(item as object),
|
|
175
|
-
'#': index + 1,
|
|
176
|
-
}));
|
|
177
|
-
const patchedOutput = dumper.getPatchedTable(
|
|
178
|
-
patchedData,
|
|
179
|
-
columns ? ['#', ...columns] : undefined
|
|
180
|
-
);
|
|
181
|
-
// eslint-disable-next-line no-console
|
|
182
|
-
console.log(patchedOutput);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Output a blank line
|
|
188
|
-
*/
|
|
189
|
-
newLine(): void {
|
|
190
|
-
if (this.outputLevel < OutputLevel.SILENT) {
|
|
191
|
-
// eslint-disable-next-line no-console
|
|
192
|
-
console.log('');
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Clear output
|
|
198
|
-
*/
|
|
199
|
-
clear(): void {
|
|
200
|
-
if (this.outputLevel < OutputLevel.SILENT) {
|
|
201
|
-
// eslint-disable-next-line no-console
|
|
202
|
-
console.clear();
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { delimiter } from 'node:path';
|
|
2
|
-
import { Inject, Service } from 'typedi';
|
|
3
|
-
import {
|
|
4
|
-
RuniumError,
|
|
5
|
-
isRuniumError,
|
|
6
|
-
RuniumTask,
|
|
7
|
-
RuniumTrigger,
|
|
8
|
-
applyMacros,
|
|
9
|
-
TaskEvent,
|
|
10
|
-
TaskStatus,
|
|
11
|
-
ProjectEvent,
|
|
12
|
-
ProjectStatus,
|
|
13
|
-
} from '@runium/core';
|
|
14
|
-
import { RuniumCommand } from '@commands/runium-command.js';
|
|
15
|
-
import {
|
|
16
|
-
CommandService,
|
|
17
|
-
FileService,
|
|
18
|
-
OutputLevel,
|
|
19
|
-
OutputService,
|
|
20
|
-
ProfileService,
|
|
21
|
-
ShutdownService,
|
|
22
|
-
} from '@services';
|
|
23
|
-
import { getVersion } from '@utils';
|
|
24
|
-
import { ErrorCode } from '@constants';
|
|
25
|
-
|
|
26
|
-
global.runium = null;
|
|
27
|
-
|
|
28
|
-
@Service()
|
|
29
|
-
export class PluginContextService {
|
|
30
|
-
constructor(
|
|
31
|
-
@Inject() private commandService: CommandService,
|
|
32
|
-
@Inject() private outputService: OutputService,
|
|
33
|
-
@Inject() private shutdownService: ShutdownService,
|
|
34
|
-
@Inject() private fileService: FileService,
|
|
35
|
-
@Inject() private profileService: ProfileService
|
|
36
|
-
) {}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Create a wrapper for a file service method that processes path parts
|
|
40
|
-
* @param methodName
|
|
41
|
-
*/
|
|
42
|
-
private createStorageWrapper<T extends keyof FileService>(
|
|
43
|
-
methodName: T
|
|
44
|
-
): FileService[T] {
|
|
45
|
-
return ((...args: unknown[]) => {
|
|
46
|
-
const [pathParts, ...rest] = args;
|
|
47
|
-
const resolvedPath = this.resolveProfilePath(
|
|
48
|
-
pathParts as string | string[]
|
|
49
|
-
);
|
|
50
|
-
const method = this.fileService[methodName] as (
|
|
51
|
-
...args: unknown[]
|
|
52
|
-
) => unknown;
|
|
53
|
-
return method(resolvedPath, ...rest);
|
|
54
|
-
}) as FileService[T];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Resolve path parts using profileService
|
|
59
|
-
* @param pathParts
|
|
60
|
-
*/
|
|
61
|
-
private resolveProfilePath(pathParts: string | string[]): string {
|
|
62
|
-
const parts = Array.isArray(pathParts)
|
|
63
|
-
? pathParts
|
|
64
|
-
: pathParts.split(delimiter);
|
|
65
|
-
if (parts.length === 0 || parts.every(part => part.trim() === '')) {
|
|
66
|
-
throw new RuniumError('Invalid path', ErrorCode.INVALID_PATH, {
|
|
67
|
-
path: pathParts,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
return this.profileService.getPath(...parts);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Initialize the plugin context service
|
|
75
|
-
*/
|
|
76
|
-
async init(): Promise<void> {
|
|
77
|
-
const command = this.commandService;
|
|
78
|
-
const output = this.outputService;
|
|
79
|
-
const shutdown = this.shutdownService;
|
|
80
|
-
|
|
81
|
-
const runium = {
|
|
82
|
-
class: {
|
|
83
|
-
RuniumCommand,
|
|
84
|
-
RuniumError,
|
|
85
|
-
RuniumTask,
|
|
86
|
-
RuniumTrigger,
|
|
87
|
-
},
|
|
88
|
-
enum: {
|
|
89
|
-
OutputLevel: Object.keys(OutputLevel)
|
|
90
|
-
.filter(key => isNaN(Number(key)))
|
|
91
|
-
.reduce(
|
|
92
|
-
(acc, key) => {
|
|
93
|
-
acc[key] = OutputLevel[key as keyof typeof OutputLevel];
|
|
94
|
-
return acc;
|
|
95
|
-
},
|
|
96
|
-
{} as Record<string, number>
|
|
97
|
-
),
|
|
98
|
-
ProjectEvent,
|
|
99
|
-
ProjectStatus,
|
|
100
|
-
TaskEvent,
|
|
101
|
-
TaskStatus,
|
|
102
|
-
},
|
|
103
|
-
utils: {
|
|
104
|
-
applyMacros,
|
|
105
|
-
isRuniumError,
|
|
106
|
-
},
|
|
107
|
-
output: {
|
|
108
|
-
getLevel: output.getLevel.bind(output),
|
|
109
|
-
setLevel: output.setLevel.bind(output),
|
|
110
|
-
trace: output.trace.bind(output),
|
|
111
|
-
debug: output.debug.bind(output),
|
|
112
|
-
info: output.info.bind(output),
|
|
113
|
-
warn: output.warn.bind(output),
|
|
114
|
-
error: output.error.bind(output),
|
|
115
|
-
table: output.table.bind(output),
|
|
116
|
-
log: output.log.bind(output),
|
|
117
|
-
},
|
|
118
|
-
shutdown: {
|
|
119
|
-
addBlocker: shutdown.addBlocker.bind(shutdown),
|
|
120
|
-
removeBlocker: shutdown.removeBlocker.bind(shutdown),
|
|
121
|
-
},
|
|
122
|
-
command: {
|
|
123
|
-
has: command.hasCommand.bind(command),
|
|
124
|
-
run: command.runCommand.bind(command),
|
|
125
|
-
},
|
|
126
|
-
storage: {
|
|
127
|
-
read: this.createStorageWrapper('read'),
|
|
128
|
-
write: this.createStorageWrapper('write'),
|
|
129
|
-
readJson: this.createStorageWrapper('readJson'),
|
|
130
|
-
writeJson: this.createStorageWrapper('writeJson'),
|
|
131
|
-
isExists: this.createStorageWrapper('isExists'),
|
|
132
|
-
ensureDirExists: this.createStorageWrapper('ensureDirExists'),
|
|
133
|
-
createAtomicWriter: this.createStorageWrapper('createAtomicWriter'),
|
|
134
|
-
getPath: this.resolveProfilePath.bind(this),
|
|
135
|
-
},
|
|
136
|
-
version: getVersion(),
|
|
137
|
-
};
|
|
138
|
-
global.runium = Object.freeze(runium);
|
|
139
|
-
}
|
|
140
|
-
}
|