gulp-add-tasks2
Version:
A tool to add tasks to a passed-in gulp instance, as a task list, or as a map of functions
297 lines (243 loc) • 6.51 kB
text/typescript
import runSequence from 'gulp-run-seq-unique/run-sequence';
//import * as runSequence from 'run-sequence';
import * as gulpHelp from 'gulp-help';
import * as gulp from 'gulp';
export interface ITaskObject
{
aliases?: string[];
description?: string;
options?: ITaskOptions;
tasks?: ITasksSequence;
deps?: Array<string>;
callback?: ITaskCallback;
}
export interface ITaskObjectList
{
default?: ITaskObject | ITaskCallback;
[key: string]: ITaskObjectList | ITaskCallback | ITaskObject;
}
export interface ITaskCallback extends Function
{
(done?): void | any | Promise<any | void>;
}
export interface ITaskOptions
{
options?: any;
aliases?: string[];
}
export interface IExportDefault extends Function
{
(...taskObjects);
}
export interface ITasksSequence extends Array<string | string[]>
{
[index: number]: string | string[];
}
const SEP = ':';
export function looksLikeGulp(gulp): boolean
{
return !!(gulp.task && gulp.watch && gulp.src && gulp.dest);
}
export function looksLikeGulpHelp(gulp): boolean
{
return !!(gulp.tasks.help);
}
export function getOptions(impl: any | ITaskOptions): ITaskOptions
{
const options = (impl.options || {}) as ITaskOptions;
if (options.options || options.aliases)
{
return options;
}
return {
options: impl.options || {},
aliases: impl.aliases || []
};
}
export function isTaskListObject(impl: any = {}): boolean
{
return Object.keys(impl).indexOf('tasks') > -1;
}
export function getTasks(tasks: any | ITasksSequence,
parentTask: string = '',
cache: IGulpAddTasksOptions = defaultGulpAddTasksOptions
): ITasksSequence
{
if (typeof tasks === 'function')
{
tasks = tasks() as ITasksSequence;
}
for (let i in tasks)
{
if (Array.isArray(tasks[i]))
{
tasks[i] = prefixTasks(tasks[i], parentTask, cache);
}
else if (typeof tasks[i] == 'string')
{
tasks[i] = prefixTasks([tasks[i]], parentTask, cache)[0];
}
}
return tasks || [];
}
export function prefixTasks(tasks: ITasksSequence | any = [],
parentTask: string = '',
cache: IGulpAddTasksOptions = defaultGulpAddTasksOptions
): Array<string>
{
if (tasks && !Array.isArray(tasks))
{
tasks = [tasks as any];
}
return (tasks || []).map(function (v: string)
{
if (typeof v !== 'string') return v;
if (!cache.sep)
{
return v;
}
if (cache.root !== '' && v.indexOf(`~${cache.sep}`) === 0)
{
return v.replace(`~${cache.sep}`, `${cache.root}${cache.sep}`)
}
if (v.indexOf(cache.sep) === 0)
{
if (parentTask === '')
{
return v.substr(cache.sep.length);
}
return parentTask + v;
}
return v;
});
}
export function validTaskObject(taskObject: ITaskObject): false | ITaskObject
{
let type = typeof taskObject;
if (type === 'function')
{
return taskObject;
}
if (type === 'object')
{
for (let k of Object.keys(taskObject))
{
if (['function', 'object', 'string'].includes(typeof taskObject[k]))
{
return taskObject;
}
}
}
return false;
}
export function addTasksToGulp(gulp,
rs,
taskObject: ITaskObjectList,
parentTask: string = '',
cache: IGulpAddTasksOptions = defaultGulpAddTasksOptions
): void
{
for (let taskName in taskObject)
{
const taskImpl = taskObject[taskName] as ITaskObject;
if (parentTask)
{
taskName = `${parentTask}:${taskName}`;
}
if (Object.keys(taskImpl).indexOf('callback') > -1)
{
let taskFn: ITaskCallback;
if (isTaskListObject(taskImpl))
{
taskFn = async function (...argv): Promise<any | void>
{
await new Promise(function (resolve, reject)
{
rs.use(gulp)(...((getTasks(taskImpl.tasks, parentTask, cache) as Array<any>).concat(resolve)))
});
await taskImpl.callback.call(this, ...argv);
};
}
else
{
taskFn = taskImpl.callback;
}
gulp.task(taskName, taskImpl.description, prefixTasks(taskImpl.deps, parentTask, cache), taskFn, getOptions(taskImpl));
}
else if (typeof taskImpl === 'function' || isTaskListObject(taskImpl))
{
const taskFn: ITaskCallback = typeof taskImpl === 'function' ? taskImpl : function (done)
{
return rs.use(gulp)(...(getTasks(taskImpl.tasks, parentTask, cache)).concat(done));
};
gulp.task(taskName, taskImpl.description, prefixTasks(taskImpl.deps, parentTask, cache), taskFn, getOptions(taskImpl));
}
else if (Object.keys(taskImpl).indexOf('deps') > -1)
{
gulp.task(taskName, taskImpl.description, prefixTasks(taskImpl.deps, parentTask, cache), () => {}, getOptions(taskImpl));
}
else if (!validTaskObject(taskImpl))
{
let { inspect } = require('util');
throw new TypeError(`argument:taskObject ${inspect(taskImpl)} not a valid ITaskObject`);
}
else
{
addTasksToGulp(gulp, rs, taskImpl as ITaskObjectList, taskName, cache);
}
}
}
export interface IGulpAddTasksOptions
{
root?: string;
sep?: string;
runSequence?;
gulpHelp?;
}
export const defaultGulpAddTasksOptions = {
sep: SEP,
runSequence: runSequence,
gulpHelp: gulpHelp,
} as IGulpAddTasksOptions;
export interface IGulpHelp extends gulp.Gulp
{
task: IGulpHelpTask;
}
export interface IGulpHelpTask
{
help;
[index: string]: any;
}
export function gulpAddTasks(gulpInstance,
parentTaskName: string | string[] = '',
options: IGulpAddTasksOptions = defaultGulpAddTasksOptions
)
{
if (!looksLikeGulp(gulpInstance))
{
throw new Error('An instance of gulp is required as the first argument');
}
if (Array.isArray(parentTaskName))
{
parentTaskName = parentTaskName.join(options.sep ? options.sep : SEP);
}
const cache = Object.assign({
root: parentTaskName,
}, defaultGulpAddTasksOptions, options) as IGulpAddTasksOptions;
return function (...taskObjects: ITaskObjectList[]): IGulpHelp
{
const runSequence = cache.runSequence;
const gulpHelp = cache.gulpHelp;
const gulp = looksLikeGulpHelp(gulpInstance) ? gulpInstance : gulpHelp(gulpInstance);
gulp.options = gulp.options || {};
gulp.options.gulpAddTasks = cache;
taskObjects
.forEach((taskObject: ITaskObjectList) =>
{
addTasksToGulp(gulp, runSequence, taskObject, parentTaskName as string, cache);
});
return gulp;
};
}
export { gulpAddTasks as init, runSequence, gulpHelp, SEP };
export default gulpAddTasks;