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

affects

v1.0.2

Published

Affects is a Algebraic Effects inspired library for Node.

Downloads

7

Readme

Affects

Affects is a Algebraic Effects inspired library for Node.

GitHub license npm version Build status Coverage PRs Welcome

What is Affects

Affects is a Algebraic Effects inspired library. If you're coming from the React world, you can think of it as the provider of Context and the useContext hook, but for regular javascript.

Affects provides user friendly thread-local storage to Node.js.

:warning: Affects only works on Node.js > 14, since it relies on Node's Experimental AsyncLocalStorage

Examples

import { createHandler, createRunner, perform } from 'affects';

// First create a handler that you can use to refer and set a default value
const User = createHandler({ name: '', email: '' });

// Use the handler in a function
async function emailUser() {
  const user = perform(User);
  await thirdPartyApi.email(user.email);
}

async function expressEmailUser(request, response) {
  if (!request.user) {
    return;
  }
  const run = createRunner(() => emailUser());
  await run([User, request.user]);
  response.send(200);
}

Although this example might not be the best, you will be able to notice that emailUser doesn't actually receive the user from an argument nor from scope, perform(User) is actually obtaining the value from storage local to that thread.

This is a feature that is helpful in multiple scenarios:

  • Dependency injection
  • Mocking
  • Etc

Mocking

Let's take the following example:

export const WriteToPath = createHandler(fs.writeFile);

export const writeConfig = createRunner(async () => {
  const home = await getUserDir();
  perform(WriteToPath)(`${home}/config.txt`, config);
});

// another file
import { writeConfig } from './writeConfig';
writeConfig();

By default, writeConfig when performing WriteToPath will obtain a copy of fs.writeToFile, with no modification.

If you would need to run the function, but replace any writing to disk with logs to console, you would:

import { writeConfig, WriteToPath } from './writeConfig';
writeConfig([WriteToPath, (path, data) => console.log(`Wrote to ${path}`)]);

If you have read Algebraic Effects for the Rest of Us, you might find the following adapted version of Dan Abramov's example easier to follow:

import { createHandler, createRunner, perform } from 'affects';

const AskName = createHandler();

function getName(user) {
  let name = user.name;
  if (name === null) {
  	name = perform(AskName);
  }
  return name;
}

function makeFriends(user1, user2) {
  user1.friendNames.push(getName(user2));
  user2.friendNames.push(getName(user1));
}

const arya = { name: null, friendNames: [] };
const gendry = { name: 'Gendry', friendNames: [] };
const run = createRunner(() => makeFriends(arya, gendry));

run([AskName, 'Arya Stark']);

Api

Affects only exports 3 functions:

createHandler

Will create an object with a unique identity that is used to refer to when calling perform. Additionally it will hold a default value that is used if perform is called outside a runner. You might find it similar to React's createContext, in fact, it's modeled after it.

const MyHandler = createHandler(defaultValue);

createRunner

In most papers and blog posts, handlers are inserted in a way similar to the handling of raised exceptions. This is sadly not possible without either modifying the language or converting everything into generator functions.

With affects, handlers are passed in as pairs to the function returned by createRunner

// someFunction is a function that calls `perform` either directly or not, synchronously or not.
const run = createRunner(someFunction);
run([Handler, customValue], [AnotherHandler, anotherCustomValue]);

perform

Perform will pull in the matching value for a handler, in a similar way to React's useContext. Note that unlike useContext, perform will work across asynchronous work boundaries. Another important feature of perform is that it's fully typed and will use the type of your defaultValue as the type that it returns.

const user = perform(User);

Typescript

Affects is fully typed, meaning that performed values will return the correct types.

Installation

npm install affects

Limitations

Affects doesn't solve the "color of your function" which means that effects that were originally intended to be synchronous can't be resumed in an asynchronous way.

License

react-nest is open source software licensed as MIT.