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

declarative-js-symbols

v1.0.3

Published

Symbols to extend JavaScript Array and Object prototypes with declarative-js functionality.

Downloads

2

Readme

declarative-js-symbols

npm version Build Status Coverage Status

Symbol that extends array and object with additional functions from declarative-js package.

Install

npm i declarative-js-symbols --save

Usage

import { extends } from 'declarative-js-symbols'
import { data } from './businessData'

const transformedData = 
    data[extends]() //extending object prototypes
        .values()[extends]() //extending array prototypes
        .present()[extends]()
        .sortBy('severity')[extends]()
        .takeWhile(x => x.severity === 'Critical')
        .map(x => x.task)[extends]()
        .groupBy('taskName')

Imagine, that we maintain two npm packages and want to ensure that all dependencies have same versions.

import { extends } from 'declarative-js-symbols'

const p1 = {
    "name": "package1",
    "version": "1.0.0",
    "devDependencies": {
        "jest": "23.6.0", // <==
        "prettier": "1.15.3"
    }
}
const p2 = {
    "name": "package2",
    "version": "1.0.0",
    "devDependencies": {
        "jest": "22.0.0", // <==
        "prettier": "1.15.3"
    }
}

function toHaveMoreVersions(entry) {
    return entry.value[extends]()
        .unique()
        .length > 1
}

function toInvalidDependency(entry) {
    return {
            name: entry.key, 
            versions: entry.value.map(e => e.value)
        }
}

const invalidDeps = [p1, p2]
    .map(pck => pck.devDependencies) // object[]
    .map(pck => pck[extend]().entries())[extend]() // {key, value}[][]
    .flat()[extend]() // {key, value}[]
    .groupBy('key')[extend]() // {dependencyName: {name: version}[]}
    .entries() // {key, value}[]
    .filter(toHaveMoreVersions)
    .map(toInvalidDependency)
// [{name: 'Jest', versions: ['23.6.0', '22.0.0']}]

Array

equal

Filters out items, that are not equal to provided item in parameters. Objects are compared to be deep equal.

interface ArrayExtension<T> {
    equal(valueToMatch: T): Array<T>
}

notEqual

Filters out items, that are equal to provided item in parameters. Objects are compared to be deep equal.

interface ArrayExtension<T> {
    notEqual(valueToMatch: T): Array<T>
}

unique

Determines uniqueness of an objects in array. Be aware that if value is not primitive, deep object equality will be checked to determine uniqueness.

interface ArrayExtension<T> {
    unique(): Array<T>
}
 [1, 2, 2][extend]().unique()
 // [1, 2]
 [{a: 1}, {a: 1}, {a: 2}][extend]().unique()
 // [{a: 1}, {a: 2}]

notEmpty

Filters out items that are empty

interface ArrayExtension<T> {
    notEmpty(): Array<T>
}
 [1, '', [], {}][extend]().notEmpty()
 // [1]

present

Filters out items that are not present undefined and null in array

    present(): Array<NonNullable<T>>

uniqueBy

Determines uniqueness objects key from callback. This value must be comparable with strict equals

interface ArrayExtension<T> {
    uniqueBy<K extends keyof T>(key: K): Array<T>
    uniqueBy(key: StringGetter<T>): Array<T>
}
 [
  { title: 'Predator', genre: 'sci-fi' },
  { title: 'Predator 2', genre: 'sci-fi' },
  { title: 'Alien vs Predator', genre: 'sci-fi' },
  { title: 'Tom & Jerry', genre: 'cartoon' },
 ][extend]()
        .uniqueBy(movie => movie.genre) 
        .uniqueBy('genre') // overload
 // [
 //  { title: 'Predator', genre: 'sci-fi' },
 //  { title: 'Tom & Jerry', genre: 'cartoon' }
 // ]

takeWhile

It will pass items from array, while predicate matches. When predicate returns false none of the items will pass.

interface ArrayExtension<T> {
    takeWhile(predicate: Predicate<T>): Array<T>
}
 [
  { title: 'Predator', genre: 'sci-fi' },
  { title: 'Predator 2', genre: 'sci-fi'},
  { title: 'Tom & Jerry', genre: 'cartoon' },
  { title: 'Alien vs Predator', genre: 'sci-fi' },
 ][extend]()
      .takeWhile(film => film.genre === 'sci-fi')
 // [
 //  { title: 'Predator', genre: 'sci-fi' },
 //  { title: 'Predator 2', genre: 'sci-fi' }
 // ]

groupBy

Function to group by provided key.

interface ArrayExtension<T> {
    groupBy<K extends keyof T>(key: K): Indexed<T[]>
    groupBy(getKey: StringGetter<T>): Indexed<T[]>
}
 [
  { title: 'Predator', genre: 'sci-fi' },
  { title: 'Predator 2', genre: 'sci-fi'},
  { title: 'Alien vs Predator', genre: 'sci-fi' },
  { title: 'Tom & Jerry', genre: 'cartoon' },
 ][extend]()
      .groupBy('genre')
    // overload  
    //.groupBy(movie => movie.genre) 

flat

Function to make from 2d array simple array

interface ArrayExtension<T> {
    flat(): T
}
[[1,2],[3,4]][extend]()
    .flat() 
