@plugjs/plug 0.0.14 → 0.0.15

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.
Files changed (212) hide show
  1. package/dist/async.cjs +20 -19
  2. package/dist/async.cjs.map +1 -1
  3. package/dist/async.d.ts +9 -9
  4. package/dist/async.mjs +18 -17
  5. package/dist/async.mjs.map +1 -1
  6. package/dist/build.cjs +144 -110
  7. package/dist/build.cjs.map +2 -2
  8. package/dist/build.d.ts +12 -56
  9. package/dist/build.mjs +146 -112
  10. package/dist/build.mjs.map +2 -2
  11. package/dist/files.cjs +2 -16
  12. package/dist/files.cjs.map +1 -1
  13. package/dist/files.d.ts +3 -10
  14. package/dist/files.mjs +3 -17
  15. package/dist/files.mjs.map +1 -1
  16. package/dist/fork.cjs +28 -40
  17. package/dist/fork.cjs.map +1 -1
  18. package/dist/fork.d.ts +6 -27
  19. package/dist/fork.mjs +29 -40
  20. package/dist/fork.mjs.map +1 -1
  21. package/dist/helpers.cjs +61 -63
  22. package/dist/helpers.cjs.map +2 -2
  23. package/dist/helpers.d.ts +15 -37
  24. package/dist/helpers.mjs +61 -64
  25. package/dist/helpers.mjs.map +2 -2
  26. package/dist/index.cjs +3 -2
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.ts +9 -13
  29. package/dist/index.mjs +3 -2
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/log/colors.cjs +3 -1
  32. package/dist/log/colors.cjs.map +1 -1
  33. package/dist/log/colors.d.ts +2 -2
  34. package/dist/log/colors.mjs +3 -1
  35. package/dist/log/colors.mjs.map +1 -1
  36. package/dist/log/emit.d.ts +1 -1
  37. package/dist/log/logger.cjs +4 -0
  38. package/dist/log/logger.cjs.map +1 -1
  39. package/dist/log/logger.d.ts +4 -1
  40. package/dist/log/logger.mjs +4 -0
  41. package/dist/log/logger.mjs.map +1 -1
  42. package/dist/log/options.d.ts +1 -1
  43. package/dist/log/report.cjs +2 -11
  44. package/dist/log/report.cjs.map +1 -1
  45. package/dist/log/report.d.ts +36 -4
  46. package/dist/log/report.mjs +1 -10
  47. package/dist/log/report.mjs.map +1 -1
  48. package/dist/log.cjs +1 -1
  49. package/dist/log.cjs.map +1 -1
  50. package/dist/log.d.ts +6 -6
  51. package/dist/log.mjs +2 -2
  52. package/dist/log.mjs.map +1 -1
  53. package/dist/pipe.cjs +41 -34
  54. package/dist/pipe.cjs.map +1 -1
  55. package/dist/pipe.d.ts +149 -119
  56. package/dist/pipe.mjs +38 -32
  57. package/dist/pipe.mjs.map +1 -1
  58. package/dist/plugs/copy.cjs +15 -25
  59. package/dist/plugs/copy.cjs.map +2 -2
  60. package/dist/plugs/copy.d.ts +14 -13
  61. package/dist/plugs/copy.mjs +15 -17
  62. package/dist/plugs/copy.mjs.map +2 -2
  63. package/dist/plugs/coverage/analysis.d.ts +2 -2
  64. package/dist/plugs/coverage/report.cjs +1 -1
  65. package/dist/plugs/coverage/report.cjs.map +1 -1
  66. package/dist/plugs/coverage/report.d.ts +3 -3
  67. package/dist/plugs/coverage/report.mjs +1 -1
  68. package/dist/plugs/coverage/report.mjs.map +1 -1
  69. package/dist/plugs/coverage.cjs +19 -25
  70. package/dist/plugs/coverage.cjs.map +1 -1
  71. package/dist/plugs/coverage.d.ts +33 -30
  72. package/dist/plugs/coverage.mjs +20 -18
  73. package/dist/plugs/coverage.mjs.map +1 -1
  74. package/dist/plugs/debug.cjs +8 -37
  75. package/dist/plugs/debug.cjs.map +1 -1
  76. package/dist/plugs/debug.d.ts +4 -11
  77. package/dist/plugs/debug.mjs +24 -20
  78. package/dist/plugs/debug.mjs.map +1 -1
  79. package/dist/plugs/esbuild/fix-extensions.mjs +1 -1
  80. package/dist/plugs/esbuild/fix-extensions.mjs.map +1 -1
  81. package/dist/plugs/esbuild.cjs +14 -25
  82. package/dist/plugs/esbuild.cjs.map +1 -1
  83. package/dist/plugs/esbuild.d.ts +11 -16
  84. package/dist/plugs/esbuild.mjs +14 -17
  85. package/dist/plugs/esbuild.mjs.map +1 -1
  86. package/dist/plugs/eslint/runner.cjs +5 -6
  87. package/dist/plugs/eslint/runner.cjs.map +1 -1
  88. package/dist/plugs/eslint/runner.d.ts +6 -20
  89. package/dist/plugs/eslint/runner.mjs +6 -7
  90. package/dist/plugs/eslint/runner.mjs.map +1 -1
  91. package/dist/{task.cjs → plugs/eslint.cjs} +7 -24
  92. package/dist/plugs/eslint.cjs.map +6 -0
  93. package/dist/plugs/eslint.d.ts +34 -0
  94. package/dist/plugs/eslint.mjs +5 -0
  95. package/dist/plugs/eslint.mjs.map +6 -0
  96. package/dist/plugs/exec.cjs +20 -24
  97. package/dist/plugs/exec.cjs.map +1 -1
  98. package/dist/plugs/exec.d.ts +53 -53
  99. package/dist/plugs/exec.mjs +20 -23
  100. package/dist/plugs/exec.mjs.map +1 -1
  101. package/dist/plugs/filter.cjs +9 -19
  102. package/dist/plugs/filter.cjs.map +1 -1
  103. package/dist/plugs/filter.d.ts +21 -15
  104. package/dist/plugs/filter.mjs +10 -12
  105. package/dist/plugs/filter.mjs.map +1 -1
  106. package/dist/plugs/mocha/reporter.cjs +12 -6
  107. package/dist/plugs/mocha/reporter.cjs.map +1 -1
  108. package/dist/plugs/mocha/reporter.d.ts +0 -2
  109. package/dist/plugs/mocha/reporter.mjs +11 -4
  110. package/dist/plugs/mocha/reporter.mjs.map +1 -1
  111. package/dist/plugs/mocha/runner.cjs +4 -5
  112. package/dist/plugs/mocha/runner.cjs.map +1 -1
  113. package/dist/plugs/mocha/runner.d.ts +5 -31
  114. package/dist/plugs/mocha/runner.mjs +5 -6
  115. package/dist/plugs/mocha/runner.mjs.map +1 -1
  116. package/dist/plugs/mocha.cjs +22 -0
  117. package/dist/plugs/mocha.cjs.map +6 -0
  118. package/dist/plugs/mocha.d.ts +35 -0
  119. package/dist/plugs/mocha.mjs +5 -0
  120. package/dist/plugs/mocha.mjs.map +6 -0
  121. package/dist/plugs/rmf.cjs +4 -32
  122. package/dist/plugs/rmf.cjs.map +1 -1
  123. package/dist/plugs/rmf.d.ts +8 -12
  124. package/dist/plugs/rmf.mjs +25 -20
  125. package/dist/plugs/rmf.mjs.map +1 -1
  126. package/dist/plugs/tsc/compiler.d.ts +1 -1
  127. package/dist/plugs/tsc/options.d.ts +1 -1
  128. package/dist/plugs/tsc/report.d.ts +2 -2
  129. package/dist/plugs/tsc/runner.cjs +12 -11
  130. package/dist/plugs/tsc/runner.cjs.map +1 -1
  131. package/dist/plugs/tsc/runner.d.ts +4 -9
  132. package/dist/plugs/tsc/runner.mjs +12 -11
  133. package/dist/plugs/tsc/runner.mjs.map +1 -1
  134. package/dist/plugs/tsc.cjs +7 -0
  135. package/dist/plugs/tsc.cjs.map +6 -0
  136. package/dist/plugs/tsc.d.ts +36 -0
  137. package/dist/plugs/tsc.mjs +15 -0
  138. package/dist/plugs/tsc.mjs.map +6 -0
  139. package/dist/plugs.cjs +3 -5
  140. package/dist/plugs.cjs.map +1 -1
  141. package/dist/plugs.d.ts +10 -17
  142. package/dist/plugs.mjs +3 -5
  143. package/dist/plugs.mjs.map +1 -1
  144. package/dist/types.cjs +19 -0
  145. package/dist/types.cjs.map +6 -0
  146. package/dist/types.d.ts +72 -0
  147. package/dist/types.mjs +1 -0
  148. package/dist/types.mjs.map +6 -0
  149. package/dist/utils/caller.cjs +8 -11
  150. package/dist/utils/caller.cjs.map +2 -2
  151. package/dist/utils/caller.d.ts +2 -7
  152. package/dist/utils/caller.mjs +8 -11
  153. package/dist/utils/caller.mjs.map +2 -2
  154. package/dist/utils/options.cjs +4 -6
  155. package/dist/utils/options.cjs.map +1 -1
  156. package/dist/utils/options.d.ts +16 -15
  157. package/dist/utils/options.mjs +4 -6
  158. package/dist/utils/options.mjs.map +1 -1
  159. package/dist/utils/walk.d.ts +2 -2
  160. package/extra/cli.mjs +31 -20
  161. package/extra/ts-loader.mjs +6 -5
  162. package/package.json +6 -6
  163. package/src/async.ts +27 -19
  164. package/src/files.ts +6 -30
  165. package/src/fork.ts +35 -76
  166. package/src/helpers.ts +89 -101
  167. package/src/index.ts +10 -15
  168. package/src/log/colors.ts +4 -3
  169. package/src/log/emit.ts +4 -4
  170. package/src/log/logger.ts +12 -4
  171. package/src/log/options.ts +1 -1
  172. package/src/log/report.ts +8 -22
  173. package/src/log/spinner.ts +3 -3
  174. package/src/log.ts +9 -9
  175. package/src/paths.ts +1 -1
  176. package/src/pipe.ts +191 -178
  177. package/src/plugs/copy.ts +40 -31
  178. package/src/plugs/coverage/analysis.ts +4 -4
  179. package/src/plugs/coverage/report.ts +6 -5
  180. package/src/plugs/coverage.ts +64 -53
  181. package/src/plugs/debug.ts +22 -27
  182. package/src/plugs/esbuild/fix-extensions.ts +2 -2
  183. package/src/plugs/esbuild.ts +42 -46
  184. package/src/plugs/eslint/runner.ts +16 -31
  185. package/src/plugs/eslint.ts +42 -0
  186. package/src/plugs/exec.ts +93 -82
  187. package/src/plugs/filter.ts +42 -27
  188. package/src/plugs/mocha/reporter.ts +10 -5
  189. package/src/plugs/mocha/runner.ts +12 -38
  190. package/src/plugs/mocha.ts +41 -0
  191. package/src/plugs/rmf.ts +21 -25
  192. package/src/plugs/tsc/compiler.ts +1 -1
  193. package/src/plugs/tsc/options.ts +2 -2
  194. package/src/plugs/tsc/report.ts +2 -2
  195. package/src/plugs/tsc/runner.ts +24 -30
  196. package/src/plugs/tsc.ts +45 -0
  197. package/src/plugs.ts +10 -25
  198. package/src/types.ts +123 -0
  199. package/src/utils/caller.ts +11 -22
  200. package/src/utils/options.ts +49 -17
  201. package/src/utils/walk.ts +4 -4
  202. package/dist/run.cjs +0 -90
  203. package/dist/run.cjs.map +0 -6
  204. package/dist/run.d.ts +0 -89
  205. package/dist/run.mjs +0 -65
  206. package/dist/run.mjs.map +0 -6
  207. package/dist/task.cjs.map +0 -6
  208. package/dist/task.d.ts +0 -15
  209. package/dist/task.mjs +0 -14
  210. package/dist/task.mjs.map +0 -6
  211. package/src/run.ts +0 -159
  212. package/src/task.ts +0 -26
