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

jinqu

v1.1.3

Published

Querying infrastructure for JavaScript, with Linq style

Downloads

228

Readme

Jinqu - LINQ for Javascript

Build Status Coverage Status Codacy Badge npm version GitHub issues GitHub license

GitHub stars GitHub forks

Jinqu, based on the LINQ design, is the ultimate querying API for Javscript & Typescript. It provides:

  • LINQ syntax
  • Lazy (i.e. deferred) Evaluation
  • Local and Remote Evaluation w/ provider model for libraries implementing remote evaluation (e.g. jinqu-odata)
  • Static Typing (in Typescript)
  • Dynamic queries (in strings)
  • Even works on IE 11 (with transpilation)

Jinqu works perfectly in both Javascript and Typescript, but is optimized for Typescript. Jinqu is itself written in Typescript.

Installation

npm install jinqu

Code Examples

First, make sure you've imported jinqu. This will add asQueryable method to Array Prototype.

import 'jinqu'

We need to call asQueryable to create a query for an Array.

const array = [1,2,3,4,5]
const query = array.asQueryable().where(c => n % 2 == 0).toArray()
for (var n of query)
    console.log (n) // outputs 2,4

If you want to use query methods directly, you need to install and import jinqu-array-extensions package.

npm i jinqu-array-extensions

import 'jinqu-array-extensions'

You actually only need to do this once, such as in the entry point for your application, to ensure the Array prototype extensions are set up.

Now let's filter an array:

const array = [1,2,3,4,5]
const query = array.where(c => n % 2 == 0).toArray()
for (var n of query)
    console.log (n) // outputs 2,4

We can chain query operators:

const array = [1,2,3,4,5]
const query = array
    .where(c => n % 2 == 0)
    .orderByDescending (n => n)
    .toArray()
for (var n of query)
  console.log (n) // outputs 4,2

Importantly, results aren't evaluated until toArray is called.

Dynamic Expressions

const filtered = orders.where('c => c.id > value', { value: 3 })

The additional argument is a variable scope that lets you pass in variables dynamically.

Supported Query Operators

The full range of LINQ operators are supported:

where  
ofType  
cast  
select  
selectMany  
join  
groupJoin  
orderBy  
orderByDescending  
thenBy  
thenByDescending  
take  
takeWhile  
skip  
skipWhile  
groupBy  
distinct  
concat  
zip  
union  
intersect  
except  
defaultIfEmpty  
reverse  
first  
firstOrDefault  
last  
lastOrDefault  
single  
singleOrDefault  
elementAt  
elementAtOrDefault  
contains  
sequenceEqual  
any  
all  
count  
min  
max  
sum  
average  
aggregate  
toArray

As well as:

ofGuardedType

And also:

range  
repeat

Remote Query Providers

Jinqu has the following remote providers:

Remote queries always return promises so are awaited. So rather than toArray to obtain the results of the query, you'll call toArrayAsync:

...
const result = await remoteQuery.toArrayAsync()
for (var item of result)
   ...

Array Prototype Extensions

Jinqu query operators build queries with a simple model: they take a query type as an input, transform it, and output another query type. However, the very first operator in a query needs to take an array type as the original source for the query. To make this work, jinqu extends the Array prototype.

Extending the array prototype is very convenient, but occasionally has conflict issues with Array's built-in prototype or other 3rd party prototype extensions.

To overcome this, you can call asQueryable or the convenience q for short, to ensure you're working with an IQuery<T> type:

[1,2,3].asQueryable().reverse()
[1,2,3].q().reverse() // same as above

In addition, the concat, join, and reverse methdos (which are built into the Array prototype), have special support: call concatWith, joinWith, and reverseTo, to start a query with these operators on the array type.

ofType and ofGuardedType

ofType and ofGuardedType filter elements of a specified type. The type arguments you must supply are a little different to what you might expect if you come from a C# background, but will make sense to you when you get a feel for the Typescript type system.

  • ofType takes either a: * constructor to filter class instances * default value to filter primitive types
  • ofGuardedType takes a: * Typescript type guard (See Typescript Advanced Types) to filter values by a condition indicative of type

Their usage is as follows:

class Panda {
    constructor (public id: number) {}
}

function isNumber(x: any): x is number {
    return typeof x === "number"
}

const array = ["1", 2, new Panda(3), "4", 5, new Panda(6)]
const justPandas = array.ofType(Panda) // panda 3, panda 6 - using constructor type filter
const justStrings = array.ofType("") // "1", "4" - using default value type filter
const justNumbers = array.ofGuardedType(isNumber) // 2, 5 - using type guard filter

Old Browsers

Jinqu uses Array.from, Array.prototype.find, Iterators, Object.assign, Promises and Symbols. If you want to be able to use Jinqu with older browsers, you need to polyfill/shim these features.

Here are the polyfill packages used for testing:

  • array-from
  • array.prototype.find
  • es6-iterator
  • es6-object-assign
  • es6-promise
  • es6-symbol

And here is the integration code (test/shim.ts).

import find = require("array.prototype.find");
find.shim();

import ArrayIterator = require("es6-iterator/array");
import "es6-object-assign/auto";
import "es6-promise/auto";
import "es6-symbol/implement";
if (![][Symbol.iterator]) {
    Array.prototype[Symbol.iterator] = function() {
        return new ArrayIterator(this);
    };
}
import arrayFrom = require("array-from");
if (!Array.from) {
    Array.from = arrayFrom;
}

You can test compatibility on a Windows computer like this:

npm run karma

License

jinqu is licensed with the MIT License.