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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@eribrary/helpers-files

v2.0.5

Published

Special functions and variables used in Node.js to manipulate files. NOTE: uses 'fs', 'path', etc.

Downloads

15

Readme

@eribrary/helpers-general v1.0.2

Helper functions for common Javascript operations. As a "general" helper function library, this does NOT cater to any special needs but is meant to be applicable to a wide variety of typical use cases. Examples provided below.

Installation

import * as gHelpers from '@eribrary/helpersGeneral'

Example Functions

Deep Clone Objects:

Forget the shallow clone crap! Go deep, take everything.
/**
 * Deep Clone an Object of any type and level of nesting, completely removing all dependencies.
 * 
 * @param {object} inObject - The Object to Deep Clone.
 * @returns A Coned Object.
 */
const deepCloneObject = (inObject) => {

    // First we create an empty returnObj that we fill in later and return.
    let returnObj = {};

    // Second we iterate through the top-level of inObject, filling in our returnObj.
    for (const [key, value] of Object.entries(inObject)) {

        // Third we check whether the value is of any Pass-by-Reference Type (Array or Object).
        // For each of these, we iterate through each value and determine if the values are Pass-by-Reference
        // or not.  If they are, we need a recursive call to this function.  Otherwise, this is the final call.

        if (value === null) { returnObj[key] = value; } // #TODO - should leave as null or set to "" ?
        else if (Array.isArray(value)) {

            // Start will an empty array and bMakeRecursiveCall = TRUE.
            // Since Arrays must always be of the same type, then if ANY value is NOT an Object / Array,
            // we can set bMakeRecursiveCall = FALSE.
            returnObj[key] = [];
            let bMakeRecursiveCall = true; // #TODO - #DELETE - #TEST - delete after testing - just want to make sure the code works and the type won't ever change.

            let arrLength = value.length;
            for (let i = 0; i < arrLength; i++) {
                if (bMakeRecursiveCall && checkIsEnumerableObject(value[i])) {
                    returnObj[key].push(deepCloneObject(value[i]));
                    if (bMakeRecursiveCall === false) {
                        notifyOnError(["bMakeRecursiveCall was FALSE", `${key}: ${value[i]} @ index ${i}`])
                    }
                    bMakeRecursiveCall = true;
                }
                else {
                    returnObj[key].push(value[i]);
                    bMakeRecursiveCall = false;
                }
            }
        }
        else if (checkIsEnumerableObject(value)) {
            returnObj[key] = deepCloneObject(value);
        }
        else {
            returnObj[key] = value;
        }
    }

    return returnObj;
}

Check Whether a Variable is an Enumberable Object:

Do you hate it when typeof returns [object] but you're not quite sure whether that means an actual Object you can iterate through or just null, undefined, a date, a function, etc.? Well wonder no more, because this function makes a final determination you can rely on!
/**
 * Check whether a variable is an enumberable Object (will have [key, value] pairs).
 * 
 * @param {object} inObject - Object to check.
 * @returns Boolean - TRUE for an Object and FALSE for NOT an Object.
 */
const checkIsEnumerableObject = (inObject) => {

    // First make sure inObject isn't null and is a typeof 'object'.
    // If it fails either of these, we return FALSE.  If it passes, then we check
    // whether it is a "true" Object (i.e. "[object Object]"), which is the only type that is enumerable.
    if (inObject !== null && typeof inObject === 'object') {
        return Object.prototype.toString.call(inObject) === '[object Object]';
    }
    else { return false };
}

Convert Any Array Into Multiple, Evenly Spaced Arrays OR 1 String[]

Have an Array you want broken down into evenly spaced mini-arrays? Or do you just want to split a String evenly into a single String[]? We've got you covered!
/**
 * Takes an Array (any type) and separates out its elements into innerArrays based on an "interval" argument.  This is especially useful for
 * the Slack interface where we may have a lengthy fieldsArray and need to split each Fields element into Sections of 2 Fields each.  
 * @param {[]} inArray - An Array of any type.
 * @param {number} interval - How many Array elements should each innerArray include in the final 2D Array (the last innerArray may contain fewer if the length of inArray is not evenly divisible by this number).  Default is 1.
 * @param {boolean} bReturnTextArray - TRUE = returns a String[] and essentially is the same as inArray.match(/.{1,X}/g) where "X" is the "interval" param and inArray is a String (but unlike .match(), this works on most types, including Number[]).  #NOTE: this will NOT work well for Object[], which returns only "[object Object]" for each element.  FALSE = behaves normally, returning a 2D array.  Default is FALSE.
 * @returns - if bReturnTextArray = FALSE, then returns a 2D Array of the same type as inArray that has the original inArray's elements spaced out in innerArrays by the interval number.  If bReturnTextArray = TRUE, then returns a String[] likewise separated.
 */
const alternateArrayElements = (inArray, interval = 1, bReturnTextArray = false) => {

    // Preliminary variables.
    let finalArray = []
    let arrayLength = inArray.length

    for (let i = 0; i < arrayLength; ++i) {

        if (((i + 1) % interval) === 0) {

            // If (i + 1) can be divided evenly by interval, then we get a number of elements equal to 
            // interval (before and including i), starting at the earliest element.

            // Here we start at interval - 1 (since we include i) and do a reverse forLoop()
            // in order to get the earliest elements first.  Each element is pushed to a dummy innerArray.
            // Then, once the forLoop() ends, we push that innerArray to the finalArray.
            let innerArray = []
            let stringArray = ""
            for (let j = interval - 1; j > -1; j--) {
                bReturnTextArray ? stringArray += inArray[i - j] : innerArray.push(inArray[i - j])
            }
            finalArray.push(bReturnTextArray ? stringArray : innerArray)
        }
        else if (i === arrayLength - 1) {
            // If we've reached the end of inArray and the arrayLength was not evenly divisible by interval
            // (in which case the above code would have been called), we will need to retrieve all unhandled elements.

            // We get unhandled elements by finding how many leftover elements there are (arrayLength % interval) and subtract -1
            // because, as before, we include i.  Then we follow the same process as above for pushing elements to the finalArray.
            let innerArray = []
            let stringArray = ""
            for (let j = (arrayLength % interval) - 1; j > -1; j--) {
                if (i - j > -1) {
                    bReturnTextArray ? stringArray += inArray[i - j] : innerArray.push(inArray[i - j])
                }
            }
            finalArray.push(bReturnTextArray ? stringArray : innerArray)
        }
    }

    return finalArray
}