@plugjs/plug 0.2.6 → 0.3.0
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/cli/plug.mjs +3 -15
- package/cli/ts-loader.mjs +1 -1
- package/cli/tsrun.mjs +1104 -36
- package/dist/asserts.cjs +4 -0
- package/dist/asserts.cjs.map +1 -1
- package/dist/asserts.mjs +4 -0
- package/dist/asserts.mjs.map +1 -1
- package/dist/fork.cjs +8 -5
- package/dist/fork.cjs.map +1 -1
- package/dist/fork.mjs +8 -5
- package/dist/fork.mjs.map +1 -1
- package/dist/fs.cjs +1 -1
- package/dist/helpers.cjs +20 -0
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.ts +6 -0
- package/dist/helpers.mjs +20 -1
- package/dist/helpers.mjs.map +1 -1
- package/dist/index.cjs +8 -8
- package/dist/logging/emit.cjs +4 -7
- package/dist/logging/emit.cjs.map +1 -1
- package/dist/logging/emit.mjs +4 -7
- package/dist/logging/emit.mjs.map +1 -1
- package/dist/logging/github.cjs +63 -0
- package/dist/logging/github.cjs.map +6 -0
- package/dist/logging/github.d.ts +13 -0
- package/dist/logging/github.mjs +38 -0
- package/dist/logging/github.mjs.map +6 -0
- package/dist/logging/options.cjs +20 -3
- package/dist/logging/options.cjs.map +1 -1
- package/dist/logging/options.d.ts +9 -2
- package/dist/logging/options.mjs +20 -3
- package/dist/logging/options.mjs.map +1 -1
- package/dist/logging/report.cjs +25 -3
- package/dist/logging/report.cjs.map +1 -1
- package/dist/logging/report.mjs +26 -4
- package/dist/logging/report.mjs.map +1 -1
- package/dist/logging.cjs +1 -0
- package/dist/logging.cjs.map +1 -1
- package/dist/logging.d.ts +1 -0
- package/dist/logging.mjs +1 -0
- package/dist/logging.mjs.map +1 -1
- package/dist/plugs/debug.mjs +18 -28
- package/dist/plugs/debug.mjs.map +1 -1
- package/dist/plugs/edit.mjs +13 -23
- package/dist/plugs/edit.mjs.map +1 -1
- package/dist/plugs/esbuild/fix-extensions.cjs +1 -1
- package/dist/plugs/rmf.mjs +14 -24
- package/dist/plugs/rmf.mjs.map +1 -1
- package/dist/utils/exec.cjs +22 -15
- package/dist/utils/exec.cjs.map +2 -2
- package/dist/utils/exec.mjs +21 -14
- package/dist/utils/exec.mjs.map +1 -1
- package/dist/utils/match.cjs +1 -1
- package/extra/plug.mts +6 -3
- package/extra/tsrun.mts +91 -28
- package/extra/utils.ts +0 -18
- package/package.json +4 -5
- package/src/asserts.ts +7 -0
- package/src/fork.ts +10 -5
- package/src/helpers.ts +24 -1
- package/src/logging/emit.ts +2 -7
- package/src/logging/github.ts +71 -0
- package/src/logging/options.ts +29 -4
- package/src/logging/report.ts +40 -6
- package/src/logging.ts +1 -0
- package/src/utils/exec.ts +29 -18
package/src/logging/options.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events'
|
|
2
|
+
import { Socket } from 'node:net'
|
|
2
3
|
|
|
3
4
|
import { getLevelNumber, NOTICE } from './levels'
|
|
4
5
|
|
|
@@ -28,6 +29,8 @@ export interface LogOptions {
|
|
|
28
29
|
showSources: boolean,
|
|
29
30
|
/** The task name to be used by default if a task is not contextualized. */
|
|
30
31
|
defaultTaskName: string,
|
|
32
|
+
/** Whether GitHub annotations are enabled or not. */
|
|
33
|
+
githubAnnotations: boolean,
|
|
31
34
|
/** The options used by NodeJS for object inspection. */
|
|
32
35
|
readonly inspectOptions: InspectOptions,
|
|
33
36
|
|
|
@@ -41,8 +44,13 @@ export interface LogOptions {
|
|
|
41
44
|
/** Remove an event listener for the specified event. */
|
|
42
45
|
off(eventName: 'changed', listener: (logOptions: this) => void): this;
|
|
43
46
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Return a record of environment variables for forking.
|
|
49
|
+
*
|
|
50
|
+
* @param taskName The default task name of the forked process
|
|
51
|
+
* @param logFd A file descriptor where logs should be sinked to
|
|
52
|
+
*/
|
|
53
|
+
forkEnv(taskName?: string, logFd?: number): Record<string, string>
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
/* ========================================================================== *
|
|
@@ -58,6 +66,7 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
58
66
|
private _lineLength = (<NodeJS.WriteStream> this._output).columns || 80
|
|
59
67
|
private _lineLengthSet = false // has line length been set manually?
|
|
60
68
|
private _showSources = true // by default, always show source snippets
|
|
69
|
+
private _githubAnnotations = false // ultimately set by the constructor
|
|
61
70
|
private _inspectOptions: InspectOptions = {}
|
|
62
71
|
private _defaultTaskName = ''
|
|
63
72
|
private _taskLength = 0
|
|
@@ -78,27 +87,34 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
78
87
|
// Other values don't change the value of `options.colors`
|
|
79
88
|
}
|
|
80
89
|
|
|
90
|
+
/* If the `GITHUB_ACTIONS` is `true` then enable annotations */
|
|
91
|
+
this._githubAnnotations = process.env.GITHUB_ACTIONS === 'true'
|
|
92
|
+
|
|
81
93
|
/*
|
|
82
94
|
* The `__LOG_OPTIONS` variable is a JSON-serialized `LogOptions` object
|
|
83
95
|
* and it's processed _last_ as it's normally only created by fork below
|
|
84
96
|
* and consumed by the `Exec` plug (which has no other way of communicating)
|
|
85
97
|
*/
|
|
86
|
-
|
|
98
|
+
const { fd, ...options } = JSON.parse(process.env.__LOG_OPTIONS || '{}')
|
|
99
|
+
if (fd) this.output = new Socket({ fd }).unref()
|
|
100
|
+
Object.assign(this, options)
|
|
87
101
|
}
|
|
88
102
|
|
|
89
103
|
private _notifyListeners(): void {
|
|
90
104
|
super.emit('changed', this)
|
|
91
105
|
}
|
|
92
106
|
|
|
93
|
-
forkEnv(taskName?: string): Record<string, string> {
|
|
107
|
+
forkEnv(taskName?: string, fd?: number): Record<string, string> {
|
|
94
108
|
return {
|
|
95
109
|
__LOG_OPTIONS: JSON.stringify({
|
|
96
110
|
level: this._level,
|
|
97
111
|
colors: this._colors,
|
|
98
112
|
lineLength: this._lineLength,
|
|
99
113
|
taskLength: this._taskLength,
|
|
114
|
+
githubAnnotations: this.githubAnnotations,
|
|
100
115
|
defaultTaskName: taskName || this._defaultTaskName,
|
|
101
116
|
spinner: false, // forked spinner is always false
|
|
117
|
+
fd, // file descriptor for logs
|
|
102
118
|
}),
|
|
103
119
|
}
|
|
104
120
|
}
|
|
@@ -189,6 +205,15 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
189
205
|
this._notifyListeners()
|
|
190
206
|
}
|
|
191
207
|
|
|
208
|
+
get githubAnnotations(): boolean {
|
|
209
|
+
return this._githubAnnotations
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
set githubAnnotations(githubAnnotations: boolean) {
|
|
213
|
+
this._githubAnnotations = githubAnnotations
|
|
214
|
+
this._notifyListeners()
|
|
215
|
+
}
|
|
216
|
+
|
|
192
217
|
get inspectOptions(): InspectOptions {
|
|
193
218
|
return {
|
|
194
219
|
colors: this._colors,
|
package/src/logging/report.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { BuildFailure } from '../asserts'
|
|
2
2
|
import { readFile } from '../fs'
|
|
3
3
|
import { $blu, $cyn, $gry, $red, $und, $wht, $ylw } from './colors'
|
|
4
|
-
import { ERROR, NOTICE, WARN } from './levels'
|
|
4
|
+
import { ERROR, logLevels, NOTICE, WARN } from './levels'
|
|
5
5
|
import { logOptions } from './options'
|
|
6
|
+
import { githubAnnotation } from './github'
|
|
6
7
|
|
|
7
8
|
import type { AbsolutePath } from '../paths'
|
|
8
9
|
import type { LogEmitter } from './emit'
|
|
9
10
|
import type { LogLevels } from './levels'
|
|
10
11
|
|
|
12
|
+
let _showSources = logOptions.showSources
|
|
13
|
+
let _githubAnnotations = logOptions.githubAnnotations
|
|
14
|
+
logOptions.on('changed', (options) => {
|
|
15
|
+
_showSources = options.showSources
|
|
16
|
+
_githubAnnotations = options.githubAnnotations
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
|
|
11
20
|
/* ========================================================================== */
|
|
12
21
|
|
|
13
22
|
/** Levels used in a {@link Report} */
|
|
@@ -267,12 +276,12 @@ export class ReportImpl implements Report {
|
|
|
267
276
|
|
|
268
277
|
|
|
269
278
|
done(showSources?: boolean | undefined): void {
|
|
270
|
-
if (showSources == null) showSources =
|
|
279
|
+
if (showSources == null) showSources = _showSources
|
|
271
280
|
if (! this.empty) this._emit(showSources)
|
|
272
281
|
if (this.errors) throw BuildFailure.fail()
|
|
273
282
|
}
|
|
274
283
|
|
|
275
|
-
private _emit(showSources: boolean):
|
|
284
|
+
private _emit(showSources: boolean): void {
|
|
276
285
|
/* Counters for all we need to print nicely */
|
|
277
286
|
let fPad = 0
|
|
278
287
|
let aPad = 0
|
|
@@ -281,7 +290,7 @@ export class ReportImpl implements Report {
|
|
|
281
290
|
let cPad = 0
|
|
282
291
|
|
|
283
292
|
/* Skip report all together if empty! */
|
|
284
|
-
if ((this._annotations.size === 0) && (this._records.size === 0)) return
|
|
293
|
+
if ((this._annotations.size === 0) && (this._records.size === 0)) return
|
|
285
294
|
|
|
286
295
|
/* This is GIANT: sort and convert our data for easy reporting */
|
|
287
296
|
const entries = [ ...this._annotations.keys(), ...this._records.keys() ]
|
|
@@ -431,7 +440,32 @@ export class ReportImpl implements Report {
|
|
|
431
440
|
this._emitter(options, [ '' ])
|
|
432
441
|
}
|
|
433
442
|
|
|
434
|
-
/*
|
|
435
|
-
|
|
443
|
+
/* Annotate in GitHub */
|
|
444
|
+
if (_githubAnnotations) {
|
|
445
|
+
for (const entry of entries) {
|
|
446
|
+
const file = entry.file === nul ? undefined : entry.file
|
|
447
|
+
|
|
448
|
+
for (const report of entry.records) {
|
|
449
|
+
const type: 'error' | 'warning' | null =
|
|
450
|
+
report.level === logLevels.ERROR ? 'error' :
|
|
451
|
+
report.level === logLevels.WARN ? 'warning' :
|
|
452
|
+
null
|
|
453
|
+
|
|
454
|
+
if (! type) continue
|
|
455
|
+
|
|
456
|
+
const title = `${this._title} (task "${this._task}")`
|
|
457
|
+
const col = report.column || undefined
|
|
458
|
+
const line = report.line || undefined
|
|
459
|
+
const endColumn =
|
|
460
|
+
report.column ?
|
|
461
|
+
report.length >= Number.MAX_SAFE_INTEGER ? undefined :
|
|
462
|
+
((report.column + report.length) || undefined) :
|
|
463
|
+
undefined
|
|
464
|
+
const message = report.messages.join('\n')
|
|
465
|
+
|
|
466
|
+
githubAnnotation({ type, title, file, col, line, endColumn }, message)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
436
470
|
}
|
|
437
471
|
}
|
package/src/logging.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { getLogger, type Log } from './logging/logger'
|
|
|
3
3
|
import { setupSpinner } from './logging/spinner'
|
|
4
4
|
|
|
5
5
|
export * from './logging/colors'
|
|
6
|
+
export * from './logging/github'
|
|
6
7
|
export * from './logging/levels'
|
|
7
8
|
export * from './logging/logger'
|
|
8
9
|
export * from './logging/options'
|
package/src/utils/exec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import
|
|
2
|
+
import readline from 'node:readline'
|
|
3
3
|
import { fork as forkProcess, spawn as spawnProcess } from 'node:child_process'
|
|
4
4
|
|
|
5
5
|
import { assert, BuildFailure } from '../asserts'
|
|
@@ -62,7 +62,7 @@ export async function execChild(
|
|
|
62
62
|
|
|
63
63
|
// Build our environment variables record
|
|
64
64
|
const PATH = childPaths.join(path.delimiter)
|
|
65
|
-
const logForkEnv = logOptions.forkEnv(context.taskName)
|
|
65
|
+
const logForkEnv = logOptions.forkEnv(context.taskName, 4)
|
|
66
66
|
const childEnv: Record<string, string> = { ...process.env, ...env, ...logForkEnv, PATH }
|
|
67
67
|
|
|
68
68
|
// Instrument coverage directory if needed
|
|
@@ -71,32 +71,43 @@ export async function execChild(
|
|
|
71
71
|
// Prepare the options for calling `spawn`
|
|
72
72
|
const childOptions: SpawnOptions = {
|
|
73
73
|
...extraOptions,
|
|
74
|
-
stdio: [ 'ignore', 'pipe', 'pipe' ],
|
|
74
|
+
stdio: [ 'ignore', 'pipe', 'pipe', 'ipc', 'pipe' ],
|
|
75
75
|
cwd: childCwd,
|
|
76
76
|
env: childEnv,
|
|
77
77
|
shell,
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// Add the 'ipc' channel to stdio options if forking
|
|
81
|
-
if (fork) childOptions.stdio = [ 'ignore', 'pipe', 'pipe', 'ipc' ]
|
|
82
|
-
|
|
83
80
|
// Spawn our subprocess and monitor its stdout/stderr
|
|
84
|
-
context.log.info('Executing', [ cmd, ...args ])
|
|
85
|
-
context.log.
|
|
81
|
+
context.log.info(fork ? 'Forking' : 'Executing', [ cmd, ...args ])
|
|
82
|
+
context.log.debug('Child process options', childOptions)
|
|
83
|
+
|
|
86
84
|
const child = fork ?
|
|
87
85
|
forkProcess(cmd, args, childOptions) :
|
|
88
86
|
spawnProcess(cmd, args, childOptions)
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
try {
|
|
89
|
+
context.log.info('Child process PID', child.pid)
|
|
90
|
+
|
|
91
|
+
// Standard output to "notice"
|
|
92
|
+
if (child.stdout) {
|
|
93
|
+
const out = readline.createInterface(child.stdout)
|
|
94
|
+
out.on('line', (line) => context.log.notice(line || '\u00a0'))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Standard error to "warning"
|
|
98
|
+
if (child.stderr) {
|
|
99
|
+
const err = readline.createInterface(child.stderr)
|
|
100
|
+
err.on('line', (line) => context.log.warn(line ||'\u00a0'))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Log output bypass
|
|
104
|
+
if (child.stdio[4]) {
|
|
105
|
+
child.stdio[4].on('data', (data) => logOptions.output.write(data))
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
// If something happens before returning our promise, kill the child...
|
|
109
|
+
child.kill()
|
|
110
|
+
throw error
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
// Return our promise from the spawn events
|