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

promise-apply-spec

v2.0.0

Published

Reduce a data structure containing promises to a promise of the data structure containing the resolved values.

Downloads

18

Readme

promise-apply-spec

version npm build status Coveralls deps status mit license

PromiseApplySpec is a Promise utility function like Promise.all plus Ramda's applySpec for arbitrary raw data structures containing Promises and functions.

Features

  • Captures and reports all errors from promises with enough detail to trace their location in the original structure.

  • (Optionally) recursively resolves Promises within promise-resolved leaf structures.

  • (Optionally) recursively expands functions in the spec with supplied arguments.

  • Differing from Ramda, handles structures with strings and classed objects, leaving them untouched.

  • Offers 3 different API styles (traditional, fluent, functional/tacit).

  • Covered by extensive functional testing.

Basic Usage

// Standard API
const applySpecP = require('promise-apply-spec');

const data = [Promise.resolve(1), {a: 2, b: Promise.resolve(3)}];
applySpecP(data); // => Promise([1, {a: 2, b: 3});

const failing = [
    Promise.resolve(1),
    {a: Promise.reject(new Error('two'))},
    Promise.reject({c: 3})
];
applySpecP(failing).catch(function(err) {
    err; // => Error('Promises rejected:\n - two\n - [Object object]')
    err.errors; // => [Error('two'), {c: 3}]
    err.errors[0].path; // => '1.a'
    err.errors[1].path; // => `undefined` (will only mutate Errors)
});

// Fluent API
const applySpecP = require('promise-apply-spec');

applySpecP
    .withSpec(data)
    .exec(); // => Promise([1, {a: 2, b: 3});

// Functional API
const { all, once, applySpec, unravel, unravelOnce } = require('promise-apply-spec');

const spec = {
  a: Promise.resolve(1),
  b: Promise.resolve({c: Promise.resolve(3), d: x => x+1})
};

// expand everything, recursively
unravel(spec, [4]).then(function(data) {
  data; // => {a: 1, b: {c: 3, d: 5}}
});

// expand initial promises and functions only
unravelOnce(spec)([4]).then(function(data) {
  data; // => {a: 1, b: {c: Promise(3), d: 5}}
});

// expand promises only, recursively
all(spec).then(function(data) {
  data; // => {a: 1, b: {c: 3, d: x => x+1}}
});

// expand functions once only
applySpec(spec)([4]); // => spec
applySpec({a: x => x+1}, [4]); // => {a: 5}

API (traditional)

const { applySpecP } = require('promise-apply-spec');

applySpecP(spec[, arg[, options]]) ⇒ Promise(data) | data

The fully featured main function — provided as both the default export and a named export — with a traditional, data-first and non-curried signature.

Params:

  • spec: Any: any combination of nested arrays, plain objects, functions, promises, and other values ('other values' that look like plain objects containing promises or functions will get recreated as truly plain objects)

  • args: Array: arguments to pass into invoked spec functions

  • options: Configuration object

    • apply: Boolean: whether to replace spec functions with their invocation — default true
    • resolve: Boolean: whether to resolve promises — default true
    • once: Boolean: when true, unwraps promises at most once, then expands functions at most once, and returns — default false

Return:

  • when options.resolve = true, a Promise of the resolved and optionally function-applied data structure
  • when options.resolve = false, the optionally function-expanded data structure

Fluent API (building operations via method chaining)

const Fluent = require('promise-apply-spec');

The initial immutable Fluent instance with options {apply: true, resolve: true, once: false}.

Fluent.applyTo(args) ⇒ Fluent

Get a new immutable Fluent with default args provided and options.apply = true.

Fluent.withSpec(spec) ⇒ Fluent

Get a new immutable Fluent with default spec provided.

Fluent.repeating(Boolean) ⇒ Fluent

Get a new immutable Fluent with options.once reconfigured.

Fluent.applying(Boolean) ⇒ Fluent

Get a new immutable Fluent with options.apply reconfigured.

Fluent.resolving(Boolean) ⇒ Fluent

Get a new immutable Fluent with options.resolve reconfigured.

Fluent.exec([spec[, args[, once]]]) ⇒ Promise(data) | data

Execute applySpecP with all arguments defaulting to the Fluent instance configuration.

Functional API (auto-curried, data-last functions)

const { all, once, applySpec, unravel, unravelOnce } = require('promise-apply-spec');

all :: spec → Promise(data)

Recursively expands promises, ignores functions.

once :: spec → Promise(data)

Expands promises once, ignores functions.

applySpec :: spec → [arg] → data

Expands functions once, ignores promises.

unravel :: spec → [arg] → Promise(data)

Recursively expands promises and functions.

unravelOnce :: spec → [arg] → Promise(data)

Expands promises once, then functions once.

Related Libraries and Functions

  • promise-all: Turns a flat array or object of promises into a promise of the same data structure with promises unwrapped. Limitations: only supports flat data (no nested objects or arrays), cannot recursively expand promises, does not expand functions.

  • promise-all-recursive: Turns a data structure containing promises into a promise of the data structure with promises recursively unwrapped. Limitation: does not handle promise rejections or expand functions.

  • promise-traverse: Turns a data structure containing promises into a promise of the data structure with promises unwrapped. Limitations: cannot recursively expand promises, does not handle promise rejections or expand functions.

  • ramda.applySpec: Turns a spec object into a function that returns the same data structure but replacing inner functions with their invocation on the supplied argument. Limitations: only works for spec objects containing only non-string primitives and functions as leaf nodes, does not resolve promises, and does not pass more than one argument to spec functions.