nextpay-querystring
Version:
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
322 lines (249 loc) • 8.59 kB
Markdown
# 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
```bash
npm install nextpay-querystring
```
## 🎯 Cách sử dụng
### Import thư viện
```typescript
// ✅ 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
```typescript
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
```typescript
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
```typescript
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
```typescript
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
- `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
```typescript
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
```typescript
// ✅ 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
```typescript
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
```bash
# 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`
```typescript
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ả
- Username: Mvtcode - Tanmv - MacTan
- Email: tanmv@mpos.vn
## 🤝 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](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](https://github.com/mvtcode/nextpay-querystring/issues).