Git Product home page Git Product logo

undertaker's People

Contributors

coreyfarrell avatar dinoboff avatar douglasduteil avatar erikkemperman avatar fabpopa avatar jpeer264 avatar kahwee avatar orta avatar pdehaan avatar phated avatar rosskevin avatar trysound avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

undertaker's Issues

sharing memory structure between tasks

I have a serve task that starts a Browsersync server. When my tasks are done running I can then call browserSyncServer.reload() to reload the page in browsers. I'm doing this with a watch. It would be nice if I could split the watch task into its own module that is isolated from the serve task.

I should mention that these tasks are registered with a custom registry that require's the individual task functions which are located in separate modules. The custom registry uses a configuration object. I could just place a reference to the Browsersync server somewhere on the configuration object and access it from the other tasks.

Is that going to be the smoothest way to accomplish sharing data between tasks forward into the future of undertaker and g4 or have you thought about any other APIs that could make it more straight forward?

Using series and parallel within a custom registry

When using Custom Registries with an Undertaker instance, is there a recommended way to use series and parallel within the custom registry?

Right now the only way I can figure out how to do so would be to pass in the Undertaker instance on instantiation

function CustomRegistry (taker) {
  DefaultRegistry.call(this)
  this.set('task1', function () {/* .. */})
  this.set('task2', function () {/* .. */})
  this.set('task3', taker.parallel('task1', 'task2'))
}
utils.inherits(CustomRegistry, DefaultRegistry)

and then to consume it...

taker.registry(new CustomRegistry(taker))

The only problem with this is that I get an error:

