@forestadmin-experimental/datasource-cosmos 1.6.2 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collection.d.ts +5 -0
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +52 -16
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/model-builder/model.d.ts +34 -11
- package/dist/model-builder/model.d.ts.map +1 -1
- package/dist/model-builder/model.js +145 -85
- package/dist/utils/aggregation-converter.d.ts +6 -0
- package/dist/utils/aggregation-converter.d.ts.map +1 -1
- package/dist/utils/aggregation-converter.js +21 -7
- package/dist/utils/pagination-cache.d.ts +116 -0
- package/dist/utils/pagination-cache.d.ts.map +1 -0
- package/dist/utils/pagination-cache.js +157 -0
- package/dist/utils/partition-key-extractor.d.ts +19 -0
- package/dist/utils/partition-key-extractor.d.ts.map +1 -0
- package/dist/utils/partition-key-extractor.js +61 -0
- package/dist/utils/query-converter.d.ts +20 -0
- package/dist/utils/query-converter.d.ts.map +1 -1
- package/dist/utils/query-converter.js +19 -2
- package/dist/utils/query-validation-error.d.ts +21 -0
- package/dist/utils/query-validation-error.d.ts.map +1 -0
- package/dist/utils/query-validation-error.js +29 -0
- package/dist/utils/query-validator.d.ts +66 -0
- package/dist/utils/query-validator.d.ts.map +1 -0
- package/dist/utils/query-validator.js +218 -0
- package/dist/utils/retry-handler.d.ts +101 -0
- package/dist/utils/retry-handler.d.ts.map +1 -0
- package/dist/utils/retry-handler.js +210 -0
- package/package.json +1 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const crypto_1 = require("crypto");
|
|
4
|
+
/**
|
|
5
|
+
* Cache for storing Cosmos DB continuation tokens to enable efficient cursor-based pagination
|
|
6
|
+
*
|
|
7
|
+
* This cache stores continuation tokens indexed by query hash and offset, allowing
|
|
8
|
+
* the system to resume pagination from the nearest cached position rather than
|
|
9
|
+
* fetching all items from the beginning.
|
|
10
|
+
*
|
|
11
|
+
* Example:
|
|
12
|
+
* - User requests offset=1000, limit=10
|
|
13
|
+
* - Cache has token for offset=900
|
|
14
|
+
* - System resumes from offset=900 and skips only 100 items instead of 1000
|
|
15
|
+
*/
|
|
16
|
+
class PaginationCache {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.cache = new Map();
|
|
19
|
+
this.options = {
|
|
20
|
+
maxEntriesPerQuery: options.maxEntriesPerQuery ?? 100,
|
|
21
|
+
ttlMs: options.ttlMs ?? 300000, // 5 minutes default
|
|
22
|
+
maxOffset: options.maxOffset ?? 100000,
|
|
23
|
+
cacheInterval: options.cacheInterval ?? 1000,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the maximum allowed offset
|
|
28
|
+
*/
|
|
29
|
+
getMaxOffset() {
|
|
30
|
+
return this.options.maxOffset;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the cache interval (how often to store continuation tokens)
|
|
34
|
+
*/
|
|
35
|
+
getCacheInterval() {
|
|
36
|
+
return this.options.cacheInterval;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Generate a unique hash for a query to use as cache key
|
|
40
|
+
* @param queryString The SQL query string
|
|
41
|
+
* @param parameters Query parameters
|
|
42
|
+
* @param partitionKey Optional partition key
|
|
43
|
+
*/
|
|
44
|
+
generateQueryHash(queryString, parameters, partitionKey) {
|
|
45
|
+
const hashInput = JSON.stringify({
|
|
46
|
+
query: queryString,
|
|
47
|
+
parameters: parameters || [],
|
|
48
|
+
partitionKey,
|
|
49
|
+
});
|
|
50
|
+
return (0, crypto_1.createHash)('sha256').update(hashInput).digest('hex').substring(0, 16);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Find the best cached continuation token for a given offset
|
|
54
|
+
* Returns the token with the highest offset that is still <= requested offset
|
|
55
|
+
*
|
|
56
|
+
* @param queryHash The query hash
|
|
57
|
+
* @param targetOffset The target offset to reach
|
|
58
|
+
* @returns The best matching cache entry, or null if none found
|
|
59
|
+
*/
|
|
60
|
+
findBestToken(queryHash, targetOffset) {
|
|
61
|
+
const entries = this.cache.get(queryHash);
|
|
62
|
+
if (!entries || entries.length === 0) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
// Clean expired entries first
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const validEntries = entries.filter(e => now - e.createdAt < this.options.ttlMs);
|
|
68
|
+
if (validEntries.length !== entries.length) {
|
|
69
|
+
// Update cache with only valid entries
|
|
70
|
+
if (validEntries.length > 0) {
|
|
71
|
+
this.cache.set(queryHash, validEntries);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.cache.delete(queryHash);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Find the entry with the highest offset that is <= targetOffset
|
|
79
|
+
let bestEntry = null;
|
|
80
|
+
for (const entry of validEntries) {
|
|
81
|
+
if (entry.offset <= targetOffset) {
|
|
82
|
+
if (!bestEntry || entry.offset > bestEntry.offset) {
|
|
83
|
+
bestEntry = entry;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return bestEntry;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Store a continuation token for a specific offset
|
|
91
|
+
*
|
|
92
|
+
* @param queryHash The query hash
|
|
93
|
+
* @param offset The offset this token represents
|
|
94
|
+
* @param continuationToken The Cosmos DB continuation token
|
|
95
|
+
*/
|
|
96
|
+
storeToken(queryHash, offset, continuationToken) {
|
|
97
|
+
let entries = this.cache.get(queryHash);
|
|
98
|
+
if (!entries) {
|
|
99
|
+
entries = [];
|
|
100
|
+
this.cache.set(queryHash, entries);
|
|
101
|
+
}
|
|
102
|
+
// Check if we already have an entry for this offset
|
|
103
|
+
const existingIndex = entries.findIndex(e => e.offset === offset);
|
|
104
|
+
if (existingIndex >= 0) {
|
|
105
|
+
// Update existing entry
|
|
106
|
+
entries[existingIndex] = {
|
|
107
|
+
continuationToken,
|
|
108
|
+
offset,
|
|
109
|
+
createdAt: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Add new entry
|
|
114
|
+
entries.push({
|
|
115
|
+
continuationToken,
|
|
116
|
+
offset,
|
|
117
|
+
createdAt: Date.now(),
|
|
118
|
+
});
|
|
119
|
+
// Sort by offset for efficient lookup
|
|
120
|
+
entries.sort((a, b) => a.offset - b.offset);
|
|
121
|
+
// Trim to max entries (remove oldest based on createdAt if over limit)
|
|
122
|
+
if (entries.length > this.options.maxEntriesPerQuery) {
|
|
123
|
+
entries.sort((a, b) => b.createdAt - a.createdAt);
|
|
124
|
+
entries.length = this.options.maxEntriesPerQuery;
|
|
125
|
+
entries.sort((a, b) => a.offset - b.offset);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Clear all cached tokens for a specific query
|
|
131
|
+
* @param queryHash The query hash
|
|
132
|
+
*/
|
|
133
|
+
clearQuery(queryHash) {
|
|
134
|
+
this.cache.delete(queryHash);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Clear all cached tokens
|
|
138
|
+
*/
|
|
139
|
+
clearAll() {
|
|
140
|
+
this.cache.clear();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get cache statistics for monitoring
|
|
144
|
+
*/
|
|
145
|
+
getStats() {
|
|
146
|
+
let totalEntries = 0;
|
|
147
|
+
for (const entries of this.cache.values()) {
|
|
148
|
+
totalEntries += entries.length;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
totalQueries: this.cache.size,
|
|
152
|
+
totalEntries,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.default = PaginationCache;
|
|
157
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wYWdpbmF0aW9uLWNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQW9DO0FBcURwQzs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQXFCLGVBQWU7SUFLbEMsWUFBWSxVQUFrQyxFQUFFO1FBSnhDLFVBQUssR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUtuRCxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2Isa0JBQWtCLEVBQUUsT0FBTyxDQUFDLGtCQUFrQixJQUFJLEdBQUc7WUFDckQsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLLElBQUksTUFBTSxFQUFFLG9CQUFvQjtZQUNwRCxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsSUFBSSxNQUFNO1lBQ3RDLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLElBQUk7U0FDN0MsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVk7UUFDVixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7SUFDcEMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsaUJBQWlCLENBQ2YsV0FBbUIsRUFDbkIsVUFBK0MsRUFDL0MsWUFBOEI7UUFFOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUMvQixLQUFLLEVBQUUsV0FBVztZQUNsQixVQUFVLEVBQUUsVUFBVSxJQUFJLEVBQUU7WUFDNUIsWUFBWTtTQUNiLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBQSxtQkFBVSxFQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMs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
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ConditionTree } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
export type PartitionKeyValue = string | number | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Extracts the partition key value from a ConditionTree if present.
|
|
5
|
+
*
|
|
6
|
+
* This optimization allows Cosmos DB to target a single partition instead of
|
|
7
|
+
* performing a cross-partition query, significantly reducing RU consumption.
|
|
8
|
+
*
|
|
9
|
+
* The extraction works when:
|
|
10
|
+
* - There's an equality condition (operator = 'Equal') on the partition key field
|
|
11
|
+
* - The condition is at the root level or within an AND branch
|
|
12
|
+
*
|
|
13
|
+
* The extraction does NOT work when:
|
|
14
|
+
* - The partition key is filtered with IN, NotEqual, or range operators
|
|
15
|
+
* - The partition key condition is inside an OR branch (multiple partitions needed)
|
|
16
|
+
* - No filter on partition key exists
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractPartitionKeyFromFilter(conditionTree: ConditionTree | undefined, partitionKeyPath: string): PartitionKeyValue;
|
|
19
|
+
//# sourceMappingURL=partition-key-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"partition-key-extractor.d.ts","sourceRoot":"","sources":["../../src/utils/partition-key-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAGd,MAAM,iCAAiC,CAAC;AAEzC,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AA6C5D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,gBAAgB,EAAE,MAAM,GACvB,iBAAiB,CAUnB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractPartitionKeyFromFilter = void 0;
|
|
4
|
+
function extractFromTree(conditionTree, partitionKeyField) {
|
|
5
|
+
// Handle leaf nodes (single conditions)
|
|
6
|
+
if (conditionTree.operator !== undefined) {
|
|
7
|
+
const leaf = conditionTree;
|
|
8
|
+
// Only extract if it's an equality condition on the partition key field
|
|
9
|
+
if (leaf.field === partitionKeyField && leaf.operator === 'Equal') {
|
|
10
|
+
const { value } = leaf;
|
|
11
|
+
// Partition keys must be string or number
|
|
12
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
// Handle branch nodes (AND/OR conditions)
|
|
19
|
+
if (conditionTree.aggregator !== undefined) {
|
|
20
|
+
const branch = conditionTree;
|
|
21
|
+
// Only extract from AND branches - OR branches require multiple partitions
|
|
22
|
+
if (branch.aggregator === 'And') {
|
|
23
|
+
for (const condition of branch.conditions) {
|
|
24
|
+
const extracted = extractFromTree(condition, partitionKeyField);
|
|
25
|
+
if (extracted !== undefined) {
|
|
26
|
+
return extracted;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// For OR branches, we cannot optimize as we'd need multiple partitions
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extracts the partition key value from a ConditionTree if present.
|
|
37
|
+
*
|
|
38
|
+
* This optimization allows Cosmos DB to target a single partition instead of
|
|
39
|
+
* performing a cross-partition query, significantly reducing RU consumption.
|
|
40
|
+
*
|
|
41
|
+
* The extraction works when:
|
|
42
|
+
* - There's an equality condition (operator = 'Equal') on the partition key field
|
|
43
|
+
* - The condition is at the root level or within an AND branch
|
|
44
|
+
*
|
|
45
|
+
* The extraction does NOT work when:
|
|
46
|
+
* - The partition key is filtered with IN, NotEqual, or range operators
|
|
47
|
+
* - The partition key condition is inside an OR branch (multiple partitions needed)
|
|
48
|
+
* - No filter on partition key exists
|
|
49
|
+
*/
|
|
50
|
+
function extractPartitionKeyFromFilter(conditionTree, partitionKeyPath) {
|
|
51
|
+
if (!conditionTree)
|
|
52
|
+
return undefined;
|
|
53
|
+
// Convert partition key path (e.g., "/tenantId" or "/address/city")
|
|
54
|
+
// to field notation (e.g., "tenantId" or "address->city")
|
|
55
|
+
const partitionKeyField = partitionKeyPath
|
|
56
|
+
.replace(/^\//, '') // Remove leading slash
|
|
57
|
+
.replace(/\//g, '->'); // Convert nested paths to arrow notation
|
|
58
|
+
return extractFromTree(conditionTree, partitionKeyField);
|
|
59
|
+
}
|
|
60
|
+
exports.extractPartitionKeyFromFilter = extractPartitionKeyFromFilter;
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFydGl0aW9uLWtleS1leHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvcGFydGl0aW9uLWtleS1leHRyYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBUUEsU0FBUyxlQUFlLENBQ3RCLGFBQTRCLEVBQzVCLGlCQUF5QjtJQUV6Qix3Q0FBd0M7SUFDeEMsSUFBSyxhQUFtQyxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNoRSxNQUFNLElBQUksR0FBRyxhQUFrQyxDQUFDO1FBRWhELHdFQUF3RTtRQUN4RSxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssaUJBQWlCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUNsRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDO1lBRXZCLDBDQUEwQztZQUMxQyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDM0QsT0FBTyxLQUFLLENBQUM7WUFDZixDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCwwQ0FBMEM7SUFDMUMsSUFBSyxhQUFxQyxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNwRSxNQUFNLE1BQU0sR0FBRyxhQUFvQyxDQUFDO1FBRXBELDJFQUEyRTtRQUMzRSxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDaEMsS0FBSyxNQUFNLFNBQVMsSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sU0FBUyxHQUFHLGVBQWUsQ0FBQyxTQUFTLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztnQkFFaEUsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQzVCLE9BQU8sU0FBUyxDQUFDO2dCQUNuQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCx1RUFBdUU7UUFDdkUsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILFNBQWdCLDZCQUE2QixDQUMzQyxhQUF3QyxFQUN4QyxnQkFBd0I7SUFFeEIsSUFBSSxDQUFDLGFBQWE7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUVyQyxvRUFBb0U7SUFDcEUsMERBQTBEO0lBQzFELE1BQU0saUJBQWlCLEdBQUcsZ0JBQWdCO1NBQ3ZDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsdUJBQXVCO1NBQzFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyx5Q0FBeUM7SUFFbEUsT0FBTyxlQUFlLENBQUMsYUFBYSxFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFDM0QsQ0FBQztBQWJELHNFQWFDIn0=
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { SqlParameter, SqlQuerySpec } from '@azure/cosmos';
|
|
2
2
|
import { ConditionTree, Sort } from '@forestadmin/datasource-toolkit';
|
|
3
|
+
import { QueryValidatorOptions } from './query-validator';
|
|
4
|
+
export interface QueryConverterOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Schema fields for validation (field names in Forest Admin notation)
|
|
7
|
+
* If not provided, only basic security validation is performed
|
|
8
|
+
*/
|
|
9
|
+
schemaFields?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Validation options
|
|
12
|
+
*/
|
|
13
|
+
validationOptions?: QueryValidatorOptions;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to skip validation entirely (not recommended for production)
|
|
16
|
+
* Default: false
|
|
17
|
+
*/
|
|
18
|
+
skipValidation?: boolean;
|
|
19
|
+
}
|
|
3
20
|
export default class QueryConverter {
|
|
4
21
|
private parameterCounter;
|
|
5
22
|
private parameters;
|
|
23
|
+
private validator;
|
|
24
|
+
private skipValidation;
|
|
25
|
+
constructor(options?: QueryConverterOptions);
|
|
6
26
|
/**
|
|
7
27
|
* Reset the converter state for a new query
|
|
8
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-converter.d.ts","sourceRoot":"","sources":["../../src/utils/query-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,aAAa,EAIb,IAAI,EACL,MAAM,iCAAiC,CAAC;AAEzC,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,UAAU,CAAsB;
|
|
1
|
+
{"version":3,"file":"query-converter.d.ts","sourceRoot":"","sources":["../../src/utils/query-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,aAAa,EAIb,IAAI,EACL,MAAM,iCAAiC,CAAC;AAEzC,OAAuB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IAE1C;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,cAAc,CAAU;gBAEpB,OAAO,CAAC,EAAE,qBAAqB;IAQ3C;;OAEG;IACH,OAAO,CAAC,KAAK;IAKb;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,eAAe;IA4HvB;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAyCvC;;OAEG;IACI,eAAe,CACpB,aAAa,CAAC,EAAE,aAAa,EAC7B,IAAI,CAAC,EAAE,IAAI,EACX,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,YAAY;IA4Df;;OAEG;IACI,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM;IAe5C;;OAEG;IACI,cAAc,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG;QACpD,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,YAAY,EAAE,CAAC;KAC5B;CAYF"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const query_validator_1 = __importDefault(require("./query-validator"));
|
|
3
7
|
class QueryConverter {
|
|
4
|
-
constructor() {
|
|
8
|
+
constructor(options) {
|
|
5
9
|
this.parameterCounter = 0;
|
|
6
10
|
this.parameters = [];
|
|
11
|
+
this.validator = null;
|
|
12
|
+
this.skipValidation = options?.skipValidation ?? false;
|
|
13
|
+
if (!this.skipValidation) {
|
|
14
|
+
this.validator = new query_validator_1.default(options?.schemaFields, options?.validationOptions);
|
|
15
|
+
}
|
|
7
16
|
}
|
|
8
17
|
/**
|
|
9
18
|
* Reset the converter state for a new query
|
|
@@ -162,6 +171,10 @@ class QueryConverter {
|
|
|
162
171
|
getSqlQuerySpec(conditionTree, sort, projection) {
|
|
163
172
|
// Reset state for new query
|
|
164
173
|
this.reset();
|
|
174
|
+
// Validate query parameters if validation is enabled
|
|
175
|
+
if (this.validator) {
|
|
176
|
+
this.validator.validateQuery(conditionTree, sort, projection);
|
|
177
|
+
}
|
|
165
178
|
// Build SELECT clause
|
|
166
179
|
// Cosmos DB doesn't handle well selecting individual nested properties
|
|
167
180
|
// (e.g., c.accountingBalance.currency). Instead, select parent objects.
|
|
@@ -224,9 +237,13 @@ class QueryConverter {
|
|
|
224
237
|
*/
|
|
225
238
|
getWhereClause(conditionTree) {
|
|
226
239
|
this.reset();
|
|
240
|
+
// Validate condition tree if validation is enabled
|
|
241
|
+
if (this.validator) {
|
|
242
|
+
this.validator.validateConditionTree(conditionTree);
|
|
243
|
+
}
|
|
227
244
|
const where = this.getWhereClauseFromConditionTree(conditionTree);
|
|
228
245
|
return { where, parameters: this.parameters };
|
|
229
246
|
}
|
|
230
247
|
}
|
|
231
248
|
exports.default = QueryConverter;
|
|
232
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3F1ZXJ5LWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLE1BQXFCLGNBQWM7SUFBbkM7UUFDVSxxQkFBZ0IsR0FBRyxDQUFDLENBQUM7UUFDckIsZUFBVSxHQUFtQixFQUFFLENBQUM7SUFtUzFDLENBQUM7SUFqU0M7O09BRUc7SUFDSyxLQUFLO1FBQ1gsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSyxZQUFZLENBQUMsS0FBYztRQUNqQyxNQUFNLFNBQVMsR0FBRyxTQUFTLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUM7UUFDM0Isa0ZBQWtGO1FBQ2xGLGlGQUFpRjtRQUNqRiw0RUFBNEU7UUFDNUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7WUFDbkIsSUFBSSxFQUFFLFNBQVM7WUFDZiwrRUFBK0U7WUFDL0UsS0FBSyxFQUFFLEtBQVk7U0FDcEIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssZUFBZSxDQUFDLEtBQWEsRUFBRSxRQUFrQixFQUFFLEtBQWU7UUFDeEUsa0RBQWtEO1FBQ2xELHFFQUFxRTtRQUNyRSxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM5QyxNQUFNLFNBQVMsR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssV0FBVyxFQUFFLENBQUM7UUFFL0QsUUFBUSxRQUFRLEVBQUUsQ0FBQztZQUNqQixXQUFXO1lBQ1gs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
|
|
249
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3F1ZXJ5LWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVNBLHdFQUEwRTtBQXFCMUUsTUFBcUIsY0FBYztJQU1qQyxZQUFZLE9BQStCO1FBTG5DLHFCQUFnQixHQUFHLENBQUMsQ0FBQztRQUNyQixlQUFVLEdBQW1CLEVBQUUsQ0FBQztRQUNoQyxjQUFTLEdBQTBCLElBQUksQ0FBQztRQUk5QyxJQUFJLENBQUMsY0FBYyxHQUFHLE9BQU8sRUFBRSxjQUFjLElBQUksS0FBSyxDQUFDO1FBRXZELElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLHlCQUFjLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUN6RixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSztRQUNYLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssWUFBWSxDQUFDLEtBQWM7UUFDakMsTUFBTSxTQUFTLEdBQUcsU0FBUyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUNuRCxJQUFJLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxDQUFDO1FBQzNCLGtGQUFrRjtRQUNsRixpRkFBaUY7UUFDakYsNEVBQTRFO1FBQzVFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ25CLElBQUksRUFBRSxTQUFTO1lBQ2YsK0VBQStFO1lBQy9FLEtBQUssRUFBRSxLQUFZO1NBQ3BCLENBQUMsQ0FBQztRQUVILE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBQyxL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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes for query validation failures
|
|
3
|
+
*/
|
|
4
|
+
export declare enum QueryValidationErrorCode {
|
|
5
|
+
INVALID_FIELD_NAME = "INVALID_FIELD_NAME",
|
|
6
|
+
FIELD_NOT_IN_SCHEMA = "FIELD_NOT_IN_SCHEMA",
|
|
7
|
+
INVALID_VALUE_TYPE = "INVALID_VALUE_TYPE",
|
|
8
|
+
POTENTIAL_INJECTION = "POTENTIAL_INJECTION",
|
|
9
|
+
MAX_DEPTH_EXCEEDED = "MAX_DEPTH_EXCEEDED",
|
|
10
|
+
INVALID_SORT_FIELD = "INVALID_SORT_FIELD",
|
|
11
|
+
INVALID_PROJECTION_FIELD = "INVALID_PROJECTION_FIELD"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Security and validation errors for query operations
|
|
15
|
+
*/
|
|
16
|
+
export default class QueryValidationError extends Error {
|
|
17
|
+
readonly code: QueryValidationErrorCode;
|
|
18
|
+
readonly field?: string;
|
|
19
|
+
constructor(message: string, code: QueryValidationErrorCode, field?: string);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=query-validation-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-validation-error.d.ts","sourceRoot":"","sources":["../../src/utils/query-validation-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,wBAAwB;IAClC,kBAAkB,uBAAuB;IACzC,mBAAmB,wBAAwB;IAC3C,kBAAkB,uBAAuB;IACzC,mBAAmB,wBAAwB;IAC3C,kBAAkB,uBAAuB;IACzC,kBAAkB,uBAAuB;IACzC,wBAAwB,6BAA6B;CACtD;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,KAAK;aAGnC,IAAI,EAAE,wBAAwB;aAC9B,KAAK,CAAC,EAAE,MAAM;gBAF9B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,wBAAwB,EAC9B,KAAK,CAAC,EAAE,MAAM;CAKjC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryValidationErrorCode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error codes for query validation failures
|
|
6
|
+
*/
|
|
7
|
+
var QueryValidationErrorCode;
|
|
8
|
+
(function (QueryValidationErrorCode) {
|
|
9
|
+
QueryValidationErrorCode["INVALID_FIELD_NAME"] = "INVALID_FIELD_NAME";
|
|
10
|
+
QueryValidationErrorCode["FIELD_NOT_IN_SCHEMA"] = "FIELD_NOT_IN_SCHEMA";
|
|
11
|
+
QueryValidationErrorCode["INVALID_VALUE_TYPE"] = "INVALID_VALUE_TYPE";
|
|
12
|
+
QueryValidationErrorCode["POTENTIAL_INJECTION"] = "POTENTIAL_INJECTION";
|
|
13
|
+
QueryValidationErrorCode["MAX_DEPTH_EXCEEDED"] = "MAX_DEPTH_EXCEEDED";
|
|
14
|
+
QueryValidationErrorCode["INVALID_SORT_FIELD"] = "INVALID_SORT_FIELD";
|
|
15
|
+
QueryValidationErrorCode["INVALID_PROJECTION_FIELD"] = "INVALID_PROJECTION_FIELD";
|
|
16
|
+
})(QueryValidationErrorCode || (exports.QueryValidationErrorCode = QueryValidationErrorCode = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Security and validation errors for query operations
|
|
19
|
+
*/
|
|
20
|
+
class QueryValidationError extends Error {
|
|
21
|
+
constructor(message, code, field) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.code = code;
|
|
24
|
+
this.field = field;
|
|
25
|
+
this.name = 'QueryValidationError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = QueryValidationError;
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktdmFsaWRhdGlvbi1lcnJvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9xdWVyeS12YWxpZGF0aW9uLWVycm9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOztHQUVHO0FBQ0gsSUFBWSx3QkFRWDtBQVJELFdBQVksd0JBQXdCO0lBQ2xDLHFFQUF5QyxDQUFBO0lBQ3pDLHVFQUEyQyxDQUFBO0lBQzNDLHFFQUF5QyxDQUFBO0lBQ3pDLHVFQUEyQyxDQUFBO0lBQzNDLHFFQUF5QyxDQUFBO0lBQ3pDLHFFQUF5QyxDQUFBO0lBQ3pDLGlGQUFxRCxDQUFBO0FBQ3ZELENBQUMsRUFSVyx3QkFBd0Isd0NBQXhCLHdCQUF3QixRQVFuQztBQUVEOztHQUVHO0FBQ0gsTUFBcUIsb0JBQXFCLFNBQVEsS0FBSztJQUNyRCxZQUNFLE9BQWUsRUFDQyxJQUE4QixFQUM5QixLQUFjO1FBRTlCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUhDLFNBQUksR0FBSixJQUFJLENBQTBCO1FBQzlCLFVBQUssR0FBTCxLQUFLLENBQVM7UUFHOUIsSUFBSSxDQUFDLElBQUksR0FBRyxzQkFBc0IsQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUFURCx1Q0FTQyJ9
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ConditionTree, Sort } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import QueryValidationError, { QueryValidationErrorCode } from './query-validation-error';
|
|
3
|
+
export { QueryValidationError, QueryValidationErrorCode };
|
|
4
|
+
export interface QueryValidatorOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Maximum allowed nesting depth for field paths (e.g., 'a->b->c' has depth 3)
|
|
7
|
+
* Default: 10
|
|
8
|
+
*/
|
|
9
|
+
maxFieldDepth?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to validate fields against schema (requires schema to be provided)
|
|
12
|
+
* Default: true when schema is provided
|
|
13
|
+
*/
|
|
14
|
+
validateAgainstSchema?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to allow unknown fields not in schema
|
|
17
|
+
* Default: false (strict mode)
|
|
18
|
+
*/
|
|
19
|
+
allowUnknownFields?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Maximum length for field names
|
|
22
|
+
* Default: 256
|
|
23
|
+
*/
|
|
24
|
+
maxFieldNameLength?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum number of conditions in a condition tree
|
|
27
|
+
* Default: 100
|
|
28
|
+
*/
|
|
29
|
+
maxConditions?: number;
|
|
30
|
+
}
|
|
31
|
+
export default class QueryValidator {
|
|
32
|
+
private options;
|
|
33
|
+
private schema;
|
|
34
|
+
private conditionCount;
|
|
35
|
+
constructor(schemaFields?: string[], options?: QueryValidatorOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Validate a field name for security and correctness
|
|
38
|
+
*/
|
|
39
|
+
validateFieldName(field: string, context?: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Validate a complete condition tree
|
|
42
|
+
*/
|
|
43
|
+
validateConditionTree(conditionTree?: ConditionTree): void;
|
|
44
|
+
private validateConditionTreeRecursive;
|
|
45
|
+
/**
|
|
46
|
+
* Validate a value for potential injection
|
|
47
|
+
*/
|
|
48
|
+
validateValue(value: unknown, field?: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Validate sort fields
|
|
51
|
+
*/
|
|
52
|
+
validateSort(sort?: Sort): void;
|
|
53
|
+
/**
|
|
54
|
+
* Validate projection fields
|
|
55
|
+
*/
|
|
56
|
+
validateProjection(projection?: string[]): void;
|
|
57
|
+
/**
|
|
58
|
+
* Validate all query parameters at once
|
|
59
|
+
*/
|
|
60
|
+
validateQuery(conditionTree?: ConditionTree, sort?: Sort, projection?: string[]): void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create a validator instance for a given schema
|
|
64
|
+
*/
|
|
65
|
+
export declare function createQueryValidator(schemaFields?: string[], options?: QueryValidatorOptions): QueryValidator;
|
|
66
|
+
//# sourceMappingURL=query-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-validator.d.ts","sourceRoot":"","sources":["../../src/utils/query-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAGb,IAAI,EACL,MAAM,iCAAiC,CAAC;AAEzC,OAAO,oBAAoB,EAAE,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAE1F,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA4BD,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,cAAc,CAAK;gBAEf,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,qBAA0B;IA0BxE;;OAEG;IACI,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,SAAU,GAAG,IAAI;IAqEhE;;OAEG;IACI,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI;IAOjE,OAAO,CAAC,8BAA8B;IA8BtC;;OAEG;IACI,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAkC1D;;OAEG;IACI,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI;IAiBtC;;OAEG;IACI,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAQtD;;OAEG;IACI,aAAa,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;CAK9F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,CAAC,EAAE,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,cAAc,CAEhB"}
|