@plugjs/plug 0.0.15 → 0.0.16

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/src/pipe.ts CHANGED
@@ -1,9 +1,17 @@
1
- import type { Files } from './files'
2
- import { getLogger, Logger } from './log'
3
- import { AbsolutePath, getAbsoluteParent, getCurrentWorkingDirectory, resolveAbsolutePath } from './paths'
1
+ import {
2
+ AbsolutePath,
3
+ commonPath,
4
+ getAbsoluteParent,
5
+ getCurrentWorkingDirectory,
6
+ resolveAbsolutePath,
7
+ } from './paths'
4
8
 
5
- import { ForkingPlug } from './fork'
6
9
  import { sep } from 'path'
10
+ import { assert } from './assert'
11
+ import { requireContext } from './async'
12
+ import { Files } from './files'
13
+ import { ForkingPlug } from './fork'
14
+ import { getLogger, Logger } from './log'
7
15
 
8
16
  /* ========================================================================== *
9
17
  * PLUGS *
@@ -50,6 +58,14 @@ export class Context {
50
58
  this.log = getLogger(taskName)
51
59
  }
52
60
 
61
+ /**
62
+ * Resolve a (set of) path(s) in this {@link Context}.
63
+ *
64
+ * If the path (or first component thereof) starts with `@...`, then the
65
+ * resolved path will be relative to the directory containing the build file
66
+ * where the current task was defined, otherwise it will be relative to the
67
+ * current working directory.
68
+ */
53
69
  resolve(path: string, ...paths: string[]): AbsolutePath {
54
70
  // Paths starting with "@" are relative to the build file directory
55
71
  if (path && path.startsWith('@')) {
@@ -79,16 +95,72 @@ abstract class PipeProto {
79
95
  }
80
96
 
81
97
  /**
82
- * The {@link Pipe} abstract defines processing pipeline where multiple
98
+ * The {@link Pipe} class defines processing pipeline where multiple
83
99
  * {@link Plug}s can transform lists of {@link Files}.
84
100
  */
85
- export abstract class Pipe extends PipeProto {
86
- abstract plug(plug: Plug<Files>): Pipe
87
- abstract plug(plug: PlugFunction<Files>): Pipe
88
- abstract plug(plug: Plug<void | undefined>): Promise<undefined>
89
- abstract plug(plug: PlugFunction<void | undefined>): Promise<undefined>
101
+ export class Pipe extends PipeProto {
102
+ constructor(
103
+ private readonly _context: Context,
104
+ private readonly _run: () => Promise<Files>,
105
+ ) {
106
+ super()
107
+ }
90
108
 
91
- abstract run(): Promise<Files>
109
+ plug(plug: Plug<Files>): Pipe
110
+ plug(plug: PlugFunction<Files>): Pipe
111
+ plug(plug: Plug<void | undefined>): Promise<undefined>
112
+ plug(plug: PlugFunction<void | undefined>): Promise<undefined>
113
+ plug(arg: Plug<PlugResult> | PlugFunction<PlugResult>): Pipe | Promise<undefined> {
114
+ const plug = typeof arg === 'function' ? { pipe: arg } : arg
115
+
116
+ const parent = this
117
+ const context = this._context
118
+ return new Pipe(context, async (): Promise<Files> => {
119
+ const previous = await parent.run()
120
+ const current = await plug.pipe(previous, context)
121
+ assert(current, 'Unable to extend pipe')
122
+ return current
123
+ })
124
+ }
125
+
126
+ run(): Promise<Files> {
127
+ return this._run()
128
+ }
129
+
130
+ /**
131
+ * Merge the results of several {@link Pipe}s into a single one.
132
+ *
133
+ * Merging is performed _in parallel_. When serial execution is to be desired,
134
+ * we can merge the awaited _result_ of the {@link Pipe}.
135
+ *
136
+ * For example:
137
+ *
138
+ * ```
139
+ * const pipe: Pipe = merge([
140
+ * // other tasks return `Pipe & Promise<Files>` so we can
141
+ * // direcrly await their result without invoking `run()`
142
+ * await this.anotherTask1(),
143
+ * await this.anotherTask2(),
144
+ * ])
145
+ * ```
146
+ */
147
+ static merge(pipes: (Pipe | Files | Promise<Files>)[]): Pipe {
148
+ const context = requireContext()
149
+ return new Pipe(context, async (): Promise<Files> => {
150
+ if (pipes.length === 0) return Files.builder(getCurrentWorkingDirectory()).build()
151
+
152
+ const [ first, ...other ] = await Promise.all(pipes.map((pipe) => {
153
+ return 'run' in pipe ? pipe.run() : pipe
154
+ }))
155
+
156
+ const firstDir = first.directory
157
+ const otherDirs = other.map((f) => f.directory)
158
+
159
+ const directory = commonPath(firstDir, ...otherDirs)
160
+
161
+ return Files.builder(directory).merge(first, ...other).build()
162
+ })
163
+ }
92
164
  }
93
165
 
94
166
  /* ========================================================================== *
package/src/plugs/copy.ts CHANGED
@@ -95,7 +95,7 @@ install('copy', class Copy implements Plug<Files> {
95
95
  }
96
96
 
97
97
  /* Record this file */
98
- builder.add(relative)
98
+ builder.add(target)
99
99
  }
100
100
 
101
101
  const result = builder.build()
@@ -1,11 +1,11 @@
1
1
  import { Files } from '../files'
2
- import { $gry, $p, $und } from '../log'
3
- import { install, Plug, Context } from '../pipe'
2
+ import { $gry, $p, $und, $ylw } from '../log'
3
+ import { install, Plug, Context, PipeParameters } from '../pipe'
4
4
 
5
5
  declare module '../pipe' {
6
6
  export interface Pipe {
7
7
  /** Log some info about the current {@link Files} being passed around. */
8
- debug(): Pipe
8
+ debug(title?: string): Pipe
9
9
  }
10
10
  }
11
11
 
@@ -15,8 +15,15 @@ declare module '../pipe' {
15
15
 
16
16
  /** Writes some info about the current {@link Files} being passed around. */
17
17
  install('debug', class Debug implements Plug<Files> {
18
+ private readonly _title: string
19
+
20
+ constructor(...args: PipeParameters<'debug'>) {
21
+ const [ title = 'Debugging' ] = args
22
+ this._title = title
23
+ }
24
+
18
25
  async pipe(files: Files, context: Context): Promise<Files> {
19
- context.log.notice('Debugging', files.length, 'files')
26
+ context.log.notice(this._title, `${$gry('(')}${$ylw(files.length)} ${$gry('files)')}`)
20
27
  context.log.notice('- base dir:', $p(context.resolve('@')))
21
28
  context.log.notice('- build file dir:', $p(context.resolve('.')))
22
29
  context.log.notice('- files dir:', $p(files.directory))
package/src/types.ts CHANGED
@@ -51,7 +51,7 @@ export interface Task<T extends Result = Result> {
51
51
  * The {@link TaskResult} type identifies _what_ can be returned by a
52
52
  * {@link TaskDef | _task definition_}.
53
53
  */
54
- export type TaskResult = Pipe | Promise<undefined> | Files | void | undefined
54
+ export type TaskResult = Pipe | Files | void | undefined
55
55
 
56
56
  /** The {@link TaskDef} type identifies the _definition_ of a task. */
57
57
  export type TaskDef<R extends TaskResult = TaskResult> = () => R | Promise<R>
@@ -70,9 +70,7 @@ export type Tasks<D extends BuildDef = BuildDef> = {
70
70
  readonly [ k in string & keyof D as D[k] extends TaskDef | Task ? k : never ] :
71
71
  D[k] extends TaskDef<infer R> ?
72
72
  R extends void | undefined ? Task<undefined> :
73
- R extends Promise<undefined> ? Task<undefined> :
74
- R extends Pipe ? Task<Files> :
75
- R extends Files ? Task<Files> :
73
+ R extends Pipe | Files ? Task<Files> :
76
74
  never :
77
75
  D[k] extends Task ? D[k] :
78
76
  never
@@ -83,9 +81,8 @@ export type Tasks<D extends BuildDef = BuildDef> = {
83
81
  * ========================================================================== */
84
82
 
85
83
  /**
86
- * The {@link BuildDef} interface describes the _definition_ of a
87
- * {@link Context}, that is the object passed to {@link build} to produce
88
- * a {@link Build}.
84
+ * The {@link BuildDef} interface describes the _definition_ of a {@link Build},
85
+ * all its properties and tasks.
89
86
  */
90
87
  export interface BuildDef {
91
88
  [ k : string ] : string | TaskDef | Task
@@ -116,8 +113,4 @@ export type ThisBuild<D extends BuildDef> = {
116
113
  * The {@link Build} type represents the collection of {@link Task}s
117
114
  * and _properties_ compiled from a {@link BuildDef | build definition}.
118
115
  */
119
- export type Build<
120
- D extends BuildDef = BuildDef,
121
- T extends Tasks<D> = Tasks<D>,
122
- P extends Props<D> = Props<D>,
123
- > = T & P
116
+ export type Build<D extends BuildDef = BuildDef> = Tasks<D> & Props<D>