// [1,2,3,4]

toObject

Collects items to object by key from callback. If function resolves key, that already exists it will throw an Error. Second callback is value mapper.

interface ArrayExtension<T> {
    toObject<K>(
        getKey: (value: T) => string, 
        getValue: (value: T) => K
    ): Indexed<K>
}
[
    { title: 'Predator', genre: 'sci-fi' },
    { title: 'Predator 2', genre: 'sci-fi'},
    { title: 'Alien vs Predator', genre: 'sci-fi' },
    { title: 'Tom & Jerry', genre: 'cartoon' },
][extend]()
    .toObject(movie => movie.title, movie => movie.genre)

Collects items to object by key from callback. If function resolves key, that already exists it will throw an Error

interface ArrayExtension<T> {
    toObject(key: (value: T) => string): Indexed<T>
}
 [
  { title: 'Predator', genre: 'sci-fi' },
  { title: 'Predator 2', genre: 'sci-fi'},
  { title: 'Alien vs Predator', genre: 'sci-fi' },
  { title: 'Tom & Jerry', genre: 'cartoon' },
 ][extend]()
      .toObject(movie => movie.title)

merge

Reduces array of objects to one object, There is three merge strategies

@see Reducer.MergeStrategy (declarative-js)

@param merge {@link MergeStrategy} = default is OVERRIDE

interface ArrayExtension<T> {
    merge<R extends object>(strategy?: Reducer.MergeStrategy): T & R
}

ascendingBy

Sorts array in ascending order by values provided. First value has highest priority in sorting and so on. It accepts as many value resolvers as You need.

interface ArrayExtension<T> {
    ascendingBy<K extends keyof T>(...keys: K[]): Array<T>
    ascendingBy(...getters: ((val: T) => string | number)[]): Array<T>
}
persons[extend]().ascendingBy(
    x => x.name,
    x => x.lastName,
    x => x.age
)
//overload
persons[extend]().ascendingBy(
    'name',
    'lastName',
    'age'
)
 // [
 //  { name: 'andrew', lastName: 'Aa', age: 1 },
 //  { name: 'andrew', lastName: 'Bb', age: 1 },
 //  { name: 'andrew', lastName: 'Bb', age: 2 },
 //  { name: 'billy', lastName: 'Cc', age: 1 },
 //  { name: 'billy', lastName: 'Cc', age: 5 },
 // ]

descendingBy

Sorts array in descending order by values provided. First value has highest priority in sorting and so on. It accepts as many values as You need.

interface ArrayExtension<T> {
    descendingBy<K extends keyof T>(...keys: K[]): Array<T>
    descendingBy(...getters: ((val: T) => string | number)[]): Array<T>
}
 persons[extend]().ascendingBy(
    x => x.name,
    x => x.lastName,
    x => x.age
)
// overload
persons[extend]().ascendingBy(
    'name',
    'lastName',
    'age'
)
 // [
 //  { name: 'billy', lastName: 'Cc', age: 5 },
 //  { name: 'billy', lastName: 'Cc', age: 1 },
 //  { name: 'andrew', lastName: 'Bb', age: 2 },
 //  { name: 'andrew', lastName: 'Bb', age: 1 },
 //  { name: 'andrew', lastName: 'Aa', age: 1 },
 // ]

sortBy

Function that will sort items in array with custom values, by provided order. It accepts as a parameter object with valueToOrderElement mapper and array of custom order rule

import { Sort } from 'declarative-js'

interface ArrayExtension<T> {
    sortBy(...conditions: Sort.SortingCondition<T, any>[]): Array<T>
    sortBy<K extends keyof T>(key: K, values: T[K][]): Array<T>
}
testTodoData[extend]().sortBy(
    { toValue: x => x.severity, order: ['low', 'medium', 'high'] },
    { toValue: x => x.task, order: ['Sleep', 'Drink'] }
)
// overload with one sorting condition
testTodoData[extend]().sortBy('severity', ['low', 'medium', 'high'])
      // { task: 'Sleep', severity: 'low' },
      // { task: 'Drink', severity: 'low' },
      // { task: 'Eat', severity: 'medium' },
      // { task: 'Code', severity: 'high' },

orderedBy

Function that will sort items in array, by provided order. It accepts as a parameter array of custom order rule. Element, that are not present in order array will be at he the end of the sorted list.

interface ArrayExtension<T> {
    orderedBy(order: Array<T>): Array<T>
}
 const testData =
   ['bar', 'medium', 'foo', 'low']
 const result =
   testData[extend]()
      .orderedBy(['low', 'medium', 'high'])
 // ['low', 'medium', 'bar', 'foo', ]

Object

keys

Returns object keys

interface ObjectExtension<T> {
    keys(): string[]
}

Returns object values

values

interface ObjectExtension<T> {
    values(): T[]
}

entries

Returns object entries as a {key, value} objects array

interface ObjectExtension<T> {
    entries(): ObjectEntry<T>[]
}
interface ObjectEntry<T> {
    key: PropertyKey,
    value: T
}

containsKey

Is object contains key

interface ObjectExtension<T> {
    containsKey(key: string): boolean
}

containsValue

Is object contains value

interface ObjectExtension<T> {
    containsValue(value: T): boolean
}