assert.js:86
  throw new assert.AssertionError({
        ^
AssertionError: Task never defined: task1

I assume this is because the Registry doesn't actually set the tasks, but just accrues them and passes them to Undertaker after instantiation, while parallel on the other hand, requires a task lookup immediately.

The current workaround I have for this is executing the parallel within a wrapper function:

  this.set('task3', function () {
    return taker.parallel('task1', 'task2')()
  })

Obviously this isn't exactly ideal, and all of these series and parallel tasks are labeled as <anonymous>

Is there a suggested approach to this? Passing in the taker instance feels kind of gross and hacky.

record task finish times

an object with the times that tasks last finished would be really useful for incremental builds.

this might belong in the default registry, putting it here because im not sure

Error handling

I've been using Undertaker in the following way:

function uberTask() {
    return new Promise( ( resolve ) => {
        const taker = new Undertaker();

        taker.task( 'a', () => {
        } );

        taker.task( 'b', () => {
        } );

       taker.series( 'a', 'b', resolve )();
    } );
}

If any of the tasks throws, then I get some useless stack on the console:

[10:41:25] Using gulpfile /www/ckeditor5/ckeditor5/gulpfile.js
[10:41:25] Starting 'test'...
events.js:165
      throw err;
      ^

Error: Uncaught, unspecified "error" event. ([object Object])
    at Undertaker.emit (events.js:163:17)
    at Object.error (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/undertaker/lib/helpers/createExtensions.js:61:10)
    at handler (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/now-and-later/lib/mapSeries.js:43:14)
    at f (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/once/once.js:25:25)
    at f (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/once/once.js:25:25)
    at done (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/async-done/index.js:24:15)
    at Domain.onError (/www/ckeditor5/ckeditor5/node_modules/@ckeditor/ckeditor5-dev-tests/node_modules/async-done/index.js:32:12)
    at Domain.g (events.js:286:16)
    at emitOne (events.js:96:13)
    at Domain.emit (events.js:188:7)
    at Domain.errorHandler [as _errorHandler] (domain.js:97:23)
    at process._fatalException (node.js:265:33)

I guess that I should handle the errors in this way:

return new Promise( ( resolve, reject ) => {
    const taker = new Undertaker();

    taker.task( 'a', () => {
        throw new Error( 'a' );
    } );

    taker.task( 'b', () => {
    } );

    taker.on( 'error', ( error ) => {
        reject( error.error );
    } );

    taker.series( 'a', 'b', resolve )();
} );

Am I right? I haven't found this in the documentation.

Late to the party

So yeah ๐Ÿ˜„, anyway, I write this here in case it is something you find interesting.

tl;dr proposal for a non-evented approach for undertaker, maybe not using what I've done but something better.

I have been working for a while now around the same idea of composing async functions using async-done and have come up with a different approach for all of this with no events and one method for series and/or parallel. This is how it looks like:

var tornado = require('tornado').create(); // <- the "registry"

tornado.set(':handle(\\d+)', function(next){
 console.log(this.params.handle);
  setTimeout(next, Math.random()*10); 
});

function handle(next){ 
  setTimeout(next, Math.random()*10); 
}

var series = tornado.stack('1 2', handle, {wait: true}); // => function
var parallel = tornado.stack('3 4', handle); // => function
series(1, 2); parallel(1, 2); 
// passing arguments to each handle works from here or with next(null, 1, 2);

The same logic applies for nesting one "stack" with another as you do with bach. As you see I have added path to regex to the mix (because why not) and string arguments don't have to necessarily be separated by a comma. A space is just fine.

Is it replacement for orchestrator?

@phated I'm trying to follow all the efforts leading to the new task system in Gulp4 and this new project took me by surprise :-) Is it meant to replace orchestrator? Or build on top of it?

Binding a context to task functions referenced in series and parallel

I have a config registry that's basically the same thing as what's in the docs. I also have about a dozen functions that represent different steps of a build process I have. I only expose three tasks to the actual gulp CLI tool (clean, build and serve).

My build task looks similar to this

gulp.task('build', gulp
    .series(cleanBuild, gulp
        .parallel(copyHtml, copyImages, babelCompile, prepareAppIndex, copyVendorFiles, lessCompile)));

Now my problem is that the functions (copyHtml, copyImages, etc) are not registered as tasks with my ConfigRegistry. That makes sense, they're not really "tasks". At least not ones I want to expose directly because that would just cause static/cruft for devs who just want an easy to use build process. So what happens is the functions try to access this.config but it's never been binded because the individual functions are not registered as tasks so I get a classic "Cannot read property 'config' of undefined" TypeError.

Any ideas how I can keep this elegant or how undertaker could be updated to make this easier? The only way I can see to do it somewhat elegantly right now is to wrap each of my functions in a factory function. The function would then close (in the closure sense) over the factory function's scope which would contain a config object I pass in (or I could just bind the config to the function).

function copyHtmlFactory(config) {
    function copyHtml() {
        // do something with the config parameter or this.config if using bind
    }

    return copyHtml; // or return copyHtml.bind({config: config});
}

I think another way I could do it would be to bind the function references (without the use of a factory function) before they are passed to .series() and .parallel().

How to see that all tasks finished?

That's a follow-up of #55, because the answer to that issue is obviously wrong, it was closed on a mistake.

How to see that all tasks are finished? In Gulp3 it was possible: gulp.on('stop') or gulp.on('err').
But in Gulp4, there seems to be no such way.

An example of a use case would be to disconnect from database when gulp is done or tests are passed.

P.S. process.on('exit') does not help here at all, because the process don't exit when gulp finishes.

P.P.S. I also guess that might be not undertaker-related, but include the overall architecture.

lastRun should return undefined on first run

Hi, I think I'm seeing an issue with Gulp 4.0 after the dependency for undertaker was bumped from ^0.7.0 to ^0.11.0 a week ago. My tasks using lastRun aren't building, since

gulp.task('build:scripts', function() {
  console.log(gulp.lastRun('build:scripts'));    // this outputs the timestamp on first run, not undefined
  return gulp.src('app/**/*.js', { since: gulp.lastRun('build:scripts') })
    .pipe(gulp.dest('dist/app'));
});

outputs the timestamp even on first run, so no change is registered in the files.
Is this just me? Thank you.

Edit documentation to register tasks to gulp alongside taker.

On the "Sharing Functionalities" section of the documentation, it goes through an example on how to collaborate tasks into the main file for usage in default.

Most people will want to be able to run individual gulp tasks from the command line. Since gulp-hub is not up to date with the latest undertaker functionality, we now have to register undertaker tasks instead of gulp tasks to properly share them through the registry.

I've found that by editing the example set function to register the gulp task, it saves a lot of headache and lines of code to register the gulp task at the same time we are setting the taker task (obviously requiring the gulp module in order to do so).

What I did was this:

    ConfigRegistry.prototype.set = function set(name, fn) {
      var task = this._tasks[name] = fn.bind();
      gulp.task(name, fn);
      return task;
    };

We run CI that use SSH commands for gulp (i.e. gulp test, gulp deploy:rebuild, etc.)

Am I doing something wrong, leading me to have to insert this code? Or is this future functionality that is not completed yet?

Tasks composition without gulp

A followup of #66.

Down the rabbit hole...

I'm a framework/library author (namely, CKEditor). We need to provide a set of dev tools such as compilers for different types of assets, watchers, test runners, bundlers, scaffolders, etc.

For us, the library is the thing we work on, but for the community it's just a small piece of their projects. This changes quite a lot.

  • We're using gulp as a task runner, they may not.
  • We need 20 tasks for all the processes we use, they may need 5 of those and 3 different ones which are a different composition of the granular sub-tasks which we expose.
  • We can pass some args to the tasks on CLI, they may want to hardcode them.
  • And last but not the least โ€“ we're perfectionists. We want to have a control e.g. over what gets logged โ€“ to give an example โ€“ I don't want to register every sub-task to gulp, because a longer process would log a lot of unnecessary things.

After a few failed attempts to organise this code we decided to simply expose a set of functions. Those functions represents granular sub-tasks, accept options as parameters and, depending on what they do, they can be synchronous or return a stream or a promise. Sounds super obvious, I know :D.

What happens now? We use gulp, so our gulpfile.js looked like this:

const compiler = require( '@ckeditor/ckeditor5-dev-compiler' );

gulp.task( 'compile:js', () => compiler.compileJS( { format: 'esnext' } ) ); // Let's say this is a stream.
gulp.task( 'compile:sass', () => compiler.compileSass( sassOpts ) ); // This returns a promise.
gulp.task( 'compile:icons', () => compiler.compileIcons( iconsOpts ) ); // And this is synchronous

gulp.task( 'compile', [ 'compile:js', 'compile:sass', 'compile:icons' ] );

Now, there are couple of things which may happen (actually, they all happened :D).

Our gulpfile grew so we wanted to combine some sub-tasks into functions representing bigger chunks (e.g. compiler.compile() should run internally compiler.compileJS(), compiler.compileSass() and compiler.compileIcons()).

Exposing the popular tasks as bigger chunks would also simplify the community's gulpfiles which is an important thing if you want a good DX. Instead of the 4 tasks above, you get now:

const compiler = require( '@ckeditor/ckeditor5-dev-compiler' );

// Mind also the changed name โ€“ for the community it's not anymore "compile".
// Compiling CKEditor is just a sub-step of "compile my project".
gulp.task( 'compile:ckeditor', compiler.compile( { all options here } ) );

What also happened was that a compiler for tests may need different options than a compiler for documentation builder or for a specific release. So at some point we had something like:

gulp.task( 'compile:js', () => compiler.compileJS( getOptsFromCLI() ) );
gulp.task( 'compile:js:esnext', () => compiler.compileJS( { format: 'esnext'} ) );
gulp.task( 'compile:js:amd', () => compiler.compileJS( { format: 'amd' } ) );

gulp.task( 'test', [ 'compile:js:amd' ], () => tests.run() );
gulp.task( 'test', [ 'compile:js:esnext' ], () => docsBuilder.build() );

Horror... :D

What also happened was that we wanted to postpone certain require() calls, because combination of all possible dev tasks was loading a ridiculously huge number of dependencies. This complicated the gulpfile even more.

And then a developer comes to you and says that they are not using gulp at all in their project and they don't want it as a dependency, so how to combine now the compilation process with linting and testing.

Way out

At some point we realised how we'd like to solve all this. We needed a tool to sequence or run in parallel the sub-tasks so we can easily expose the less granular ones (like compile()) and that we can tell community how to run our code when they are not using gulp. Also, by registering only the end point tasks, and not the intermediate ones, we're able to keep the gulp -T short and prevent from logging too many things on the output.

After some research we found undertaker. "Task registry that allows composition through series/parallel methods." sounds for me exactly like what I wrote above :D Just, you said it shouldn't.

Anyway, this is how we use it now: https://github.com/ckeditor/ckeditor5-dev-compiler/blob/93d521e2e1b0e63fbf62133c1dff9ca9518a51f1/lib/tasks.js#L303-L330.

I hope that this better explains what we want to achieve (and what we don't want to do) and how undertaker could help.

Add jscs

Use jscs-preset-gulp as the preset

Error in parallel

I run in parallel 4 tasks: markup, script, style, image. If at least one of them is failed, build breaks in the same time. I think end of all tasks in parallel should be waited and then errored. Paralleled tasks do not depends on each other so they should be ended correctly.

[02:23:51] Using gulpfile D:\_host\github\case\gulpfile.js
[02:23:51] Starting 'build'...
[02:23:51] Starting 'clean (skipped)'...
[02:23:51] Finished 'clean (skipped)' after 2.09 ms
[02:23:51] Starting '<parallel>'...
[02:23:51] Starting 'markup'...
[02:23:51] Starting 'script'...
[02:23:51] Starting 'style'...
[02:23:51] Starting 'image'...
[02:23:52] Finished 'image' after 1.14 s
[02:23:52] 'markup' errored after 1.16 s
[02:23:52] Error in plugin 'gulp-file-include'
Message:
    ENOENT, no such file or directory 'D:\_host\github\case\app\markup\sss'
Details:
    domainEmitter: [object Object]
    domain: [object Object]
    domainThrown: false
[02:23:52] '<parallel>' errored after 1.17 s
[02:23:52] 'build' errored after 1.18 s
[02:23:52] The following tasks did not complete: script, style
[02:23:52] Did you forget to signal async completion?

settle not working with es2015 async functions

When async function throw Error, process terminated with node errors.
was expecting it will settle and error will be available in callback.

import * as Undertaker from 'undertaker';
process.env.UNDERTAKER_SETTLE = 'true'

const tasker = new Undertaker();
console.log(tasker._settle)
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
tasker.task('test1', async () => {
    await delay(1000);
    console.log('in test1 ...');
    return 1;
});
tasker.task('test2', async () => {
    console.log('in test2 ...');
    // return 2;
    throw new Error('test6 error')
});
tasker.task('test3', async () => {
    await delay(2000);
    console.log('in test3 ...');
    return 3;
});

tasker.task('test4', async () => {
    await delay(1000);
    console.log('in test4 ...');
    return 4;
});
tasker.task('test5', async () => {
    console.log('in test5 ...');
    return 5;
});
tasker.task('test6', async () => {
    await delay(1000);
    console.log('in test6 ...');
    return 6;
});

tasker.task('ser', tasker.series('test1', 'test2'));
tasker.task('par', tasker.parallel( 'test3', 'test4', 'test5'));
tasker.task('serpar', tasker.series('ser', 'par', 'test6'));
tasker.task('serpar1', tasker.series(tasker.series('test1', 'test2'), tasker.parallel('test3', 'test4', 'test5'), 'test6'));
tasker.task('serpar2', tasker.parallel(tasker.series('test1', 'test2'), tasker.parallel('test3', 'test4', 'test5'),'test6'));


(async () => {
    try {
        // let tree = tasker.tree({deep: true});
        // console.log('tree', tree);

        /** case 1 **/
        tasker.task('serpar1')((err, res) => {
            if(err) {
                console.log('final error', err)
            }
            console.log('res', res);
            console.log('lastRun for test3', tasker.lastRun('test6'))
        });

    } catch (err) {
        console.log('Error:::',err)
    }
})();

Output

 ts-node src/run2.ts 
true
in test1 ...
in test2 ...
(node:13530) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Uncaught, unspecified "error" event. ([object Object])
(node:13530) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Deprecate 'done' callback?

Maybe done for tasks can be deprecated now? Example:

taker.task('task1', function(done){
  done();
});

If ES6 now support promises why need to support 2 ways handling async things?

More consise task definition or update example

I was looking at your example that returns a promise and was wondering why you would return a promise that way.

taker.task('task3', function(){
  return new Promise(function(resolve, reject){
    // do things
    resolve();
  });
});

What's the use case? Wanting to call reject? If so, something like this seems more elegant and also handles the callback use case.

taker.task('task1', function(resolve, reject){
  // do things
  resolve(); // when everything is done
});

However, it still does make sense to support promises if you are using a library that returns promises.

var http = require('some-http-library');

taker.task('task1', function(){
  return http.get('http://github.com'); // returns a promise
});

I just don't understand why you would ever want to define a promise within a task. Not that big of a deal though.

Task Never Defined

Never is a long time. You might want to change the message to "Task not defined".

Ran across this in Gulp 4 - they pointed me here.

New release

Any chance you could bump a patch release? The task naming issue is fixed in master, but current gulp4 is hardly usable with currently tagged undertaker version. Thanks!

How to see that all tasks finished?

E.g I want to disconnect from database when gulp is done.

How can I detect and do that?

In the past, gulp.on('stop') with orchestrator could help, but now stop works on every task.

Integration tests

I want to create tests that have common gulp uses in order to make sure we don't break the use cases like I did in a few versions of orchestrator.

tree() returns an array

I'm consuming the tree() function from the gulp implementation and I get an array of task names returned. The documentation indicates that an object graph should be returned. Can someone clarify how this is supposed to work?

Error - "Task function must be specified"

I've updated my GULP to v4 and i'm getting this error. Here's the log:

C:\xampp\htdocs\project>gulp

assert.js:89
  throw new assert.AssertionError({
  ^
 AssertionError: Task function must be specified
    at Gulp.set [as _setTask] (C:\xampp\htdocs\project\node_modules\gulp\node_modules\undertaker\lib\set-task.js:12:3)
    at Gulp.task (C:\xampp\htdocs\project\node_modules\gulp\node_modules\undertaker\lib\task.js:13:8)
    at Object.<anonymous> (C:\xampp\htdocs\project\gulpfile.js:47:6)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at Liftoff.handleArguments (C:\Users\vsync\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js:116:3)

Should tasks inherit the `branch` flag

@erikkemperman
I am taking a look at implementing gulpjs/gulp#1411 (comment) and gulpjs/gulp#1330 through the use of the branch flag you added to the metadata (awesome idea, btw). However, when we do something like the following, that flag isn't attached to the metadata for the new task.

gulp.task('default', gulp.series(...));

Do you think that the task should inherit the branch flag if we already have metadata and the metadata tells us it is a branch?

How run a task programmatically ?

Hi @phated,

I think I missed or misunderstood something.

But how can I start a task defined by Undertaker without Gulp?

Example:

var Undertaker = require('undertaker');

var taker = new Undertaker();

taker.task('awesome', function(cb) {
  console.log('awesome');
  cb();
});

taker.task('raccoon', function(cb) {
  console.log('raccoon');
  cb();
});

taker.task('default', taker.series('awesome', 'raccoon'));

I would run default task by something like taker.run('default') or taker.start('default').

[suggestion] pass the arguments to the task for running task in parallel

The user story: In many cases, we need to perform file tasks in parallel, simultaneous processing of multiple files.

Could you add an option object(optional) argument to pass into the task. like this:

taker.task('processFile', function(file){
  return new Promise(function(resolve, reject){
    // process a file
    ...
    resolve();
  });
});

taker.task('processAll', function(files, cb){
  Promise.map(files, function(file){
    return take.task('processFile', file)
  }).nodeify(cb);
});

Add a task uniq id as an event attribute

Currently, events come with a uid attribute (to match a "start" event to a "stop"/"error" event) and the name (a provided string or the function name). The task name is not necessary unique.

Is it possible to add task id attribute unique to each task?

name/displayName order

What should we do when we have displayName and name at the same time?

IMHO displayName should have a higher order than name and task name should be resolved as name = fn.displayName || fn.name; instead of name = fn.name || fn.displayName;

What do you think?

stack trace is unintelligible since error is not serialized properly

This line:

causes my stacktrace to look like this

Error: Uncaught, unspecified "error" event. ([object Object])
    at Gulp.emit (events.js:163:17)
    at Object.error (<cut>/createExtensions.js:62:10)
    at handler (<cut>/node_modules/now-and-later/lib/map.js:46:14)
    at f (<cut>/node_modules/once/once.js:25:25)
    at f (<cut>/node_modules/once/once.js:25:25)
    at done (<cut>/node_modules/async-done/index.js:24:15)
    at _combinedTickCallback (internal/process/next_tick.js:77:11)
    at Immediate._tickDomainCallback (internal/process/next_tick.js:128:9)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)

The underlying error has being thrown with JSON.stringify method:

{ TypeError: Cannot create property 'serializeMetadata' on string 'ast'
    at new JsonSerializer (<cut>/node_modules/raml-1-parser/dist/util/jsonSerializer.js:96:44)
    at ApiImpl.BasicNodeImpl.toJSON (<cut>/node_modules/raml-1-parser/dist/parser/wrapped-ast/parserCore.js:276:20)
    at Object.stringify (native)
    at client (<cut>/buildClient.js:13:54)
    at bound (domain.js:280:14)
    at runBound (domain.js:293:12)
    at asyncRunner (<cut>/node_modules/async-done/index.js:39:18)
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
  domain: 
   Domain {
     domain: null,
     _events: {},
     _eventsCount: 0,
     _maxListeners: undefined,
     members: [] },
  domainThrown: true }

Another underlying error that triggered the same unintelligible stack trace:

{ AssertionError: Task never defined: undefined
    at getFunction (<cut>r/node_modules/undertaker/lib/helpers/normalizeArgs.js:15:5)
    at map (<cut>/node_modules/arr-map/index.js:20:14)
    at normalizeArgs (<cut>/node_modules/undertaker/lib/helpers/normalizeArgs.js:22:10)
    at Gulp.series (<cut>/node_modules/undertaker/lib/series.js:13:14)
    at <cut>/update.js:97:39
    at next (native)
    at fulfilled (<cut>/update.js:4:58)
  name: 'AssertionError',
  actual: undefined,
  expected: true,
  operator: '==',
  message: 'Task never defined: undefined',
  generatedMessage: false }

util.inspect is what I used just before aforementioned string (createExtensions.js#L65) to get the error description. I don't know if it's a proper fix for this issue. It probably isn't.
The error is displayed correctly when there is no gulp in the pipeline.

get / set

I'm really interested in inheriting undertaking in a couple of applications I'm building/have. Any chance you might consider using more semantically-specific method names than .get() and .set()?

The rationale is that, given how common those two method names are, this creates an implementation challenge for an application to inherit undertaker if those methods are already on the prototype. Otherwise it would just be as simple as Undertaker.call(this) etc., as you're doing with gulp. I know there are ways around it, but if the method names were something like .getTask() and .setTask() implementation be a bit easier.

I also realize this is late in the game, and if using undertaker as a building block in other applications isn't really a goal feel free to close. thx

Test fails on Node v6.9.1+

In tree.js the test should form a 3 level nested tree fails as var anon = fn() is not directly an anonymous function. The name of the task is anon as the expected <anonymous>

var anon = function(cb) {
    cb();
};
taker.task('fn1', taker.parallel(anon, noop)); // anon should be <anonymous>

If you want, I can make an PR in writing the anonymous function directly in taker.parallel, this would fix the issue.

taker.task('fn1', taker.parallel(function (cb) {
    cb()
}, noop));

EDIT:

same for the last test: should use the proper labels for aliased tasks (nested)

meta is undefined

I'm using latest in gulpjs/gulp#4.0. When I try to use any of the commands like gulp --tasks or when WebStorm tries to run gulp --tasks-json I get an error.

 return meta.tree;
            ^

TypeError: Cannot read property 'tree' of undefined

I can post the full stack trace if needed. This may just be a known issue because it's in the middle of development but I thought I'd at least get it logged in case not.

Task definition order is important

But why do they have to be?

gulp.task('first', gulp.series('one', 'two'));
gulp.task('one', function(done) {
  // do stuff
  done();
});

gulp.task('two', function(done) {
  // do stuff
  done();
});

throws:

assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: Task never defined: one

Can't get task description and flags because returning wrapped function

By modification that gulp.task(name) returns wrapped function instead of original function, gulp-cli can't get task description and flags now.

Since gulp.task(name).unwrap() returns original function, we can get description and flags by gulp.task(name).unwrap().description and gulp.task(name).unwrap().flags.

Is this intentional way?

Custom registry must have `get` function

In my Gulp build step I get the following error.

`
throw err;
^

AssertionError [ERR_ASSERTION]: Custom registry must have get function
at validateRegistry (C:\Users\john\Source\Repos\Contoso\ProductTasksExtension\node_modules\undertaker\lib\helpers\validateRegistry.js:28:5)
at Gulp.registry (C:\Users\john\Source\Repos\Contoso\ProductTasksExtension\node_modules\undertaker\lib\registry.js:17:3)
at Object. (C:\Users\john\Source\Repos\Contoso\ProductTasksExtension\gulpfile.js:10:6)
at Module._compile (module.js:660:30)
at Object.Module._extensions..js (module.js:671:10)
at Module.load (module.js:573:32)
at tryModuleLoad (module.js:513:12)
at Function.Module._load (module.js:505:3)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)
`
How do I troubleshoot is error?

Thanks
Stefan

Skipping null tasks

It would be cool to implement accepting null values in gulp.series and gulp.parallel. My case is

gulp.task('build', gulp.series(
    env.clean ? 'clean' : null,
    gulp.parallel(
        conf.markup ? 'markup' : null,
        'script',
        'style',
        'image'
    )
));

For now I should pass something like

function (done) {
  done();
}

But I don't like to pass anonymous or named task, I just would like to skip it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.