@plugjs/plug 0.0.26 → 0.1.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/dist/{failure.cjs → asserts.cjs} +29 -9
- 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 +21 -30
- package/dist/build.cjs.map +1 -1
- package/dist/build.d.ts +2 -13
- package/dist/build.mjs +16 -24
- package/dist/build.mjs.map +1 -1
- package/dist/files.cjs +3 -3
- package/dist/files.cjs.map +1 -1
- package/dist/files.mjs +1 -1
- 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/{utils/asyncfs.cjs.map → fs.cjs.map} +2 -2
- package/dist/{utils/asyncfs.d.ts → fs.d.ts} +1 -1
- package/dist/{utils/asyncfs.mjs → fs.mjs} +3 -3
- package/dist/{utils/asyncfs.mjs.map → fs.mjs.map} +2 -2
- package/dist/helpers.cjs +21 -14
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.ts +24 -1
- package/dist/helpers.mjs +13 -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 +0 -0
- 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 +0 -0
- 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 +10 -9
- package/dist/{log → logging}/report.cjs.map +2 -2
- package/dist/{log → logging}/report.d.ts +0 -0
- package/dist/{log → logging}/report.mjs +7 -6
- package/dist/{log → logging}/report.mjs.map +2 -2
- 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} +12 -12
- package/dist/{log.cjs.map → logging.cjs.map} +2 -2
- package/dist/{log.d.ts → logging.d.ts} +6 -6
- package/dist/{log.mjs → logging.mjs} +9 -9
- package/dist/{log.mjs.map → logging.mjs.map} +1 -1
- package/dist/paths.cjs +5 -5
- package/dist/paths.cjs.map +1 -1
- package/dist/paths.mjs +1 -1
- package/dist/pipe.cjs +10 -13
- package/dist/pipe.cjs.map +1 -1
- package/dist/pipe.d.ts +6 -12
- 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 +4 -4
- package/dist/plugs/esbuild/fix-extensions.cjs.map +1 -1
- package/dist/plugs/esbuild/fix-extensions.mjs +1 -1
- 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 +1 -1
- 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 +1 -1
- 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/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 +2 -2
- package/package.json +90 -15
- package/src/{assert.ts → asserts.ts} +36 -1
- package/src/async.ts +3 -1
- package/src/files.ts +1 -1
- package/src/fork.ts +19 -11
- package/src/{utils/asyncfs.ts → fs.ts} +1 -1
- package/src/helpers.ts +40 -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 +1 -1
- 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/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 -218
- package/dist/plugs/coverage/report.cjs.map +0 -6
- package/dist/plugs/coverage/report.d.ts +0 -53
- package/dist/plugs/coverage/report.mjs +0 -203
- package/dist/plugs/coverage/report.mjs.map +0 -6
- package/dist/plugs/coverage.cjs +0 -137
- package/dist/plugs/coverage.cjs.map +0 -6
- package/dist/plugs/coverage.d.ts +0 -49
- package/dist/plugs/coverage.mjs +0 -120
- 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/src/failure.ts +0 -43
- package/src/plugs/coverage/analysis.ts +0 -400
- package/src/plugs/coverage/report.ts +0 -345
- package/src/plugs/coverage.ts +0 -213
- 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
|
@@ -2,7 +2,42 @@
|
|
|
2
2
|
* BUILD FAILURES *
|
|
3
3
|
* ========================================================================== */
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** A symbol marking {@link BuildFailure} instances */
|
|
6
|
+
const buildFailure = Symbol.for('plugjs:buildFailure')
|
|
7
|
+
|
|
8
|
+
/** Check if the specified argument is a {@link BuildFailure} */
|
|
9
|
+
export function isBuildFailure(arg: any): arg is BuildFailure {
|
|
10
|
+
return arg && arg[buildFailure] === buildFailure
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** A {@link BuildFailure} represents an error _already logged_ in our build. */
|
|
14
|
+
export class BuildFailure extends Error {
|
|
15
|
+
readonly errors!: readonly any[]
|
|
16
|
+
|
|
17
|
+
/** Construct a {@link BuildFailure} */
|
|
18
|
+
private constructor(message: string | undefined, errors: any[]) {
|
|
19
|
+
super(message || '')
|
|
20
|
+
|
|
21
|
+
/* Basic error setup, stack and marker */
|
|
22
|
+
Error.captureStackTrace(this, BuildFailure)
|
|
23
|
+
Object.defineProperties(this, {
|
|
24
|
+
'errors': { value: Object.freeze([ ...errors ]) },
|
|
25
|
+
[buildFailure]: { value: buildFailure },
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static fail(): BuildFailure {
|
|
30
|
+
return new BuildFailure(undefined, [])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static withMessage(message: string): BuildFailure {
|
|
34
|
+
return new BuildFailure(message || undefined, [])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static withErrors(errors: any[]): BuildFailure {
|
|
38
|
+
return new BuildFailure(undefined, errors)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
6
41
|
|
|
7
42
|
/** Await and assert that all specified promises were fulfilled */
|
|
8
43
|
export async function assertPromises<T>(promises: (T | Promise<T>)[]): Promise<T[]> {
|
package/src/async.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
2
|
|
|
3
|
+
import { assert } from './asserts'
|
|
4
|
+
|
|
3
5
|
import type { Context } from './pipe'
|
|
4
6
|
|
|
5
7
|
|
|
@@ -40,7 +42,7 @@ export function currentContext(): Context | undefined {
|
|
|
40
42
|
*/
|
|
41
43
|
export function requireContext(): Context {
|
|
42
44
|
const context = storage.getStore()
|
|
43
|
-
|
|
45
|
+
assert(context, 'Unable to retrieve current context')
|
|
44
46
|
return context
|
|
45
47
|
}
|
|
46
48
|
|
package/src/files.ts
CHANGED
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
|
|
package/src/helpers.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { assert, assertPromises } from './
|
|
1
|
+
import { assert, assertPromises } from './asserts'
|
|
2
2
|
import { requireContext } from './async'
|
|
3
3
|
import { Files } from './files'
|
|
4
|
-
import {
|
|
4
|
+
import { rm } from './fs'
|
|
5
|
+
import { $p, log } from './logging'
|
|
5
6
|
import { commonPath, getCurrentWorkingDirectory, resolveDirectory, resolveFile } from './paths'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { PipeImpl } from './pipe'
|
|
8
|
+
import { execChild } from './utils/exec'
|
|
8
9
|
import { parseOptions } from './utils/options'
|
|
9
10
|
import { walk } from './utils/walk'
|
|
10
11
|
|
|
12
|
+
import type { Pipe } from './index'
|
|
11
13
|
import type { AbsolutePath } from './paths'
|
|
14
|
+
import type { ExecChildOptions } from './utils/exec'
|
|
12
15
|
import type { ParseOptions } from './utils/options'
|
|
13
16
|
import type { WalkOptions } from './utils/walk'
|
|
14
17
|
|
|
@@ -35,7 +38,7 @@ export function find(...args: ParseOptions<FindOptions>): Pipe {
|
|
|
35
38
|
const { params: globs, options } = parseOptions(args, {})
|
|
36
39
|
|
|
37
40
|
const context = requireContext()
|
|
38
|
-
return new
|
|
41
|
+
return new PipeImpl(context, Promise.resolve().then(async () => {
|
|
39
42
|
const directory = options.directory ?
|
|
40
43
|
context.resolve(options.directory) :
|
|
41
44
|
getCurrentWorkingDirectory()
|
|
@@ -88,7 +91,7 @@ export async function rmrf(directory: string): Promise<void> {
|
|
|
88
91
|
*/
|
|
89
92
|
export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
90
93
|
const context = requireContext()
|
|
91
|
-
return new
|
|
94
|
+
return new PipeImpl(context, Promise.resolve().then(async () => {
|
|
92
95
|
// No pipes? Just send off an empty pipe...
|
|
93
96
|
if (pipes.length === 0) return Files.builder(getCurrentWorkingDirectory()).build()
|
|
94
97
|
|
|
@@ -97,7 +100,7 @@ export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
|
97
100
|
|
|
98
101
|
// Find the common directory between all the Files instances
|
|
99
102
|
const [ firstDir, ...otherDirs ] = results.map((f) => f.directory)
|
|
100
|
-
const directory = commonPath(firstDir
|
|
103
|
+
const directory = commonPath(firstDir!, ...otherDirs)
|
|
101
104
|
|
|
102
105
|
// Build our new files instance merging all the results
|
|
103
106
|
return Files.builder(directory).merge(...results).build()
|
|
@@ -121,7 +124,7 @@ export function merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
|
|
|
121
124
|
export function noop(): Pipe {
|
|
122
125
|
const context = requireContext()
|
|
123
126
|
const files = new Files(getCurrentWorkingDirectory())
|
|
124
|
-
return new
|
|
127
|
+
return new PipeImpl(context, Promise.resolve(files))
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
/**
|
|
@@ -155,3 +158,32 @@ export function isDirectory(...paths: [ string, ...string[] ]): AbsolutePath | u
|
|
|
155
158
|
const path = requireContext().resolve(...paths)
|
|
156
159
|
return resolveDirectory(path)
|
|
157
160
|
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Execute a command and await for its result from within a task.
|
|
164
|
+
*
|
|
165
|
+
* For example:
|
|
166
|
+
*
|
|
167
|
+
* ```
|
|
168
|
+
* import { exec } from '@plugjs/plugjs'
|
|
169
|
+
*
|
|
170
|
+
* export default build({
|
|
171
|
+
* async runme() {
|
|
172
|
+
* await exec('ls', '-la', '/')
|
|
173
|
+
* // or similarly letting the shell interpret the command
|
|
174
|
+
* await exec('ls -la /', { shell: true })
|
|
175
|
+
* },
|
|
176
|
+
* })
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* @param cmd The command to execute
|
|
180
|
+
* @param args Any additional argument for the command to execute
|
|
181
|
+
* @param options Extra {@link ExecChildOptions | options} for process execution
|
|
182
|
+
*/
|
|
183
|
+
export function exec(
|
|
184
|
+
cmd: string,
|
|
185
|
+
...args: [ ...args: string[] ] | [ ...args: string[], options: ExecChildOptions ]
|
|
186
|
+
): Promise<void> {
|
|
187
|
+
const { params, options } = parseOptions(args)
|
|
188
|
+
return execChild(cmd, params, options, requireContext())
|
|
189
|
+
}
|
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
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { currentContext } from './async'
|
|
2
|
-
import { getLogger, type Log } from './
|
|
3
|
-
import { setupSpinner } from './
|
|
2
|
+
import { getLogger, type Log } from './logging/logger'
|
|
3
|
+
import { setupSpinner } from './logging/spinner'
|
|
4
4
|
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
5
|
+
export * from './logging/colors'
|
|
6
|
+
export * from './logging/levels'
|
|
7
|
+
export * from './logging/logger'
|
|
8
|
+
export * from './logging/options'
|
|
9
|
+
export * from './logging/report'
|
|
10
10
|
|
|
11
11
|
/* ========================================================================== *
|
|
12
12
|
* INITIALIZATION *
|
package/src/paths.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from 'node:module'
|
|
|
3
3
|
import { dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path'
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
5
5
|
|
|
6
|
-
import { assert } from './
|
|
6
|
+
import { assert } from './asserts'
|
|
7
7
|
|
|
8
8
|
/** A _branded_ `string` representing an _absolute_ path name */
|
|
9
9
|
export type AbsolutePath = string & { __brand_absolute_path: never }
|
package/src/pipe.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { sep } from 'node:path'
|
|
2
2
|
|
|
3
|
-
import { assert, assertPromises } from './
|
|
4
|
-
import { getLogger } from './
|
|
3
|
+
import { assert, assertPromises } from './asserts'
|
|
4
|
+
import { getLogger } from './logging'
|
|
5
5
|
import { getAbsoluteParent, getCurrentWorkingDirectory, resolveAbsolutePath } from './paths'
|
|
6
6
|
|
|
7
7
|
import type { Files } from './files'
|
|
8
|
-
import type { Logger } from './
|
|
8
|
+
import type { Logger } from './logging'
|
|
9
9
|
import type { AbsolutePath } from './paths'
|
|
10
10
|
import type { Result } from './types'
|
|
11
|
+
import type { Pipe } from './index'
|
|
11
12
|
|
|
12
13
|
/* ========================================================================== *
|
|
13
14
|
* PLUGS *
|
|
@@ -138,27 +139,19 @@ export class ContextPromises {
|
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
*/
|
|
145
|
-
abstract class PipeProto {
|
|
146
|
-
abstract plug(plug: Plug<PlugResult>): Pipe | Promise<undefined>
|
|
142
|
+
/** The default implementation of the {@link Pipe} interface. */
|
|
143
|
+
export interface PipeImpl extends Pipe {
|
|
144
|
+
// used simply for merging types
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
/**
|
|
150
|
-
|
|
151
|
-
* {@link Plug}s can transform lists of {@link Files}.
|
|
152
|
-
*/
|
|
153
|
-
export class Pipe extends PipeProto implements Promise<Files> {
|
|
147
|
+
/** The default implementation of the {@link Pipe} interface. */
|
|
148
|
+
export class PipeImpl implements Pipe {
|
|
154
149
|
readonly [Symbol.toStringTag] = 'Pipe'
|
|
155
150
|
|
|
156
151
|
constructor(
|
|
157
152
|
private readonly _context: Context,
|
|
158
153
|
private readonly _promise: Promise<Result>,
|
|
159
154
|
) {
|
|
160
|
-
super()
|
|
161
|
-
|
|
162
155
|
// New "Pipe", remember the promise!
|
|
163
156
|
ContextPromises.get(_context).hot(_promise)
|
|
164
157
|
}
|
|
@@ -218,7 +211,7 @@ export class Pipe extends PipeProto implements Promise<Files> {
|
|
|
218
211
|
ContextPromises.get(this._context).cold(this._promise)
|
|
219
212
|
|
|
220
213
|
// Create and return the new Pipe
|
|
221
|
-
return new
|
|
214
|
+
return new PipeImpl(this._context, this._promise.then(async (result) => {
|
|
222
215
|
assert(result, 'Unable to extend pipe')
|
|
223
216
|
const result2 = await plug.pipe(result, this._context)
|
|
224
217
|
return result2 || undefined
|
|
@@ -335,14 +328,14 @@ export function install<
|
|
|
335
328
|
Ctor extends PlugConstructor<Name>,
|
|
336
329
|
>(name: Name, ctor: Ctor): void {
|
|
337
330
|
/* The function plugging the newly constructed plug in a pipe */
|
|
338
|
-
function plug(this:
|
|
331
|
+
function plug(this: PipeImpl, ...args: PipeParameters<Name>): Pipe | Promise<undefined> {
|
|
339
332
|
// eslint-disable-next-line new-cap
|
|
340
|
-
return this.plug(new ctor(...args))
|
|
333
|
+
return this.plug(new ctor(...args) as any)
|
|
341
334
|
}
|
|
342
335
|
|
|
343
336
|
/* Setup name so that stack traces look better */
|
|
344
337
|
Object.defineProperty(plug, 'name', { value: name })
|
|
345
338
|
|
|
346
339
|
/* Inject the create function in the Pipe's prototype */
|
|
347
|
-
Object.defineProperty(
|
|
340
|
+
void Object.defineProperty(PipeImpl.prototype, name, { value: plug })
|
|
348
341
|
}
|
package/src/plugs/copy.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { assert } from '../
|
|
1
|
+
import { assert } from '../asserts'
|
|
2
2
|
import { Files } from '../files'
|
|
3
|
-
import {
|
|
3
|
+
import { chmod, copyFile, fsConstants, mkdir } from '../fs'
|
|
4
|
+
import { $p } from '../logging'
|
|
4
5
|
import { assertAbsolutePath, getAbsoluteParent, resolveAbsolutePath } from '../paths'
|
|
5
6
|
import { install } from '../pipe'
|
|
6
|
-
import { chmod, copyFile, fsConstants, mkdir } from '../utils/asyncfs'
|
|
7
7
|
|
|
8
8
|
import type { Context, PipeParameters, Plug } from '../pipe'
|
|
9
9
|
|
|
@@ -19,7 +19,7 @@ export interface CopyOptions {
|
|
|
19
19
|
rename?: (relative: string) => string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
declare module '../
|
|
22
|
+
declare module '../index' {
|
|
23
23
|
export interface Pipe {
|
|
24
24
|
/**
|
|
25
25
|
* Copy the curent {@link Files} to a different directory
|
package/src/plugs/debug.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $gry, $p, $und, $ylw } from '../
|
|
1
|
+
import { $gry, $p, $und, $ylw } from '../logging'
|
|
2
2
|
import { install } from '../pipe'
|
|
3
3
|
|
|
4
4
|
import type { Files } from '../files'
|
|
5
5
|
import type { Context, PipeParameters, Plug } from '../pipe'
|
|
6
6
|
|
|
7
|
-
declare module '../
|
|
7
|
+
declare module '../index' {
|
|
8
8
|
export interface Pipe {
|
|
9
9
|
/** Log some info about the current {@link Files} being passed around. */
|
|
10
10
|
debug(title?: string): Pipe
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { readFile, writeFile } from '../fs'
|
|
2
|
+
import { install } from '../pipe'
|
|
3
|
+
|
|
4
|
+
import type { Files } from '../files'
|
|
5
|
+
import type { PipeParameters, Plug } from '../pipe'
|
|
6
|
+
|
|
7
|
+
declare module '../index' {
|
|
8
|
+
export interface Pipe {
|
|
9
|
+
/** Edits the content of all files in a pipeline. */
|
|
10
|
+
edit(callback: (content: string) => string | void | Promise<string | void>): Pipe
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* ========================================================================== *
|
|
15
|
+
* INSTALLATION / IMPLEMENTATION *
|
|
16
|
+
* ========================================================================== */
|
|
17
|
+
|
|
18
|
+
/** Edits the content of all files in a pipeline. */
|
|
19
|
+
install('edit', class Edit implements Plug<Files> {
|
|
20
|
+
private readonly _callback: (content: string) => string | void | Promise<string | void>
|
|
21
|
+
|
|
22
|
+
constructor(...args: PipeParameters<'edit'>) {
|
|
23
|
+
this._callback = args[0]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async pipe(files: Files): Promise<Files> {
|
|
27
|
+
for (const file of files.absolutePaths()) {
|
|
28
|
+
const data = await readFile(file, 'utf-8')
|
|
29
|
+
const edited = await this._callback(data)
|
|
30
|
+
if (edited !== undefined) await writeFile(file, edited, 'utf-8')
|
|
31
|
+
}
|
|
32
|
+
return files
|
|
33
|
+
}
|
|
34
|
+
})
|