Skip to content

Modernize query filter syntax to object-based DSL#162

Merged
hotlong merged 7 commits intomainfrom
copilot/refactor-query-filters-syntax
Jan 22, 2026
Merged

Modernize query filter syntax to object-based DSL#162
hotlong merged 7 commits intomainfrom
copilot/refactor-query-filters-syntax

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 22, 2026

ObjectQL's filter syntax required comprehensive modernization from array-based to object-based DSL per @objectstack/spec FilterCondition.

Changes

Type System (@objectql/types)

  • Replace FilterExpression array type with FilterCondition object type from spec
  • Update UnifiedQuery.filters signature and all dependent API types

Core Translation (@objectql/core)

  • Implement translateFilters() converting FilterCondition → FilterNode arrays
  • Add recursive convertFilterToNode() handling nested logical operators
  • Map modern operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, $startsWith, $endsWith, $null, $exist
  • Support $and, $or logical composition
  • Maintain backward compatibility for legacy array syntax

Testing

  • 14 new tests covering operator combinations and edge cases
  • All 290 core tests passing

Documentation

  • Complete syntax reference with migration guide

Example

// Before
filters: [
  ['category', '=', 'Electronics'],
  'and',
  ['price', '>', 100]
]

// After
filters: {
  category: 'Electronics',
  price: { $gt: 100 }
}

// Complex queries
filters: {
  status: { $in: ['active', 'featured'] },
  price: { $gte: 100, $lte: 500 },
  $or: [
    { discount: { $gt: 0 } },
    { featured: true }
  ]
}

Architecture

Translation happens in core repository layer - drivers receive legacy FilterNode format unchanged. Zero driver modifications required.

Limitation: $not operator throws error (legacy format incompatible). Use $ne for field negation.

Security: CodeQL scan clean, type-safe implementation.

Original prompt

审视objectstack 最新的query filters语法规范,全面改造并不需要考虑向后兼容。


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel
Copy link
Copy Markdown

vercel bot commented Jan 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
objectql-site Ready Ready Preview, Comment Jan 22, 2026 11:56am

Request Review

- Replace FilterExpression array syntax with FilterCondition object syntax
- Update UnifiedQuery to use Filter (FilterCondition) type
- Implement filter translation from new object syntax to legacy array format
- Update all API types to use new Filter type
- Add operator mapping: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, etc.

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI and others added 4 commits January 22, 2026 11:47
- Detect when filters are already in legacy array format
- Pass through array filters without conversion
- All core tests passing (276 tests)

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Add 14 tests for new object-based filter syntax
- Test all operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin
- Test logical operators: $and, $or, nested combinations
- Test implicit equality and mixed syntax
- Test backward compatibility with legacy array syntax
- All 290 core tests passing

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Complete reference for new object-based filter syntax
- Migration guide from legacy array-based syntax
- Real-world examples for common use cases
- Operator reference table
- TypeScript support examples
- Best practices and performance considerations

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Remove incomplete $not operator implementation
- Throw clear error if $not is used
- Update documentation to reflect limitation
- Recommend using $ne for field-level negation instead
- All 290 tests still passing

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
- Fix multiple operators on same field (always AND them together)
- Remove $not from type documentation
- Clarify range operators use $gte/$lte not $between
- All 290 tests passing

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor objectstack query filters syntax Modernize query filter syntax to object-based DSL Jan 22, 2026
Copilot AI requested a review from hotlong January 22, 2026 12:00
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ No Changeset Found

This PR does not include a changeset file.
If this PR includes user-facing changes, please add a changeset by running:

pnpm changeset

@hotlong hotlong marked this pull request as ready for review January 22, 2026 12:07
Copilot AI review requested due to automatic review settings January 22, 2026 12:07
@hotlong hotlong merged commit d6048c9 into main Jan 22, 2026
8 checks passed
@hotlong hotlong deleted the copilot/refactor-query-filters-syntax branch January 22, 2026 12:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes ObjectQL's query filter syntax from array-based to object-based DSL, following the @objectstack/spec FilterCondition specification while maintaining backward compatibility.

Changes:

  • Type system updated to use FilterCondition from spec instead of array-based FilterExpression
  • Core translation layer converts modern object syntax to legacy FilterNode format for drivers
  • Comprehensive test suite added with 14 new tests covering operator combinations

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/foundation/types/src/query.ts Replaces FilterExpression with Filter (FilterCondition) type and adds comprehensive documentation
packages/foundation/types/src/api.ts Updates API interfaces to use new Filter type
packages/foundation/core/test/filter-syntax.test.ts Adds test coverage for modern filter syntax translation
packages/foundation/core/src/repository.ts Implements translateFilters() and convertFilterToNode() for syntax conversion
packages/drivers/sdk/src/index.ts Updates SDK to use Filter type
docs/filter-syntax.md Complete documentation of new syntax with migration guide

const [op, opValue] = entries[i];

// Add 'and' before each operator (except the very first node)
if (nodes.length > 0 || i > 0) {
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition nodes.length > 0 || i > 0 could be simplified. Since we're adding 'and' before each operator except the very first node, consider restructuring to check if this is not the first overall node. The current logic may add an extra 'and' operator when processing the first field operator if nodes already contains logical operators.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants