UNPKG

15.3 kBJavaScriptView Raw
1"use strict";
2// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3// See LICENSE in the project root for license information.
4function __export(m) {
5 for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
6}
7Object.defineProperty(exports, "__esModule", { value: true });
8if (process.argv.indexOf('--no-color') === -1) {
9 process.argv.push('--color');
10}
11const path = require("path");
12const GulpTask_1 = require("./tasks/GulpTask");
13const GulpProxy_1 = require("./GulpProxy");
14const CleanTask_1 = require("./tasks/CleanTask");
15const CleanFlagTask_1 = require("./tasks/CleanFlagTask");
16const CopyStaticAssetsTask_1 = require("./tasks/copyStaticAssets/CopyStaticAssetsTask");
17const State_1 = require("./State");
18const logging_1 = require("./logging");
19const logging_2 = require("./logging");
20const config_1 = require("./config");
21const notifier = require("node-notifier");
22const JestTask_1 = require("./tasks/JestTask");
23var logging_3 = require("./logging");
24exports.addSuppression = logging_3.addSuppression;
25exports.coverageData = logging_3.coverageData;
26exports.functionalTestRun = logging_3.functionalTestRun;
27exports.getErrors = logging_3.getErrors;
28exports.getWarnings = logging_3.getWarnings;
29exports.TestResultState = logging_3.TestResultState;
30exports.warn = logging_3.warn;
31exports.verbose = logging_3.verbose;
32exports.error = logging_3.error;
33exports.fileError = logging_3.fileError;
34exports.fileLog = logging_3.fileLog;
35exports.fileWarning = logging_3.fileWarning;
36exports.reset = logging_3.reset;
37exports.log = logging_3.log;
38exports.logSummary = logging_3.logSummary;
39var GCBTerminalProvider_1 = require("./utilities/GCBTerminalProvider");
40exports.GCBTerminalProvider = GCBTerminalProvider_1.GCBTerminalProvider;
41__export(require("./tasks/CopyTask"));
42__export(require("./tasks/GenerateShrinkwrapTask"));
43__export(require("./tasks/GulpTask"));
44__export(require("./tasks/CleanTask"));
45__export(require("./tasks/CleanFlagTask"));
46__export(require("./tasks/ValidateShrinkwrapTask"));
47__export(require("./tasks/copyStaticAssets/CopyStaticAssetsTask"));
48__export(require("./tasks/JestTask"));
49const _taskMap = {};
50const _uniqueTasks = [];
51const packageFolder = (State_1.builtPackage.directories && State_1.builtPackage.directories.packagePath)
52 ? State_1.builtPackage.directories.packagePath
53 : '';
54let _buildConfig = {
55 maxBuildTimeMs: 0,
56 // gulp and rootPath are set to undefined here because they'll be defined in the initialize function below,
57 // but we don't want their types to be nullable because a task that uses StrictNullChecks should expect them
58 // to be defined without checking their values.
59 gulp: undefined,
60 rootPath: undefined,
61 packageFolder,
62 srcFolder: 'src',
63 distFolder: path.join(packageFolder, 'dist'),
64 libAMDFolder: undefined,
65 libESNextFolder: undefined,
66 libFolder: path.join(packageFolder, 'lib'),
67 tempFolder: 'temp',
68 properties: {},
69 relogIssues: config_1.getFlagValue('relogIssues', true),
70 showToast: config_1.getFlagValue('showToast', true),
71 buildSuccessIconPath: path.resolve(__dirname, 'pass.png'),
72 buildErrorIconPath: path.resolve(__dirname, 'fail.png'),
73 verbose: config_1.getFlagValue('verbose', false),
74 production: config_1.getFlagValue('production', false),
75 args: State_1.args,
76 shouldWarningsFailBuild: false
77};
78/**
79 * Merges the given build config settings into existing settings.
80 *
81 * @param config - The build config settings.
82 * @public
83 */
84function setConfig(config) {
85 // eslint-disable-next-line
86 const objectAssign = require('object-assign');
87 _buildConfig = objectAssign({}, _buildConfig, config);
88}
89exports.setConfig = setConfig;
90/**
91 * Merges the given build config settings into existing settings.
92 *
93 * @param config - The build config settings.
94 * @public
95 */
96function mergeConfig(config) {
97 // eslint-disable-next-line
98 const merge = require('lodash.merge');
99 _buildConfig = merge({}, _buildConfig, config);
100}
101exports.mergeConfig = mergeConfig;
102/**
103 * Replaces the build config.
104 *
105 * @param config - The build config settings.
106 * @public
107 */
108function replaceConfig(config) {
109 _buildConfig = config;
110}
111exports.replaceConfig = replaceConfig;
112/**
113 * Gets the current config.
114 * @returns the current build configuration
115 * @public
116 */
117function getConfig() {
118 return _buildConfig;
119}
120exports.getConfig = getConfig;
121/** @public */
122exports.cleanFlag = new CleanFlagTask_1.CleanFlagTask();
123/**
124 * Registers an IExecutable to gulp so that it can be called from the command line
125 * @param taskName - the name of the task, can be called from the command line (e.g. "gulp <taskName>")
126 * @param taskExecutable - the executable to execute when the task is invoked
127 * @returns the task parameter
128 * @public
129 */
130function task(taskName, taskExecutable) {
131 taskExecutable = serial(exports.cleanFlag, taskExecutable);
132 _taskMap[taskName] = taskExecutable;
133 _trackTask(taskExecutable);
134 return taskExecutable;
135}
136exports.task = task;
137/** @public */
138class CustomTask extends GulpTask_1.GulpTask {
139 constructor(name, fn) {
140 super(name);
141 this._fn = fn.bind(this);
142 }
143 executeTask(gulp, completeCallback) {
144 return this._fn(gulp, getConfig(), completeCallback);
145 }
146}
147/**
148 * Creates a new subtask from a function callback. Useful as a shorthand way
149 * of defining tasks directly in a gulpfile.
150 *
151 * @param taskName - the name of the task, appearing in build logs
152 * @param fn - the callback function to execute when this task runs
153 * @returns an IExecutable which can be registered to the command line with task()
154 * @public
155 */
156function subTask(taskName, fn) {
157 const customTask = new CustomTask(taskName, fn);
158 return customTask;
159}
160exports.subTask = subTask;
161/**
162 * Defines a gulp watch and maps it to a given IExecutable.
163 *
164 * @param watchMatch - the list of files patterns to watch
165 * @param taskExecutable - the task to execute when a file changes
166 * @returns IExecutable
167 * @public
168 */
169function watch(watchMatch, taskExecutable) {
170 _trackTask(taskExecutable);
171 let isWatchRunning = false;
172 let shouldRerunWatch = false;
173 let lastError = undefined;
174 const successMessage = 'Build succeeded';
175 const failureMessage = 'Build failed';
176 return {
177 execute: (buildConfig) => {
178 return new Promise(() => {
179 function _runWatch() {
180 if (isWatchRunning) {
181 shouldRerunWatch = true;
182 return Promise.resolve();
183 }
184 else {
185 isWatchRunning = true;
186 return _executeTask(taskExecutable, buildConfig)
187 .then(() => {
188 if (lastError) {
189 lastError = undefined;
190 if (buildConfig.showToast) {
191 notifier.notify({
192 title: successMessage,
193 message: (State_1.builtPackage ? State_1.builtPackage.name : ''),
194 icon: buildConfig.buildSuccessIconPath
195 });
196 }
197 else {
198 logging_1.log(successMessage);
199 }
200 }
201 return _finalizeWatch();
202 })
203 .catch((error) => {
204 if (!lastError || lastError !== error) {
205 lastError = error;
206 if (buildConfig.showToast) {
207 notifier.notify({
208 title: failureMessage,
209 message: error.toString(),
210 icon: buildConfig.buildErrorIconPath
211 });
212 }
213 else {
214 logging_1.log(failureMessage);
215 }
216 }
217 return _finalizeWatch();
218 });
219 }
220 }
221 function _finalizeWatch() {
222 isWatchRunning = false;
223 if (shouldRerunWatch) {
224 shouldRerunWatch = false;
225 return _runWatch();
226 }
227 return Promise.resolve();
228 }
229 logging_2.setWatchMode();
230 buildConfig.gulp.watch(watchMatch, _runWatch);
231 _runWatch().catch(console.error);
232 });
233 }
234 };
235}
236exports.watch = watch;
237/**
238 * Takes in IExecutables as arguments and returns an IExecutable that will execute them in serial.
239 * @public
240 */
241function serial(...tasks) {
242 const flatTasks = _flatten(tasks).filter(taskExecutable => {
243 // eslint-disable-next-line @rushstack/no-null
244 return taskExecutable !== null && taskExecutable !== undefined;
245 });
246 for (const flatTask of flatTasks) {
247 _trackTask(flatTask);
248 }
249 return {
250 execute: (buildConfig) => {
251 let output = Promise.resolve();
252 for (const taskExecutable of flatTasks) {
253 output = output.then(() => _executeTask(taskExecutable, buildConfig));
254 }
255 return output;
256 }
257 };
258}
259exports.serial = serial;
260/**
261 * Takes in IExecutables as arguments and returns an IExecutable that will execute them in parallel.
262 * @public
263 */
264function parallel(...tasks) {
265 const flatTasks = _flatten(tasks).filter(taskExecutable => {
266 // eslint-disable-next-line @rushstack/no-null
267 return taskExecutable !== null && taskExecutable !== undefined;
268 });
269 for (const flatTask of flatTasks) {
270 _trackTask(flatTask);
271 }
272 return {
273 // eslint-disable-next-line @typescript-eslint/no-explicit-any
274 execute: (buildConfig) => {
275 return new Promise((resolve, reject) => {
276 const promises = [];
277 for (const taskExecutable of flatTasks) {
278 promises.push(_executeTask(taskExecutable, buildConfig));
279 }
280 // Use promise all to make sure errors are propagated correctly
281 Promise.all(promises).then(resolve, reject);
282 });
283 }
284 };
285}
286exports.parallel = parallel;
287/**
288 * Initializes the gulp tasks.
289 * @public
290 */
291function initialize(gulp) {
292 _buildConfig.rootPath = process.cwd();
293 _buildConfig.gulp = new GulpProxy_1.GulpProxy(gulp);
294 _buildConfig.uniqueTasks = _uniqueTasks;
295 _buildConfig.jestEnabled = JestTask_1._isJestEnabled(_buildConfig.rootPath);
296 _handleCommandLineArguments();
297 for (const uniqueTask of _buildConfig.uniqueTasks) {
298 if (uniqueTask.onRegister) {
299 uniqueTask.onRegister();
300 }
301 }
302 logging_2.initialize(gulp, getConfig(), undefined, undefined);
303 Object.keys(_taskMap).forEach(taskName => _registerTask(gulp, taskName, _taskMap[taskName]));
304 logging_2.markTaskCreationTime();
305}
306exports.initialize = initialize;
307/**
308 * Registers a given gulp task given a name and an IExecutable.
309 */
310function _registerTask(gulp, taskName, taskExecutable) {
311 gulp.task(taskName, (cb) => {
312 const maxBuildTimeMs = taskExecutable.maxBuildTimeMs === undefined
313 ? _buildConfig.maxBuildTimeMs
314 : taskExecutable.maxBuildTimeMs;
315 const timer = maxBuildTimeMs === 0
316 ? undefined
317 : setTimeout(() => {
318 logging_1.error(`Build ran for ${maxBuildTimeMs} milliseconds without completing. Cancelling build with error.`);
319 cb(new Error('Timeout'));
320 }, maxBuildTimeMs);
321 _executeTask(taskExecutable, _buildConfig).then(() => {
322 if (timer) {
323 clearTimeout(timer);
324 }
325 cb();
326 }, (error) => {
327 if (timer) {
328 clearTimeout(timer);
329 }
330 cb(logging_2.generateGulpError(error));
331 });
332 });
333}
334/**
335 * Executes a given IExecutable.
336 */
337function _executeTask(taskExecutable, buildConfig) {
338 // Try to fallback to the default task if provided.
339 if (taskExecutable && !taskExecutable.execute) {
340 // eslint-disable-next-line @typescript-eslint/no-explicit-any
341 if (taskExecutable.default) {
342 // eslint-disable-next-line @typescript-eslint/no-explicit-any
343 taskExecutable = taskExecutable.default;
344 }
345 }
346 // If the task is missing, throw a meaningful error.
347 if (!taskExecutable || !taskExecutable.execute) {
348 return Promise.reject(new Error(`A task was scheduled, but the task was null. This probably means the task wasn't imported correctly.`));
349 }
350 if (taskExecutable.isEnabled === undefined || taskExecutable.isEnabled(buildConfig)) {
351 const startTime = process.hrtime();
352 if (buildConfig.onTaskStart && taskExecutable.name) {
353 buildConfig.onTaskStart(taskExecutable.name);
354 }
355 const taskPromise = taskExecutable.execute(buildConfig)
356 .then(() => {
357 if (buildConfig.onTaskEnd && taskExecutable.name) {
358 buildConfig.onTaskEnd(taskExecutable.name, process.hrtime(startTime));
359 }
360 }, (error) => {
361 if (buildConfig.onTaskEnd && taskExecutable.name) {
362 buildConfig.onTaskEnd(taskExecutable.name, process.hrtime(startTime), error);
363 }
364 return Promise.reject(error);
365 });
366 return taskPromise;
367 }
368 // No-op otherwise.
369 return Promise.resolve();
370}
371function _trackTask(taskExecutable) {
372 if (_uniqueTasks.indexOf(taskExecutable) < 0) {
373 _uniqueTasks.push(taskExecutable);
374 }
375}
376/**
377 * Flattens a set of arrays into a single array.
378 */
379function _flatten(oArr) {
380 const output = [];
381 function traverse(arr) {
382 for (let i = 0; i < arr.length; ++i) {
383 if (Array.isArray(arr[i])) {
384 traverse(arr[i]);
385 }
386 else {
387 output.push(arr[i]);
388 }
389 }
390 }
391 traverse(oArr);
392 return output;
393}
394function _handleCommandLineArguments() {
395 _handleTasksListArguments();
396}
397function _handleTasksListArguments() {
398 /* eslint-disable dot-notation */
399 if (State_1.args['tasks'] || State_1.args['tasks-simple'] || State_1.args['T']) {
400 global['dontWatchExit'] = true;
401 }
402 if (State_1.args['h']) {
403 // we are showing a help command prompt via yargs or ts-command-line
404 global['dontWatchExit'] = true;
405 }
406 /* eslint-enable dot-notation */
407}
408/** @public */
409exports.clean = new CleanTask_1.CleanTask();
410/** @public */
411exports.copyStaticAssets = new CopyStaticAssetsTask_1.CopyStaticAssetsTask();
412/** @public */
413exports.jest = new JestTask_1.JestTask();
414// Register default clean task.
415task('clean', exports.clean);
416//# sourceMappingURL=index.js.map
\No newline at end of file