SkillAgentSearch skills...

FlexQL

FlexQL – A powerful, secure, and extensible query language for flexible data filtering without complex SQL or ORM queries.

Install / Use

/learn @schart/FlexQL
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🧩 FlexQL

A lightweight query language engine for building filters without writing complex SQL or ORM queries.

<p align="center"> <img src="docs/Flexql-architecture.png" width="650"/> </p>

🚀 Overview

FlexQL lets you write readable and compact queries, which are parsed and converted into database-specific formats like SQL or Sequelize. Instead of manually building queries, you can write:

username==heja;age>18,status==active

Which means:

(username == "heja" AND age > 18) OR (status == "active")

⚠️ Note: Do not use spaces in the query string as separators. Use ; for AND and , for OR.


✨ Features

  • 🧠 Readable syntax — intuitive query format
  • 🔀 Flexible separators; = AND, , = OR
  • 🔒 Safe — parameterized output to prevent SQL injection
  • 🛡️ Column protection — restrict or block access to sensitive columns
  • ⚙️ Adapter-based — SQL, Sequelize, MongoDB (coming), Elasticsearch (coming)
  • 🧱 Lexer → Parser → Adapter — modular and extensible
  • 🧪 Type-validated — automatically checks numbers, strings, booleans
  • 🧰 Easy to extend — add new adapters or operators quickly

⚙️ How FlexQL Works

Query String
     ↓
  Lexer → tokens
     ↓
  Parser → AST (Abstract Syntax Tree)
     ↓
  Adapter → SQL / Sequelize / MongoDB

🌳 AST Example

Query

username==heja;age>18,status==active

Generated AST (simplified)

{
  "type": "OR",
  "children": [
    {
      "type": "AND",
      "children": [
        { "field": "username", "operator": "==", "value": "heja" },
        { "field": "age", "operator": ">", "value": 18 }
      ]
    },
    { "field": "status", "operator": "==", "value": "active" }
  ]
}

FlexQL builds a structured query, not just parses a string.


🧱 Adapter Outputs

🔹 SQL Adapter

Basic filter — single AND chain

username==heja;age>18;country==NL
{
  type: 'sql',
  payload: {
    conditions: 'WHERE username = ? AND age > ? AND country = ?',
    values: ['heja', 18, 'NL']
  }
}

Usage:

import { FlexQL } from "flexql";
import db from "./db"; // your database connection

const result = FlexQL.parse('username==heja;age>18;country==NL', {
  adapter: "sql",
});

const rows = await db.query(
  `SELECT * FROM users ${result.payload.conditions}`,
  result.payload.values,
);

Mixed AND/OR — user search with fallback

username==heja;age>18,status==active
{
  type: 'sql',
  payload: {
    conditions: 'WHERE username = ? AND age > ? OR status = ?',
    values: ['heja', 18, 'active']
  }
}

Usage:

const result = FlexQL.parse('username==heja;age>18,status==active', {
  adapter: "sql",
});

const users = await db.query(
  `SELECT * FROM users ${result.payload.conditions}`,
  result.payload.values,
);

Date range filter

created_at>=2025-01-01;created_at<=2025-12-31;active==true
{
  type: 'sql',
  payload: {
    conditions: 'WHERE created_at >= ? AND created_at <= ? AND active = ?',
    values: ['2025-01-01', '2025-12-31', true]
  }
}

Usage:

const result = FlexQL.parse(
  'created_at>=2025-01-01;created_at<=2025-12-31;active==true',
  { adapter: "sql" },
);

const logs = await db.query(
  `SELECT * FROM audit_logs ${result.payload.conditions} ORDER BY created_at DESC`,
  result.payload.values,
);

Safe and parameterized — values are never interpolated into the query string.


🔹 Sequelize Adapter

Multi-country OR filter

username==heja,country==NL;score>90,rank>=5;active==true,verified==true
{
  type: 'sequelize',
  payload: {
    conditions: {
      [Op.and]: [
        {
          [Op.or]: [
            { username: 'heja' },
            { country: 'NL' }
          ]
        },
        {
          [Op.or]: [
            { score: { [Op.gt]: 90 } },
            { rank: { [Op.gte]: 5 } }
          ]
        },
        {
          [Op.or]: [
            { active: true },
            { verified: true }
          ]
        }
      ]
    }
  }
}

Usage:

import { FlexQL } from "flexql";
import { User } from "./models";

const result = FlexQL.parse(
  'username==heja,country==NL;score>90,rank>=5;active==true,verified==true',
  { adapter: "sequelize" },
);

const users = await User.findAll({
  where: result.payload.conditions,
});

Admin dashboard — dynamic filter from query params

role==admin,role==moderator;banned==false;last_login>=2025-06-01
{
  type: 'sequelize',
  payload: {
    conditions: {
      [Op.and]: [
        {
          [Op.or]: [
            { role: 'admin' },
            { role: 'moderator' }
          ]
        },
        { banned: false },
        { last_login: { [Op.gte]: '2025-06-01' } }
      ]
    }
  }
}

