Jinqu - LINQ for Javascript
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.
We need to call asQueryable to create a query for an Array.
for 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
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:
for of query console.log n // outputs 2,4
We can chain query operators:
.wheren % 2 == 0 .orderByDescending n .toArrayfor 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:
- Jinqu-OData - Query OData endpoints
- Linquest - Query Remote LINQ endpoints
Remote queries always return promises so are awaited. So rather than toArray
to obtain the results of the query, you'll call toArrayAsync
:
...for 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:
.asQueryable.reverse.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 typesofGuardedType
takes a: * Typescript type guard (See Typescript Advanced Types) to filter values by a condition indicative of type
Their usage is as follows:
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).
;find.shim; ;;;;if ! ;if !Array.from
You can test compatibility on a Windows computer like this:
npm run karma
License
jinqu is licensed with the MIT License.