@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
|
@@ -3,8 +3,38 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configurePaginationCache = exports.getSharedPaginationCache = exports.getSharedRetryOptions = exports.configureRetryOptions = void 0;
|
|
6
7
|
const crypto_1 = require("crypto");
|
|
8
|
+
const pagination_cache_1 = __importDefault(require("../utils/pagination-cache"));
|
|
9
|
+
const retry_handler_1 = require("../utils/retry-handler");
|
|
10
|
+
Object.defineProperty(exports, "configureRetryOptions", { enumerable: true, get: function () { return retry_handler_1.configureRetryOptions; } });
|
|
11
|
+
Object.defineProperty(exports, "getSharedRetryOptions", { enumerable: true, get: function () { return retry_handler_1.getSharedRetryOptions; } });
|
|
7
12
|
const serializer_1 = __importDefault(require("../utils/serializer"));
|
|
13
|
+
/**
|
|
14
|
+
* Shared pagination cache instance for all models
|
|
15
|
+
* This is shared to allow cache reuse across collections and reduce memory usage
|
|
16
|
+
*/
|
|
17
|
+
let sharedPaginationCache = null;
|
|
18
|
+
/**
|
|
19
|
+
* Get or create the shared pagination cache instance
|
|
20
|
+
* @param options Optional configuration options (only used on first call)
|
|
21
|
+
*/
|
|
22
|
+
function getSharedPaginationCache(options) {
|
|
23
|
+
if (!sharedPaginationCache) {
|
|
24
|
+
sharedPaginationCache = new pagination_cache_1.default(options);
|
|
25
|
+
}
|
|
26
|
+
return sharedPaginationCache;
|
|
27
|
+
}
|
|
28
|
+
exports.getSharedPaginationCache = getSharedPaginationCache;
|
|
29
|
+
/**
|
|
30
|
+
* Configure the shared pagination cache with custom options
|
|
31
|
+
* Must be called before any queries are made
|
|
32
|
+
* @param options Pagination cache configuration
|
|
33
|
+
*/
|
|
34
|
+
function configurePaginationCache(options) {
|
|
35
|
+
sharedPaginationCache = new pagination_cache_1.default(options);
|
|
36
|
+
}
|
|
37
|
+
exports.configurePaginationCache = configurePaginationCache;
|
|
8
38
|
class ModelCosmos {
|
|
9
39
|
constructor(cosmosClient, name, databaseName, containerName, partitionKeyPath, schema, overrideTypeConverter, enableCount) {
|
|
10
40
|
this.name = name;
|
|
@@ -16,6 +46,8 @@ class ModelCosmos {
|
|
|
16
46
|
this.enableCount = enableCount;
|
|
17
47
|
this.cosmosClient = cosmosClient;
|
|
18
48
|
this.container = this.cosmosClient.database(databaseName).container(containerName);
|
|
49
|
+
this.paginationCache = getSharedPaginationCache();
|
|
50
|
+
this.retryOptions = (0, retry_handler_1.getSharedRetryOptions)();
|
|
19
51
|
}
|
|
20
52
|
getCosmosClient() {
|
|
21
53
|
return this.cosmosClient;
|
|
@@ -41,136 +73,164 @@ class ModelCosmos {
|
|
|
41
73
|
...unflattenedRecord,
|
|
42
74
|
};
|
|
43
75
|
// eslint-disable-next-line no-await-in-loop -- Sequential execution maintains order
|
|
44
|
-
const { resource } = await this.container.items.create(itemToCreate);
|
|
76
|
+
const { resource } = await (0, retry_handler_1.withRetry)(() => this.container.items.create(itemToCreate), this.retryOptions);
|
|
45
77
|
// Flatten and serialize the response
|
|
46
78
|
createdRecords.push(serializer_1.default.serialize(resource));
|
|
47
79
|
}
|
|
48
80
|
return createdRecords;
|
|
49
81
|
}
|
|
50
|
-
async update(
|
|
51
|
-
// Cosmos DB requires both id and partition key for updates
|
|
52
|
-
// We need to fetch the items first to get their partition keys
|
|
53
|
-
const itemsToUpdate = await this.getItemsByIds(ids);
|
|
82
|
+
async update(items, patch) {
|
|
54
83
|
// Unflatten the patch to restore nested structure for Cosmos DB
|
|
55
84
|
const unflattenedPatch = serializer_1.default.unflatten(patch);
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
for (const
|
|
59
|
-
|
|
60
|
-
// Deep merge the unflattened patch with the existing item
|
|
61
|
-
const updatedItem = serializer_1.default.deepMerge(item, unflattenedPatch);
|
|
85
|
+
// Use point reads to fetch items (1 RU each) instead of cross-partition query
|
|
86
|
+
// Then perform point updates (also optimized with partition key)
|
|
87
|
+
for (const { id, partitionKey } of items) {
|
|
88
|
+
// Point read: directly fetch item using id + partition key (1 RU)
|
|
62
89
|
// eslint-disable-next-line no-await-in-loop -- Sequential maintains consistency
|
|
63
|
-
await this.container.item(
|
|
90
|
+
const { resource: existingItem } = await (0, retry_handler_1.withRetry)(() => this.container.item(id, partitionKey).read(), this.retryOptions);
|
|
91
|
+
if (existingItem) {
|
|
92
|
+
// Deep merge the unflattened patch with the existing item
|
|
93
|
+
const updatedItem = serializer_1.default.deepMerge(existingItem, unflattenedPatch);
|
|
94
|
+
// Point update: directly update using id + partition key
|
|
95
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential maintains consistency
|
|
96
|
+
await (0, retry_handler_1.withRetry)(() => this.container.item(id, partitionKey).replace(updatedItem), this.retryOptions);
|
|
97
|
+
}
|
|
64
98
|
}
|
|
65
99
|
}
|
|
66
|
-
async delete(
|
|
67
|
-
//
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
// to ensure consistency and prevent conflicts
|
|
71
|
-
for (const item of itemsToDelete) {
|
|
72
|
-
const partitionKeyValue = this.getPartitionKeyValue(item);
|
|
100
|
+
async delete(items) {
|
|
101
|
+
// Use point deletes with id + partition key (optimized, no cross-partition scan needed)
|
|
102
|
+
for (const { id, partitionKey } of items) {
|
|
103
|
+
// Point delete: directly delete using id + partition key
|
|
73
104
|
// eslint-disable-next-line no-await-in-loop -- Sequential maintains consistency
|
|
74
|
-
await this.container.item(
|
|
105
|
+
await (0, retry_handler_1.withRetry)(() => this.container.item(id, partitionKey).delete(), this.retryOptions);
|
|
75
106
|
}
|
|
76
107
|
}
|
|
77
|
-
async query(querySpec, offset, limit) {
|
|
108
|
+
async query(querySpec, offset, limit, partitionKey) {
|
|
109
|
+
// Build query options
|
|
110
|
+
const queryOptions = {};
|
|
111
|
+
// Add partition key if provided (enables single-partition query optimization)
|
|
112
|
+
if (partitionKey !== undefined) {
|
|
113
|
+
queryOptions.partitionKey = partitionKey;
|
|
114
|
+
}
|
|
78
115
|
// If no pagination parameters, fetch all (backward compatibility)
|
|
79
116
|
if (offset === undefined && limit === undefined) {
|
|
80
|
-
const { resources } = await this.container.items.query(querySpec).fetchAll();
|
|
117
|
+
const { resources } = await (0, retry_handler_1.withRetry)(() => this.container.items.query(querySpec, queryOptions).fetchAll(), this.retryOptions);
|
|
81
118
|
return resources.map(item => serializer_1.default.serialize(item));
|
|
82
119
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
120
|
+
const effectiveOffset = offset || 0;
|
|
121
|
+
const effectiveLimit = limit || 100; // Default limit if not specified
|
|
122
|
+
// Check if offset exceeds maximum allowed
|
|
123
|
+
const maxOffset = this.paginationCache.getMaxOffset();
|
|
124
|
+
if (effectiveOffset > maxOffset) {
|
|
125
|
+
throw new Error(`Offset ${effectiveOffset} exceeds maximum allowed offset of ${maxOffset}. ` +
|
|
126
|
+
`Consider using filters to narrow down your results instead of deep pagination.`);
|
|
127
|
+
}
|
|
128
|
+
// Generate query hash for cache lookup
|
|
129
|
+
const queryHash = this.paginationCache.generateQueryHash(querySpec.query, querySpec.parameters, partitionKey);
|
|
130
|
+
// Try to find a cached continuation token close to our target offset
|
|
131
|
+
const cachedEntry = this.paginationCache.findBestToken(queryHash, effectiveOffset);
|
|
132
|
+
let startOffset = 0;
|
|
133
|
+
if (cachedEntry) {
|
|
134
|
+
// Resume from cached position
|
|
135
|
+
startOffset = cachedEntry.offset;
|
|
136
|
+
queryOptions.continuationToken = cachedEntry.continuationToken;
|
|
137
|
+
}
|
|
138
|
+
// Calculate how many items we need to skip from the start position
|
|
139
|
+
const itemsToSkip = effectiveOffset - startOffset;
|
|
140
|
+
const totalItemsNeeded = itemsToSkip + effectiveLimit;
|
|
141
|
+
// Set page size - use a reasonable batch size for efficiency
|
|
142
|
+
// Larger batches = fewer round trips but more memory
|
|
143
|
+
const pageSize = Math.min(Math.max(effectiveLimit, 100), 1000);
|
|
144
|
+
queryOptions.maxItemCount = pageSize;
|
|
89
145
|
const results = [];
|
|
90
146
|
let itemsFetched = 0;
|
|
91
|
-
|
|
147
|
+
let lastContinuationToken;
|
|
148
|
+
let currentOffset = startOffset;
|
|
149
|
+
// Create query iterator
|
|
150
|
+
const queryIterator = this.container.items.query(querySpec, queryOptions);
|
|
92
151
|
// Iterate through pages until we have enough items
|
|
93
152
|
// eslint-disable-next-line no-restricted-syntax
|
|
94
|
-
for await (const
|
|
153
|
+
for await (const response of queryIterator.getAsyncIterator()) {
|
|
154
|
+
const { resources: page, continuationToken } = response;
|
|
155
|
+
// Store continuation token for future use at regular intervals
|
|
156
|
+
const cacheInterval = this.paginationCache.getCacheInterval();
|
|
157
|
+
if (continuationToken && currentOffset > 0 && currentOffset % cacheInterval < pageSize) {
|
|
158
|
+
this.paginationCache.storeToken(queryHash, currentOffset, continuationToken);
|
|
159
|
+
}
|
|
95
160
|
results.push(...page);
|
|
96
161
|
itemsFetched += page.length;
|
|
162
|
+
currentOffset += page.length;
|
|
163
|
+
lastContinuationToken = continuationToken;
|
|
97
164
|
// Stop fetching if we have enough items
|
|
98
|
-
if (
|
|
165
|
+
if (itemsFetched >= totalItemsNeeded) {
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
// Safety check: if no more pages, break
|
|
169
|
+
if (!continuationToken) {
|
|
99
170
|
break;
|
|
100
171
|
}
|
|
101
172
|
}
|
|
102
|
-
//
|
|
173
|
+
// Store the final continuation token if we have one
|
|
174
|
+
if (lastContinuationToken && currentOffset > startOffset) {
|
|
175
|
+
this.paginationCache.storeToken(queryHash, currentOffset, lastContinuationToken);
|
|
176
|
+
}
|
|
177
|
+
// Apply offset (skip items we don't need) and limit
|
|
103
178
|
let finalResults = results;
|
|
104
|
-
if (
|
|
105
|
-
finalResults = finalResults.slice(
|
|
179
|
+
if (itemsToSkip > 0) {
|
|
180
|
+
finalResults = finalResults.slice(itemsToSkip);
|
|
106
181
|
}
|
|
107
|
-
if (
|
|
108
|
-
finalResults = finalResults.slice(0,
|
|
182
|
+
if (effectiveLimit) {
|
|
183
|
+
finalResults = finalResults.slice(0, effectiveLimit);
|
|
109
184
|
}
|
|
110
185
|
return finalResults.map(item => serializer_1.default.serialize(item));
|
|
111
186
|
}
|
|
112
|
-
async aggregateQuery(querySpec) {
|
|
113
|
-
|
|
187
|
+
async aggregateQuery(querySpec, partitionKey) {
|
|
188
|
+
// Build query options with partition key if provided
|
|
189
|
+
const queryOptions = {};
|
|
190
|
+
if (partitionKey !== undefined) {
|
|
191
|
+
queryOptions.partitionKey = partitionKey;
|
|
192
|
+
}
|
|
193
|
+
const { resources } = await (0, retry_handler_1.withRetry)(() => this.container.items.query(querySpec, queryOptions).fetchAll(), this.retryOptions);
|
|
114
194
|
return resources.map(item => serializer_1.default.serialize(item));
|
|
115
195
|
}
|
|
116
|
-
async count(querySpec) {
|
|
196
|
+
async count(querySpec, partitionKey) {
|
|
197
|
+
// Build query options with partition key if provided
|
|
198
|
+
const queryOptions = {};
|
|
199
|
+
if (partitionKey !== undefined) {
|
|
200
|
+
queryOptions.partitionKey = partitionKey;
|
|
201
|
+
}
|
|
117
202
|
if (!querySpec) {
|
|
118
203
|
// Simple count without filters
|
|
119
204
|
const countQuery = {
|
|
120
205
|
query: 'SELECT VALUE COUNT(1) FROM c',
|
|
121
206
|
};
|
|
122
|
-
const { resources } = await this.container.items.query(countQuery).fetchAll();
|
|
207
|
+
const { resources } = await (0, retry_handler_1.withRetry)(() => this.container.items.query(countQuery, queryOptions).fetchAll(), this.retryOptions);
|
|
123
208
|
return resources[0] || 0;
|
|
124
209
|
}
|
|
125
|
-
//
|
|
126
|
-
const
|
|
127
|
-
|
|
210
|
+
// Convert the query to a COUNT query to avoid fetching all records
|
|
211
|
+
const countQuery = this.convertToCountQuery(querySpec);
|
|
212
|
+
const { resources } = await (0, retry_handler_1.withRetry)(() => this.container.items.query(countQuery, queryOptions).fetchAll(), this.retryOptions);
|
|
213
|
+
return resources[0] || 0;
|
|
128
214
|
}
|
|
129
|
-
// INTERNAL HELPER METHODS
|
|
130
215
|
/**
|
|
131
|
-
*
|
|
216
|
+
* Convert a SELECT query to a COUNT query
|
|
217
|
+
* Extracts the WHERE clause and creates a COUNT query with the same filters
|
|
132
218
|
*/
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
219
|
+
convertToCountQuery(querySpec) {
|
|
220
|
+
const { query, parameters } = querySpec;
|
|
221
|
+
// Extract WHERE clause from original query
|
|
222
|
+
// Query format: "SELECT ... FROM c WHERE ... ORDER BY ..."
|
|
223
|
+
const whereMatch = query.match(/WHERE\s+(.+?)(?:\s+ORDER\s+BY|$)/i);
|
|
224
|
+
const whereClause = whereMatch ? whereMatch[1].trim() : '';
|
|
225
|
+
const countQueryString = whereClause
|
|
226
|
+
? `SELECT VALUE COUNT(1) FROM c WHERE ${whereClause}`
|
|
227
|
+
: 'SELECT VALUE COUNT(1) FROM c';
|
|
228
|
+
return {
|
|
229
|
+
query: countQueryString,
|
|
230
|
+
parameters,
|
|
142
231
|
};
|
|
143
|
-
const { resources } = await this.container.items.query(querySpec).fetchAll();
|
|
144
|
-
return resources;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Extract the partition key value from an item
|
|
148
|
-
*/
|
|
149
|
-
getPartitionKeyValue(item) {
|
|
150
|
-
// Remove leading slash from partition key path
|
|
151
|
-
const keyPath = this.partitionKeyPath.replace(/^\//, '');
|
|
152
|
-
// Handle nested paths (e.g., "/address/city")
|
|
153
|
-
const keys = keyPath.split('/');
|
|
154
|
-
let value = item;
|
|
155
|
-
for (const key of keys) {
|
|
156
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
157
|
-
value = value[key];
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// Validate that we found a valid partition key value
|
|
164
|
-
if (value === undefined || value === null) {
|
|
165
|
-
throw new Error(`Partition key '${this.partitionKeyPath}' is undefined or null in item. ` +
|
|
166
|
-
`Item ID: ${item.id || 'unknown'}`);
|
|
167
|
-
}
|
|
168
|
-
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
169
|
-
throw new Error(`Partition key '${this.partitionKeyPath}' must be string or number, ` +
|
|
170
|
-
`but got ${typeof value}. Item ID: ${item.id || 'unknown'}`);
|
|
171
|
-
}
|
|
172
|
-
return value;
|
|
173
232
|
}
|
|
233
|
+
// INTERNAL HELPER METHODS
|
|
174
234
|
/**
|
|
175
235
|
* Generate a unique ID for new items
|
|
176
236
|
*/
|
|
@@ -209,4 +269,4 @@ class ModelCosmos {
|
|
|
209
269
|
}
|
|
210
270
|
}
|
|
211
271
|
exports.default = ModelCosmos;
|
|
212
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kZWwtYnVpbGRlci9tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLG1DQUFvQztBQUdwQyxxRUFBNkM7QUFVN0MsTUFBcUIsV0FBVztJQXFDOUIsWUFDRSxZQUEwQixFQUMxQixJQUFZLEVBQ1osWUFBb0IsRUFDcEIsYUFBcUIsRUFDckIsZ0JBQXdCLEVBQ3hCLE1BQW9CLEVBQ3BCLHFCQUE2QyxFQUM3QyxXQUFxQjtRQUVyQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztRQUNuQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7UUFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQ25ELElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBRS9CLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFTSxlQUFlO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBRU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFrQjtRQUNwQyxNQUFNLGNBQWMsR0FBaUIsRUFBRSxDQUFDO1FBRXhDLHlDQUF5QztRQUN6QyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtnQkFDdkIsU0FBUyxDQUFD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
|
|
272
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kZWwtYnVpbGRlci9tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFFQSxtQ0FBb0M7QUFHcEMsaUZBQW9GO0FBQ3BGLDBEQUtnQztBQUdULHNHQU5yQixxQ0FBcUIsT0FNcUI7QUFBRSxzR0FMNUMscUNBQXFCLE9BSzRDO0FBRm5FLHFFQUE2QztBQWlCN0M7OztHQUdHO0FBQ0gsSUFBSSxxQkFBcUIsR0FBMkIsSUFBSSxDQUFDO0FBRXpEOzs7R0FHRztBQUNILFNBQWdCLHdCQUF3QixDQUFDLE9BQWdDO0lBQ3ZFLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQzNCLHFCQUFxQixHQUFHLElBQUksMEJBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRUQsT0FBTyxxQkFBcUIsQ0FBQztBQUMvQixDQUFDO0FBTkQsNERBTUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsT0FBK0I7SUFDdEUscUJBQXFCLEdBQUcsSUFBSSwwQkFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFGRCw0REFFQztBQUVELE1BQXFCLFdBQVc7SUErQzlCLFlBQ0UsWUFBMEIsRUFDMUIsSUFBWSxFQUNaLFlBQW9CLEVBQ3BCLGFBQXFCLEVBQ3JCLGdCQUF3QixFQUN4QixNQUFvQixFQUNwQixxQkFBNkMsRUFDN0MsV0FBcUI7UUFFckIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbkMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxxQkFBcUIs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
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { SqlQuerySpec } from '@azure/cosmos';
|
|
2
2
|
import { AggregateResult, Aggregation, AggregationOperation, ConditionTree } from '@forestadmin/datasource-toolkit';
|
|
3
3
|
export default class AggregationConverter {
|
|
4
|
+
/**
|
|
5
|
+
* Shared validator instance for field name validation
|
|
6
|
+
* Using permissive options since aggregation fields come from Forest Admin SDK
|
|
7
|
+
*/
|
|
8
|
+
private static validator;
|
|
4
9
|
private static AGGREGATION_OPERATION;
|
|
5
10
|
/**
|
|
6
11
|
* Convert Forest Admin field notation (arrow ->) to Cosmos DB notation (dot .)
|
|
12
|
+
* Also validates the field name to prevent SQL injection
|
|
7
13
|
*/
|
|
8
14
|
private static toCosmosField;
|
|
9
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregation-converter.d.ts","sourceRoot":"","sources":["../../src/utils/aggregation-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,aAAa,EAEd,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"aggregation-converter.d.ts","sourceRoot":"","sources":["../../src/utils/aggregation-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,aAAa,EAEd,MAAM,iCAAiC,CAAC;AAMzC,MAAM,CAAC,OAAO,OAAO,oBAAoB;IACvC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAGrB;IAEH,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAMlC;IAEF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAO5B;;OAEG;IACH,MAAM,CAAC,qBAAqB,CAC1B,WAAW,EAAE,WAAW,EACxB,aAAa,CAAC,EAAE,aAAa,EAC7B,KAAK,CAAC,EAAE,MAAM,GACb,YAAY;IAiBf;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAavC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA8D3C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;IA0BvC;;OAEG;IACH,MAAM,CAAC,yBAAyB,CAC9B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC1C,WAAW,EAAE,WAAW,GACvB,eAAe,EAAE;IAoCpB;;OAEG;IACH,MAAM,CAAC,2BAA2B,CAChC,SAAS,EAAE,oBAAoB,EAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,aAAa,CAAC,EAAE,aAAa,EAC7B,KAAK,CAAC,EAAE,MAAM,GACb,YAAY;CAyChB"}
|
|
@@ -4,12 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const query_converter_1 = __importDefault(require("./query-converter"));
|
|
7
|
+
const query_validator_1 = __importDefault(require("./query-validator"));
|
|
7
8
|
const serializer_1 = __importDefault(require("./serializer"));
|
|
8
9
|
class AggregationConverter {
|
|
9
10
|
/**
|
|
10
11
|
* Convert Forest Admin field notation (arrow ->) to Cosmos DB notation (dot .)
|
|
12
|
+
* Also validates the field name to prevent SQL injection
|
|
11
13
|
*/
|
|
12
|
-
static toCosmosField(field) {
|
|
14
|
+
static toCosmosField(field, context = 'Aggregation field') {
|
|
15
|
+
// Validate field name to prevent SQL injection
|
|
16
|
+
this.validator.validateFieldName(field, context);
|
|
13
17
|
return field.replace(/->/g, '.');
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
@@ -37,7 +41,7 @@ class AggregationConverter {
|
|
|
37
41
|
return 'COUNT(1)';
|
|
38
42
|
}
|
|
39
43
|
const operation = this.AGGREGATION_OPERATION[aggregation.operation];
|
|
40
|
-
const cosmosField = this.toCosmosField(aggregation.field);
|
|
44
|
+
const cosmosField = this.toCosmosField(aggregation.field, 'Aggregation target field');
|
|
41
45
|
const fieldPath = `c.${cosmosField}`;
|
|
42
46
|
return `${operation}(${fieldPath})`;
|
|
43
47
|
}
|
|
@@ -54,7 +58,7 @@ class AggregationConverter {
|
|
|
54
58
|
// For now, we'll use VALUE syntax with DISTINCT for simple grouping
|
|
55
59
|
if (groups.length === 1 && !groups[0].operation) {
|
|
56
60
|
// Simple single field grouping
|
|
57
|
-
const cosmosGroupField = this.toCosmosField(groups[0].field);
|
|
61
|
+
const cosmosGroupField = this.toCosmosField(groups[0].field, 'Group by field');
|
|
58
62
|
const groupField = `c.${cosmosGroupField}`;
|
|
59
63
|
// For Count operation without field, we need a different approach
|
|
60
64
|
if (aggregation.operation === 'Count' && !aggregation.field) {
|
|
@@ -94,7 +98,7 @@ class AggregationConverter {
|
|
|
94
98
|
* Build date grouping expression
|
|
95
99
|
*/
|
|
96
100
|
static buildDateGroupExpression(field, operation, alias) {
|
|
97
|
-
const cosmosField = this.toCosmosField(field);
|
|
101
|
+
const cosmosField = this.toCosmosField(field, 'Date group field');
|
|
98
102
|
const fieldPath = `c.${cosmosField}`;
|
|
99
103
|
switch (operation) {
|
|
100
104
|
case 'Year':
|
|
@@ -154,8 +158,10 @@ class AggregationConverter {
|
|
|
154
158
|
let selectClause;
|
|
155
159
|
let groupByClause = '';
|
|
156
160
|
let orderByClause = '';
|
|
157
|
-
const cosmosField = field ? this.toCosmosField(field) : null;
|
|
158
|
-
const cosmosGroupByField = groupByField
|
|
161
|
+
const cosmosField = field ? this.toCosmosField(field, 'Aggregation target field') : null;
|
|
162
|
+
const cosmosGroupByField = groupByField
|
|
163
|
+
? this.toCosmosField(groupByField, 'Group by field')
|
|
164
|
+
: null;
|
|
159
165
|
if (!cosmosField) {
|
|
160
166
|
// COUNT(*) case
|
|
161
167
|
selectClause = cosmosGroupByField
|
|
@@ -180,6 +186,14 @@ class AggregationConverter {
|
|
|
180
186
|
return { query, parameters };
|
|
181
187
|
}
|
|
182
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Shared validator instance for field name validation
|
|
191
|
+
* Using permissive options since aggregation fields come from Forest Admin SDK
|
|
192
|
+
*/
|
|
193
|
+
AggregationConverter.validator = new query_validator_1.default(undefined, {
|
|
194
|
+
allowUnknownFields: true,
|
|
195
|
+
maxFieldDepth: 10,
|
|
196
|
+
});
|
|
183
197
|
AggregationConverter.AGGREGATION_OPERATION = {
|
|
184
198
|
Sum: 'SUM',
|
|
185
199
|
Avg: 'AVG',
|
|
@@ -188,4 +202,4 @@ AggregationConverter.AGGREGATION_OPERATION = {
|
|
|
188
202
|
Min: 'MIN',
|
|
189
203
|
};
|
|
190
204
|
exports.default = AggregationConverter;
|
|
191
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdncmVnYXRpb24tY29udmVydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2FnZ3JlZ2F0aW9uLWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVNBLHdFQUErQztBQUMvQyx3RUFBK0M7QUFDL0MsOERBQXNDO0FBRXRDLE1BQXFCLG9CQUFvQjtJQWtCdkM7OztPQUdHO0lBQ0ssTUFBTSxDQUFDLGFBQWEsQ0FBQyxLQUFhLEVBQUUsT0FBTyxHQUFHLG1CQUFtQjtRQUN2RSwrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFakQsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMscUJBQXFCLENBQzFCLFdBQXdCLEVBQ3hCLGFBQTZCLEVBQzdCLEtBQWM7UUFFZCxNQUFNLGNBQWMsR0FBRyxJQUFJLHlCQUFjLEVBQUUsQ0FBQztRQUM1QyxNQUFNLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxHQUFHLGNBQWMsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDM0UsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFFcEQsNkNBQTZDO1FBQzdDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzNELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRSxNQUFNLEtBQUssR0FBRyxVQUFVLFlBQVksNkJBQTZCLGFBQWEsRUFBRSxDQUFDO1lBRWpGLE9BQU8sRUFBRSxL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
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache entry for storing continuation tokens with their associated offset
|
|
3
|
+
*/
|
|
4
|
+
interface CacheEntry {
|
|
5
|
+
/** The Cosmos DB continuation token */
|
|
6
|
+
continuationToken: string;
|
|
7
|
+
/** The offset (number of items) this token represents */
|
|
8
|
+
offset: number;
|
|
9
|
+
/** Timestamp when this entry was created */
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configuration options for the pagination cache
|
|
14
|
+
*/
|
|
15
|
+
export interface PaginationCacheOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of entries to store per query
|
|
18
|
+
* Default: 100
|
|
19
|
+
*/
|
|
20
|
+
maxEntriesPerQuery?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Time-to-live for cache entries in milliseconds
|
|
23
|
+
* Default: 300000 (5 minutes)
|
|
24
|
+
*/
|
|
25
|
+
ttlMs?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Maximum offset allowed for pagination
|
|
28
|
+
* Requests beyond this offset will throw an error
|
|
29
|
+
* Default: 100000
|
|
30
|
+
*/
|
|
31
|
+
maxOffset?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Interval (in number of records) at which to cache continuation tokens
|
|
34
|
+
*
|
|
35
|
+
* Lower values = more cache hits, faster page jumps, but more memory usage
|
|
36
|
+
* Higher values = fewer cache entries, less memory, but slower random page access
|
|
37
|
+
*
|
|
38
|
+
* Recommended values:
|
|
39
|
+
* - Small collections (<10K): 500
|
|
40
|
+
* - Medium collections (10K-100K): 1000 (default)
|
|
41
|
+
* - Large collections (>100K): 2000-5000
|
|
42
|
+
*
|
|
43
|
+
* Default: 1000
|
|
44
|
+
*/
|
|
45
|
+
cacheInterval?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Cache for storing Cosmos DB continuation tokens to enable efficient cursor-based pagination
|
|
49
|
+
*
|
|
50
|
+
* This cache stores continuation tokens indexed by query hash and offset, allowing
|
|
51
|
+
* the system to resume pagination from the nearest cached position rather than
|
|
52
|
+
* fetching all items from the beginning.
|
|
53
|
+
*
|
|
54
|
+
* Example:
|
|
55
|
+
* - User requests offset=1000, limit=10
|
|
56
|
+
* - Cache has token for offset=900
|
|
57
|
+
* - System resumes from offset=900 and skips only 100 items instead of 1000
|
|
58
|
+
*/
|
|
59
|
+
export default class PaginationCache {
|
|
60
|
+
private cache;
|
|
61
|
+
private options;
|
|
62
|
+
constructor(options?: PaginationCacheOptions);
|
|
63
|
+
/**
|
|
64
|
+
* Get the maximum allowed offset
|
|
65
|
+
*/
|
|
66
|
+
getMaxOffset(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get the cache interval (how often to store continuation tokens)
|
|
69
|
+
*/
|
|
70
|
+
getCacheInterval(): number;
|
|
71
|
+
/**
|
|
72
|
+
* Generate a unique hash for a query to use as cache key
|
|
73
|
+
* @param queryString The SQL query string
|
|
74
|
+
* @param parameters Query parameters
|
|
75
|
+
* @param partitionKey Optional partition key
|
|
76
|
+
*/
|
|
77
|
+
generateQueryHash(queryString: string, parameters?: {
|
|
78
|
+
name: string;
|
|
79
|
+
value: unknown;
|
|
80
|
+
}[], partitionKey?: string | number): string;
|
|
81
|
+
/**
|
|
82
|
+
* Find the best cached continuation token for a given offset
|
|
83
|
+
* Returns the token with the highest offset that is still <= requested offset
|
|
84
|
+
*
|
|
85
|
+
* @param queryHash The query hash
|
|
86
|
+
* @param targetOffset The target offset to reach
|
|
87
|
+
* @returns The best matching cache entry, or null if none found
|
|
88
|
+
*/
|
|
89
|
+
findBestToken(queryHash: string, targetOffset: number): CacheEntry | null;
|
|
90
|
+
/**
|
|
91
|
+
* Store a continuation token for a specific offset
|
|
92
|
+
*
|
|
93
|
+
* @param queryHash The query hash
|
|
94
|
+
* @param offset The offset this token represents
|
|
95
|
+
* @param continuationToken The Cosmos DB continuation token
|
|
96
|
+
*/
|
|
97
|
+
storeToken(queryHash: string, offset: number, continuationToken: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Clear all cached tokens for a specific query
|
|
100
|
+
* @param queryHash The query hash
|
|
101
|
+
*/
|
|
102
|
+
clearQuery(queryHash: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* Clear all cached tokens
|
|
105
|
+
*/
|
|
106
|
+
clearAll(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get cache statistics for monitoring
|
|
109
|
+
*/
|
|
110
|
+
getStats(): {
|
|
111
|
+
totalQueries: number;
|
|
112
|
+
totalEntries: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=pagination-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-cache.d.ts","sourceRoot":"","sources":["../../src/utils/pagination-cache.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,UAAU,UAAU;IAClB,uCAAuC;IACvC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,OAAO,CAAC,KAAK,CAAwC;IAErD,OAAO,CAAC,OAAO,CAAmC;gBAEtC,OAAO,GAAE,sBAA2B;IAShD;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;;;;OAKG;IACH,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,EAC/C,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAC7B,MAAM;IAUT;;;;;;;OAOG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAoCzE;;;;;;OAMG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAsC9E;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB;;OAEG;IACH,QAAQ,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;CAY3D"}
|