@plugjs/plug 0.3.5 → 0.4.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/asserts.cjs +10 -12
- package/dist/asserts.cjs.map +1 -1
- package/dist/asserts.d.ts +1 -2
- package/dist/asserts.mjs +9 -10
- package/dist/asserts.mjs.map +1 -1
- package/dist/async.cjs +5 -20
- package/dist/async.cjs.map +2 -2
- package/dist/async.mjs +5 -20
- package/dist/async.mjs.map +2 -2
- package/dist/build.cjs +113 -64
- package/dist/build.cjs.map +2 -2
- package/dist/build.d.ts +9 -7
- package/dist/build.mjs +110 -63
- package/dist/build.mjs.map +2 -2
- package/dist/cli.d.mts +12 -0
- package/dist/cli.mjs +266 -0
- package/dist/cli.mjs.map +6 -0
- package/dist/files.cjs +5 -3
- package/dist/files.cjs.map +1 -1
- package/dist/files.d.ts +2 -1
- package/dist/files.mjs +11 -4
- package/dist/files.mjs.map +1 -1
- package/dist/fork.cjs +30 -12
- package/dist/fork.cjs.map +1 -1
- package/dist/fork.d.ts +10 -0
- package/dist/fork.mjs +31 -13
- package/dist/fork.mjs.map +1 -1
- package/dist/helpers.cjs +32 -13
- package/dist/helpers.cjs.map +2 -2
- package/dist/helpers.d.ts +12 -0
- package/dist/helpers.mjs +37 -14
- package/dist/helpers.mjs.map +2 -2
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +4 -1
- package/dist/index.mjs.map +1 -1
- package/dist/logging/emit.cjs +4 -4
- package/dist/logging/emit.cjs.map +1 -1
- package/dist/logging/emit.mjs +4 -4
- package/dist/logging/emit.mjs.map +1 -1
- package/dist/logging/logger.cjs +43 -2
- package/dist/logging/logger.cjs.map +1 -1
- package/dist/logging/logger.d.ts +36 -3
- package/dist/logging/logger.mjs +43 -3
- package/dist/logging/logger.mjs.map +1 -1
- package/dist/logging/options.cjs +8 -12
- package/dist/logging/options.cjs.map +1 -1
- package/dist/logging/options.d.ts +44 -1
- package/dist/logging/options.mjs +8 -12
- package/dist/logging/options.mjs.map +1 -1
- package/dist/logging.cjs +14 -3
- package/dist/logging.cjs.map +1 -1
- package/dist/logging.d.ts +2 -0
- package/dist/logging.mjs +13 -3
- package/dist/logging.mjs.map +1 -1
- package/dist/plugs/build.cjs +63 -0
- package/dist/plugs/build.cjs.map +6 -0
- package/dist/plugs/build.d.ts +13 -0
- package/dist/plugs/build.mjs +37 -0
- package/dist/plugs/build.mjs.map +6 -0
- package/dist/plugs/debug.cjs +7 -9
- package/dist/plugs/debug.cjs.map +1 -1
- package/dist/plugs/debug.mjs +8 -10
- package/dist/plugs/debug.mjs.map +1 -1
- package/dist/types.cjs +12 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +35 -9
- package/dist/types.mjs +5 -0
- package/dist/types.mjs.map +2 -2
- package/dist/utils/diff.cjs +1 -4
- package/dist/utils/diff.cjs.map +1 -1
- package/dist/utils/diff.mjs +1 -4
- package/dist/utils/diff.mjs.map +1 -1
- package/dist/utils/exec.cjs +5 -12
- package/dist/utils/exec.cjs.map +2 -2
- package/dist/utils/exec.d.ts +0 -2
- package/dist/utils/exec.mjs +6 -13
- package/dist/utils/exec.mjs.map +1 -1
- package/dist/utils/{types.cjs → singleton.cjs} +14 -13
- package/dist/utils/singleton.cjs.map +6 -0
- package/dist/utils/singleton.d.ts +12 -0
- package/dist/utils/singleton.mjs +13 -0
- package/dist/utils/singleton.mjs.map +6 -0
- package/dist/utils.cjs +2 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +7 -9
- package/src/asserts.ts +10 -12
- package/src/async.ts +6 -29
- package/src/build.ts +169 -106
- package/{extra/plug.mts → src/cli.mts} +115 -141
- package/src/files.ts +14 -6
- package/src/fork.ts +42 -16
- package/src/helpers.ts +56 -5
- package/src/index.ts +2 -1
- package/src/logging/emit.ts +4 -4
- package/src/logging/logger.ts +60 -7
- package/src/logging/options.ts +9 -14
- package/src/logging.ts +20 -5
- package/src/plugs/build.ts +45 -0
- package/src/plugs/debug.ts +10 -9
- package/src/types.ts +54 -23
- package/src/utils/diff.ts +1 -6
- package/src/utils/exec.ts +6 -20
- package/src/utils/singleton.ts +19 -0
- package/src/utils.ts +1 -1
- package/cli/plug.mjs +0 -1385
- package/cli/ts-loader.mjs +0 -275
- package/cli/tsrun.mjs +0 -1204
- package/dist/utils/types.cjs.map +0 -6
- package/dist/utils/types.d.ts +0 -4
- package/dist/utils/types.mjs +0 -12
- package/dist/utils/types.mjs.map +0 -6
- package/extra/ts-loader.mts +0 -546
- package/extra/tsrun.mts +0 -127
- package/extra/utils.ts +0 -150
- package/src/utils/types.ts +0 -11
package/src/build.ts
CHANGED
|
@@ -1,78 +1,126 @@
|
|
|
1
1
|
import { assert } from './asserts'
|
|
2
2
|
import { runAsync } from './async'
|
|
3
|
-
import { $ms, $p, $t, getLogger, logOptions } from './logging'
|
|
3
|
+
import { $gry, $ms, $p, $t, getLogger, logOptions } from './logging'
|
|
4
4
|
import { Context, ContextPromises, PipeImpl } from './pipe'
|
|
5
5
|
import { findCaller } from './utils/caller'
|
|
6
|
+
import { getSingleton } from './utils/singleton'
|
|
7
|
+
import { buildMarker } from './types'
|
|
6
8
|
|
|
7
9
|
import type { Pipe } from './index'
|
|
8
10
|
import type { AbsolutePath } from './paths'
|
|
9
11
|
import type {
|
|
10
12
|
Build,
|
|
13
|
+
BuildProps,
|
|
11
14
|
BuildDef,
|
|
12
|
-
Props,
|
|
13
15
|
Result,
|
|
14
16
|
State,
|
|
15
17
|
Task,
|
|
16
18
|
TaskDef,
|
|
17
|
-
Tasks,
|
|
18
19
|
ThisBuild,
|
|
20
|
+
Props,
|
|
21
|
+
TaskCall,
|
|
22
|
+
BuildTasks,
|
|
23
|
+
Tasks,
|
|
19
24
|
} from './types'
|
|
20
25
|
|
|
21
26
|
/* ========================================================================== *
|
|
22
|
-
*
|
|
27
|
+
* INTERNAL UTILITIES *
|
|
23
28
|
* ========================================================================== */
|
|
24
29
|
|
|
25
|
-
/** Symbol indicating that an object is a {@link
|
|
26
|
-
const
|
|
30
|
+
/** Symbol indicating that an object is a {@link TaskCall} */
|
|
31
|
+
const taskCallMarker = Symbol.for('plugjs:plug:types:TaskCall')
|
|
32
|
+
|
|
33
|
+
/** Type guard for {@link TaskCall}s */
|
|
34
|
+
function isTaskCall(something: any): something is TaskCall {
|
|
35
|
+
return something[taskCallMarker] === taskCallMarker
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Shallow merge two records */
|
|
39
|
+
function merge<A, B>(a: A, b: B): A & B {
|
|
40
|
+
return Object.assign(Object.create(null), a, b)
|
|
41
|
+
}
|
|
27
42
|
|
|
28
|
-
/**
|
|
29
|
-
function
|
|
30
|
-
|
|
43
|
+
/** Create a {@link State} from its components */
|
|
44
|
+
function makeState(state: {
|
|
45
|
+
cache?: Map<Task, Promise<Result>>
|
|
46
|
+
stack?: Task[],
|
|
47
|
+
tasks?: Record<string, Task>
|
|
48
|
+
props?: Record<string, string>
|
|
49
|
+
fails?: Set<Task>
|
|
50
|
+
}): State {
|
|
51
|
+
const {
|
|
52
|
+
cache = new Map(),
|
|
53
|
+
fails = new Set(),
|
|
54
|
+
stack = [],
|
|
55
|
+
tasks = {},
|
|
56
|
+
props = {},
|
|
57
|
+
} = state
|
|
58
|
+
|
|
59
|
+
return { cache, fails, stack, tasks, props } as State
|
|
31
60
|
}
|
|
32
61
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
/* ========================================================================== *
|
|
63
|
+
* TASK IMPLEMENTATION *
|
|
64
|
+
* ========================================================================== */
|
|
65
|
+
|
|
66
|
+
const lastIdKey = Symbol.for('plugjs:plug:singleton:taskId')
|
|
67
|
+
const taskId = getSingleton(lastIdKey, () => ({ id: 0 }))
|
|
68
|
+
|
|
69
|
+
class TaskImpl<R extends Result> implements Task<R> {
|
|
70
|
+
public readonly before: Task<Result>[] = []
|
|
71
|
+
public readonly after: Task<Result>[] = []
|
|
72
|
+
public readonly id: number = ++ taskId.id
|
|
73
|
+
|
|
74
|
+
props: Props<BuildDef>
|
|
75
|
+
tasks: Tasks<BuildDef>
|
|
76
|
+
|
|
77
|
+
constructor(
|
|
78
|
+
public readonly name: string,
|
|
79
|
+
public readonly buildFile: AbsolutePath,
|
|
80
|
+
private readonly _def: TaskDef,
|
|
81
|
+
_tasks: Record<string, Task>,
|
|
82
|
+
_props: Record<string, string>,
|
|
83
|
+
) {
|
|
84
|
+
this.tasks = _tasks as Tasks
|
|
85
|
+
this.props = _props as Props
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async invoke(state: State, taskName: string): Promise<R> {
|
|
89
|
+
assert(! state.stack.includes(this), `Recursion detected calling ${$t(taskName)}`)
|
|
44
90
|
|
|
45
91
|
/* Check cache */
|
|
46
|
-
const cached = state.cache.get(
|
|
47
|
-
if (cached) return cached
|
|
92
|
+
const cached = state.cache.get(this)
|
|
93
|
+
if (cached) return cached as Promise<R>
|
|
48
94
|
|
|
49
95
|
/* Create new substate merging sibling tasks/props and adding this to the stack */
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
96
|
+
state = makeState({
|
|
97
|
+
props: merge(this.props, state.props),
|
|
98
|
+
tasks: merge(this.tasks, state.tasks),
|
|
99
|
+
stack: [ ...state.stack, this ],
|
|
100
|
+
cache: state.cache,
|
|
101
|
+
fails: state.fails,
|
|
102
|
+
})
|
|
55
103
|
|
|
56
104
|
/* Create run context and build */
|
|
57
|
-
const context = new Context(
|
|
105
|
+
const context = new Context(this.buildFile, taskName)
|
|
58
106
|
|
|
59
107
|
/* The build (the `this` value calling the definition) is a proxy */
|
|
60
108
|
const build = new Proxy({}, {
|
|
61
|
-
get(_: any, name: string): void | string | (() => Pipe) {
|
|
109
|
+
get: (_: any, name: string): void | string | (() => Pipe) => {
|
|
62
110
|
// Tasks first, props might come also from environment
|
|
63
|
-
if (name in tasks) {
|
|
111
|
+
if (name in state.tasks) {
|
|
64
112
|
return (): Pipe => {
|
|
65
|
-
const promise = tasks[name]!.invoke(state, name)
|
|
113
|
+
const promise = (state as any).tasks[name]!.invoke(state, name)
|
|
66
114
|
return new PipeImpl(context, promise)
|
|
67
115
|
}
|
|
68
|
-
} else if (name in props) {
|
|
69
|
-
return props[name]
|
|
116
|
+
} else if (name in state.props) {
|
|
117
|
+
return (state as any).props[name]
|
|
70
118
|
}
|
|
71
119
|
},
|
|
72
120
|
})
|
|
73
121
|
|
|
74
122
|
/* Run all tasks hooked _before_ this one */
|
|
75
|
-
for (const before of
|
|
123
|
+
for (const before of this.before) await before.invoke(state, before.name)
|
|
76
124
|
|
|
77
125
|
/* Some logging */
|
|
78
126
|
context.log.info('Running...')
|
|
@@ -80,54 +128,31 @@ function makeTask(
|
|
|
80
128
|
|
|
81
129
|
/* Run asynchronously in an asynchronous context */
|
|
82
130
|
const promise = runAsync(context, taskName, async () => {
|
|
83
|
-
return await _def.call(build) || undefined
|
|
131
|
+
return await this._def.call(build) || undefined
|
|
84
132
|
}).then(async (result) => {
|
|
85
133
|
const level = taskName.startsWith('_') ? 'info' : 'notice'
|
|
86
134
|
context.log[level](`Success ${$ms(Date.now() - now)}`)
|
|
87
135
|
return result
|
|
88
136
|
}).catch((error) => {
|
|
137
|
+
state.fails.add(this)
|
|
89
138
|
throw context.log.fail(`Failure ${$ms(Date.now() - now)}`, error)
|
|
90
139
|
}).finally(async () => {
|
|
91
140
|
await ContextPromises.wait(context)
|
|
92
141
|
}).then(async (result) => {
|
|
93
|
-
for (const after of
|
|
142
|
+
for (const after of this.after) await after.invoke(state, after.name)
|
|
94
143
|
return result
|
|
95
144
|
})
|
|
96
145
|
|
|
97
146
|
/* Cache the resulting promise and return it */
|
|
98
|
-
cache.set(
|
|
99
|
-
return promise
|
|
147
|
+
state.cache.set(this, promise)
|
|
148
|
+
return promise as Promise<R>
|
|
100
149
|
}
|
|
101
|
-
|
|
102
|
-
/* Create the new Task. The function will simply create an empty state */
|
|
103
|
-
const task: Task = Object.assign((overrideProps: Props = {}) => {
|
|
104
|
-
const state: State = {
|
|
105
|
-
cache: new Map<Task, Promise<Result>>(),
|
|
106
|
-
stack: [] as Task[],
|
|
107
|
-
props: Object.assign({}, props, overrideProps),
|
|
108
|
-
tasks: tasks,
|
|
109
|
-
}
|
|
110
|
-
return invoke(state, _name)
|
|
111
|
-
}, { buildFile, tasks, props, invoke, before: [], after: [] })
|
|
112
|
-
|
|
113
|
-
/* Assign the task's marker and name and return it */
|
|
114
|
-
Object.defineProperty(task, taskMarker, { value: true })
|
|
115
|
-
Object.defineProperty(task, 'name', { value: _name })
|
|
116
|
-
return task
|
|
117
150
|
}
|
|
118
151
|
|
|
119
152
|
/* ========================================================================== *
|
|
120
153
|
* BUILD COMPILER *
|
|
121
154
|
* ========================================================================== */
|
|
122
155
|
|
|
123
|
-
/**
|
|
124
|
-
* Symbol indicating that an object is a {@link Build}.
|
|
125
|
-
*
|
|
126
|
-
* In a compiled {@link Build} this symbol will be associated with a function
|
|
127
|
-
* taking an array of strings (task names) and record of props to override
|
|
128
|
-
*/
|
|
129
|
-
const buildMarker = Symbol.for('plugjs:isBuild')
|
|
130
|
-
|
|
131
156
|
/** Compile a {@link BuildDef | build definition} into a {@link Build} */
|
|
132
157
|
export function build<
|
|
133
158
|
D extends BuildDef, B extends ThisBuild<D>
|
|
@@ -139,13 +164,14 @@ export function build<
|
|
|
139
164
|
/* Iterate through all definition extracting properties and tasks */
|
|
140
165
|
for (const [ key, val ] of Object.entries(def)) {
|
|
141
166
|
let len = 0
|
|
142
|
-
if (
|
|
143
|
-
tasks[key] = val
|
|
167
|
+
if (isTaskCall(val)) { // this goes first, tasks calls _are_ functions!
|
|
168
|
+
tasks[key] = val.task
|
|
144
169
|
len = key.length
|
|
145
170
|
} else if (typeof val === 'string') {
|
|
146
171
|
props[key] = val
|
|
147
172
|
} else if (typeof val === 'function') {
|
|
148
|
-
tasks[key] =
|
|
173
|
+
tasks[key] = new TaskImpl(key, buildFile, val, tasks, props)
|
|
174
|
+
// tasks[key] = makeTask(buildFile, tasks, props, val, key)
|
|
149
175
|
len = key.length
|
|
150
176
|
}
|
|
151
177
|
|
|
@@ -154,83 +180,120 @@ export function build<
|
|
|
154
180
|
if (len > logOptions.taskLength) logOptions.taskLength = len
|
|
155
181
|
}
|
|
156
182
|
|
|
157
|
-
/*
|
|
158
|
-
const
|
|
159
|
-
|
|
183
|
+
/* A function _starting_ a build */
|
|
184
|
+
const start = async function start<R>(
|
|
185
|
+
callback: (state: State) => Promise<R>,
|
|
160
186
|
overrideProps: Record<string, string | undefined> = {},
|
|
161
|
-
): Promise<
|
|
162
|
-
/* Our "root" logger and initial (empty) state */
|
|
163
|
-
const logger = getLogger()
|
|
164
|
-
const state = {
|
|
165
|
-
cache: new Map<Task, Promise<Result>>(),
|
|
166
|
-
stack: [] as Task[],
|
|
167
|
-
props: Object.assign({}, props, overrideProps),
|
|
168
|
-
tasks: tasks,
|
|
169
|
-
}
|
|
170
|
-
|
|
187
|
+
): Promise<R> {
|
|
171
188
|
/* Let's go down to business */
|
|
189
|
+
const state = makeState({ tasks, props: merge(props, overrideProps) })
|
|
190
|
+
const logger = getLogger()
|
|
172
191
|
logger.notice('Starting...')
|
|
173
192
|
const now = Date.now()
|
|
174
193
|
|
|
175
194
|
try {
|
|
176
|
-
|
|
195
|
+
const result = await callback(state)
|
|
196
|
+
logger.notice(`Build successful ${$ms(Date.now() - now)}`)
|
|
197
|
+
return result
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (state.fails.size) {
|
|
200
|
+
logger.error('')
|
|
201
|
+
logger.error(state.fails.size, state.fails.size === 1 ? 'task' : 'tasks', 'failed:')
|
|
202
|
+
state.fails.forEach((task) => logger.error($gry('*'), $t(task.name)))
|
|
203
|
+
logger.error('')
|
|
204
|
+
}
|
|
205
|
+
throw logger.fail(`Build failed ${$ms(Date.now() - now)}`, error)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Create the "invoke" function for this build */
|
|
210
|
+
const invoke = async function invoke(
|
|
211
|
+
taskNames: readonly string[],
|
|
212
|
+
overrideProps: Record<string, string | undefined> = {},
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
await start(async (state: State): Promise<void> => {
|
|
177
215
|
for (const name of taskNames) {
|
|
178
216
|
const task = tasks[name]
|
|
179
217
|
assert(task, `Task ${$t(name)} not found in build ${$p(buildFile)}`)
|
|
180
218
|
await task.invoke(state, name)
|
|
181
219
|
}
|
|
182
|
-
|
|
183
|
-
} catch (error) {
|
|
184
|
-
throw logger.fail(`Build failed ${$ms(Date.now() - now)}`, error)
|
|
185
|
-
}
|
|
220
|
+
}, overrideProps)
|
|
186
221
|
}
|
|
187
222
|
|
|
188
|
-
/*
|
|
189
|
-
const
|
|
223
|
+
/* Convert our Tasks into TaskCalls */
|
|
224
|
+
const callables: Record<string, TaskCall> = {}
|
|
225
|
+
for (const [ name, task ] of Object.entries(tasks)) {
|
|
226
|
+
/** The callable function, using "start" */
|
|
227
|
+
const callable = async (overrideProps?: Record<string, string>): Promise<Result> =>
|
|
228
|
+
start(async (state: State): Promise<Result> =>
|
|
229
|
+
task.invoke(state, name), overrideProps)
|
|
230
|
+
|
|
231
|
+
/* Extra properties for our callable: marker, task and name */
|
|
232
|
+
callables[name] = Object.defineProperties(callable, {
|
|
233
|
+
[taskCallMarker]: { value: taskCallMarker },
|
|
234
|
+
'task': { value: task },
|
|
235
|
+
'name': { value: name },
|
|
236
|
+
}) as TaskCall
|
|
237
|
+
}
|
|
190
238
|
|
|
191
|
-
/*
|
|
239
|
+
/* Create and return our build */
|
|
240
|
+
const compiled = merge(props, callables)
|
|
192
241
|
Object.defineProperty(compiled, buildMarker, { value: invoke })
|
|
242
|
+
return compiled as Build<D>
|
|
243
|
+
}
|
|
193
244
|
|
|
194
|
-
|
|
195
|
-
|
|
245
|
+
/** Check if the specified build is actually a {@link Build} */
|
|
246
|
+
export function isBuild(build: any): build is Build<Record<string, any>> {
|
|
247
|
+
return build && typeof build[buildMarker] === 'function'
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Invoke a number of tasks in a {@link Build} */
|
|
251
|
+
export function invokeTasks<B extends Build>(
|
|
252
|
+
build: B,
|
|
253
|
+
tasks: readonly BuildTasks<B>[],
|
|
254
|
+
props?: BuildProps<B>,
|
|
255
|
+
): Promise<void> {
|
|
256
|
+
if (isBuild(build)) {
|
|
257
|
+
return build[buildMarker](tasks, props)
|
|
258
|
+
} else {
|
|
259
|
+
throw new TypeError('Invalid build instance')
|
|
260
|
+
}
|
|
196
261
|
}
|
|
197
262
|
|
|
198
263
|
/* ========================================================================== *
|
|
199
264
|
* HOOKS *
|
|
200
265
|
* ========================================================================== */
|
|
201
266
|
|
|
202
|
-
|
|
203
|
-
[ name in keyof B as B[name] extends Task ? name : never ] : any
|
|
204
|
-
}
|
|
205
|
-
|
|
267
|
+
/** Make sure that the specified hooks run _before_ the given tasks */
|
|
206
268
|
export function hookBefore<B extends Build, T extends keyof B>(
|
|
207
269
|
build: B,
|
|
208
|
-
taskName: string & T &
|
|
209
|
-
hooks: (string & Exclude<
|
|
270
|
+
taskName: string & T & BuildTasks<B>,
|
|
271
|
+
hooks: readonly (string & Exclude<BuildTasks<B>, T>)[],
|
|
210
272
|
): void {
|
|
211
|
-
const
|
|
212
|
-
assert(
|
|
273
|
+
const taskCall = build[taskName]
|
|
274
|
+
assert(isTaskCall(taskCall), `Task "${$t(taskName)}" not found in build`)
|
|
213
275
|
|
|
214
276
|
for (const hook of hooks) {
|
|
215
277
|
const beforeHook = build[hook]
|
|
216
|
-
assert(
|
|
217
|
-
if (task.before.includes(beforeHook)) continue
|
|
218
|
-
task.before.push(beforeHook)
|
|
278
|
+
assert(isTaskCall(beforeHook), `Task "${$t(hook)}" to hook before "${$t(taskName)}" not found in build`)
|
|
279
|
+
if (taskCall.task.before.includes(beforeHook.task)) continue
|
|
280
|
+
taskCall.task.before.push(beforeHook.task)
|
|
219
281
|
}
|
|
220
282
|
}
|
|
221
283
|
|
|
284
|
+
/** Make sure that the specified hooks run _after_ the given tasks */
|
|
222
285
|
export function hookAfter<B extends Build, T extends keyof B>(
|
|
223
286
|
build: B,
|
|
224
|
-
taskName: string & T &
|
|
225
|
-
hooks: (string & Exclude<
|
|
287
|
+
taskName: string & T & BuildTasks<B>,
|
|
288
|
+
hooks: readonly (string & Exclude<BuildTasks<B>, T>)[],
|
|
226
289
|
): void {
|
|
227
|
-
const
|
|
228
|
-
assert(
|
|
290
|
+
const taskCall = build[taskName]
|
|
291
|
+
assert(isTaskCall(taskCall), `Task "${$t(taskName)}" not found in build`)
|
|
229
292
|
|
|
230
293
|
for (const hook of hooks) {
|
|
231
294
|
const afterHook = build[hook]
|
|
232
|
-
assert(
|
|
233
|
-
if (task.after.includes(afterHook)) continue
|
|
234
|
-
task.after.push(afterHook)
|
|
295
|
+
assert(isTaskCall(afterHook), `Task "${$t(hook)}" to hook after "${$t(taskName)}" not found in build`)
|
|
296
|
+
if (taskCall.task.after.includes(afterHook.task)) continue
|
|
297
|
+
taskCall.task.after.push(afterHook.task)
|
|
235
298
|
}
|
|
236
299
|
}
|