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

array-sqlizr

v1.0.4

Published

A typescript utility that allows you to work with arrays in a SQLish way.

Downloads

22

Readme

Array SQLizr

What is it?

Have you ever found that working with Arrays in Javascript was a little too straightforward and easy? Do you wish you could make it unnecessarily complicated? Then this is the library for you!

SQLizr is a utility that lets you work with Javascript arrays in a more SQL like way, by chaining From, Join, and Select objects together to form a new array based on queries from a source (or set of source) arrays. It works with arrays of objects, not primitives, so it's extra unhelpful for simple tasks.

SQLizr trys to be non-destructive to your base array, and will always return cloned representations of your objects where possible.

And yes, Typescript definitions are included!

Installation

npm -i array-sqlizr

Un-installation (usually followed shortly after installation)

npm r array-sqlizr

How to use

General usage is very straightforward:

Basic (useless) example

const myCoolArray = []
// just return the same array.
// SELECT * FROM myCoolArray
const myNewArray = SQLizr.from(myCoolArray).select()

You can of course do more than just that useless example above. For instance, actually selecting attributes to output:

Using Query Attributes

const myCoolArray = [
  { 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21
  }, 
  {
    name: { first: 'Bill', last: 'Smith'}, 
    age: 62
  }]

// SELECT name.first AS firstName, name.last AS lastName FROM myCoolAray
const myNewArray = SQLizr.from(myCoolArray).select([new QueryAttribute('name.first', 'firstName'), new QueryAttribute('name.last', 'lastName')])

/* result
  [{
    firstName: 'Jim',
    lastName: 'Jam'
  },{
    firstName: 'Bill',
    lastName: 'Smith'
  }]
*/

If you don't want to alias your attribute values, you can pass in an array of strings instead of QueryAttribute objects.

const myCoolArray = [
  { 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21
  }, 
  {
    name: { first: 'Bill', last: 'Smith'}, 
    age: 62
  }]

// SELECT name.first AS firstName, name.last AS lastName FROM myCoolAray
const myNewArray = SQLizr.from(myCoolArray).select(['name.first', 'name.last'])

/* result
  [{
    name: { 
      first: 'Jim',
      last: 'Jam'
    }
  },{
    name: {
      first: 'Bill',
      last: 'Smith'
    }
  }]
*/

Joins

You can join to other arrays as well. Join syntax works like SQL joins:

.join(array, arrayName, fromAttribute, joinAttribute, innerJoin)

The arrayName is the identifier that you can use to refer to joined attributes. All joined attributes will be found under that identifier.

fromAttribute and joinAttribute are the attributes to use for finding a match. Only matches will append to the from array's items.

innerJoin is a boolean that determines if the join should be an inner join. This defaults to false, and the default behaviour is an outer join.

const employees = [
  { 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21,
    job: 'Mechanic'
  }, 
  {
    name: { first: 'Bill', last: 'Smith'}, 
    age: 62,
    job: 'CEO'
  }]

const wages = [
{ 
  job: 'Mechanic',
  wagePerHour: 25.00
},{
  job: 'CEO',
  wagePerHour: 50.00
},{
  job: 'Janitor',
  wagePerHour: 37.23
}]

// SELECT ... FROM employees JOIN wages w ON wages.job = job
const myNewArray = SQLizr.from(employees)
                          .join(wages, 'w', 'job', 'job')
                          .select([new QueryAttribute('name.first', 'firstName'),
                                   new QueryAttribute('name.last', 'lastName'),
                                   new QueryAttribute('w.wagePerHour', 'wage')])

/* result
  [{
    firstName: 'Jim',
    lastName: 'Jam',
    wage: 25.00
  },{
    firstName: 'Bill',
    lastName: 'Smith',
    wage: 50.00
  }]
*/

Where?

Of course you can supply a where clause. There are two methods for executing a where clause; where and whereFilter

.where('expression')
.whereFilter(myFilterFunction)

The default where evaluates a provided expression, and returns matching results. Your expression should obviously evaluate as a boolean. Note that this does not use eval in the code, but instead uses the expression-eval library (which itself uses jsep). Running evaluated expressions always contains an element of risk. Ensure your expressions aren't going to attempt to execute something you wouldn't want executed!

