cirquery
v0.2.2
Published
Core Common/Intermediate Representation for transforming human-friendly query DSLs to backend adapters.
Downloads
28
Maintainers
Readme
cirquery
Read this in other languages: 日本語
cirquery (Canonical Intermediate Representation Query) is a TypeScript library that provides a human-friendly query DSL for filtering JSON data, with a common intermediate representation (CIR) that can be adapted to multiple backends.
🔬 JSON Playground
Try cirquery instantly in your browser—no installation required.
Drag and drop your JSON files and execute queries in real-time.
✨ Features
- Human-Readable Query Language: Write intuitive search queries with natural syntax
- Common Intermediate Representation (CIR): Normalize queries into a backend-agnostic format for reusability
- Type-Safe: Fully typed TypeScript implementation
- Extensible: Easily add custom adapters or field search capabilities
- Multi-Language Support: Built-in accent folding and case normalization
🚀 Installation
From npm
npm install cirquery- npm package: cirquery@npm
For local development and testing, see the 🛠️ Development section below.
📖 Quick Start
Query Syntax Examples
cirquery uses an intuitive DSL (Domain-Specific Language) to query JSON data. Here are common patterns:
Basic Logical Operations
Supports equality (=), inequality (!=), numeric comparisons (<, >, <=, >=), and logical operators (AND, OR).
category = "drink" AND price < 10is_alcoholic = true OR contains_citrus = true
Text Search
Use colon (:) as shorthand for contains:
name:"Tonic"
Use function syntax for prefix/suffix matching:
startsWith(name, "Gin")endsWith(garnish, "peel")
Array Quantifiers
Query array elements with any (at least one element matches) or all (all elements match):
any(ingredients, name = "rum")
all(ingredients, type = "spirit")
Access nested properties with dot notation:
ingredients.name:"gin"
Negation and Grouping
Use NOT for negation and parentheses () for precedence:
NOT (year >= 2000)is_alcoholic = false OR (type = "spirit" AND NOT is_carbonated = true)
JavaScript/TypeScript Usage
import { parse, normalize, buildPredicate } from 'cirquery';
// Parse DSL and normalize to CIR
const { ast } = parse('category = "cocktail" AND price < 15');
const cir = normalize(ast);
// Generate predicate function from CIR
const predicate = buildPredicate(cir);
// Filter data
const data = [
{ category: 'cocktail', price: 12, name: 'Mojito' },
{ category: 'wine', price: 20, name: 'Chardonnay' }
];
const results = data.filter(predicate);
console.log(results); // [{ category: 'cocktail', price: 12, name: 'Mojito' }]CLI Usage
# Launch REPL
npx cirquery
# Query from stdin
echo '{"name":"test","category":"drink"}' | npx cirquery 'category = "drink"'📚 Documentation
- DSL Syntax Reference - Detailed query language syntax
- CIR Specification - Intermediate representation types
- Normalization Design - DSL to CIR conversion rules
- Examples - Practical query examples
🛠️ Development
Prerequisites
- Node.js 22+
- npm or pnpm
Setup
git clone https://github.com/cirquery/cirquery.git
cd cirquery
npm install
npm run build
npm testLocal Development Methods
For contributors who want to test locally or develop new features:
Method A: npm link (Recommended)
Create link in repository root:
npm ci npm run build npm linkLink from your project:
npm link cirqueryImport as usual:
import 'cirquery';
Unlink:
npm unlink cirquery && npm unlink --global cirqueryMethod B: Relative Install (Simple)
npm install /absolute/path/to/cirqueryNote: This includes all source files. For production-like testing, use Method A.
Method C: Pack and Install (Production-like)
Generate tarball:
npm run build npm packInstall in your project:
npm install /path/to/cirquery-0.2.1.tgz
Directory Structure
├── src/ # Source code
│ ├── parser/ # DSL parser
│ ├── cir/ # CIR normalization & evaluation
│ ├── cli/ # CLI tool
│ └── adapters/ # Backend adapters
├── test/ # Tests
├── docs/ # Documentation
├── examples/ # Sample data & queries
└── scripts/ # Development scriptsScripts
npm run build- Build TypeScript (ESM/CJS)npm test- Run testsnpm run typecheck- Type checkingnpm run lint- Run ESLintnpm run format- Format with Prettier
🔧 Architecture
[DSL] → [Parser] → [AST] → [Normalize] → [CIR] → [Evaluator/Adapters]- DSL: Human-friendly query language
- Parser: Parse DSL into Abstract Syntax Tree (AST)
- Normalize: Transform AST into Common Intermediate Representation (CIR)
- Evaluator/Adapters: Execute CIR (JavaScript evaluation, DB conversion, etc.)
🎯 Roadmap
v0.1 (Completed)
- [x] Basic DSL syntax (logical operations, comparisons, text search, quantifiers)
- [x] CIR normalization (De Morgan's laws, NOT optimization)
- [x] JavaScript evaluator
- [x] Accent folding & case normalization
v0.2 (Current)
- [x] Multi-level array path shorthand support
v0.3 (Planned)
- [ ] Explicit OR/AND in ValueList
- [ ] Full-field search (ANYFIELD)
- [ ] Additional backend adapters (MongoDB, SQLite)
🤝 Contributing
Bug reports, feature requests, and pull requests are welcome!
- Fork this repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
See CONTRIBUTING.md for details.
📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
- Chevrotain - Parser generator
- Vitest - Test framework
- tsup - TypeScript bundler
