Thank you for your interest in contributing to QueryKit! This document provides guidelines and instructions for contributing to the project.
Please read and follow our Code of Conduct to maintain a respectful and inclusive environment for everyone.
- Fork the repository and clone it locally
- Install dependencies with
npm install - Create a branch for your contribution
- Make your changes
- Run tests to ensure everything works
- Submit a pull request
QueryKit is organized into several key components:
-
Parser (
src/parser): Core query parsing engine that converts DSL expressions into structured internal format (AST)- Lexical analyzer
- Syntax parser
- AST type definitions
- Validation logic
- Integrates with Liqe for Lucene-like query parsing
-
Translators (
src/translators): Convert parsed queries into target-specific formats- SQL translator (for Drizzle)
- JavaScript translator (for in-memory filtering)
- Each translator implements the standard translator interface
-
Adapters (
src/adapters): Connect QueryKit to external systems- Drizzle ORM adapter
- In-memory filtering adapter
- Each adapter implements the standard adapter interface
-
CLI (
src/cli): Command-line interface for testing and debugging- Query parsing/testing tools
- Query translation debugging
- Code generation utilities
-
Frontend Utilities (
src/frontend): Browser-specific implementations- Query builder components
- Client-side filtering utilities
- Browser-optimized parsing
-
Server Helpers (
src/server): Server-side integration utilities- Middleware for Express/Fastify
- Request parsing helpers
- Database integration utilities
-
Common (
src/common): Shared utilities and types
When contributing to QueryKit, you should be familiar with these key dependencies:
-
Liqe: A Lucene-like parser that we use for parsing the query syntax. Rather than implementing our own parser from scratch, we'll leverage Liqe's capabilities to parse queries into an abstract syntax tree (AST) that our translators can then work with.
-
Drizzle ORM: The TypeScript ORM we integrate with for SQL database operations. Contributions to the Drizzle adapter should be familiar with how Drizzle ORM works.
- Choose an issue from the issue tracker or propose a new feature
- Discuss major changes in issues before implementation
- Follow coding standards as outlined below
- Write tests for your changes
- Update documentation if necessary
- Submit a PR with a clear description of changes
- Use English for all code and documentation
- Always declare explicit types
- Document public APIs with JSDoc
- One export per file when possible
- Follow SOLID principles
PascalCasefor classes, interfaces, type aliases, and enumscamelCasefor variables, functions, methods, and propertieskebab-casefor file names and directory namesUPPERCASEfor constants and environment variablesIprefix for interfaces (e.g.,ITranslator)
- Keep functions short (< 20 instructions)
- Follow single responsibility principle
- Use early returns to avoid nesting
- Prefer higher-order functions
- Use default parameters instead of null checks
- Co-locate tests with source files
- Use descriptive test file names:
[feature].test.tsor[feature].spec.ts - Group related tests in describe blocks
- Use clear test case descriptions
- Public APIs: 100% coverage
- Internal implementation: 80% coverage
- Test both success and failure cases
- Include edge cases
- Ensure all tests pass
- Update documentation if needed
- Link related issues
- Wait for code review
- Address feedback and requested changes
- Once approved, a maintainer will merge your PR
When working on query language features, follow these principles:
- Syntax should be readable and intuitive (OData/Lucene-inspired)
- Support basic comparison operators:
==,!=,>,>=,<,<= - Support logical operators:
&&,||,! - Support complex operations: string matching, array operations, nested property access
- Ensure consistent behavior across environments
- Prioritize type safety
- Design for extensibility
For the query parsing capabilities of QueryKit, we're using Liqe as our foundation. When working with this aspect of the codebase:
- Learn the Liqe API and AST structure before making changes
- When extending the parser, ensure compatibility with Liqe's existing functionality
- Write comprehensive tests for any modifications to the parsing logic
- Consider the performance implications of your changes, as parsing is a critical path
- Document any extensions or modifications to the standard Liqe syntax
Example of using Liqe in QueryKit:
import { parse, filter } from 'liqe';
// Parse a query string into an AST
const ast = parse('title:"Meeting notes" AND priority:>2');
// Use the AST with our translator or directly with Liqe's filter
const results = filter(ast, dataCollection);We're currently focusing on:
- Implementing Lucene-style query syntax parser using Liqe
- Creating an internal AST representation
- Developing a type-safe query building API
- Adding comprehensive validation
- Drizzle ORM integration
- In-memory JavaScript filtering
- Error handling and validation
- CLI tools for testing and debugging queries
- Performance optimizations for large queries
- Support for complex operators and functions
- Query composition utilities
- Frontend query builder components
- Additional ORM adapters
- Server middleware for Express/Fastify
- Documentation and examples
By contributing to QueryKit, you agree that your contributions will be licensed under the same MIT License that covers the project.