npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

easyflow

v1.0.4

Published

Easy workflow engine with status and messaging utilities.

Downloads

6

Readme

easyflow

Easy workflow engine with status and messaging utilities, for javascript.

Easyflow provides a centralized view for workflow definition. It provides clear and robust workflow by moving flow dependency out from business logic unit.

const Easyflow = require('./easyflow.js')

const util = require('util')
const MySubFlow = require('./MySubFlow.js')
const MyBigTask = require('./MyBigTask.js')

//----------------------------------------------------------------------------
Promise.resolve()
.then(demo1)
.then(demo2)
.then(demo3)
.then(demo4)
.then(demo5)
.then(demo6)
.then(() => {
	console.log('Demo complete')
}).catch((e) => {
	console.log('Demo error:', e)
})
//----------------------------------------------------------------------------
function demo1() {
	console.log()
	console.log('-------------------- demo1: basic --------------------')
	console.log()
	
	/*
	[Task Unit]
	Use easyflow.sequence(...) to wrap a series of tasks to run in sequence, as a Task Unit.
	easyflow.parallel(...) wraps a series of tasks to run in parallel.

	Chained .sequence/.parallel will be executed in sequence
	*/
	
	/*
                            /- tsak4 -\
    task1 -> task2 -> task3 -> task5 -> task7 -> task8
                            \- task6 -/
	*/
		
	return new Easyflow().sequence(
		task1,
		task2,
		task3
	).parallel(
		task4,
		task5,
		task6
	).sequence(
		task7,
		task8
	).run('my initial param for the first task')
	.then((result) => {
		console.log('Success. Result:', result)
	})
}
//----------------------------------------------------------------------------
function demo2() {
	console.log()
	console.log('-------------------- demo2: nested task --------------------')
	console.log()
	
	/*
	Tasks can be a bare function, another Task Unit, another easyflow, or a task class (described later).
	Task can be nested.
	*/
	
	let flow = new Easyflow()

	return flow.sequence(
		task1,
		task2,
		task3
	).parallel(
		task4,
		flow.sequence(task5, task6, task7),
		flow.sequence(task8, task9)
	).sequence(
		task10,
		flow.parallel(
			flow.sequence(task11, task12),
			flow
				.sequence(task13, task14, task15)
				.sequence(task16, task17),
			flow.sequence(task18, task19)
		),
		task20
	).run()
}
//----------------------------------------------------------------------------
function demo3() {
	console.log()
	console.log('-------------------- demo3: Status --------------------')
	console.log()
	
	/*
	[Named Task Unit and Status Object]
	If the first parameter for .sequence() or .parallel() is a string, then the unit is a Named Unit, which
	has a status object associated with it:
	{
		status: '<pending|skipped|error|complete>',
		message: '<message>',
		error: '<error message, optional>'
	}

	The 'status' property will be automatically updated by framework upon start/complete/error, or 'skipped' if being disabled.
	Concrete task function can update the 'message' property of its owning status object in the following way:
	
	function task1() {
		this.message = 'Hello, mortal.'
	}
	
	Message from nested anonymous subtask will be updated to the status object of the first named ascenstor unit, if any.
	*/
	
	let flow = new Easyflow()

	flow.sequence('Major task 1',	//named task unit
		task1,
		task2,
		task3
	).parallel('Major task 2 (parallel)',
		task4,
		flow.sequence(task5, task6, task7),	//nested, anonymous task unit
		flow.sequence(task8, task9)
	).sequence('Major task 3',
		task10,
		flow.parallel(
			flow.sequence(task11, task12),
			flow
				.sequence('Named subtask 4', task13, task14, task15)
				.sequence('Named subtask 5', task16, task17),
			flow.sequence(task18, task19)
		),
		task20
	)
	
	//flow.status() will be updated automatically along the execution of tasks, 
	//and can be retrieved any time. E.g. continuously polled by UI
	let status = flow.status()
	console.log('Status', util.inspect(status, null, 4))
	
	//optionally, status event can be hooked. For named units only.
	flow.onStatus((id, name, status) => {
		console.log('onStatus: name=' + name + ', id=' + id + ', status=' + status)
	})
	
	return flow.run().then((result) => {
		console.log('Status', util.inspect(status, null, 4))
	})	
}
//----------------------------------------------------------------------------
function demo4() {
	console.log()
	console.log('-------------------- demo4: nested easyflow, and task class --------------------')
	console.log()
	
	/*
	Subtask can also be another easyflow, or a task class, imported from other modules
	*/
	
	let subflow = MySubFlow()
	
	let flow = new Easyflow().sequence('Demo nested easyflow & task class',
		task1,
		MyBigTask,	//a task class
		subflow,	//another flow. If you want to enable/disable it, use "subflow.id('...')," here to specify an id for the subflow.
		task3
	)
	return flow.run().then(() => {
		console.log('Status:', util.inspect(flow.status(), null, 4))
	})
}
//----------------------------------------------------------------------------
function demo5() {
	console.log()
	console.log('-------------------- demo5: nested status --------------------')
	console.log()
	
	let flow = new Easyflow()
	
	//message issued by anonymous subtask (task103, task104) will go to status object of the owner named task 'DemoMessage'
	
	flow.sequence('DemoMessage',
		task101,
		task102,
		flow.sequence(task103, task104),
		task105
	)
	
	let status = flow.status()
	console.log('Status:', status)
	let n = 0
	let timer = setInterval(() => {
		console.log(status)
		if (++n == 6)
			clearInterval(timer)
	}, 1000)
	
	return flow.run()
}

//----------------------------------------------------------------------------
function demo6() {
	console.log()
	console.log('---------- demo6: disable tasks ----------')
	console.log()
		
	let subflow = MySubFlow().id('myNestedFlow')
	
	function demo6func1() {
		this.workflow
			.disable(task6)	//programmatically disable a task
			.enable(task7)	//enable a disabled task at run time(from config)
	}
	
	return new Easyflow().sequence(
		task1,
		task2			//will not run.
	).parallel(			//specify an id for this unit. The step is also disabled and will not run
		task3,
		task4
	).id('myStep2')		
	.sequence(
		task5, 			//will not run.
		MyBigTask,		//task class has ID matches its name. It's disabled later and will not run.
		subflow,		//sub-flow has ID assigned previously. It's disabled later and will not run.
		demo6func1,
		task6,			//will not run. Programmatically disabled in demo6func1
		task7			//Configured as disabled, but programmatically enabled in demo6func1
	).disable(task2, task5, task7, 'myStep2', MyBigTask, 'myNestedFlow')	//disable some tasks
	.run()
}