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

aperol

v2.2.0

Published

JS library for asynchronous processing of side effects in action based application.

Downloads

12

Readme

Aperol

Build Status

JS library for asynchronous processing of side effects in action based application.

Install

npm install aperol --save

Usage

Basic with redux

const wait = (timeout) => new Promise((resolve) => setTimeout(resolve, timeout));
const { createModelSaga, put } = require('aperol');
const appReducer = require('./appReducer');
const appSaga = {
	reducer(model, action) {
		switch (action.type) {
			case 'SET_GREETING':
				return { ...model, message: 'hello world' };
			default:
				return model;
		}
	},
	async *updater(model, action) {
		switch (action.type) {
			case 'GREET_WITH_DELAY':
				await wait(1e3); // wait 1 second
				// dispatch GREET action to store after delay
				yield put({ type: 'GREET', message: model.message });
				break;
		}
	},
};
const modelSaga = createModelSaga(appSaga);
const store = createStore(appReducer, applyMiddleware(modelSaga.middleware));

Observing continual side-effects

const { ObservableSubscribed, put, observe } = require('aperol');
function repeat(interval) {
	return new Observable((observer) => {
		const handler = setInterval(() => observer.next());
		return () => clearInterval(handler);
	});
}
const appSaga = {
	reducer(model, action) {
		switch (action.type) {
			case 'GREET':
				return { ...model, count: model.count + 1 };
			case ObservableSubscribed:
				if (action.sourceAction.type === 'GREET_REPEATABLE') {
					return { ...model, greetingSubscription: action.subscription };
				}
			default:
				return model;
		}
	},
	async *updater(model, action) {
		switch (action.type) {
			case 'GREET_REPEATABLE':
				yield observe(repeat(1e3) // repeat every 1 second
				.map(function () {
					// dispatch GREET action to store repeatable
					yield put({ type: 'GREET' });
				}));
				break;
			case 'GREET':
				if (model.count > 10) {
					// dispatch GREETED_10_TIMES action to store after every 10th greeting
					yield put({ type: 'GREETED_10_TIMES' });
				}
				break;
			case 'STOP_GREETING':
				// When no more needed subscribing side-effect greeting
				model.greetingSubscription.unsubscribe();
				break;
		}
	},
};
// ... app code

Combining more sagas

const { combineSagas } = require('aperol');
const appSaga = combineSagas({
	greetSaga,
	otherCoolSaga,
});
const modelSaga = createModelSaga(appSaga);
// ... app code

Destroy for backend

When you plan to use aperol in node.js on backend it should be destroyed model saga when you no more needs it for user.

// It will unsubscribe all Observable subscriptions
modelSaga.destroy();

Profiler

You can start saga models with profiler which is measuring time of every single action processed by sagas

const modelSaga = createModelSaga(appSaga, {
	profiler: {
		thresholdMs: 1e3, // Show warnings when action execution reached 1 second
		onWarning: (message, action) => console.log(message, action), // Optional callback far warning. Default is console.warn function.
	},
});

ES5 transpiled and bundled

If you do not transpile code or not using bundler (like webpack) and need to have pre-transpiled code, import file aperol/dist/es5 instead.

Notes

library automatically polyfill Observable if not available in global Symbol context with zen-observable library automatically polyfill asyncIterator if not available in global Symbol context

Motivation

Many other projects like redux-saga & simple libraries like prism already supports side-effects, continual processing etc. However there are some deal breakers which motivates me to write self library. Here are the main points:

  • using asyncIterators with support for async/await instead of yielding promises (like in redux-saga),
  • model should be functional mainteined (like a redux state)
  • functional model allows you to use already existing dev tools for redux
  • Be less robust (then redux-saga)
  • Better static typing (with TypeScript)
  • Allow use same library for server-side rendering

TypeScript support

Library is written in TypeScript & we are supporting it for you. It can be found all compiled *.d.ts files in aperol/dist/ folder. By importing module with node module resolution configuration the library is typed automatically.

import { ISaga } from 'aperol';
const mySaga: ISaga = ...my typed saga :)

For Async Iterator types support add "esnext" flag to "libs" property of tsconfig.json

Nightly builds

New ideas, unconfirmed issueses & pull requests are always available in nightly build branch next. The corresponding built of npm package is also available under npm tag next in npm registry.

npm install aperol@next --save

Conclusion

This library was involved because there was no standardized pure-functional way how handle asynchronous side effects in redux based application. Also missing standard way how to handle continual side-effects. Aperol was inspired in some existing libraries like a prism or redux-saga. Aperol uses the last syntactic sugar from ES2016/TypeScript like a async/await, iterator, asyncIterator etc. For using is strictly recommended using transpilers like a TypeScript or Babel.