package/src/fork.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import { fork } from 'node:child_process'
2
- import { assert, failure } from './assert.js'
3
- import { runAsync } from './async.js'
4
- import { Files } from './files.js'
5
- import { $gry, $p, LogOptions, logOptions } from './log.js'
6
- import { AbsolutePath, resolveFile, requireFilename } from './paths.js'
7
- import { install, Plug, PlugName } from './pipe.js'
8
- import { Run, RunImpl } from './run.js'
2
+ import { assert, failure } from './assert'
3
+ import { runAsync } from './async'
4
+ import { Files } from './files'
5
+ import { $gry, $p, LogOptions, logOptions } from './log'
6
+ import { AbsolutePath, requireFilename, resolveFile } from './paths'
7
+ import { Plug, PlugResult, Context } from './pipe'
9
8
 
10
9
  /** Fork data, from parent to child process */
11
10
  export interface ForkData {
@@ -17,8 +16,6 @@ export interface ForkData {
17
16
  taskName: string,
18
17
  /** Build file name */
19
18
  buildFile: AbsolutePath,
20
- /** Build directory */
21
- buildDir: AbsolutePath,
22
19
  /** Files directory */
23
20
  filesDir: AbsolutePath,
24
21
  /** All files to pipe */
@@ -37,67 +34,30 @@ export interface ForkResult {
37
34
  filesList?: AbsolutePath[] | undefined,
38
35
  }
39
36
 
40
- /* ========================================================================== *
41
- * PIPE INSTALLATION *
42
- * ========================================================================== */
43
-
44
- /**
45
- * Install a _forking_ {@link Plug} in the {@link Pipe}, in other words
46
- * execute the plug in a separate process.
47
- *
48
- * As a contract, if the _last non-null_ parameter of the constructor is an
49
- * object and contains the key `coverageDir`, the process will be forked with
50
- * the approptiately resolved `NODE_V8_COVERAGE` environment variable.
51
- *
52
- * Also, forking plugs require some special attention:
53
- *
54
- * * plug functions are not supported, only classes implementing the
55
- * {@link Plug} interface can be used with this.
56
- *
57
- * * the class itself _MUST_ be exported as the _default_ export for the
58
- * `scriptFile` specified below. This is to simplify interoperability between
59
- * CommonJS and ESM modules as we use dynamic `import(...)` statements.
60
- */
61
- export function installForking(
62
- plugName: PlugName,
63
- scriptFile: AbsolutePath,
64
- ): void {
65
- /** Extend out our ForkingPlug below */
66
- const ctor = class extends ForkingPlug {
67
- constructor(...args: any[]) {
68
- super(scriptFile, args)
69
- }
70
- }
71
-
72
- /** Install the plug in */
73
- install(plugName, ctor)
74
- }
75
-
76
37
  /* ========================================================================== *
77
38
  * PARENT PROCESS SIDE OF THE FORKING PLUG IMPLEMENTATION *
78
39
  * ========================================================================== */
79
40
 
80
- export abstract class ForkingPlug implements Plug<Files | undefined> {
41
+ export abstract class ForkingPlug implements Plug<PlugResult> {
81
42
  constructor(
82
43
  private readonly _scriptFile: AbsolutePath,
83
44
  private readonly _arguments: any[],
84
45
  ) {}
85
46
 
86
- pipe(files: Files, run: Run): Promise<Files | undefined> {
47
+ pipe(files: Files, context: Context): Promise<PlugResult> {
87
48
  const message: ForkData = {
88
49
  scriptFile: this._scriptFile,
89
50
  constructorArgs: this._arguments,
90
- taskName: run.taskName,
91
- buildFile: run.buildFile,
92
- buildDir: run.buildDir,
51
+ taskName: context.taskName,
52
+ buildFile: context.buildFile,
93
53
  filesDir: files.directory,
94
54
  filesList: [ ...files.absolutePaths() ],
95
- logOpts: logOptions.fork(run.taskName),
55
+ logOpts: logOptions.fork(context.taskName),
96
56
  }
97
57
 
98
58
  /* Get _this_ filename to spawn */
99
59
  const script = requireFilename(__fileurl)
100
- run.log.debug('About to fork plug from', $p(script))
60
+ context.log.debug('About to fork plug from', $p(script))
101
61
 
102
62
  /* Environment variables */
103
63
  const env = { ...process.env }
@@ -107,8 +67,8 @@ export abstract class ForkingPlug implements Plug<Files | undefined> {
107
67
  if (this._arguments[i] == null) continue // null or undefined... optionals
108
68
  if (typeof this._arguments[i] === 'object') {
109
69
  if (typeof this._arguments[i].coverageDir === 'string') {
110
- const dir = env.NODE_V8_COVERAGE = run.resolve(this._arguments[i].coverageDir)
111
- run.log.debug('Forked process will produce coverage in', $p(dir))
70
+ const dir = env.NODE_V8_COVERAGE = context.resolve(this._arguments[i].coverageDir)
71
+ context.log.debug('Forked process will produce coverage in', $p(dir))
112
72
  }
113
73
  }
114
74
  }
@@ -119,32 +79,32 @@ export abstract class ForkingPlug implements Plug<Files | undefined> {
119
79
  env,
120
80
  })
121
81
 
122
- run.log.info('Running', $p(script), $gry(`(pid=${child.pid})`))
82
+ context.log.info('Running', $p(script), $gry(`(pid=${child.pid})`))
123
83
 
124
84
  /* Return a promise from the child process events */
125
85
  let done = false // this will be fixed up in "finally" below
126
- return new Promise<Files | undefined>((resolve, reject) => {
86
+ return new Promise<PlugResult>((resolve, reject) => {
127
87
  let result: ForkResult | undefined = undefined
128
88
 
129
89
  child.on('error', (error) => {
130
- run.log.error('Child process error', error)
90
+ context.log.error('Child process error', error)
131
91
  return done || reject(failure())
132
92
  })
133
93
 
134
94
  child.on('message', (message: ForkResult) => {
135
- run.log.debug('Message from child process', message)
95
+ context.log.debug('Message from child process', message)
136
96
  result = message
137
97
  })
138
98
 
139
99
  child.on('exit', (code, signal) => {
140
100
  if (signal) {
141
- run.log.error(`Child process exited with signal ${signal}`, $gry(`(pid=${child.pid})`))
101
+ context.log.error(`Child process exited with signal ${signal}`, $gry(`(pid=${child.pid})`))
142
102
  return done || reject(failure())
143
103
  } else if (code !== 0) {
144
- run.log.error(`Child process exited with code ${code}`, $gry(`(pid=${child.pid})`))
104
+ context.log.error(`Child process exited with code ${code}`, $gry(`(pid=${child.pid})`))
145
105
  return done || reject(failure())
146
106
  } else if (! result) {
147
- run.log.error('Child process exited with no result', $gry(`(pid=${child.pid})`))
107
+ context.log.error('Child process exited with no result', $gry(`(pid=${child.pid})`))
148
108
  return done || reject(failure())
149
109
  } else if (result.failed) {
150
110
  // definitely logged on the child side
@@ -153,7 +113,7 @@ export abstract class ForkingPlug implements Plug<Files | undefined> {
153
113
 
154
114
  /* We definitely have a successful result! */
155
115
  return done || resolve(message.filesDir && message.filesList ?
156
- run.files(message.filesDir).unchecked(...message.filesList).build() :
116
+ Files.builder(message.filesDir).add(...message.filesList).build() :
157
117
  undefined)
158
118
  })
159
119
 
@@ -161,16 +121,16 @@ export abstract class ForkingPlug implements Plug<Files | undefined> {
161
121
  try {
162
122
  const result = child.send(message, (error) => {
163
123
  if (error) {
164
- run.log.error('Error sending message to child process (callback failure)', error)
124
+ context.log.error('Error sending message to child process (callback failure)', error)
165
125
  reject(failure())
166
126
  }
167
127
  })
168
128
  if (! result) {
169
- run.log.error('Error sending message to child process (send returned false)')
129
+ context.log.error('Error sending message to child process (send returned false)')
170
130
  reject(failure())
171
131
  }
172
132
  } catch (error) {
173
- run.log.error('Error sending message to child process (exception caught)', error)
133
+ context.log.error('Error sending message to child process (exception caught)', error)
174
134
  reject(failure())
175
135
  }
176
136
  }).finally(() => done = true)
@@ -204,7 +164,6 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
204
164
  constructorArgs,
205
165
  taskName,
206
166
  buildFile,
207
- buildDir,
208
167
  filesDir,
209
168
  filesList,
210
169
  logOpts,
@@ -213,12 +172,12 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
213
172
  /* Restore logging options first */
214
173
  Object.assign(logOptions, logOpts)
215
174
 
216
- /* First of all, our Run */
217
- const run = new RunImpl({ buildDir, buildFile, taskName })
218
- run.log.debug('Message from parent process', message)
175
+ /* First of all, our plug context */
176
+ const context = new Context(buildFile, taskName)
177
+ context.log.debug('Message from parent process', message)
219
178
 
220
179
  /* Contextualize this run, and go! */
221
- const result = runAsync(run, taskName, async () => {
180
+ const result = runAsync(context, taskName, async () => {
222
181
  /* Check that we have a proper script file name */
223
182
  assert(resolveFile(scriptFile), `Script file ${$p(scriptFile)} not found`)
224
183
  const script = await import(scriptFile)
@@ -232,11 +191,11 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
232
191
  `Script ${$p(scriptFile)} does not export a default constructor`)
233
192
 
234
193
  /* Create the Plug instance and our Files instance */
235
- const plug = new Ctor(...constructorArgs) as Plug<Files | undefined>
236
- const files = run.files(filesDir).unchecked(...filesList).build()
194
+ const plug = new Ctor(...constructorArgs) as Plug<PlugResult>
195
+ const files = Files.builder(filesDir).add(...filesList).build()
237
196
 
238
197
  /* Run and return the result */
239
- return plug.pipe(files, run)
198
+ return plug.pipe(files, context)
240
199
  })
241
200
 
242
201
  /* The result promise generates a message back to the parent process */
@@ -248,7 +207,7 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
248
207
  process.send!(message, (err: Error) => err ? reject(err) : resolve())
249
208
  })
250
209
  }, (error) => {
251
- run.log.error(error)
210
+ context.log.error(error)
252
211
  return new Promise<void>((resolve, reject) => {
253
212
  process.send!({ failed: true }, (err: Error) => err ? reject(err) : resolve())
254
213
  })
@@ -256,10 +215,10 @@ if ((process.argv[1] === requireFilename(__fileurl)) && (process.send)) {
256
215
 
257
216
  /* The promise generated by `process.send()` simply triggers process exit */
258
217
  promise.then(() => {
259
- run.log.debug('Forked plug exiting')
218
+ context.log.debug('Forked plug exiting')
260
219
  process.exit(0)
261
220
  }, (error) => {
262
- run.log.error('Error sending message back to parent process', error)
221
+ context.log.error('Error sending message back to parent process', error)
263
222
  process.exit(1)
264
223
  })
265
224
  })
package/src/helpers.ts CHANGED
@@ -1,133 +1,121 @@
1
- import {
2
- AbsolutePath,
3
- commonPath,
4
- getCurrentWorkingDirectory,
5
- resolveDirectory,
6
- resolveFile,
7
- } from './paths.js'
8
-
9
- import { assert } from './assert.js'
10
- import { currentRun } from './async.js'
11
- import { Files, FilesBuilder } from './files.js'
12
- import { $p, log, LogLevelString } from './log.js'
13
- import { Pipe } from './pipe.js'
14
- import { FindOptions } from './run.js'
15
- import { rm } from './utils/asyncfs.js'
16
- import { ParseOptions } from './utils/options.js'
17
-
18
- /**
19
- * Recursively remove the specified directory _**(use with care)**_.
20
- */
21
- export async function rmrf(directory: string): Promise<void> {
22
- const run = currentRun()
23
- assert(run, 'Unable to find files outside a running task')
24
- const dir = run.resolve(directory)
25
-
26
- assert(dir !== getCurrentWorkingDirectory(),
27
- `Cowardly refusing to wipe current working directory ${$p(dir)}`)
28
-
29
- assert(dir !== run.buildDir,
30
- `Cowardly refusing to wipe build file directory ${$p(dir)}`)
1
+ import { assert } from './assert'
2
+ import { requireContext } from './async'
3
+ import { Files } from './files'
4
+ import { $p, log } from './log'
5
+ import { AbsolutePath, commonPath, getCurrentWorkingDirectory, resolveDirectory, resolveFile } from './paths'
6
+ import { Context, Pipe, Plug, PlugFunction, PlugResult } from './pipe'
7
+ import { rm } from './utils/asyncfs'
8
+ import { ParseOptions, parseOptions } from './utils/options'
9
+ import { walk, WalkOptions } from './utils/walk'
10
+
11
+ class PipeImpl extends Pipe implements Pipe {
12
+ constructor(private readonly _start: (context: Context) => Promise<Files>) {
13
+ super()
14
+ }
31
15
 
32
- if (! resolveDirectory(dir)) {
33
- log.info('Directory', $p(dir), 'not found')
34
- return
16
+ plug(plug: Plug<Files>): Pipe
17
+ plug(plug: PlugFunction<Files>): Pipe
18
+ plug(plug: Plug<void | undefined>): Promise<undefined>
19
+ plug(plug: PlugFunction<void | undefined>): Promise<undefined>
20
+ plug(arg: Plug<PlugResult> | PlugFunction<PlugResult>): Pipe | Promise<undefined> {
21
+ const plug = typeof arg === 'function' ? { pipe: arg } : arg
22
+
23
+ const parent = this
24
+ return new PipeImpl(async (context: Context): Promise<Files> => {
25
+ const files = await parent._start(context)
26
+ const files2 = await plug.pipe(files, context)
27
+ assert(files2, 'Unable to extend pipe (part tres)')
28
+ return files2
29
+ })
35
30
  }
36
31
 
37
- log.notice('Removing directory', $p(dir), 'recursively')
38
- await rm(dir, { recursive: true })
32
+ async run(): Promise<Files> {
33
+ return this._start(requireContext())
34
+ }
39
35
  }
40
36
 
41
- /**
42
- * Set the current _log level_.
43
- *
44
- * The _level_ will be applied _only_ within the execution of the current task.
45
- */
46
- export function setLogLevel(level: LogLevelString): void {
47
- const run = currentRun()
48
- assert(run, 'Unable to find files outside a running task')
49
- return run.setLogLevel(level)
37
+ /** The {@link FindOptions} interface defines the options for finding files. */
38
+ export interface FindOptions extends WalkOptions {
39
+ /** The directory where to start looking for files. */
40
+ directory?: string
50
41
  }
51
42
 
52
- /**
53
- * Resolve a path into an {@link AbsolutePath}.
54
- *
55
- * If the path starts with `@...` it is considered to be relative to the
56
- * _directory containing the build file where the task was defined_, otherwise
57
- * it will be relative to the {@link process.cwd | current working directory}.
58
- */
59
- export function resolve(...paths: string[]): AbsolutePath {
60
- const run = currentRun()
61
- assert(run, 'Unable to find files outside a running task')
62
- return run.resolve(...paths)
63
- }
64
43
 
44
+ export function find(glob: string): Pipe
45
+ export function find(glob: string, ...globs: string[]): Pipe
46
+ export function find(glob: string, options: FindOptions): Pipe
47
+ export function find(glob: string, ...extra: [...globs: string[], options: FindOptions]): Pipe
65
48
 
66
- /**
67
- * Create a new {@link Files} instance.
68
- */
69
- export function files(files: Files): FilesBuilder
70
- export function files(directory: string, ...paths: string[]): FilesBuilder
71
- export function files(first: Files | string | undefined, ...paths: string[]): FilesBuilder {
72
- const run = currentRun()
73
- assert(run, 'Unable to create files builder outside a running task')
74
- if (typeof first === 'string') {
75
- return run.files(first, ...paths)
76
- } else if (first) {
77
- return run.files(first)
78
- } else {
79
- return run.files()
80
- }
49
+ export function find(...args: ParseOptions<FindOptions>): Pipe {
50
+ const { params: globs, options } = parseOptions(args, {})
51
+
52
+ return new PipeImpl(async (context: Context): Promise<Files> => {
53
+ const directory = options.directory ?
54
+ context.resolve(options.directory) :
55
+ getCurrentWorkingDirectory()
56
+
57
+ const builder = Files.builder(directory)
58
+ for await (const file of walk(directory, globs, options)) {
59
+ builder.add(file)
60
+ }
61
+
62
+ return builder.build()
63
+ })
81
64
  }
82
65
 
83
- /**
84
- * Merge multiple {@link Files} instance.
85
- */
86
- export function merge(args: (Files | Promise<Files>)[]): Promise<Files> & Pipe {
87
- const run = currentRun()
88
- assert(run, 'Unable to create files builder outside a running task')
66
+ export function merge(...pipes: Pipe[]): Pipe {
67
+ return new PipeImpl(async (): Promise<Files> => {
68
+ if (pipes.length === 0) return Files.builder(getCurrentWorkingDirectory()).build()
69
+
70
+ const results: Files[] = []
89
71
 
90
- const promise = Promise.resolve().then(async () => {
91
- // No arguments, no files... Just convenience!
92
- if (args.length === 0) return run.pipe(run.files().build())
72
+ for (const pipe of pipes) {
73
+ const result = await pipe.run()
74
+ assert(result, 'Pipe did not return a Files result')
75
+ results.push(result)
76
+ }
93
77
 
94
- // Resolve all the `Files` instances (might be from other tasks)
95
- const instances = await Promise.all(args)
96
- const [ first, ...others ] = instances
78
+ const [ first, ...others ] = results
97
79
 
98
80
  const firstDir = first.directory
99
81
  const otherDirs = others.map((f) => f.directory)
100
82
 
101
83
  const directory = commonPath(firstDir, ...otherDirs)
102
84
 
103
- return run.files(directory).merge(first, ...others).build()
85
+ return Files.builder(directory).merge(first, ...others).build()
104
86
  })
105
-
106
- return run.pipe(promise)
107
87
  }
108
88
 
109
89
  /**
110
- * Find files according to the globs and {@link FindOptions} specified.
90
+ * Recursively remove the specified directory _**(use with care)**_.
111
91
  */
112
- export function find(glob: string, ...args: ParseOptions<FindOptions>): Pipe & Promise<Files> {
113
- const run = currentRun()
114
- assert(run, 'Unable to find files outside a running task')
115
- return run.find(glob, ...args)
116
- }
92
+ export async function rmrf(directory: string): Promise<void> {
93
+ const context = requireContext()
94
+ const dir = context.resolve(directory)
117
95
 
118
- /** Create a {@link Pipe} from a {@link Files} instance. */
119
- export function pipe(files: Files | Promise<Files>): Pipe & Promise<Files> {
120
- const run = currentRun()
121
- assert(run, 'Unable to create pipes outside a running task')
122
- return run.pipe(files)
96
+ assert(dir !== getCurrentWorkingDirectory(),
97
+ `Cowardly refusing to wipe current working directory ${$p(dir)}`)
98
+
99
+ assert(dir !== context.resolve('@'),
100
+ `Cowardly refusing to wipe build file directory ${$p(dir)}`)
101
+
102
+ if (! resolveDirectory(dir)) {
103
+ log.info('Directory', $p(dir), 'not found')
104
+ return
105
+ }
106
+
107
+ log.notice('Removing directory', $p(dir), 'recursively')
108
+ await rm(dir, { recursive: true })
123
109
  }
124
110
 
125
111
  /** Return an absolute path of the file if it exist on disk */
126
- export function isFile(...paths: string[]): AbsolutePath | undefined {
127
- return resolveFile(resolve(...paths))
112
+ export function isFile(...paths: [ string, ...string[] ]): AbsolutePath | undefined {
113
+ const path = requireContext().resolve(...paths)
114
+ return resolveFile(path)
128
115
  }
129
116
 
130
117
  /** Return an absolute path of the file if it exist on disk */
131
- export function isDirectory(...paths: string[]): AbsolutePath | undefined {
132
- return resolveDirectory(resolve(...paths))
118
+ export function isDirectory(...paths: [ string, ...string[] ]): AbsolutePath | undefined {
119
+ const path = requireContext().resolve(...paths)
120
+ return resolveDirectory(path)
133
121
  }
package/src/index.ts CHANGED
@@ -1,20 +1,15 @@
1
1
  /// <reference path="../extra/webassembly.d.ts" />
2
2
 
3
- // Our minimal exports
4
- export * from './assert.js'
5
- export * from './build.js'
6
- export * from './plugs.js'
7
- export * from './log.js'
8
- export * from './helpers.js'
3
+ export type { AbsolutePath } from './paths'
4
+ export type { Files, FilesBuilder } from './files'
5
+ export type { Pipe } from './pipe'
9
6
 
10
- // Utility types
11
- export type { MatchOptions, MatchResult } from './utils/match.js'
12
- export type { ParseOptions } from './utils/options.js'
13
- export type { WalkOptions } from './utils/walk.js'
7
+ // Our minimal exports
8
+ export * from './assert'
9
+ export * from './build'
10
+ export * from './helpers'
11
+ export * from './log'
14
12
 
15
13
  // PlugJS types
16
- export type { AbsolutePath } from './paths.js'
17
- export type { Files, FilesBuilder } from './files.js'
18
- export type { FindOptions, Run } from './run.js'
19
- export type { Pipe, Plug, PlugFunction } from './pipe.js'
20
- export type { Task } from './task.js'
14
+ export * from './plugs'
15
+ export * from './types'
package/src/log/colors.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { sep } from 'node:path'
2
- import { AbsolutePath, getCurrentWorkingDirectory, resolveRelativeChildPath } from '../paths.js'
3
- import { logOptions } from './options.js'
2
+ import { AbsolutePath, getCurrentWorkingDirectory, resolveRelativeChildPath } from '../paths'
3
+ import { logOptions } from './options'
4
4
 
5
5
  /* ========================================================================== */
6
6
 
@@ -49,7 +49,7 @@ export function $t(task: string): string {
49
49
  }
50
50
 
51
51
  /** Colorize milliseconds. */
52
- export function $ms(millis: number): string {
52
+ export function $ms(millis: number, note?: string): string {
53
53
  let string: string
54
54
  if (millis >= 60000) {
55
55
  // One minute or more: style is Xm Ys
@@ -70,6 +70,7 @@ export function $ms(millis: number): string {
70
70
  // Milliseconds: style is 123ms
71
71
  string = `${millis}ms`
72
72
  }
73
+ if (note) string = `${note} ${string}`
73
74
  return _colors ? `${gry}[${string}]${rst}` : `[${string}]`
74
75
  }
75
76
 
package/src/log/emit.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { formatWithOptions } from 'node:util'
2
- import { $blu, $grn, $gry, $red, $t, $ylw } from './colors.js'
3
- import { DEBUG, INFO, LogLevel, NOTICE, TRACE, WARN } from './levels.js'
4
- import { logOptions } from './options.js'
5
- import { zapSpinner } from './spinner.js'
2
+ import { $blu, $grn, $gry, $red, $t, $ylw } from './colors'
3
+ import { DEBUG, INFO, LogLevel, NOTICE, TRACE, WARN } from './levels'
4
+ import { logOptions } from './options'
5
+ import { zapSpinner } from './spinner'
6
6
 
7
7
  /* ========================================================================== */
8
8
 
package/src/log/logger.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { isBuildError, isBuildFailure } from '../assert.js'
2
- import { emitColor, emitPlain, LogEmitter } from './emit.js'
3
- import { DEBUG, ERROR, INFO, LogLevel, NOTICE, TRACE, WARN } from './levels.js'
4
- import { logOptions } from './options.js'
1
+ import { isBuildError, isBuildFailure } from '../assert'
2
+ import { emitColor, emitPlain, LogEmitter } from './emit'
3
+ import { DEBUG, ERROR, INFO, LogLevel, NOTICE, TRACE, WARN } from './levels'
4
+ import { logOptions } from './options'
5
+ import { Report, ReportImpl } from './report'
5
6
 
6
7
  /* ========================================================================== */
7
8
 
@@ -48,6 +49,8 @@ export interface Logger extends Log {
48
49
  leave(): this
49
50
  /** Leave a sub-level of logging, decreasing indent */
50
51
  leave(level: LogLevel, message: string): this
52
+ /** Create a {@link Report} associated with this instance */
53
+ report(title: string): Report
51
54
  }
52
55
 
53
56
  /** Return a {@link Logger} associated with the specified task name. */
@@ -149,6 +152,7 @@ class LoggerImpl implements Logger {
149
152
  const [ level, message ] = args
150
153
  this._stack.push({ level, message, indent: this._indent })
151
154
  }
155
+
152
156
  this._indent ++
153
157
  return this
154
158
  }
@@ -168,4 +172,8 @@ class LoggerImpl implements Logger {
168
172
 
169
173
  return this
170
174
  }
175
+
176
+ report(title: string): Report {
177
+ return new ReportImpl(title, this._task, this._emitter)
178
+ }
171
179
  }
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from 'node:events'
2
2
  import { Writable } from 'node:stream'
3
3
  import { InspectOptions } from 'node:util'
4
- import { getLevelNumber, LogLevel, LogLevelString, NOTICE } from './levels.js'
4
+ import { getLevelNumber, LogLevel, LogLevelString, NOTICE } from './levels'
5
5
 
6
6
  /* ========================================================================== */
7
7
 
package/src/log/report.ts CHANGED
@@ -1,21 +1,13 @@
1
- import { fail, failure } from '../assert.js'
2
- import { AbsolutePath } from '../paths.js'
3
- import { readFile } from '../utils/asyncfs.js'
4
- import { $blu, $cyn, $gry, $red, $und, $wht, $ylw } from './colors.js'
5
- import { emitColor, emitPlain, LogEmitter } from './emit.js'
6
- import { ERROR, LogLevels, NOTICE, WARN } from './levels.js'
7
- import { logOptions } from './options.js'
1
+ import { fail, failure } from '../assert'
2
+ import { AbsolutePath } from '../paths'
3
+ import { readFile } from '../utils/asyncfs'
4
+ import { $blu, $cyn, $gry, $red, $und, $wht, $ylw } from './colors'
5
+ import { LogEmitter } from './emit'
6
+ import { ERROR, LogLevels, NOTICE, WARN } from './levels'
7
+ import { logOptions } from './options'
8
8
 
9
9
  /* ========================================================================== */
10
10
 
11
- /* Track changes for colors */
12
- let _colors = logOptions.colors
13
- logOptions.on('changed', ({ colors }) => {
14
- _colors = colors
15
- })
16
-
17
- /* ========================================================================== *
18
-
19
11
  /** Levels used in a {@link Report} */
20
12
  export type ReportLevel = LogLevels['NOTICE' | 'WARN' | 'ERROR']
21
13
 
@@ -91,12 +83,6 @@ export interface Report {
91
83
  done(showSources?: boolean | undefined): void
92
84
  }
93
85
 
94
- /** Create a new {@link Report} with the given title */
95
- export function createReport(title: string, taskName: string): Report {
96
- const emitter = _colors ? emitColor : emitPlain
97
- return new ReportImpl(title, taskName, emitter)
98
- }
99
-
100
86
  /* ========================================================================== *
101
87
  * REPORT IMPLEMENTATION *
102
88
  * ========================================================================== */
@@ -118,7 +104,7 @@ interface ReportInternalAnnotation {
118
104
  readonly note: string
119
105
  }
120
106
 
121
- class ReportImpl implements Report {
107
+ export class ReportImpl implements Report {
122
108
  private readonly _sources = new Map<AbsolutePath, string[]>()
123
109
  private readonly _annotations = new Map<AbsolutePath, ReportInternalAnnotation>()
124
110
  private readonly _records = new Map<AbsolutePath | Null, Set<ReportInternalRecord>>()
@@ -1,6 +1,6 @@
1
- import { runningTasks } from '../async.js'
2
- import { $cyn, $gry, $t } from './colors.js'
3
- import { logOptions } from './options.js'
1
+ import { runningTasks } from '../async'
2
+ import { $cyn, $gry, $t } from './colors'
3
+ import { logOptions } from './options'
4
4
 
5
5
  /* ========================================================================== */
6
6