npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

nextpay-querystring

v1.0.7

Published

Thư viện QueryString của NextPay - Chuyển đổi QueryString thành điều kiện select cho MongoDB và MySQL với kiểm soát bảo mật

Readme

nextpay-querystring

Thư viện QueryString của NextPay - Chuyển đổi QueryString thành điều kiện select cho MongoDB và MySQL với kiểm soát bảo mật và tránh SQL injection.

🚀 Tính năng

  • ✅ Chuyển đổi QueryString thành MongoDB criteria
  • ✅ Chuyển đổi QueryString thành MySQL WHERE clause
  • ✅ Hỗ trợ nhiều loại operator: ==, !=, >, >=, <, <=, IN, NIN, BETWEEN, LIKE
  • ✅ Validation field và data type
  • ✅ Bảo mật chống SQL injection
  • ✅ Hỗ trợ TypeScript
  • ✅ Lightweight và performant

📦 Cài đặt

npm install nextpay-querystring

🎯 Cách sử dụng

Import thư viện

// ✅ sử dụng cho mongodb
import { toMongoCriteria, FieldDescription, DataType } from 'nextpay-querystring';

// ✅ sử dụng cho Mysql
import { toMySqlCriteria, FieldDescription, DataType } from 'nextpay-querystring';

Khai báo Field Descriptions

const fieldDescriptions: FieldDescription[] = [
  {
    field: '_id',
    required: true,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: '_id',
  },
  {
    field: 'title',
    required: true,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: 'title',
  },
  {
    field: 'status',
    required: true,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: 'status',
  },
  {
    field: 'createdAt',
    required: true,
    dataType: DataType.DATE,
    maxOccurrence: 5,
    mapTo: 'createdAt',
  },
  {
    field: 'isActive',
    required: true,
    dataType: DataType.BOOLEAN,
    maxOccurrence: 5,
    mapTo: 'isActive',
  },
];

Sử dụng với MongoDB

const queryString = "{title} == '''MACQ''' AND {status} IN ['''OPEN''', '''ON-HOLD'''] AND {isActive} == true";

const mongoCriteria = toMongoCriteria(queryString, fieldDescriptions);
const whereCondition = JSON.parse(mongoCriteria);

// Kết quả: {title: "MACQ", status: {$in: ["OPEN", "ON-HOLD"]}, isActive: true}

const result = await collection.find(whereCondition);

Sử dụng với MySQL

const queryString = "{title} == '''MACQ''' AND {status} IN ['''OPEN''', '''ON-HOLD'''] AND {isActive} == true";

const mysqlCriteria = toMySqlCriteria(queryString, fieldDescriptions);

// Kết quả: title = 'MACQ' AND status IN ('OPEN', 'ON-HOLD') AND isActive = true

const result = await connection.query(`SELECT * FROM table WHERE ${mysqlCriteria}`);

Ví dụ hoàn chỉnh với Grouping

import { toMongoCriteria, toMySqlCriteria, FieldDescription, DataType } from 'nextpay-querystring';

const fieldDescriptions: FieldDescription[] = [
  {
    field: 'status',
    required: true,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: 'status',
  },
  {
    field: 'id',
    required: true,
    dataType: DataType.INTEGER,
    maxOccurrence: 5,
    mapTo: 'id',
  },
  {
    field: 'title',
    required: true,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: 'title',
  },
  {
    field: 'category',
    required: false,
    dataType: DataType.STRING,
    maxOccurrence: 5,
    mapTo: 'category',
  },
];

// Query với grouping
const queryString = "{status} == '''ACTIVE''' AND ({id} == 1 OR {title} LIKE '''admin''') AND ({priority} >= 3 OR {category} == '''VIP''')";

// MongoDB
const mongoResult = toMongoCriteria(queryString, fieldDescriptions);
const mongoCriteria = JSON.parse(mongoResult);
console.log('MongoDB:', mongoCriteria);
// Output: {
//   $and: [
//     { status: 'ACTIVE' },
//     { $or: [{ id: 1 }, { title: { $regex: 'admin', $options: 'i' } }] },
//     { $or: [{ priority: { $gte: 3 } }, { category: 'VIP' }] }
//   ]
// }

// MySQL
const mysqlResult = toMySqlCriteria(queryString, fieldDescriptions);
console.log('MySQL:', mysqlResult);
// Output: (status = "ACTIVE") AND ((id = 1) OR (title LIKE %"admin"%)) AND ((priority >= 3) OR (category = "VIP"))

📝 Quy tắc viết QueryString

Format cơ bản

{<tên-field>} <operator> <value>

Các loại giá trị

| Kiểu dữ liệu | Cú pháp | Ví dụ | |-------------|---------|-------| | String | '''value''' | {title} == '''MACQ''' | | Number | value | {id} == 1 | | Boolean | true/false | {isActive} == true | | Date | #value# | {createdAt} == #2025-01-15# |

Các operator được hỗ trợ

Comparison Operators

  • == - Equals
  • != - Not equals
  • === - Triple equals
  • > - Greater than
  • >= - Greater than or equal
  • < - Less than
  • <= - Less than or equal

Array Operators

  • IN - In array
  • NIN - Not in array
  • BETWEEN - Between range
  • NBETWEEN - Not between range

String Operators

  • like% - Starts with
  • like - Contains
  • %like - Ends with
  • nlike - Not contains
  • nlike% - Not starts with
  • %nlike - Not ends with

