@plugjs/plug 0.0.27 → 0.1.1
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/dist/{failure.cjs → asserts.cjs} +30 -10
- package/dist/asserts.cjs.map +6 -0
- package/dist/{failure.d.ts → asserts.d.ts} +4 -1
- package/dist/asserts.mjs +51 -0
- package/dist/asserts.mjs.map +6 -0
- package/dist/async.cjs +2 -2
- package/dist/async.cjs.map +1 -1
- package/dist/async.mjs +2 -2
- package/dist/async.mjs.map +1 -1
- package/dist/build.cjs +22 -33
- package/dist/build.cjs.map +1 -1
- package/dist/build.d.ts +2 -13
- package/dist/build.mjs +17 -27
- package/dist/build.mjs.map +1 -1
- package/dist/files.cjs +7 -11
- package/dist/files.cjs.map +1 -1
- package/dist/files.mjs +5 -9
- package/dist/files.mjs.map +1 -1
- package/dist/fork.cjs +35 -30
- package/dist/fork.cjs.map +1 -1
- package/dist/fork.d.ts +6 -3
- package/dist/fork.mjs +18 -13
- package/dist/fork.mjs.map +1 -1
- package/dist/{utils/asyncfs.cjs → fs.cjs} +6 -6
- package/dist/fs.cjs.map +6 -0
- package/dist/{utils/asyncfs.d.ts → fs.d.ts} +1 -1
- package/dist/{utils/asyncfs.mjs → fs.mjs} +3 -3
- package/dist/fs.mjs.map +6 -0
- package/dist/helpers.cjs +31 -14
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.ts +30 -1
- package/dist/helpers.mjs +22 -7
- package/dist/helpers.mjs.map +1 -1
- package/dist/index.cjs +36 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +25 -8
- package/dist/index.mjs +20 -5
- package/dist/index.mjs.map +1 -1
- package/dist/{log → logging}/colors.cjs +1 -1
- package/dist/{log → logging}/colors.cjs.map +1 -1
- package/dist/{log → logging}/colors.d.ts +0 -0
- package/dist/{log → logging}/colors.mjs +1 -1
- package/dist/{log → logging}/colors.mjs.map +1 -1
- package/dist/{log → logging}/emit.cjs +1 -2
- package/dist/{log → logging}/emit.cjs.map +2 -2
- package/dist/{log → logging}/emit.d.ts +1 -1
- package/dist/{log → logging}/emit.mjs +1 -2
- package/dist/{log → logging}/emit.mjs.map +2 -2
- package/dist/{log → logging}/levels.cjs +1 -1
- package/dist/{log → logging}/levels.cjs.map +1 -1
- package/dist/{log → logging}/levels.d.ts +6 -6
- package/dist/{log → logging}/levels.mjs +1 -1
- package/dist/{log → logging}/levels.mjs.map +1 -1
- package/dist/{log → logging}/logger.cjs +13 -7
- package/dist/logging/logger.cjs.map +6 -0
- package/dist/{log → logging}/logger.d.ts +0 -0
- package/dist/{log → logging}/logger.mjs +11 -5
- package/dist/logging/logger.mjs.map +6 -0
- package/dist/{log → logging}/options.cjs +12 -6
- package/dist/logging/options.cjs.map +6 -0
- package/dist/{log → logging}/options.d.ts +1 -1
- package/dist/{log → logging}/options.mjs +12 -6
- package/dist/logging/options.mjs.map +6 -0
- package/dist/{log → logging}/report.cjs +11 -11
- package/dist/logging/report.cjs.map +6 -0
- package/dist/{log → logging}/report.d.ts +1 -1
- package/dist/{log → logging}/report.mjs +8 -8
- package/dist/logging/report.mjs.map +6 -0
- package/dist/{log → logging}/spinner.cjs +1 -1
- package/dist/{log → logging}/spinner.cjs.map +1 -1
- package/dist/{log → logging}/spinner.d.ts +0 -0
- package/dist/{log → logging}/spinner.mjs +1 -1
- package/dist/{log → logging}/spinner.mjs.map +1 -1
- package/dist/{log.cjs → logging.cjs} +13 -16
- package/dist/logging.cjs.map +6 -0
- package/dist/logging.d.ts +10 -0
- package/dist/{log.mjs → logging.mjs} +10 -13
- package/dist/logging.mjs.map +6 -0
- package/dist/paths.cjs +25 -27
- package/dist/paths.cjs.map +1 -1
- package/dist/paths.d.ts +8 -8
- package/dist/paths.mjs +23 -25
- package/dist/paths.mjs.map +1 -1
- package/dist/pipe.cjs +10 -13
- package/dist/pipe.cjs.map +1 -1
- package/dist/pipe.d.ts +13 -19
- package/dist/pipe.mjs +6 -9
- package/dist/pipe.mjs.map +1 -1
- package/dist/plugs/copy.cjs +14 -14
- package/dist/plugs/copy.cjs.map +1 -1
- package/dist/plugs/copy.d.ts +1 -1
- package/dist/plugs/copy.mjs +3 -3
- package/dist/plugs/copy.mjs.map +1 -1
- package/dist/plugs/debug.cjs +7 -7
- package/dist/plugs/debug.cjs.map +1 -1
- package/dist/plugs/debug.d.ts +1 -1
- package/dist/plugs/debug.mjs +1 -1
- package/dist/plugs/edit.cjs +21 -0
- package/dist/plugs/edit.cjs.map +6 -0
- package/dist/plugs/edit.d.ts +7 -0
- package/dist/plugs/edit.mjs +29 -0
- package/dist/plugs/edit.mjs.map +6 -0
- package/dist/plugs/esbuild/fix-extensions.cjs +7 -8
- package/dist/plugs/esbuild/fix-extensions.cjs.map +1 -1
- package/dist/plugs/esbuild/fix-extensions.mjs +4 -5
- package/dist/plugs/esbuild/fix-extensions.mjs.map +1 -1
- package/dist/plugs/esbuild.cjs +19 -14
- package/dist/plugs/esbuild.cjs.map +1 -1
- package/dist/plugs/esbuild.d.ts +2 -2
- package/dist/plugs/esbuild.mjs +8 -3
- package/dist/plugs/esbuild.mjs.map +1 -1
- package/dist/plugs/exec.cjs +2 -82
- package/dist/plugs/exec.cjs.map +2 -2
- package/dist/plugs/exec.d.ts +6 -32
- package/dist/plugs/exec.mjs +2 -68
- package/dist/plugs/exec.mjs.map +1 -1
- package/dist/plugs/filter.d.ts +1 -1
- package/dist/plugs/rmf.cjs +5 -5
- package/dist/plugs/rmf.cjs.map +1 -1
- package/dist/plugs/rmf.d.ts +1 -1
- package/dist/plugs/rmf.mjs +2 -2
- package/dist/plugs/rmf.mjs.map +1 -1
- package/dist/plugs.cjs +1 -4
- package/dist/plugs.cjs.map +1 -1
- package/dist/plugs.d.ts +1 -4
- package/dist/plugs.mjs +1 -4
- package/dist/plugs.mjs.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/utils/caller.cjs +8 -5
- package/dist/utils/caller.cjs.map +1 -1
- package/dist/utils/caller.mjs +6 -3
- package/dist/utils/caller.mjs.map +1 -1
- package/dist/utils/exec.cjs +102 -0
- package/dist/utils/exec.cjs.map +6 -0
- package/dist/utils/exec.d.ts +15 -0
- package/dist/utils/exec.mjs +71 -0
- package/dist/utils/exec.mjs.map +6 -0
- package/dist/utils/match.d.ts +1 -1
- package/dist/utils/options.d.ts +3 -3
- package/dist/utils/walk.cjs +7 -7
- package/dist/utils/walk.cjs.map +1 -1
- package/dist/utils/walk.mjs +2 -2
- package/dist/utils/walk.mjs.map +1 -1
- package/dist/{plugs/tsc.cjs → utils.cjs} +9 -7
- package/dist/utils.cjs.map +6 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.mjs +6 -0
- package/dist/utils.mjs.map +6 -0
- package/extra/cli.mjs +26 -5
- package/extra/ts-loader.mjs +4 -4
- package/package.json +101 -20
- package/src/{assert.ts → asserts.ts} +36 -1
- package/src/async.ts +3 -1
- package/src/build.ts +179 -0
- package/src/files.ts +5 -5
- package/src/fork.ts +19 -11
- package/src/{utils/asyncfs.ts → fs.ts} +7 -6
- package/src/helpers.ts +56 -8
- package/src/index.ts +30 -8
- package/src/{log → logging}/colors.ts +0 -0
- package/src/{log → logging}/emit.ts +0 -1
- package/src/{log → logging}/levels.ts +0 -0
- package/src/{log → logging}/logger.ts +13 -4
- package/src/{log → logging}/options.ts +11 -7
- package/src/{log → logging}/report.ts +10 -9
- package/src/{log → logging}/spinner.ts +0 -0
- package/src/{log.ts → logging.ts} +7 -7
- package/src/paths.ts +36 -41
- package/src/pipe.ts +13 -20
- package/src/plugs/copy.ts +4 -4
- package/src/plugs/debug.ts +2 -2
- package/src/plugs/edit.ts +34 -0
- package/src/plugs/esbuild/fix-extensions.ts +2 -2
- package/src/plugs/esbuild.ts +13 -7
- package/src/plugs/exec.ts +8 -129
- package/src/plugs/filter.ts +1 -1
- package/src/plugs/rmf.ts +3 -3
- package/src/plugs.ts +1 -13
- package/src/types.ts +1 -1
- package/src/utils/caller.ts +6 -3
- package/src/utils/exec.ts +112 -0
- package/src/utils/walk.ts +3 -3
- package/src/utils.ts +4 -0
- package/types/{webassembly.d.ts → plugjs.d.ts} +7 -1
- package/dist/assert.cjs +0 -52
- package/dist/assert.cjs.map +0 -6
- package/dist/assert.d.ts +0 -4
- package/dist/assert.mjs +0 -26
- package/dist/assert.mjs.map +0 -6
- package/dist/failure.cjs.map +0 -6
- package/dist/failure.mjs +0 -33
- package/dist/failure.mjs.map +0 -6
- package/dist/log/logger.cjs.map +0 -6
- package/dist/log/logger.mjs.map +0 -6
- package/dist/log/options.cjs.map +0 -6
- package/dist/log/options.mjs.map +0 -6
- package/dist/log/report.cjs.map +0 -6
- package/dist/log/report.mjs.map +0 -6
- package/dist/log.cjs.map +0 -6
- package/dist/log.d.ts +0 -10
- package/dist/log.mjs.map +0 -6
- package/dist/plugs/coverage/analysis.cjs +0 -234
- package/dist/plugs/coverage/analysis.cjs.map +0 -6
- package/dist/plugs/coverage/analysis.d.ts +0 -104
- package/dist/plugs/coverage/analysis.mjs +0 -207
- package/dist/plugs/coverage/analysis.mjs.map +0 -6
- package/dist/plugs/coverage/report.cjs +0 -235
- package/dist/plugs/coverage/report.cjs.map +0 -6
- package/dist/plugs/coverage/report.d.ts +0 -59
- package/dist/plugs/coverage/report.mjs +0 -220
- package/dist/plugs/coverage/report.mjs.map +0 -6
- package/dist/plugs/coverage.cjs +0 -140
- package/dist/plugs/coverage.cjs.map +0 -6
- package/dist/plugs/coverage.d.ts +0 -49
- package/dist/plugs/coverage.mjs +0 -123
- package/dist/plugs/coverage.mjs.map +0 -6
- package/dist/plugs/eslint/runner.cjs +0 -91
- package/dist/plugs/eslint/runner.cjs.map +0 -6
- package/dist/plugs/eslint/runner.d.ts +0 -8
- package/dist/plugs/eslint/runner.mjs +0 -68
- package/dist/plugs/eslint/runner.mjs.map +0 -6
- package/dist/plugs/eslint.cjs +0 -22
- package/dist/plugs/eslint.cjs.map +0 -6
- package/dist/plugs/eslint.d.ts +0 -34
- package/dist/plugs/eslint.mjs +0 -5
- package/dist/plugs/eslint.mjs.map +0 -6
- package/dist/plugs/mocha/reporter.cjs +0 -159
- package/dist/plugs/mocha/reporter.cjs.map +0 -6
- package/dist/plugs/mocha/reporter.d.ts +0 -6
- package/dist/plugs/mocha/reporter.mjs +0 -127
- package/dist/plugs/mocha/reporter.mjs.map +0 -6
- package/dist/plugs/mocha/runner.cjs +0 -82
- package/dist/plugs/mocha/runner.cjs.map +0 -6
- package/dist/plugs/mocha/runner.d.ts +0 -8
- package/dist/plugs/mocha/runner.mjs +0 -53
- package/dist/plugs/mocha/runner.mjs.map +0 -6
- package/dist/plugs/mocha.cjs +0 -22
- package/dist/plugs/mocha.cjs.map +0 -6
- package/dist/plugs/mocha.d.ts +0 -37
- package/dist/plugs/mocha.mjs +0 -5
- package/dist/plugs/mocha.mjs.map +0 -6
- package/dist/plugs/tsc/compiler.cjs +0 -74
- package/dist/plugs/tsc/compiler.cjs.map +0 -6
- package/dist/plugs/tsc/compiler.d.ts +0 -24
- package/dist/plugs/tsc/compiler.mjs +0 -43
- package/dist/plugs/tsc/compiler.mjs.map +0 -6
- package/dist/plugs/tsc/options.cjs +0 -82
- package/dist/plugs/tsc/options.cjs.map +0 -6
- package/dist/plugs/tsc/options.d.ts +0 -8
- package/dist/plugs/tsc/options.mjs +0 -51
- package/dist/plugs/tsc/options.mjs.map +0 -6
- package/dist/plugs/tsc/report.cjs +0 -90
- package/dist/plugs/tsc/report.cjs.map +0 -6
- package/dist/plugs/tsc/report.d.ts +0 -5
- package/dist/plugs/tsc/report.mjs +0 -59
- package/dist/plugs/tsc/report.mjs.map +0 -6
- package/dist/plugs/tsc/runner.cjs +0 -124
- package/dist/plugs/tsc/runner.cjs.map +0 -6
- package/dist/plugs/tsc/runner.d.ts +0 -8
- package/dist/plugs/tsc/runner.mjs +0 -95
- package/dist/plugs/tsc/runner.mjs.map +0 -6
- package/dist/plugs/tsc.cjs.map +0 -6
- package/dist/plugs/tsc.d.ts +0 -48
- package/dist/plugs/tsc.mjs +0 -5
- package/dist/plugs/tsc.mjs.map +0 -6
- package/dist/utils/asyncfs.cjs.map +0 -6
- package/dist/utils/asyncfs.mjs.map +0 -6
- package/src/failure.ts +0 -43
- package/src/plugs/coverage/analysis.ts +0 -400
- package/src/plugs/coverage/report.ts +0 -368
- package/src/plugs/coverage.ts +0 -216
- package/src/plugs/eslint/runner.ts +0 -100
- package/src/plugs/eslint.ts +0 -42
- package/src/plugs/mocha/reporter.ts +0 -178
- package/src/plugs/mocha/runner.ts +0 -66
- package/src/plugs/mocha.ts +0 -43
- package/src/plugs/tsc/compiler.ts +0 -68
- package/src/plugs/tsc/options.ts +0 -100
- package/src/plugs/tsc/report.ts +0 -77
- package/src/plugs/tsc/runner.ts +0 -133
- package/src/plugs/tsc.ts +0 -58
- package/types/globals.d.ts +0 -15
package/src/build.ts
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { assert } from './asserts'
|
|
2
|
+
import { runAsync } from './async'
|
|
3
|
+
import { $ms, $t, getLogger, log, logOptions } from './logging'
|
|
4
|
+
import { Context, ContextPromises, PipeImpl } from './pipe'
|
|
5
|
+
import { findCaller } from './utils/caller'
|
|
6
|
+
import { parseOptions } from './utils/options'
|
|
7
|
+
|
|
8
|
+
import type { Pipe } from './index'
|
|
9
|
+
import type { AbsolutePath } from './paths'
|
|
10
|
+
import type {
|
|
11
|
+
Build,
|
|
12
|
+
BuildDef,
|
|
13
|
+
Props,
|
|
14
|
+
Result,
|
|
15
|
+
State,
|
|
16
|
+
Task,
|
|
17
|
+
TaskDef,
|
|
18
|
+
Tasks,
|
|
19
|
+
ThisBuild,
|
|
20
|
+
} from './types'
|
|
21
|
+
|
|
22
|
+
/* ========================================================================== *
|
|
23
|
+
* TASK *
|
|
24
|
+
* ========================================================================== */
|
|
25
|
+
|
|
26
|
+
class TaskImpl implements Task {
|
|
27
|
+
constructor(
|
|
28
|
+
public readonly buildFile: AbsolutePath,
|
|
29
|
+
public readonly tasks: Tasks,
|
|
30
|
+
public readonly props: Props,
|
|
31
|
+
private readonly _def: TaskDef,
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
invoke(state: State, taskName: string): Promise<Result> {
|
|
35
|
+
assert(! state.stack.includes(this), `Recursion detected calling ${$t(taskName)}`)
|
|
36
|
+
|
|
37
|
+
/* Check cache */
|
|
38
|
+
const cached = state.cache.get(this)
|
|
39
|
+
if (cached) return cached
|
|
40
|
+
|
|
41
|
+
/* Create new substate merging sibling tasks/props and adding this to the stack */
|
|
42
|
+
const props: Record<string, string> = Object.assign({}, this.props, state.props)
|
|
43
|
+
const tasks: Record<string, Task> = Object.assign({}, this.tasks, state.tasks)
|
|
44
|
+
const stack = [ ...state.stack, this ]
|
|
45
|
+
const cache = state.cache
|
|
46
|
+
|
|
47
|
+
/* Create run context and build */
|
|
48
|
+
const context = new Context(this.buildFile, taskName)
|
|
49
|
+
|
|
50
|
+
const build = new Proxy({}, {
|
|
51
|
+
get(_: any, name: string): void | string | (() => Pipe) {
|
|
52
|
+
// Tasks first, props might come also from environment
|
|
53
|
+
if (name in tasks) {
|
|
54
|
+
return (): Pipe => {
|
|
55
|
+
const state = { stack, cache, tasks, props }
|
|
56
|
+
const promise = tasks[name]!.invoke(state, name)
|
|
57
|
+
return new PipeImpl(context, promise)
|
|
58
|
+
}
|
|
59
|
+
} else if (name in props) {
|
|
60
|
+
return props[name]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
/* Some logging */
|
|
66
|
+
context.log.info('Running...')
|
|
67
|
+
const now = Date.now()
|
|
68
|
+
|
|
69
|
+
/* Run asynchronously in an asynchronous context */
|
|
70
|
+
const promise = runAsync(context, taskName, async () => {
|
|
71
|
+
return await this._def.call(build) || undefined
|
|
72
|
+
}).then((result) => {
|
|
73
|
+
context.log.notice(`Success ${$ms(Date.now() - now)}`)
|
|
74
|
+
return result
|
|
75
|
+
}).catch((error) => {
|
|
76
|
+
throw context.log.fail(`Failure ${$ms(Date.now() - now)}`, error)
|
|
77
|
+
}).finally(() => ContextPromises.wait(context))
|
|
78
|
+
|
|
79
|
+
/* Cache the resulting promise and return it */
|
|
80
|
+
cache.set(this, promise)
|
|
81
|
+
return promise
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ========================================================================== *
|
|
86
|
+
* BUILD COMPILER *
|
|
87
|
+
* ========================================================================== */
|
|
88
|
+
|
|
89
|
+
/** Symbol indicating that an object is a {@link Build} */
|
|
90
|
+
const buildMarker = Symbol.for('plugjs:isBuild')
|
|
91
|
+
|
|
92
|
+
/** Compile a {@link BuildDef | build definition} into a {@link Build} */
|
|
93
|
+
export function build<
|
|
94
|
+
D extends BuildDef, B extends ThisBuild<D>
|
|
95
|
+
>(def: D & ThisType<B>): Build<D> {
|
|
96
|
+
const buildFile = findCaller(build)
|
|
97
|
+
const tasks: Record<string, Task> = {}
|
|
98
|
+
const props: Record<string, string> = {}
|
|
99
|
+
|
|
100
|
+
/* Iterate through all definition extracting properties and tasks */
|
|
101
|
+
for (const [ key, val ] of Object.entries(def)) {
|
|
102
|
+
let len = 0
|
|
103
|
+
if (typeof val === 'string') {
|
|
104
|
+
props[key] = val
|
|
105
|
+
} else if (typeof val === 'function') {
|
|
106
|
+
tasks[key] = new TaskImpl(buildFile, tasks, props, val)
|
|
107
|
+
len = key.length
|
|
108
|
+
} else if (val instanceof TaskImpl) {
|
|
109
|
+
tasks[key] = val
|
|
110
|
+
len = key.length
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Update the logger's own "taskLength" for nice printing */
|
|
114
|
+
/* coverage ignore if */
|
|
115
|
+
if (len > logOptions.taskLength) logOptions.taskLength = len
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Create the "call" function for this build */
|
|
119
|
+
const invoke: InvokeBuild = async function invoke(
|
|
120
|
+
taskNames: string[],
|
|
121
|
+
overrideProps: Record<string, string | undefined> = {},
|
|
122
|
+
): Promise<void> {
|
|
123
|
+
/* Our "root" logger and initial (empty) state */
|
|
124
|
+
const logger = getLogger()
|
|
125
|
+
const state = {
|
|
126
|
+
cache: new Map<Task, Promise<Result>>(),
|
|
127
|
+
stack: [] as Task[],
|
|
128
|
+
props: Object.assign({}, props, overrideProps),
|
|
129
|
+
tasks: tasks,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Let's go down to business */
|
|
133
|
+
logger.notice('Starting...')
|
|
134
|
+
const now = Date.now()
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
/* Run tasks _serially_ */
|
|
138
|
+
for (const name of taskNames) {
|
|
139
|
+
const task = tasks[name]
|
|
140
|
+
assert(task, `Task ${$t(name)} not found in build yoooo`)
|
|
141
|
+
await task.invoke(state, name)
|
|
142
|
+
}
|
|
143
|
+
logger.notice(`Build successful ${$ms(Date.now() - now)}`)
|
|
144
|
+
} catch (error) {
|
|
145
|
+
throw logger.fail(`Build failed ${$ms(Date.now() - now)}`, error)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Create our build, the collection of all props and tasks */
|
|
150
|
+
const compiled = Object.assign({}, props, tasks) as Build<D>
|
|
151
|
+
|
|
152
|
+
/* Sneak our "call" function in the build, for the CLI and "call" below */
|
|
153
|
+
Object.defineProperty(compiled, buildMarker, { value: invoke })
|
|
154
|
+
|
|
155
|
+
/* All done! */
|
|
156
|
+
return compiled
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Internal type describing the build invocation function */
|
|
160
|
+
type InvokeBuild = (tasks: string[], props?: Record<string, string | undefined>) => Promise<void>
|
|
161
|
+
|
|
162
|
+
/** Serially invoke tasks in a {@link Build} optionally overriding properties */
|
|
163
|
+
export async function invoke(
|
|
164
|
+
build: Build,
|
|
165
|
+
...args:
|
|
166
|
+
| [ ...taskNames: [ string, ...string[] ] ]
|
|
167
|
+
| [ ...taskNames: [ string, ...string[] ], options: Record<string, string | undefined> ]
|
|
168
|
+
): Promise<void> {
|
|
169
|
+
const { params: tasks, options: props } = parseOptions(args, {})
|
|
170
|
+
|
|
171
|
+
/* Get the calling function from the sneaked-in property in build */
|
|
172
|
+
const invoke: InvokeBuild = (build as any)[buildMarker]
|
|
173
|
+
|
|
174
|
+
/* Triple check that we actually _have_ a function (no asserts here, log!) */
|
|
175
|
+
if (typeof invoke !== 'function') log.fail('Unknown build type')
|
|
176
|
+
|
|
177
|
+
/* Call everyhin that needs to be called */
|
|
178
|
+
return await invoke(tasks, props)
|
|
179
|
+
}
|
package/src/files.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { assert } from './asserts'
|
|
2
|
+
import { mkdir, writeFile } from './fs'
|
|
1
3
|
import { assertRelativeChildPath, getAbsoluteParent, resolveAbsolutePath } from './paths'
|
|
2
|
-
import { mkdir, writeFile } from './utils/asyncfs'
|
|
3
4
|
|
|
4
5
|
import type { AbsolutePath } from './paths'
|
|
5
6
|
|
|
@@ -88,9 +89,8 @@ export class Files {
|
|
|
88
89
|
directory: instance.directory,
|
|
89
90
|
|
|
90
91
|
add(...files: string[]): FilesBuilder {
|
|
91
|
-
|
|
92
|
+
assert(! built, 'FileBuilder "build()" already called')
|
|
92
93
|
|
|
93
|
-
if (typeof files === 'string') files = [ files ]
|
|
94
94
|
for (const file of files) {
|
|
95
95
|
const relative = assertRelativeChildPath(instance.directory, file)
|
|
96
96
|
set.add(relative)
|
|
@@ -100,7 +100,7 @@ export class Files {
|
|
|
100
100
|
},
|
|
101
101
|
|
|
102
102
|
merge(...args: Files[]): FilesBuilder {
|
|
103
|
-
|
|
103
|
+
assert(! built, 'FileBuilder "build()" already called')
|
|
104
104
|
|
|
105
105
|
for (const files of args) {
|
|
106
106
|
for (const file of files.absolutePaths()) {
|
|
@@ -124,7 +124,7 @@ export class Files {
|
|
|
124
124
|
},
|
|
125
125
|
|
|
126
126
|
build(): Files {
|
|
127
|
-
|
|
127
|
+
assert(! built, 'FileBuilder "build()" already called')
|
|
128
128
|
|
|
129
129
|
built = true
|
|
130
130
|
instance._files.push(...set)
|
package/src/fork.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { fork } from 'node:child_process'
|
|
2
2
|
|
|
3
|
-
import { assert } from './
|
|
3
|
+
import { assert, BuildFailure } from './asserts'
|
|
4
4
|
import { runAsync } from './async'
|
|
5
|
-
import { BuildFailure } from './failure'
|
|
6
5
|
import { Files } from './files'
|
|
7
|
-
import { $gry, $p, logOptions } from './
|
|
6
|
+
import { $gry, $p, logOptions } from './logging'
|
|
8
7
|
import { requireFilename, resolveFile } from './paths'
|
|
9
8
|
import { Context, install } from './pipe'
|
|
10
9
|
|
|
11
|
-
import type { LogOptions } from './
|
|
10
|
+
import type { LogOptions } from './logging'
|
|
12
11
|
import type { AbsolutePath } from './paths'
|
|
13
12
|
import type { Plug, PlugName, PlugResult } from './pipe'
|
|
14
13
|
|
|
@@ -16,6 +15,8 @@ import type { Plug, PlugName, PlugResult } from './pipe'
|
|
|
16
15
|
export interface ForkData {
|
|
17
16
|
/** Script name for the Plug to execute */
|
|
18
17
|
scriptFile: AbsolutePath,
|
|
18
|
+
/** Export name in the script for the Plug to execute */
|
|
19
|
+
exportName: string,
|
|
19
20
|
/** Plug constructor arguments */
|
|
20
21
|
constructorArgs: any[],
|
|
21
22
|
/** Task name (for logs) */
|
|
@@ -48,11 +49,13 @@ export abstract class ForkingPlug implements Plug<PlugResult> {
|
|
|
48
49
|
constructor(
|
|
49
50
|
private readonly _scriptFile: AbsolutePath,
|
|
50
51
|
private readonly _arguments: any[],
|
|
52
|
+
private readonly _exportName: string,
|
|
51
53
|
) {}
|
|
52
54
|
|
|
53
55
|
pipe(files: Files, context: Context): Promise<PlugResult> {
|
|
54
56
|
const message: ForkData = {
|
|
55
57
|
scriptFile: this._scriptFile,
|
|
58
|
+
exportName: this._exportName,
|
|
56
59
|
constructorArgs: this._arguments,
|
|
57
60
|
taskName: context.taskName,
|
|
58
61
|
buildFile: context.buildFile,
|
|
@@ -167,6 +170,7 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
|
|
|
167
170
|
|
|
168
171
|
const {
|
|
169
172
|
scriptFile,
|
|
173
|
+
exportName,
|
|
170
174
|
constructorArgs,
|
|
171
175
|
taskName,
|
|
172
176
|
buildFile,
|
|
@@ -189,12 +193,15 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
|
|
|
189
193
|
const script = await import(scriptFile)
|
|
190
194
|
|
|
191
195
|
/* Figure out the constructor, in the "default" chain */
|
|
192
|
-
let Ctor
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
let Ctor
|
|
197
|
+
if (exportName === 'default') {
|
|
198
|
+
Ctor = script
|
|
199
|
+
while (Ctor && (typeof Ctor !== 'function')) Ctor = Ctor.default
|
|
200
|
+
assert(typeof Ctor === 'function', `Script ${$p(scriptFile)} does not export a default constructor`)
|
|
201
|
+
} else {
|
|
202
|
+
Ctor = script[exportName]
|
|
203
|
+
assert(typeof Ctor === 'function', `Script ${$p(scriptFile)} does not export "${exportName}"`)
|
|
204
|
+
}
|
|
198
205
|
|
|
199
206
|
/* Create the Plug instance and our Files instance */
|
|
200
207
|
const plug = new Ctor(...constructorArgs) as Plug<PlugResult>
|
|
@@ -250,11 +257,12 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
|
|
|
250
257
|
export function installForking<Name extends PlugName>(
|
|
251
258
|
plugName: Name,
|
|
252
259
|
scriptFile: AbsolutePath,
|
|
260
|
+
exportName: string = 'default',
|
|
253
261
|
): void {
|
|
254
262
|
/** Extend out our ForkingPlug below */
|
|
255
263
|
const ctor = class extends ForkingPlug {
|
|
256
264
|
constructor(...args: any[]) {
|
|
257
|
-
super(scriptFile, args)
|
|
265
|
+
super(scriptFile, args, exportName)
|
|
258
266
|
}
|
|
259
267
|
}
|
|
260
268
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { constants } from 'node:fs'
|
|
2
1
|
import fsp from 'node:fs/promises'
|
|
2
|
+
import { constants } from 'node:fs'
|
|
3
3
|
|
|
4
4
|
type FsPromises = typeof fsp
|
|
5
5
|
|
|
@@ -30,11 +30,12 @@ const fs = Object.entries(fsp as any).reduce((fs, [ key, val ]) => {
|
|
|
30
30
|
/* If the value is a function, wrap it! */
|
|
31
31
|
const f = function(...args: any[]): any {
|
|
32
32
|
/* Call the function, and _catch_ any error */
|
|
33
|
-
return val.apply(fsp, args)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
return val.apply(fsp, args)
|
|
34
|
+
.catch(/* coverage ignore next*/ (error: any) => {
|
|
35
|
+
/* For any error caught, we fill in the stack trace */
|
|
36
|
+
Error.captureStackTrace(error)
|
|
37
|
+
throw error
|
|
38
|
+
})
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/* Make sure that the functions are called correctly */
|
package/src/helpers.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tmpdir } from 'node:os'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { mkdtempSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
import { assert, assertPromises } from './asserts'
|
|
2
6
|
import { requireContext } from './async'
|
|
3
7
|
import { Files } from './files'
|
|
4
|
-
import {
|
|
8
|
+
import { rm } from './fs'
|
|
9
|
+
import { $p, log } from './logging'
|
|
5
10
|
import { commonPath, getCurrentWorkingDirectory, resolveDirectory, resolveFile } from './paths'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
11
|
+
import { PipeImpl } from './pipe'
|
|
12
|
+
import { execChild } from './utils/exec'
|
|
8
13
|
import { parseOptions } from './utils/options'
|
|
9
14
|
import { walk } from './utils/walk'
|
|
10
15
|
|
|
16
|
+
import type { Pipe } from './index'
|
|
11
17
|
import type { AbsolutePath } from './paths'
|
|
18
|
+
import type { ExecChildOptions } from './utils/exec'
|
|
12
19
|
import type { ParseOptions } from './utils/options'
|
|
13
20
|
import type { WalkOptions } from './utils/walk'
|
|
14
21
|
|
|
@@ -35,7 +42,7 @@ export function find(...args: ParseOptions<FindOptions>): Pipe {
|
|
|
35
42
|
const { params: globs, options } = parseOptions(args, {})
|
|
36
43
|
|
|
37
44
|
const context = requireContext()
|
|
38
|
-
return new
|
|
45
|
+
return new PipeImpl(context, Promise.resolve().then(async () => {
|
|
39
46
|
const directory = options.directory ?
|
|
40
47
|
context.resolve(options.directory) :
|
|
41
48
|
getCurrentWorkingDirectory()
|
|
@@ -62,6 +69,7 @@ export async function rmrf(directory: string): Promise<void> {
|
|
|
62
69
|
assert(dir !== context.resolve('@'),
|
|
63
70
|
`Cowardly refusing to wipe build file directory ${$p(dir)}`)
|
|
64
71
|
|
|
72
|
+
/* coverage ignore if */
|
|
65
73
|
if (! resolveDirectory(dir)) {
|
|
66
74
|
log.info('Directory', $p(dir), 'not found')
|
|
67
75
|
return
|
|
@@ -88,7 +96,7 @@ export async function rmrf(directory: string): Promise<void> {
|
|
|
88
96
|
*/
|
|
89
97
|
export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
90
98
|
const context = requireContext()
|
|
91
|
-
return new
|
|
99
|
+
return new PipeImpl(context, Promise.resolve().then(async () => {
|
|
92
100
|
// No pipes? Just send off an empty pipe...
|
|
93
101
|
if (pipes.length === 0) return Files.builder(getCurrentWorkingDirectory()).build()
|
|
94
102
|
|
|
@@ -97,7 +105,7 @@ export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
|
97
105
|
|
|
98
106
|
// Find the common directory between all the Files instances
|
|
99
107
|
const [ firstDir, ...otherDirs ] = results.map((f) => f.directory)
|
|
100
|
-
const directory = commonPath(firstDir
|
|
108
|
+
const directory = commonPath(firstDir!, ...otherDirs)
|
|
101
109
|
|
|
102
110
|
// Build our new files instance merging all the results
|
|
103
111
|
return Files.builder(directory).merge(...results).build()
|
|
@@ -121,7 +129,7 @@ export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
|
121
129
|
export function noop(): Pipe {
|
|
122
130
|
const context = requireContext()
|
|
123
131
|
const files = new Files(getCurrentWorkingDirectory())
|
|
124
|
-
return new
|
|
132
|
+
return new PipeImpl(context, Promise.resolve(files))
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
/**
|
|
@@ -155,3 +163,43 @@ export function isDirectory(...paths: [ string, ...string[] ]): AbsolutePath | u
|
|
|
155
163
|
const path = requireContext().resolve(...paths)
|
|
156
164
|
return resolveDirectory(path)
|
|
157
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Create a temporary directory and return its {@link AbsolutePath}.
|
|
169
|
+
*
|
|
170
|
+
* The directory will be rooted in `/tmp` or wherever `os.tmpdir()` decides.
|
|
171
|
+
*/
|
|
172
|
+
export function mkdtemp(): AbsolutePath {
|
|
173
|
+
const prefix = join(tmpdir(), 'plugjs-')
|
|
174
|
+
const path = mkdtempSync(prefix)
|
|
175
|
+
return resolve(path)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Execute a command and await for its result from within a task.
|
|
180
|
+
*
|
|
181
|
+
* For example:
|
|
182
|
+
*
|
|
183
|
+
* ```
|
|
184
|
+
* import { exec } from '@plugjs/plugjs'
|
|
185
|
+
*
|
|
186
|
+
* export default build({
|
|
187
|
+
* async runme() {
|
|
188
|
+
* await exec('ls', '-la', '/')
|
|
189
|
+
* // or similarly letting the shell interpret the command
|
|
190
|
+
* await exec('ls -la /', { shell: true })
|
|
191
|
+
* },
|
|
192
|
+
* })
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @param cmd The command to execute
|
|
196
|
+
* @param args Any additional argument for the command to execute
|
|
197
|
+
* @param options Extra {@link ExecChildOptions | options} for process execution
|
|
198
|
+
*/
|
|
199
|
+
export function exec(
|
|
200
|
+
cmd: string,
|
|
201
|
+
...args: [ ...args: string[] ] | [ ...args: string[], options: ExecChildOptions ]
|
|
202
|
+
): Promise<void> {
|
|
203
|
+
const { params, options } = parseOptions(args)
|
|
204
|
+
return execChild(cmd, params, options, requireContext())
|
|
205
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
// Reference our extra "webassembly" type fix here. As we're using esbuild
|
|
2
2
|
// everywhere, we want our dependants to have this type known...
|
|
3
|
-
/// <reference path="../types/
|
|
3
|
+
/// <reference path="../types/plugjs.d.ts" />
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// This is a main constituent of our build system!
|
|
6
|
+
import type { Files } from './files'
|
|
7
|
+
import type { Plug, PlugFunction } from './pipe'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The {@link Pipe} interface defines a processing pipeline where multiple
|
|
11
|
+
* {@link Plug}s can transform lists of {@link Files}.
|
|
12
|
+
*/
|
|
13
|
+
export interface Pipe extends Promise<Files> {
|
|
14
|
+
plug(plug: Plug<Files>): Pipe
|
|
15
|
+
plug(plug: PlugFunction<Files>): Pipe
|
|
16
|
+
plug(plug: Plug<void | undefined>): Promise<undefined>
|
|
17
|
+
plug(plug: PlugFunction<void | undefined>): Promise<undefined>
|
|
18
|
+
plug(plug: Plug<Files | void | undefined>): Pipe | Promise<undefined>
|
|
19
|
+
plug(plug: PlugFunction<Files | void | undefined>): Pipe | Promise<undefined>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Submodule exports (our package.json exports)
|
|
23
|
+
export * as asserts from './asserts'
|
|
24
|
+
export * as files from './files'
|
|
25
|
+
export * as fork from './fork'
|
|
26
|
+
export * as fs from './fs'
|
|
27
|
+
export * as logging from './logging'
|
|
28
|
+
export * as paths from './paths'
|
|
29
|
+
export * as pipe from './pipe'
|
|
30
|
+
export * as utils from './utils'
|
|
31
|
+
|
|
32
|
+
// Individual utilities
|
|
33
|
+
export { log } from './logging'
|
|
34
|
+
export { assert } from './asserts'
|
|
10
35
|
|
|
11
36
|
// Our minimal exports
|
|
12
|
-
export * from './assert'
|
|
13
37
|
export * from './build'
|
|
14
|
-
export * from './fork'
|
|
15
38
|
export * from './helpers'
|
|
16
|
-
export * from './log'
|
|
17
39
|
export * from './plugs'
|
|
18
40
|
export * from './types'
|
|
File without changes
|
|
@@ -120,7 +120,6 @@ export const emitPlain: LogEmitter = (options: LogEmitterOptions, args: any[]):
|
|
|
120
120
|
|
|
121
121
|
/* Write each individual line out */
|
|
122
122
|
for (const line of message.split('\n')) {
|
|
123
|
-
_output.write(zapSpinner)
|
|
124
123
|
_output.write(linePrefix)
|
|
125
124
|
_output.write(line)
|
|
126
125
|
_output.write('\n')
|
|
File without changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BuildFailure, isBuildFailure } from '../
|
|
1
|
+
import { BuildFailure, isBuildFailure } from '../asserts'
|
|
2
2
|
import { emitColor, emitPlain } from './emit'
|
|
3
3
|
import { DEBUG, ERROR, INFO, NOTICE, TRACE, WARN } from './levels'
|
|
4
4
|
import { logOptions } from './options'
|
|
@@ -74,6 +74,8 @@ export function getLogger(task: string = _defaultTaskName): Logger {
|
|
|
74
74
|
|
|
75
75
|
/** Cache of loggers by task-name. */
|
|
76
76
|
const _loggers = new Map<string, Logger>()
|
|
77
|
+
/** Weak set of already logged build failures */
|
|
78
|
+
const _loggedFailures = new WeakSet<BuildFailure>()
|
|
77
79
|
|
|
78
80
|
/** Default implementation of the {@link Logger} interface. */
|
|
79
81
|
class LoggerImpl implements Logger {
|
|
@@ -93,14 +95,21 @@ class LoggerImpl implements Logger {
|
|
|
93
95
|
const params = args.filter((arg) => {
|
|
94
96
|
if (isBuildFailure(arg)) {
|
|
95
97
|
// Filter out any previously logged build failure and mark
|
|
96
|
-
if (arg
|
|
97
|
-
arg
|
|
98
|
+
if (_loggedFailures.has(arg)) return false
|
|
99
|
+
_loggedFailures.add(arg)
|
|
98
100
|
|
|
99
101
|
// If the build failure has any root cause, log those
|
|
100
102
|
arg.errors.forEach((error) => this._emit(level, [ error ]))
|
|
101
103
|
|
|
102
104
|
// Log this only if it has a message
|
|
103
|
-
|
|
105
|
+
if (! arg.message) return false
|
|
106
|
+
|
|
107
|
+
// Log the full error (with stack) if the _default_ level is DEBUG
|
|
108
|
+
if (_level < INFO) return true
|
|
109
|
+
|
|
110
|
+
// Log only the message in other cases
|
|
111
|
+
this._emit(level, [ arg.message ])
|
|
112
|
+
return false
|
|
104
113
|
} else {
|
|
105
114
|
return true
|
|
106
115
|
}
|
|
@@ -2,9 +2,9 @@ import { EventEmitter } from 'node:events'
|
|
|
2
2
|
|
|
3
3
|
import { getLevelNumber, NOTICE } from './levels'
|
|
4
4
|
|
|
5
|
-
import type { LogLevel, LogLevelString } from './levels'
|
|
6
5
|
import type { Writable } from 'node:stream'
|
|
7
6
|
import type { InspectOptions } from 'node:util'
|
|
7
|
+
import type { LogLevel, LogLevelString } from './levels'
|
|
8
8
|
|
|
9
9
|
/* ========================================================================== */
|
|
10
10
|
|
|
@@ -54,8 +54,10 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
54
54
|
private _output: Writable = process.stderr
|
|
55
55
|
private _level: LogLevel = NOTICE
|
|
56
56
|
private _colors = (<NodeJS.WriteStream> this._output).isTTY
|
|
57
|
+
private _colorsSet = false // have colors been set manually?
|
|
57
58
|
private _spinner = true // by default, the spinner is enabled
|
|
58
59
|
private _lineLength = (<NodeJS.WriteStream> this._output).columns || 80
|
|
60
|
+
private _lineLengthSet = false // has line length been set manually?
|
|
59
61
|
private _showSources = true // by default, always show source snippets
|
|
60
62
|
private _inspectOptions: InspectOptions = {}
|
|
61
63
|
private _defaultTaskName = ''
|
|
@@ -70,10 +72,10 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
70
72
|
this._level = getLevelNumber(process.env.LOG_LEVEL as LogLevelString)
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
/* If the `
|
|
74
|
-
if (process.env.
|
|
75
|
-
if (process.env.
|
|
76
|
-
if (process.env.
|
|
75
|
+
/* If the `LOG_COLORS` variable is specified, it should be `true` or `false` */
|
|
76
|
+
if (process.env.LOG_COLORS) {
|
|
77
|
+
if (process.env.LOG_COLORS.toLowerCase() === 'true') this.colors = true
|
|
78
|
+
if (process.env.LOG_COLORS.toLowerCase() === 'false') this.colors = false
|
|
77
79
|
// Other values don't change the value of `options.colors`
|
|
78
80
|
}
|
|
79
81
|
|
|
@@ -106,8 +108,8 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
106
108
|
|
|
107
109
|
set output(output: Writable) {
|
|
108
110
|
this._output = output
|
|
109
|
-
this._colors = !! (<NodeJS.WriteStream> output).isTTY
|
|
110
|
-
this._lineLength = (<NodeJS.WriteStream> output).columns
|
|
111
|
+
if (! this._colorsSet) this._colors = !! (<NodeJS.WriteStream> output).isTTY
|
|
112
|
+
if (! this._lineLengthSet) this._lineLength = (<NodeJS.WriteStream> output).columns
|
|
111
113
|
this._notifyListeners()
|
|
112
114
|
}
|
|
113
115
|
|
|
@@ -126,6 +128,7 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
126
128
|
|
|
127
129
|
set colors(color: boolean) {
|
|
128
130
|
this._colors = color
|
|
131
|
+
this._colorsSet = true
|
|
129
132
|
this._notifyListeners()
|
|
130
133
|
}
|
|
131
134
|
|
|
@@ -144,6 +147,7 @@ class LogOptionsImpl extends EventEmitter implements LogOptions {
|
|
|
144
147
|
|
|
145
148
|
set lineLength(lineLength: number) {
|
|
146
149
|
this._lineLength = lineLength
|
|
150
|
+
this._lineLengthSet = true
|
|
147
151
|
this._notifyListeners()
|
|
148
152
|
}
|
|
149
153
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BuildFailure } from '../
|
|
2
|
-
import { readFile } from '../
|
|
1
|
+
import { BuildFailure } from '../asserts'
|
|
2
|
+
import { readFile } from '../fs'
|
|
3
3
|
import { $blu, $cyn, $gry, $red, $und, $wht, $ylw } from './colors'
|
|
4
4
|
import { ERROR, NOTICE, WARN } from './levels'
|
|
5
5
|
import { logOptions } from './options'
|
|
@@ -336,7 +336,7 @@ export class ReportImpl implements Report {
|
|
|
336
336
|
|
|
337
337
|
/* Iterate through all our [file,reports] tuple */
|
|
338
338
|
for (let f = 0; f < entries.length; f ++) {
|
|
339
|
-
const { file, records, annotation } = entries[f]
|
|
339
|
+
const { file, records, annotation } = entries[f]!
|
|
340
340
|
const source = file && file != nul && this._sources.get(file)
|
|
341
341
|
|
|
342
342
|
if ((f === 0) || entries[f - 1]?.records.length) {
|
|
@@ -358,7 +358,7 @@ export class ReportImpl implements Report {
|
|
|
358
358
|
|
|
359
359
|
/* Now get each message and do our magic */
|
|
360
360
|
for (let r = 0; r < records.length; r ++) {
|
|
361
|
-
const { level, messages, tags, line, column, length = 1 } = records[r]
|
|
361
|
+
const { level, messages, tags, line, column, length = 1 } = records[r]!
|
|
362
362
|
|
|
363
363
|
/* Prefix includes line and column */
|
|
364
364
|
let pfx: string
|
|
@@ -382,13 +382,13 @@ export class ReportImpl implements Report {
|
|
|
382
382
|
|
|
383
383
|
/* Print out our messages, one by one */
|
|
384
384
|
if (messages.length === 1) {
|
|
385
|
-
this._emitter({ ...options, level }, [ $gry(pfx), messages[0]
|
|
385
|
+
this._emitter({ ...options, level }, [ $gry(pfx), messages[0]!.padEnd(mPad), tag ])
|
|
386
386
|
} else {
|
|
387
387
|
for (let m = 0; m < messages.length; m ++) {
|
|
388
388
|
if (! m) { // first line
|
|
389
389
|
this._emitter({ ...options, level }, [ $gry(pfx), messages[m] ])
|
|
390
390
|
} else if (m === messages.length - 1) { // last line
|
|
391
|
-
this._emitter({ ...options, level, prefix }, [ messages[m]
|
|
391
|
+
this._emitter({ ...options, level, prefix }, [ messages[m]!.padEnd(mPad), tag ])
|
|
392
392
|
} else { // in between lines
|
|
393
393
|
this._emitter({ ...options, level, prefix }, [ messages[m] ])
|
|
394
394
|
}
|
|
@@ -400,9 +400,10 @@ export class ReportImpl implements Report {
|
|
|
400
400
|
if (column) {
|
|
401
401
|
const $col = level === NOTICE ? $blu : level === WARN ? $ylw : $red
|
|
402
402
|
const offset = column - 1
|
|
403
|
-
const
|
|
404
|
-
const
|
|
405
|
-
const
|
|
403
|
+
const text = source[line - 1] || ''
|
|
404
|
+
const head = $gry(text.substring(0, offset))
|
|
405
|
+
const body = $und($col(text.substring(offset, offset + length)))
|
|
406
|
+
const tail = $gry(text.substring(offset + length))
|
|
406
407
|
|
|
407
408
|
this._emitter({ ...options, level, prefix }, [ $gry(`| ${head}${body}${tail}`) ])
|
|
408
409
|
} else {
|
|
File without changes
|