Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/TomerAberbach/grfn
🦅 A tiny (~315B) utility that executes a dependency graph of async functions as concurrently as possible.
https://github.com/TomerAberbach/grfn
async concurrency graph node-module node-package package
Last synced: 2 months ago
JSON representation
🦅 A tiny (~315B) utility that executes a dependency graph of async functions as concurrently as possible.
- Host: GitHub
- URL: https://github.com/TomerAberbach/grfn
- Owner: TomerAberbach
- License: apache-2.0
- Created: 2020-12-31T06:15:34.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2024-10-15T03:14:34.000Z (3 months ago)
- Last Synced: 2024-11-06T14:20:25.247Z (3 months ago)
- Topics: async, concurrency, graph, node-module, node-package, package
- Language: TypeScript
- Homepage: https://npm.im/grfn
- Size: 1.03 MB
- Stars: 609
- Watchers: 5
- Forks: 4
- Open Issues: 3
-
Metadata Files:
- Readme: readme.md
- Contributing: contributing.md
- License: license
Awesome Lists containing this project
- awesome-list - grfn
README
grfn
A tiny (~315B) utility that executes a dependency graph of async functions as concurrently as possible.## Features
- **Lightweight:** ~315 bytes gzipped
- **Unobtrusive and Unopinionated:** takes normal functions; returns a normal
function!
- **Isomorphic:** works in node and the browser
- **Easy Debugging:** provides type-level validation of the input graph,
including cycle detection!
- **Awesome Logo:** designed by [Jill Marbach](https://jillmarbach.com)!## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [API](#api)
- [Contributing](#contributing)
- [License](#license)## Install
```sh
$ npm i grfn
```## Usage
```js
import { setTimeout } from 'node:timers/promises'
import grfn from 'grfn'const fn = grfn({
// `e` depends on `a`, `c`, and `d`. Call `e` with the results of the
// functions once their returned promises resolve.
e: [
async (a, c, d) => {
await setTimeout(10)
return a * c * d
},
[`a`, `c`, `d`],
],// `d` depends on `b`.
d: [
async b => {
await setTimeout(1)
return b * 2
},
[`b`],
],// `c` depends on `a` and `b`.
c: [
async (a, b) => {
await setTimeout(5)
return a + b
},
[`a`, `b`],
],// `a` and `b` have no dependencies! But they must still be listed. They take
// the input given to `fn`.
a: async (n1, n2, n3) => {
await setTimeout(15)
return n1 + n2 + n3
},
b: async (n1, n2, n3) => {
await setTimeout(10)
return n1 * n2 * n3
},
})const output = await fn(4, 2, 3)
// This will be the output of `e` because no function depends on it!
console.log(`final output: ${output}`)
```Output:
```
final output: 14256
```### Debugging
The graph will be automatically validated, including cycle detection, via
TypeScript magic!## API
### `grfn(vertices) => (...args) => Promise`
Returns a function that runs the dependency graph of functions described by
`vertices`:- Input: passed to the functions that don't have dependencies in the graph.
- Output: a `Promise` that resolves to the value returned from the graph's
_output function_, the function that is not depended on by any function.#### `vertices`
Type: `{ [key: string]: Function | [Function, string[]?] }`
An object describing a dependency graph of functions.
Each value in `vertices` must be either:
- A pair containing a function and its array of dependencies by key (e.g.
`[fnA, ['keyB', 'keyC']]`)
- Or a function (equivalent to `[fn, []]`)The following constraints, which are validated via TypeScript magic, must also
be met:- Each dependency in `vertices` must also appear as a non-dependency:
- Not okay (`b` doesn't appear as a non-dependency):
```js
grfn({
a: [fnA, [`b`]],
})
```
- Okay:
```js
grfn({
a: [fnA, [`b`]],
b: fnB,
})
```
- `vertices` must describe an
[acyclic](https://en.wikipedia.org/wiki/Directed_acyclic_graph) dependency
graph:
- Not okay (cycle: `a -> b -> a`):
```js
grfn({
a: [fnA, [`b`]],
b: [fnB, [`a`]],
})
```
- Okay:
```js
grfn({
a: [fnA, [`b`]],
b: fnB,
})
```
- `vertices` must have exactly one _output function_, a function that is not
depended on by any function:
- Not okay (both `b` and `c` are not depended on by any function):
```js
grfn({
b: [fnB, [`a`]],
c: [fnC, [`a`]],
a: fnA,
})
```
- Okay:
```js
grfn({
d: [fnD, [`b`, `c`]],
b: [fnB, [`a`]],
c: [fnC, [`a`]],
a: fnA,
})
```## Contributing
Stars are always welcome!
For bugs and feature requests,
[please create an issue](https://github.com/TomerAberbach/grfn/issues/new).For pull requests, please read the
[contributing guidelines](https://github.com/TomerAberbach/grfn/blob/main/contributing.md).## License
[Apache 2.0](https://github.com/TomerAberbach/grfn/blob/main/license)
This is not an official Google product.