NULL Operators

  • is_null - Is null
  • is_not_null - Is not null

Logical Operators

  • AND - Logical AND
  • OR - Logical OR
  • NOT - Logical NOT

Ví dụ phức tạp

const complexQuery = `
  {title} == '''MACQ''' AND 
  {id} == 1 AND 
  {status} IN ['''OPEN''', '''ON-HOLD'''] AND 
  {isPrivate} == true AND 
  {dueDate} == #2025-08-25# AND
  {description} like '''important'''
`;

Ví dụ với Negative Operators

// String negative operators
const negativeStringQuery = `
  {title} nlike '''admin''' AND 
  {description} nlike% '''draft''' AND 
  {filename} %nlike '''.tmp'''
`;

// Range negative operator
const negativeRangeQuery = `
  {priority} nbetween [1, 5] AND 
  {createdAt} nbetween [#2024-01-01#, #2024-12-31#]
`;

// Complex negative query
const complexNegativeQuery = `
  {title} nlike '''admin''' AND 
  {status} nbetween ['''DELETED''', '''ARCHIVED'''] AND 
  ({priority} >= 3 OR {category} == '''VIP''')
`;

// NULL operators
const nullQuery = `
  {title} is_not_null AND 
  {description} is_null AND 
  {priority} >= 3
`;

// Complex query with NULL operators
const complexNullQuery = `
  ({title} is_null OR {description} is_not_null) AND 
  {status} == '''ACTIVE''' AND 
  {priority} is_not_null
`;

// BETWEEN operator examples
const betweenQuery = `
  {priority} between [1, 5] AND 
  {createdAt} between [#2024-01-01#, #2024-12-31#] AND 
  {status} between ['''ACTIVE''', '''PENDING''']
`;

Ví dụ với Grouping/Parentheses

// ✅ Simple OR group
const orGroup = "({id} == 1 OR {id} == 2)";

// ✅ AND với OR group
const andWithOr = "{status} == '''ACTIVE''' AND ({id} == 1 OR {title} LIKE '''tan''')";

// ✅ Nested groups
const nestedGroups = "({status} == '''ACTIVE''' AND ({id} == 1 OR {id} == 2)) OR ({category} == '''VIP''')";

// ✅ Multiple groups
const multipleGroups = "({id} == 1 OR {id} == 2) AND ({status} == '''ACTIVE''' OR {status} == '''PENDING''')";

// ✅ Group với IN operator
const groupWithIn = "({id} == 1 OR {id} == 2) AND {status} IN ['''ACTIVE''', '''PENDING''']";

// ✅ Complex nested groups
const complexNested = "({status} == '''ACTIVE''' AND ({id} == 1 OR {id} == 2)) AND ({priority} >= 3 OR ({category} == '''VIP''' AND {isActive} == true))";

🔧 Data Types

enum DataType {
  STRING,    // String values
  INTEGER,   // Integer numbers
  DOUBLE,    // Decimal numbers
  BOOLEAN,   // true/false
  DATE,      // Date values
}

🛡️ Bảo mật

  • Field Validation: Chỉ cho phép sử dụng các field đã được khai báo
  • Data Type Validation: Kiểm tra kiểu dữ liệu phù hợp
  • SQL Injection Prevention: Escape và validate tất cả input
  • Occurrence Limit: Giới hạn số lần xuất hiện của mỗi field

🧪 Testing

# Chạy tests
npm test

# Chạy tests với watch mode
npm run test:watch

# Chạy tests với coverage
npm test -- --coverage

📦 Exports

Functions

  • toMongoCriteria(queryString: string, fieldDescriptions: FieldDescription[]): string - Chuyển đổi QueryString thành MongoDB criteria
  • toMySqlCriteria(queryString: string, fieldDescriptions: FieldDescription[]): string - Chuyển đổi QueryString thành MySQL WHERE clause

Types & Interfaces

  • FieldDescription - Interface cho field description
  • FieldDescriptionContainer - Class container cho field descriptions
  • DataType - Enum cho các kiểu dữ liệu (STRING, INTEGER, DOUBLE, BOOLEAN, DATE)

Backward Compatibility

  • FieldDescriptionType - Alias cho FieldDescription

📚 API Reference

toMongoCriteria(queryString: string, fieldDescriptions: FieldDescription[]): string

Chuyển đổi QueryString thành MongoDB criteria dạng JSON string.

toMySqlCriteria(queryString: string, fieldDescriptions: FieldDescription[]): string

Chuyển đổi QueryString thành MySQL WHERE clause.

FieldDescription

interface FieldDescription {
  readonly field: string;        // Tên field trong QueryString
  readonly required: boolean;    // Field có bắt buộc không
  readonly dataType: DataType;   // Kiểu dữ liệu
  readonly maxOccurrence: number; // Số lần xuất hiện tối đa
  readonly mapTo: string;        // Tên field trong database
}

👨‍💻 Tác giả

🤝 Contributing

  1. Fork project
  2. Tạo feature branch (git checkout -b feature/AmazingFeature)
  3. Commit changes (git commit -m 'Add some AmazingFeature')
  4. Push to branch (git push origin feature/AmazingFeature)
  5. Tạo Pull Request

📄 License

MIT License - xem file LICENSE để biết thêm chi tiết.

🆘 Support

Nếu gặp vấn đề, vui lòng tạo issue tại GitHub Issues.