@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.
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wYWdpbmF0aW9uLWNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQW9DO0FBcURwQzs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQXFCLGVBQWU7SUFLbEMsWUFBWSxVQUFrQyxFQUFFO1FBSnhDLFVBQUssR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUtuRCxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2Isa0JBQWtCLEVBQUUsT0FBTyxDQUFDLGtCQUFrQixJQUFJLEdBQUc7WUFDckQsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLLElBQUksTUFBTSxFQUFFLG9CQUFvQjtZQUNwRCxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsSUFBSSxNQUFNO1lBQ3RDLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLElBQUk7U0FDN0MsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVk7UUFDVixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7SUFDcEMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsaUJBQWlCLENBQ2YsV0FBbUIsRUFDbkIsVUFBK0MsRUFDL0MsWUFBOEI7UUFFOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUMvQixLQUFLLEVBQUUsV0FBVztZQUNsQixVQUFVLEVBQUUsVUFBVSxJQUFJLEVBQUU7WUFDNUIsWUFBWTtTQUNiLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBQSxtQkFBVSxFQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILGFBQWEsQ0FBQyxTQUFpQixFQUFFLFlBQW9CO1FBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTFDLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNyQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCw4QkFBOEI7UUFDOUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWpGLElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDM0MsdUNBQXVDO1lBQ3ZDLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQzFDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFFN0IsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUVELGlFQUFpRTtRQUNqRSxJQUFJLFNBQVMsR0FBc0IsSUFBSSxDQUFDO1FBRXhDLEtBQUssTUFBTSxLQUFLLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakMsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLFlBQVksRUFBRSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNsRCxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUNwQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsVUFBVSxDQUFDLFNBQWlCLEVBQUUsTUFBYyxFQUFFLGlCQUF5QjtRQUNyRSxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUV4QyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFFRCxvREFBb0Q7UUFDcEQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDLENBQUM7UUFFbEUsSUFBSSxhQUFhLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdkIsd0JBQXdCO1lBQ3hCLE9BQU8sQ0FBQyxhQUFhLENBQUMsR0FBRztnQkFDdkIsaUJBQWlCO2dCQUNqQixNQUFNO2dCQUNOLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO2FBQ3RCLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLGdCQUFnQjtZQUNoQixPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUNYLGlCQUFpQjtnQkFDakIsTUFBTTtnQkFDTixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTthQUN0QixDQUFDLENBQUM7WUFFSCxzQ0FBc0M7WUFDdEMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTVDLHVFQUF1RTtZQUN2RSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO2dCQUNyRCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2xELE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztnQkFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILFVBQVUsQ0FBQyxTQUFpQjtRQUMxQixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRO1FBQ04sSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRO1FBQ04sSUFBSSxZQUFZLEdBQUcsQ0FBQyxDQUFDO1FBRXJCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQzFDLFlBQVksSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQ2pDLENBQUM7UUFFRCxPQUFPO1lBQ0wsWUFBWSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSTtZQUM3QixZQUFZO1NBQ2IsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQXZLRCxrQ0F1S0MifQ==
@@ -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;IAExC;;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;IAuDf;;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;CAMF"}
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"}