const people = [
  { 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21
  }, 
  {
    name: { first: 'Bill', last: 'Smith'}, 
    age: 62
  }]
// SELECT * FROM people WHERE name.first = "Jim"
const myNewArray = SQLizr.from(people)
                         .where('name.first === "Jim"')
                         .select()

/* result
  [{ 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21
  }]
*/

Alternatively, you can use whereFilter, which is simply a wrapper around the Array.filter() method.

const myNewArray = SQLizr.from(people)
                         .whereFilter(person => person.name.first === 'Jim')
                         .select()

/* result
  [{ 
    name: { first: 'Jim', last: 'Jam'}, 
    age: 21
  }]
*/

Finally, you can include an empty where if you dont want to filter your array at all, and want to jump straight on to where object functions

Where object functions: Order By, Limit, Sum, Average, and Union

Once you've executed a where, you can further refine your array by sorting, or limiting results. OrderByAsc and OrderByDesc are wrappers around the Array.sort method. There's also a a simple OrderBy that is a direct wrap of Sort, allowing you to pass in your own sorting function.

The limit function reduces your results to a specified number.

The union function wraps the Array.concat method, and simply merges two arrays together. Mostly useful when the objects in the arrays have matching models!

sum and average are utility functions that can calculate and return the sum or average value of a supplied attribute.

QueryAttribute expressions

A final select contains an array of QueryAttributes. These are usually the attribute name, and an alias that you want to use for it. However, you can also supply an expression that can be added to your result.

Expression evaluation is done via the same method as where clause expression evaluation.

// SELECT (name.first.length + name.last.length) as nameCharacterCount FROM people
const myNewArray = SQLizr.from(people)
                         .where()
                         .select([{ attributeName: 'expression', alias: 'nameCharacterCount', expression: 'name.first.length + name.last.length'}])

/* result
  [{ 
    nameCharacterCount: 6
  },{ 
    nameCharacterCount: 9
  }]
*/

Parsing a SQLish String

You can also parse a SQLish string, instead of using the syntax above. The string parsing is still fairly basic; complex queries aren't quite supported yet, but you can do the basics. Inline queries within a string can't be done, but you can supply other parsed queries as your from, join, or union arrays. Should go without saying, but avoid using reserved words as attribute names, alias names, join identifiers, etc. or things will go weird quickly. Specifically don't use the following (case insensitive!):

  • SELECT
  • FROM
  • OUTER
  • INNER
  • JOIN
  • ON
  • WHERE
  • LIMIT
  • ORDER BY
  • ASC
  • DSC
  • UNION

How to use the parser:

SQLizr.parse(queryString, fromArray, [joinArrays], [unionArrays])

Example:

const result = SQLizr.parse('SELECT name, boss.name AS bossName, (wages.wage * 40) AS weeklyIncome FROM employees JOIN wages ON job = title WHERE active === true LIMIT 10 ORDER BY wage ASC', employees, [wages])

Select

Your select clause can contains attribute names, aliases, and basic expressions (which must have an alias). Expressions must be wrapped in brackets.

From

Can be more or less ignored, but it's nice to keep the syntax consistent. From will be derived by the array you pass into the parse function. The supplied name doesn't actually do anything!

Join

Supply joins by specifying a join name and ON expression, like JOIN wages ON job = title. The name will be used as your join identifier. The expression follows a specific syntax of fromAttribute = joinAttribute. So in the example, it will match where job on the from array items equals title on the wages array items. The = sign is used as a delimiter, so don't leave it out!

By default, Joins are outer joins, but you can specify OUTER JOIN for outer joins, and INNER JOIN to perform an inner join.

The SQLizr.parse function will use the supplied array of arrays in the joins parameter. Because there's no name/id matching, it goes in order, so your first array on that parameter will be used for your first join, etc. So make sure you put things on in the correct order you need!

Where

Uses a where expression. See documentation above

Unions

You bet. The SQLizr.parse function will use the supplied array of arrays in the unions parameter. Works in the same way as the joins parameter

Why would you release this abomination unto the world?

Sometimes you spend so much time wondering if you could do something, you don't stop to wonder if you should...

Thanks!