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

@byte-this/funscript

v1.0.42

Published

A typescript API which facilitates functional programming.

Downloads

1,001

Readme

Funscript - Functional Typescript

Coverage lines Coverage functions Coverage branches Coverage statements

For details + info on how to use: https://bytethisstore.com/articles/pg/funscript

This library facilitates functional programming practices by offering:

  • recursive object cloning
  • recursive object locking
  • asynchronous versions of array functions
  • compose utility to pipe multiple functions into one
  • deep equality checking

These will aid in creating and working with immutable objects.

Install

Library with typescript definitions available as npm package.

npm install @byte-this/funscript

Clone

The Clone function is straightforward: it recursively clones an object and returns the new object:

const newObj = Clone(oldObject);
console.log(oldObject === newObj); //false

If the object has its own clone method, this function will utilize it. Otherwise, it will do a default recursive clone.

Lock

The Lock function clones an object and recursively freezes all properties on that clone, preventing any further mutation:

const oldObj = {
    property: {
        a: true,
        b: false,
    },
};
const newObj = Lock(oldObject);
console.log(oldObject === newObj); //fales

try {
    newObj.property.a = false;
    //if 'strict mode' is not enabled, no error will be thrown
    //but the object field will not be updated
} catch (err) {
    //an error will be thrown if you have 'strict mode' enabled
    //which I recommend you should
}

FunAr

FunAr: functional asynchronous array, provides asynchronous versions of the common functional array methods in sequential and parallel flavors:

  • Sequential
    • map
    • filter
    • reduce
    • find
    • forEach (not technically functional but included for completeness)
  • Parallel
    • map
    • filter
    • forEach (not technically functional but included for completeness)

The sequential methods invoke the callback for each item one after another. The parallel methods invoke the callback for each item simultaneously.

//the methods have the same signature as the regular version, except the input array is added as the first argument
const reduced = await FunAr.async.seq.reduce(inputArray, reduceFunction, initialValue);

const mapped = await FunAr.async.parallel.map(inputArray, (item, index) => /*..async*/ return mapped);

Compose

Compose multiple functions and assign it to a single variable or execute immediately:

const compositeFunction = Compose(fOne, fTwo, fThree, fFour);
const result = compositeFunction(initialParam, otherParm); //first input function can accept more than one parameter

//async version
const compositeAsyncFunction = ComposeAsync(fOneAsync, fTwoAsync, fThreeAsync);
const result = await compositeAsyncFunction(input);

//dynamic composition
const dynamicComposition = Compose(...arrayOfFunctions);
const result = dynamicComposition();

Equals

Check if two objects are equal. The following are considered to be equal:

  • Two primitives with the same value
  • Two objects with the same object reference
  • Two dates with the same datetime
  • Two arrays with the same contents in the same order and the contents are Equal
  • Two objects with the same keys and value pairs are Equal
Equals(true, true); //true

Memoization

Memoization is a technique where the response of a function is stored so that future calls with the same parameters receive the cached response instead of executing from scratch. Below is a basic example:

const memoized = Memoize(exensiveFunc);
const resultOne = memoized(funcParamOne, funcParamTwo); //this first call runs the expensiveFunc
const resultTwo = memoized(funcParamOne, funcParamTwo); //this second call does not run expensiveFunc, it returns the result from the first execution
const resultThree = memoized(newFuncParamOne, newFuncParamTwo); //this runs expensiveFunc again because the arguments are different than the first call

With the default parameters, cached values are stored indefinitely. It is also possible to configure an expiration time:

const memoized = Memoize(exensiveFunc, {
    cacheExpiration: {
        evaluate: () => numMs, //a function which returns a number in milliseconds
        type: "relative" | "absolute", //specificy if the timestamp is relative to now or absolute
    },
});

When the cache item expires, the memoized fnction will run the real function the next time it is invoked.

Async version:

const memoized = MemoizeAsync(expensiveFunc);

Decorator version:

class TestClass {
    @MemoizeMethod() //this can take the same options as the normal method call
    expensiveFuncOne() {
        /** some expensive operation */
    }

    @MemoizeAsyncMethod()
    async expensiveFuncTwo() {
        /** some async expensive operation */
    }
}

Collect Pending Method Invocations

Wrap an async function so it collects multiple invocations and waits for the response of the first call instead of calling the function multiple times.

const asyncFunc = async () => { /** some async function, such as network call */ return response; };

const wrappedFunc = CollectPendingInvocations(asyncFunc);

Promise.all([
    wrappedFunc(param),
    wrappedFunc(param),
    wrappedFunc(param)
]).then(data => console.log(data)); //logs array of three responses, but original method was only called once

There is also a decorator for class methods:

class TestClass {
    @CollectPendingMethodInvocations
    asyncOperation() {
        /** some async operation */
        return response;
    }
}

Other Array Functions

The following functions exist on FunAr and can have custom equality comparators passed in when applicable

  • uniqueValues: get the unique values of an array
  • subset: get a subset of an array from the start to end index
  • isSubsetOf: check if an array is a subset of another array
  • isSupersetOf: check if an array is a superset of another array
  • intersection: get the intersection (common values) of two arrays
  • intersects: check if two arrays have any intersection