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
import { toMongoCriteria, FieldDescription, DataType } from 'nextpay-querystring';
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);
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);
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',
},
];
const queryString = "{status} == '''ACTIVE''' AND ({id} == 1 OR {title} LIKE '''admin''') AND ({priority} >= 3 OR {category} == '''VIP''')";
const mongoResult = toMongoCriteria(queryString, fieldDescriptions);
const mongoCriteria = JSON.parse(mongoResult);
console.log('MongoDB:', mongoCriteria);
const mysqlResult = toMySqlCriteria(queryString, fieldDescriptions);
console.log('MySQL:', mysqlResult);
📝 Quy tắc viết QueryString
Format cơ bản
{<tên-field>} <operator> <value>
Các loại giá trị
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
RANGE
- Between range
String Operators
like%
- Starts with
like
- Contains
%like
- Ends with
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 Grouping/Parentheses
const orGroup = "({id} == 1 OR {id} == 2)";
const andWithOr = "{status} == '''ACTIVE''' AND ({id} == 1 OR {title} LIKE '''tan''')";
const nestedGroups = "({status} == '''ACTIVE''' AND ({id} == 1 OR {id} == 2)) OR ({category} == '''VIP''')";
const multipleGroups = "({id} == 1 OR {id} == 2) AND ({status} == '''ACTIVE''' OR {status} == '''PENDING''')";
const groupWithIn = "({id} == 1 OR {id} == 2) AND {status} IN ['''ACTIVE''', '''PENDING''']";
const complexNested = "({status} == '''ACTIVE''' AND ({id} == 1 OR {id} == 2)) AND ({priority} >= 3 OR ({category} == '''VIP''' AND {isActive} == true))";
🔧 Data Types
enum DataType {
STRING,
INTEGER,
DOUBLE,
BOOLEAN,
DATE,
}
🛡️ 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
npm test
npm run test:watch
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;
readonly required: boolean;
readonly dataType: DataType;
readonly maxOccurrence: number;
readonly mapTo: string;
}
👨💻 Tác giả
🤝 Contributing
- Fork project
- Tạo feature branch (
git checkout -b feature/AmazingFeature
)
- Commit changes (
git commit -m 'Add some AmazingFeature'
)
- Push to branch (
git push origin feature/AmazingFeature
)
- 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.