Usage:

// req.query.filter = 'role==admin,role==moderator;banned==false;last_login>=2025-06-01'
const result = FlexQL.parse(req.query.filter, { adapter: "sequelize" });

const admins = await User.findAll({
  where: result.payload.conditions,
  order: [["last_login", "DESC"]],
});

Paginated product listing

category==electronics;price>=100;price<=999;in_stock==true
{
  type: 'sequelize',
  payload: {
    conditions: {
      [Op.and]: [
        { category: 'electronics' },
        { price: { [Op.gte]: 100 } },
        { price: { [Op.lte]: 999 } },
        { in_stock: true }
      ]
    }
  }
}

Usage:

const result = FlexQL.parse(
  'category==electronics;price>=100;price<=999;in_stock==true',
  { adapter: "sequelize" },
);

const products = await Product.findAndCountAll({
  where: result.payload.conditions,
  limit: 20,
  offset: page * 20,
});

🛡️ Column Protection

FlexQL lets you restrict which columns can be queried and which operators are allowed per column. This is useful for preventing access to sensitive fields and enforcing query rules on the server side.

Options

| Option | Type | Description | | --------- | --------------------------------- | ------------------------------------------------ | | exclude | string[] | Columns that cannot be queried at all | | rules | { [column: string]: Operator[] } | Allowed operators per column |

Exclude — block sensitive columns

Prevent querying sensitive columns like password, token, or secret:

const result = FlexQL.parse('username==heja;password==1234', {
  adapter: "sql",
  columnProtect: {
    exclude: ["password", "token"],
  },
});
// ❌ Throws: "Access to protected column is not allowed."

Rules — restrict operators per column

Allow only specific operators for a column. For example, email should only support exact match, while age should only support comparison operators:

const result = FlexQL.parse('age>=30;username==heja', {
  adapter: "sql",
  columnProtect: {
    rules: {
      age: [">", "<", "<=", ">="],
      email: ["=="],
    },
  },
});

If a disallowed operator is used:

FlexQL.parse('email>a', {
  adapter: "sql",
  columnProtect: {
    rules: {
      email: ["=="],
    },
  },
});
// ❌ Throws: "Operator '>' is not allowed for column 'email'. Allowed: =="

Combining exclude and rules

const flexQl = new FlexQL();

const result = flexQl.parse(
  'age>=30;username==heja,username==admin,country==NL;score>80,rank>=10;active==true,verified==true',
  {
    separators: { and: ";", or: "," },
    adapter: "sql",
    columnProtect: {
      exclude: ["password"],
      rules: {
        age: [">", "<", "<=", ">="],
      },
    },
  },
);

Supported Operators

| Operator | Description | | -------- | --------------------- | | == | Equal | | != | Not equal | | > | Greater than | | < | Less than | | >= | Greater than or equal | | <= | Less than or equal |


🔤 Syntax Reference

| Element | Description | Examples | | -------------- | ------------------ | -------------------------------- | | Identifier | Column / field | username, age | | Operator | Comparison | ==, !=, >, <, >=, <= | | Logic | Combine conditions | ; = AND, , = OR | | Value | Match value | heja, 18, true |


🧩 Example Queries

Basic

username==test;age>10
username==test,status==false

Medium

age>=18;(country==TR,country==DE);premium_user==true
score>50,rank>=3;active==true,verified==true

Complex

username==heja,country==NL;score>90,rank>=5;active==true,verified==true;created_at>=2025-01-01;updated_at<=2025-10-01,last_login>=2025-09-01

📦 Installation & Usage

🚧 Coming Soon — FlexQL will be available on npm shortly. Stay tuned!

npm install flexql
import { FlexQL } from "flexql";
const query = 'username==heja;age>18;country==NL';
const result = FlexQL.parse(query, { adapter: "sequelize" });
console.log(result.payload.conditions);

💡 Why FlexQL?

  • Readable and compact queries
  • 🧱 Works across multiple databases
  • 🧠 Logical precedence support — AND > OR
  • 🔒 Safe parameterized output
  • 🛡️ Column-level access control — exclude or restrict operators per column
  • 🌍 Portable architecture via adapters
  • 🧩 Modular & extensible

🧑‍💻 Use Cases

  • Admin dashboards with dynamic filters
  • API query parameter parsing
  • ORM-independent rule engines
  • Safe filtering for user input
  • Multi-tenant apps with column-level access control

🧭 Roadmap

  • [x] SQL adapter
  • [x] Sequelize adapter
  • [x] Column protection (exclude + operator rules)
  • [ ] MongoDB adapter
  • [ ] Elasticse
View on GitHub
GitHub Stars30
CategoryData
Updated10d ago
Forks1

Languages

TypeScript

Security Score

95/100

Audited on Mar 21, 2026

No findings