inqjs
v2.0.0
Published
A lightweight, dependency-free LINQ engine for TypeScript and JavaScript with comprehensive query capabilities
Maintainers
Readme
inqjs (Integrated Query for JavaScript)
A lightweight, dependency-free LINQ engine for TypeScript and JavaScript with comprehensive query capabilities.
Note: This project was developed with heavy assistance from AI (Google Gemini), demonstrating modern AI-powered software development workflows.
Features
✨ Comprehensive LINQ Operations
- Filtering:
where,distinct - Projection:
select,selectMany - Ordering:
orderBy,thenBy - Partitioning:
skip,take - Aggregation:
sum,min,max,count - Quantifiers:
any,all - Element:
first - Set Operations:
union,intersect,except - Sequence:
append,prepend,concat - Grouping & Joining:
groupBy,join
🚀 Lazy Evaluation
- Operators are lazily evaluated using generators
- Only materializes when calling terminal operators like
toArray()
⚡ Async Support
- Full async/await support with
AsyncQuery - Works with
Iterable<T>andAsyncIterable<T>
📦 JSON Querying
- Query JSON data directly with
fromJson,fromJsonArray,fromJsonObject
🔒 Type Safe
- Written in TypeScript with
strict: true - Full type inference and safety
🎯 Zero Dependencies
- No external runtime dependencies
- Works with any
Iterable<T>(Arrays, Sets, Maps, Generators)
Installation
npm install inqjsImports
import { from, fromAsync, fromJsonArray } from 'inqjs';
import { fromAsync as fromAsyncOnly } from 'inqjs/async';
import { fromJson } from 'inqjs/json';CommonJS is supported too:
const { from, fromAsync } = require('inqjs');Quick Start
Basic Query (Sync)
import { from } from 'inqjs';
const numbers = [1, 2, 3, 4, 5, 6];
const result = from(numbers)
.where(x => x % 2 === 0)
.select(x => x * x)
.orderBy()
.toArray();
console.log(result); // [4, 16, 36]Async Query
import { fromAsync } from 'inqjs';
async function* asyncNumbers() {
yield 1; yield 2; yield 3;
}
const result = await fromAsync(asyncNumbers())
.where(async x => x > 1)
.select(async x => x * 2)
.toArray();
console.log(result); // [4, 6]JSON Querying
import { fromJsonArray } from 'inqjs';
const json = '[{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]';
const adults = fromJsonArray(json)
.where(user => user.age >= 18)
.select(user => user.name)
.toArray();
console.log(adults); // ['Alice', 'Bob']Set Operations
import { from } from 'inqjs';
const list1 = [1, 2, 3, 4];
const list2 = [3, 4, 5, 6];
// Union
from(list1).union(list2).toArray();
// => [1, 2, 3, 4, 5, 6]
// Intersect
from(list1).intersect(list2).toArray();
// => [3, 4]
// Except
from(list1).except(list2).toArray();
// => [1, 2]API Reference
Query Creation
from(iterable)- Create query from any iterablefromAsync(iterableOrAsyncIterable)- Create async queryfromJson(jsonString)- Parse and query JSONfromJsonArray(jsonString)- Parse JSON arrayfromJsonObject(jsonString)- Parse JSON object
Filtering & Projection
where(predicate)- Filter elementsselect(selector)- Transform elementsselectMany(collectionSelector, resultSelector?)- Project and flatten nested sequencesdistinct(keySelector?)- Remove duplicates
Ordering & Partitioning
orderBy(keySelector?, comparer?)- Sort elementsthenBy(keySelector?, comparer?)- Add a secondary sort afterorderByskip(count)- Skip first N elementstake(count)- Take first N elements
Grouping & Joining
groupBy(keySelector, elementSelector?)- Group elements by keyjoin(inner, outerKeySelector, innerKeySelector, resultSelector)- Inner join two sequences by matching keys
Aggregation
sum(selector?)- Sum numeric valuesmin(selector?)- Find minimummax(selector?)- Find maximumcount(predicate?)- Count elements
Quantifiers
any(predicate?)- Check if any matchall(predicate)- Check if all match
Element Access
first(predicate?)- Get first element
Set Operations
union(other, keySelector?)- Set unionintersect(other, keySelector?)- Set intersectionexcept(other, keySelector?)- Set difference
Sequence Operations
append(element)- Add element to endprepend(element)- Add element to startconcat(other)- Concatenate sequences
Terminal Operations
toArray()- Materialize to arraytoAsync()- Convert to async query
Testing
# Build, run TypeScript tests, and run JavaScript smoke tests
npm test
# Run just the JavaScript smoke tests
npm run test:jsTest Coverage: TypeScript unit/package smoke tests plus pure JavaScript consumer smoke tests.
Examples
See the examples/ directory for more usage examples:
examples/usage.ts- Basic LINQ operationsexamples/json-usage.ts- JSON querying examples
Architecture
- Lazy Evaluation: Uses generator functions for deferred execution
- Immutable: Each operation returns a new
Queryinstance - Type Safe: Full TypeScript support with strict mode
- Modular: Operators are separate modules in
src/operators/
Limitations
orderBymaterializes the sequence (requires full iteration to sort)- Set operations (
union,intersect,except) store keys in memory;intersectandexceptread the second sequence before yielding results - Equality uses JavaScript
Setsemantics on each value or selected key; object values compare by reference unless you provide akeySelector - Generator-backed queries keep the source's natural behavior, so a one-shot generator can only be consumed once
groupByandjoinmaterialize lookup data before yielding results
Development
This project was developed using AI-assisted coding with Google Gemini, showcasing:
- Rapid prototyping and iteration
- Comprehensive test coverage generation
- Documentation and example creation
- Code refactoring and optimization
The AI helped with:
- Initial architecture design
- Operator implementations (sync and async)
- Test suite creation and organization
- JSON querying capabilities
- Set operations implementation
- Documentation and examples
License
MIT
Contributing
Contributions are welcome! This project demonstrates how AI can accelerate development while maintaining code quality through comprehensive testing.
