Skip to content

Commit

Permalink
feat: Add versioned handler for gulp v5 (#265)
Browse files Browse the repository at this point in the history
  • Loading branch information
phated committed Mar 23, 2024
1 parent e16d675 commit f06ff30
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/versioned/^5.0.0/format-error.js
@@ -0,0 +1,24 @@
'use strict';

// Format orchestrator errors
/* istanbul ignore next */
function formatError(e) {
if (!e.error) {
return e.message;
}

// PluginError
if (typeof e.error.showStack === 'boolean') {
return e.error.toString();
}

// Normal error
if (e.error.stack) {
return e.error.stack;
}

// Unknown (string, number, etc.)
return new Error(String(e.error)).stack;
}

module.exports = formatError;
89 changes: 89 additions & 0 deletions lib/versioned/^5.0.0/index.js
@@ -0,0 +1,89 @@
'use strict';

var fs = require('fs');

var log = require('gulplog');
var stdout = require('mute-stdout');
var messages = require('@gulpjs/messages');

var exit = require('../../shared/exit');

var logTasks = require('../../shared/log/tasks');
var logEvents = require('./log/events');
var logSyncTask = require('./log/sync-task');
var logTasksSimple = require('./log/tasks-simple');
var registerExports = require('../../shared/register-exports');

var copyTree = require('../../shared/log/copy-tree');
var getTask = require('./log/get-task');
var requireOrImport = require('../../shared/require-or-import');

function execute(env, opts, translate) {
var tasks = opts._;
var toRun = tasks.length ? tasks : ['default'];

if (opts.tasksSimple || opts.tasks || opts.tasksJson) {
// Mute stdout if we are listing tasks
stdout.mute();
}

var gulpInst = require(env.modulePath);
logEvents(gulpInst);
logSyncTask(gulpInst, opts);

// This is what actually loads up the gulpfile
requireOrImport(env.configPath, function(err, exported) {
// Before import(), if require() failed we got an unhandled exception on the module level.
// So console.error() & exit() were added here to mimic the old behavior as close as possible.
if (err) {
console.error(err);
exit(1);
}

registerExports(gulpInst, exported);

// Always unmute stdout after gulpfile is required
stdout.unmute();

var tree;
if (opts.tasksSimple) {
tree = gulpInst.tree();
return logTasksSimple(tree.nodes);
}
if (opts.tasks) {
tree = gulpInst.tree({ deep: true });
tree.label = translate.message({ tag: messages.DESCRIPTION, path: env.configPath });

return logTasks(tree, opts, getTask(gulpInst), translate);
}
if (opts.tasksJson) {
tree = gulpInst.tree({ deep: true });
tree.label = translate.message({ tag: messages.DESCRIPTION, path: env.configPath });

var output = JSON.stringify(copyTree(tree, opts));

if (typeof opts.tasksJson === 'boolean' && opts.tasksJson) {
return console.log(output);
}
return fs.writeFileSync(opts.tasksJson, output, 'utf-8');
}
try {
log.info({ tag: messages.GULPFILE, path: env.configPath });
var runMethod = opts.series ? 'series' : 'parallel';
gulpInst[runMethod](toRun)(function(err) {
if (err) {
exit(1);
}
});
} catch (err) {
if (err.task) {
log.error({ tag: messages.TASK_MISSING, task: err.task, similar: err.similar });
} else {
log.error({ tag: messages.EXEC_ERROR, message: err.message, error: err });
}
exit(1);
}
});
}

module.exports = execute;
39 changes: 39 additions & 0 deletions lib/versioned/^5.0.0/log/events.js
@@ -0,0 +1,39 @@
'use strict';

var log = require('gulplog');
var messages = require('@gulpjs/messages');

var formatError = require('../format-error');

// Wire up logging events
function logEvents(gulpInst) {

var loggedErrors = [];

gulpInst.on('start', function(evt) {
/* istanbul ignore next */
// TODO: batch these
// so when 5 tasks start at once it only logs one time with all 5
var level = evt.branch ? 'debug' : 'info';
log[level]({ tag: messages.TASK_START, task: evt.name });
});

gulpInst.on('stop', function(evt) {
/* istanbul ignore next */
var level = evt.branch ? 'debug' : 'info';
log[level]({ tag: messages.TASK_STOP, task: evt.name, duration: evt.duration });
});

gulpInst.on('error', function(evt) {
var level = evt.branch ? 'debug' : 'error';
log[level]({ tag: messages.TASK_FAILURE, task: evt.name, duration: evt.duration });

// If we haven't logged this before, log it and add to list
if (loggedErrors.indexOf(evt.error) === -1) {
log.error({ tag: messages.TASK_ERROR, message: formatError(evt) });
loggedErrors.push(evt.error);
}
});
}

module.exports = logEvents;
43 changes: 43 additions & 0 deletions lib/versioned/^5.0.0/log/get-task.js
@@ -0,0 +1,43 @@
'use strict';

var isObject = require('../../../shared/is-object');

function getTask(gulpInst) {
return function(name) {
var task = gulpInst.task(name);
return {
description: getDescription(task),
flags: getFlags(task),
};
};
}

function getDescription(task) {
if (typeof task.description === 'string') {
return task.description;
}
/* istanbul ignore else */
if (typeof task.unwrap === 'function') {
var origFn = task.unwrap();
if (typeof origFn.description === 'string') {
return origFn.description;
}
}
return undefined;
}

function getFlags(task) {
if (isObject(task.flags)) {
return task.flags;
}
/* istanbul ignore else */
if (typeof task.unwrap === 'function') {
var origFn = task.unwrap();
if (isObject(origFn.flags)) {
return origFn.flags;
}
}
return undefined;
}

module.exports = getTask;
46 changes: 46 additions & 0 deletions lib/versioned/^5.0.0/log/sync-task.js
@@ -0,0 +1,46 @@
'use strict';

var log = require('gulplog');
var messages = require('@gulpjs/messages');

var tasks = {};

function warn() {
var taskKeys = Object.keys(tasks);

if (!taskKeys.length) {
return;
}

var taskNames = taskKeys.map(function(key) {
return tasks[key];
}).join(', ');

process.exitCode = 1;

log.warn({ tag: messages.TASK_SYNC, tasks: taskNames });
}

function start(e) {
tasks[e.uid] = e.name;
}

function clear(e) {
delete tasks[e.uid];
}

function clearAll() {
tasks = {};
}

function logSyncTask(gulpInst, opts) {

process.once('exit', warn);
gulpInst.on('start', start);
gulpInst.on('stop', clear);
// When not running in --continue mode, we need to clear everything on error to avoid
// false positives.
gulpInst.on('error', opts.continue ? clear : clearAll);
}

module.exports = logSyncTask;
7 changes: 7 additions & 0 deletions lib/versioned/^5.0.0/log/tasks-simple.js
@@ -0,0 +1,7 @@
'use strict';

function logTasksSimple(nodes) {
console.log(nodes.join('\n').trim());
}

module.exports = logTasksSimple;

0 comments on commit f06ff30

Please sign in to comment.