forge-sql-orm 2.1.24 → 2.1.26
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/README.md +126 -23
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.js +38 -1
- package/dist/core/ForgeSQLQueryBuilder.js.map +1 -1
- package/dist/core/VectorTiDB.d.ts +120 -0
- package/dist/core/VectorTiDB.d.ts.map +1 -0
- package/dist/core/VectorTiDB.js +169 -0
- package/dist/core/VectorTiDB.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/utils/cacheUtils.d.ts +13 -1
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/cacheUtils.js +60 -47
- package/dist/utils/cacheUtils.js.map +1 -1
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts +24 -4
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts.map +1 -1
- package/dist/webtriggers/clearCacheSchedulerTrigger.js +24 -4
- package/dist/webtriggers/clearCacheSchedulerTrigger.js.map +1 -1
- package/package.json +13 -13
- package/src/core/ForgeSQLQueryBuilder.ts +48 -5
- package/src/core/VectorTiDB.ts +192 -0
- package/src/core/index.ts +1 -0
- package/src/utils/cacheUtils.ts +70 -47
- package/src/webtriggers/clearCacheSchedulerTrigger.ts +24 -4
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.vectorTiDBType = void 0;
|
|
4
|
+
exports.vecFromText = vecFromText;
|
|
5
|
+
exports.vecAsText = vecAsText;
|
|
6
|
+
exports.vecDims = vecDims;
|
|
7
|
+
exports.vecL2Norm = vecL2Norm;
|
|
8
|
+
exports.vecL2Distance = vecL2Distance;
|
|
9
|
+
exports.vecCosineDistance = vecCosineDistance;
|
|
10
|
+
exports.vecNegativeInnerProduct = vecNegativeInnerProduct;
|
|
11
|
+
exports.vecL1Distance = vecL1Distance;
|
|
12
|
+
const mysql_core_1 = require("drizzle-orm/mysql-core");
|
|
13
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
14
|
+
function validateVectorValue(value) {
|
|
15
|
+
if (!Array.isArray(value)) {
|
|
16
|
+
throw new Error("TiDB vector value must be an array of numbers");
|
|
17
|
+
}
|
|
18
|
+
for (const item of value) {
|
|
19
|
+
if (typeof item !== "number" || !Number.isFinite(item)) {
|
|
20
|
+
throw new Error("TiDB vector contains invalid number");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function parseVectorText(value) {
|
|
25
|
+
const trimmed = value.trim();
|
|
26
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) {
|
|
27
|
+
throw new Error(`Invalid TiDB vector text: ${value}`);
|
|
28
|
+
}
|
|
29
|
+
// TiDB stores vectors as textual representation, e.g. "[0.3,0.5,-0.1]".
|
|
30
|
+
const parsed = JSON.parse(trimmed);
|
|
31
|
+
if (!Array.isArray(parsed)) {
|
|
32
|
+
throw new Error(`Invalid TiDB vector text: ${value}`);
|
|
33
|
+
}
|
|
34
|
+
const result = parsed.map((item) => {
|
|
35
|
+
if (typeof item !== "number" || !Number.isFinite(item)) {
|
|
36
|
+
throw new Error(`Invalid TiDB vector element: ${String(item)}`);
|
|
37
|
+
}
|
|
38
|
+
return item;
|
|
39
|
+
});
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
function vectorToText(value) {
|
|
43
|
+
validateVectorValue(value);
|
|
44
|
+
return `[${value.join(",")}]`;
|
|
45
|
+
}
|
|
46
|
+
function vectorExpr(value) {
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
return drizzle_orm_1.sql.raw(`VEC_FROM_TEXT('${vectorToText(value)}')`);
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
return drizzle_orm_1.sql.raw(value);
|
|
52
|
+
}
|
|
53
|
+
return (0, drizzle_orm_1.sql) `${value}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* TiDB `VECTOR` column type (same call shapes as other Drizzle MySQL builders).
|
|
57
|
+
*
|
|
58
|
+
* - `vectorTiDBType('embedding', { dimension: 1536 })` — SQL column name + fixed dimension (`VECTOR(1536)`).
|
|
59
|
+
* - `vectorTiDBType({ dimension: 1536 })` — config only; column name comes from the object key in `mysqlTable`.
|
|
60
|
+
* - `vectorTiDBType('embedding')` or `vectorTiDBType()` — `VECTOR` without a fixed size in DDL.
|
|
61
|
+
*
|
|
62
|
+
* Values are `number[]` in application code; the driver maps to TiDB’s text form.
|
|
63
|
+
*/
|
|
64
|
+
exports.vectorTiDBType = (0, mysql_core_1.customType)({
|
|
65
|
+
dataType(config) {
|
|
66
|
+
const dim = config?.dimension;
|
|
67
|
+
return dim ? `vector(${dim})` : "vector";
|
|
68
|
+
},
|
|
69
|
+
toDriver(value) {
|
|
70
|
+
validateVectorValue(value);
|
|
71
|
+
return `[${value.join(",")}]`;
|
|
72
|
+
},
|
|
73
|
+
fromDriver(value) {
|
|
74
|
+
if (value === null || value === undefined) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value !== "string") {
|
|
78
|
+
throw new Error(`Invalid TiDB vector driver value type: ${typeof value}`);
|
|
79
|
+
}
|
|
80
|
+
return parseVectorText(value);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Converts a text representation of a vector into a TiDB VECTOR expression.
|
|
85
|
+
*
|
|
86
|
+
* TiDB function: `VEC_FROM_TEXT(string)`.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* vecFromText("[1, 2, 3]")
|
|
90
|
+
*/
|
|
91
|
+
function vecFromText(text) {
|
|
92
|
+
return (0, drizzle_orm_1.sql) `VEC_FROM_TEXT('${text}')`;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Converts a vector value/expression to its normalized string representation.
|
|
96
|
+
*
|
|
97
|
+
* TiDB function: `VEC_AS_TEXT(vector)`.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* vecAsText(table.embedding)
|
|
101
|
+
*/
|
|
102
|
+
function vecAsText(vector) {
|
|
103
|
+
return (0, drizzle_orm_1.sql) `VEC_AS_TEXT(${vectorExpr(vector)})`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the dimension (number of elements) of a vector.
|
|
107
|
+
*
|
|
108
|
+
* TiDB function: `VEC_DIMS(vector)`.
|
|
109
|
+
*
|
|
110
|
+
* Accepts vector column/expression, `sql.raw(...)`, raw SQL string expression,
|
|
111
|
+
* or `number[]`.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* vecDims(table.embedding)
|
|
115
|
+
* vecDims(sql.raw("CAST('[0.3, 0.5, -0.1]' AS VECTOR)"))
|
|
116
|
+
* vecDims("CAST('[0.3, 0.5, -0.1]' AS VECTOR)")
|
|
117
|
+
*/
|
|
118
|
+
function vecDims(vector) {
|
|
119
|
+
return (0, drizzle_orm_1.sql) `VEC_DIMS(${vectorExpr(vector)})`;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Calculates L2 norm (Euclidean norm) of a vector.
|
|
123
|
+
*
|
|
124
|
+
* TiDB function: `VEC_L2_NORM(vector)`.
|
|
125
|
+
*/
|
|
126
|
+
function vecL2Norm(vector) {
|
|
127
|
+
return (0, drizzle_orm_1.sql) `VEC_L2_NORM(${vectorExpr(vector)})`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Calculates L2 distance (Euclidean distance) between two vectors.
|
|
131
|
+
*
|
|
132
|
+
* TiDB function: `VEC_L2_DISTANCE(vector1, vector2)`.
|
|
133
|
+
*
|
|
134
|
+
* Both vectors must have the same dimensions.
|
|
135
|
+
*/
|
|
136
|
+
function vecL2Distance(left, right) {
|
|
137
|
+
return (0, drizzle_orm_1.sql) `VEC_L2_DISTANCE(${vectorExpr(left)}, ${vectorExpr(right)})`;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Calculates cosine distance between two vectors.
|
|
141
|
+
*
|
|
142
|
+
* TiDB function: `VEC_COSINE_DISTANCE(vector1, vector2)`.
|
|
143
|
+
*
|
|
144
|
+
* Both vectors must have the same dimensions.
|
|
145
|
+
*/
|
|
146
|
+
function vecCosineDistance(left, right) {
|
|
147
|
+
return (0, drizzle_orm_1.sql) `VEC_COSINE_DISTANCE(${vectorExpr(left)}, ${vectorExpr(right)})`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Calculates negative inner product distance between two vectors.
|
|
151
|
+
*
|
|
152
|
+
* TiDB function: `VEC_NEGATIVE_INNER_PRODUCT(vector1, vector2)`.
|
|
153
|
+
*
|
|
154
|
+
* Both vectors must have the same dimensions.
|
|
155
|
+
*/
|
|
156
|
+
function vecNegativeInnerProduct(left, right) {
|
|
157
|
+
return (0, drizzle_orm_1.sql) `VEC_NEGATIVE_INNER_PRODUCT(${vectorExpr(left)}, ${vectorExpr(right)})`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Calculates L1 distance (Manhattan distance) between two vectors.
|
|
161
|
+
*
|
|
162
|
+
* TiDB function: `VEC_L1_DISTANCE(vector1, vector2)`.
|
|
163
|
+
*
|
|
164
|
+
* Both vectors must have the same dimensions.
|
|
165
|
+
*/
|
|
166
|
+
function vecL1Distance(left, right) {
|
|
167
|
+
return (0, drizzle_orm_1.sql) `VEC_L1_DISTANCE(${vectorExpr(left)}, ${vectorExpr(right)})`;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=VectorTiDB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VectorTiDB.js","sourceRoot":"","sources":["../../src/core/VectorTiDB.ts"],"names":[],"mappings":";;;AA2GA,kCAEC;AAUD,8BAEC;AAeD,0BAEC;AAOD,8BAEC;AASD,sCAEC;AASD,8CAEC;AASD,0DAEC;AASD,sCAEC;AA/LD,uDAAoD;AACpD,6CAA4D;AAM5D,SAAS,mBAAmB,CAAC,KAAe;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,wEAAwE;IACxE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,KAAe;IACnC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAChC,CAAC;AAYD,SAAS,UAAU,CAAC,KAAkB;IACpC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,iBAAG,CAAC,GAAG,CAAC,kBAAkB,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,iBAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,IAAA,iBAAG,EAAA,GAAG,KAAK,EAAE,CAAC;AACvB,CAAC;AAED;;;;;;;;GAQG;AACU,QAAA,cAAc,GAAG,IAAA,uBAAU,EAIrC;IACD,QAAQ,CAAC,MAAM;QACb,MAAM,GAAG,GAAG,MAAM,EAAE,SAAS,CAAC;QAC9B,OAAO,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3C,CAAC;IACD,QAAQ,CAAC,KAAe;QACtB,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,CAAC;IACD,UAAU,CAAC,KAAc;QACvB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,KAA4B,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,0CAA0C,OAAO,KAAK,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,IAAA,iBAAG,EAAA,kBAAkB,IAAI,IAAI,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,SAAS,CAAC,MAAmB;IAC3C,OAAO,IAAA,iBAAG,EAAQ,eAAe,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,OAAO,CAAC,MAAmB;IACzC,OAAO,IAAA,iBAAG,EAAQ,YAAY,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,MAAmB;IAC3C,OAAO,IAAA,iBAAG,EAAA,eAAe,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,IAAiB,EAAE,KAAkB;IACjE,OAAO,IAAA,iBAAG,EAAQ,mBAAmB,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;AACjF,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,IAAiB,EAAE,KAAkB;IACrE,OAAO,IAAA,iBAAG,EAAQ,uBAAuB,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;AACrF,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CAAC,IAAiB,EAAE,KAAkB;IAC3E,OAAO,IAAA,iBAAG,EAAQ,8BAA8B,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;AAC5F,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,IAAiB,EAAE,KAAkB;IACjE,OAAO,IAAA,iBAAG,EAAQ,mBAAmB,UAAU,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC;AACjF,CAAC"}
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -18,4 +18,5 @@ __exportStar(require("./ForgeSQLQueryBuilder"), exports);
|
|
|
18
18
|
__exportStar(require("./ForgeSQLCrudOperations"), exports);
|
|
19
19
|
__exportStar(require("./ForgeSQLSelectOperations"), exports);
|
|
20
20
|
__exportStar(require("./SystemTables"), exports);
|
|
21
|
+
__exportStar(require("./VectorTiDB"), exports);
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,2DAAyC;AACzC,6DAA2C;AAC3C,iDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,2DAAyC;AACzC,6DAA2C;AAC3C,iDAA+B;AAC/B,+CAA6B"}
|
|
@@ -25,6 +25,7 @@ export declare function clearCache<T extends AnyMySqlTable>(schema: T, options:
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function clearTablesCache(tables: string[], options: ForgeSqlOrmOptions): Promise<void>;
|
|
27
27
|
/**
|
|
28
|
+
* since https://developer.atlassian.com/platform/forge/changelog/#CHANGE-3038
|
|
28
29
|
* Clears expired cache entries with retry logic and performance logging.
|
|
29
30
|
*
|
|
30
31
|
* @param options - ForgeSQL ORM options
|
|
@@ -34,6 +35,10 @@ export declare function clearExpiredCache(options: ForgeSqlOrmOptions): Promise<
|
|
|
34
35
|
/**
|
|
35
36
|
* Retrieves data from cache if it exists and is not expired.
|
|
36
37
|
*
|
|
38
|
+
* Note: Due to Forge KVS asynchronous deletion (up to 48 hours), expired entries may still
|
|
39
|
+
* be returned. This function checks the expiration timestamp to filter out expired entries.
|
|
40
|
+
* If cache growth impacts performance, use the Clear Cache Scheduler Trigger.
|
|
41
|
+
*
|
|
37
42
|
* @param query - Query object with toSQL method
|
|
38
43
|
* @param options - ForgeSQL ORM options
|
|
39
44
|
* @returns Cached data if found and valid, undefined otherwise
|
|
@@ -44,11 +49,18 @@ export declare function getFromCache<T>(query: {
|
|
|
44
49
|
/**
|
|
45
50
|
* Stores query results in cache with specified TTL.
|
|
46
51
|
*
|
|
52
|
+
* Uses Forge KVS TTL feature to set expiration. Note that expired data deletion is asynchronous:
|
|
53
|
+
* expired data is not removed immediately upon expiry. Deletion may take up to 48 hours.
|
|
54
|
+
* During this window, read operations may still return expired results. If your app requires
|
|
55
|
+
* strict expiry semantics, consider using the Clear Cache Scheduler Trigger to proactively
|
|
56
|
+
* clean up expired entries, especially if cache growth impacts INSERT/UPDATE performance.
|
|
57
|
+
*
|
|
47
58
|
* @param query - Query object with toSQL method
|
|
48
59
|
* @param options - ForgeSQL ORM options
|
|
49
60
|
* @param results - Data to cache
|
|
50
|
-
* @param cacheTtl - Time to live in seconds
|
|
61
|
+
* @param cacheTtl - Time to live in seconds (maximum TTL is 1 year from write time)
|
|
51
62
|
* @returns Promise that resolves when data is stored in cache
|
|
63
|
+
* @see https://developer.atlassian.com/platform/forge/runtime-reference/storage-api-basic-api/#ttl
|
|
52
64
|
*/
|
|
53
65
|
export declare function setCacheResult(query: {
|
|
54
66
|
toSQL: () => Query;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"cacheUtils.d.ts","sourceRoot":"","sources":["../../src/utils/cacheUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAoElE;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAK5C;AAiKD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,aAAa,EACtD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAiBf;AACD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,KAAK,CAAA;CAAE,EAC7B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CA2CxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,KAAK,CAAA;CAAE,EAC7B,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAyCf"}
|
package/dist/utils/cacheUtils.js
CHANGED
|
@@ -77,6 +77,29 @@ function nowPlusSeconds(secondsToAdd) {
|
|
|
77
77
|
const dt = luxon_1.DateTime.now().plus({ seconds: secondsToAdd });
|
|
78
78
|
return Math.floor(dt.toSeconds());
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Logs a message to console.debug when options.logCache is enabled.
|
|
82
|
+
*
|
|
83
|
+
* @param message - Message to log
|
|
84
|
+
* @param options - ForgeSQL ORM options (optional)
|
|
85
|
+
*/
|
|
86
|
+
function debugLog(message, options) {
|
|
87
|
+
if (options?.logCache) {
|
|
88
|
+
// eslint-disable-next-line no-console
|
|
89
|
+
console.debug(message);
|
|
90
|
+
}
|
|
91
|
+
} /**
|
|
92
|
+
* Logs a message to console.debug when options.logCache is enabled.
|
|
93
|
+
*
|
|
94
|
+
* @param message - Message to log
|
|
95
|
+
* @param options - ForgeSQL ORM options (optional)
|
|
96
|
+
*/
|
|
97
|
+
function warnLog(message, options) {
|
|
98
|
+
if (options?.logCache) {
|
|
99
|
+
// eslint-disable-next-line no-console
|
|
100
|
+
console.warn(message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
80
103
|
/**
|
|
81
104
|
* Generates a hash key for a query based on its SQL and parameters.
|
|
82
105
|
*
|
|
@@ -94,16 +117,14 @@ function hashKey(query) {
|
|
|
94
117
|
*
|
|
95
118
|
* @param results - Array of cache entries to delete
|
|
96
119
|
* @param cacheEntityName - Name of the cache entity
|
|
120
|
+
* @param options - Forge SQL ORM properties
|
|
97
121
|
* @returns Promise that resolves when all deletions are complete
|
|
98
122
|
*/
|
|
99
|
-
async function deleteCacheEntriesInBatches(results, cacheEntityName) {
|
|
123
|
+
async function deleteCacheEntriesInBatches(results, cacheEntityName, options) {
|
|
100
124
|
for (let i = 0; i < results.length; i += CACHE_CONSTANTS.BATCH_SIZE) {
|
|
101
125
|
const batch = results.slice(i, i + CACHE_CONSTANTS.BATCH_SIZE);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
transactionBuilder = transactionBuilder.delete(result.key, { entityName: cacheEntityName });
|
|
105
|
-
}
|
|
106
|
-
await transactionBuilder.execute();
|
|
126
|
+
const batchResult = await kvs_1.kvs.batchDelete(batch.map((result) => ({ key: result.key, entityName: cacheEntityName })));
|
|
127
|
+
batchResult.failedKeys.forEach((failedKey) => warnLog(JSON.stringify(failedKey), options));
|
|
107
128
|
}
|
|
108
129
|
}
|
|
109
130
|
/**
|
|
@@ -134,11 +155,8 @@ async function clearCursorCache(tables, cursor, options) {
|
|
|
134
155
|
entityQueryBuilder = entityQueryBuilder.cursor(cursor);
|
|
135
156
|
}
|
|
136
157
|
const listResult = await entityQueryBuilder.limit(100).getMany();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
console.warn(`clear cache Records: ${JSON.stringify(listResult.results.map((r) => r.key))}`);
|
|
140
|
-
}
|
|
141
|
-
await deleteCacheEntriesInBatches(listResult.results, cacheEntityName);
|
|
158
|
+
debugLog(`clear cache Records: ${JSON.stringify(listResult.results.map((r) => r.key))}`, options);
|
|
159
|
+
await deleteCacheEntriesInBatches(listResult.results, cacheEntityName, options);
|
|
142
160
|
if (listResult.nextCursor) {
|
|
143
161
|
return (listResult.results.length + (await clearCursorCache(tables, listResult.nextCursor, options)));
|
|
144
162
|
}
|
|
@@ -168,10 +186,7 @@ async function clearExpirationCursorCache(cursor, options) {
|
|
|
168
186
|
entityQueryBuilder = entityQueryBuilder.cursor(cursor);
|
|
169
187
|
}
|
|
170
188
|
const listResult = await entityQueryBuilder.limit(100).getMany();
|
|
171
|
-
|
|
172
|
-
// eslint-disable-next-line no-console
|
|
173
|
-
console.warn(`clear expired Records: ${JSON.stringify(listResult.results.map((r) => r.key))}`);
|
|
174
|
-
}
|
|
189
|
+
debugLog(`clear expired Records: ${JSON.stringify(listResult.results.map((r) => r.key))}`, options);
|
|
175
190
|
await deleteCacheEntriesInBatches(listResult.results, cacheEntityName);
|
|
176
191
|
if (listResult.nextCursor) {
|
|
177
192
|
return (listResult.results.length + (await clearExpirationCursorCache(listResult.nextCursor, options)));
|
|
@@ -243,14 +258,12 @@ async function clearTablesCache(tables, options) {
|
|
|
243
258
|
totalRecords = await executeWithRetry(() => clearCursorCache(tables, "", options), "clearing cache");
|
|
244
259
|
}
|
|
245
260
|
finally {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
// eslint-disable-next-line no-console
|
|
249
|
-
console.info(`Cleared ${totalRecords} cache records in ${duration} seconds`);
|
|
250
|
-
}
|
|
261
|
+
const duration = luxon_1.DateTime.now().toSeconds() - startTime.toSeconds();
|
|
262
|
+
debugLog(`Cleared ${totalRecords} cache records in ${duration} seconds`, options);
|
|
251
263
|
}
|
|
252
264
|
}
|
|
253
265
|
/**
|
|
266
|
+
* since https://developer.atlassian.com/platform/forge/changelog/#CHANGE-3038
|
|
254
267
|
* Clears expired cache entries with retry logic and performance logging.
|
|
255
268
|
*
|
|
256
269
|
* @param options - ForgeSQL ORM options
|
|
@@ -267,15 +280,16 @@ async function clearExpiredCache(options) {
|
|
|
267
280
|
}
|
|
268
281
|
finally {
|
|
269
282
|
const duration = luxon_1.DateTime.now().toSeconds() - startTime.toSeconds();
|
|
270
|
-
|
|
271
|
-
// eslint-disable-next-line no-console
|
|
272
|
-
console.debug(`Cleared ${totalRecords} expired cache records in ${duration} seconds`);
|
|
273
|
-
}
|
|
283
|
+
debugLog(`Cleared ${totalRecords} expired cache records in ${duration} seconds`, options);
|
|
274
284
|
}
|
|
275
285
|
}
|
|
276
286
|
/**
|
|
277
287
|
* Retrieves data from cache if it exists and is not expired.
|
|
278
288
|
*
|
|
289
|
+
* Note: Due to Forge KVS asynchronous deletion (up to 48 hours), expired entries may still
|
|
290
|
+
* be returned. This function checks the expiration timestamp to filter out expired entries.
|
|
291
|
+
* If cache growth impacts performance, use the Clear Cache Scheduler Trigger.
|
|
292
|
+
*
|
|
279
293
|
* @param query - Query object with toSQL method
|
|
280
294
|
* @param options - ForgeSQL ORM options
|
|
281
295
|
* @returns Cached data if found and valid, undefined otherwise
|
|
@@ -291,23 +305,21 @@ async function getFromCache(query, options) {
|
|
|
291
305
|
const key = hashKey(sqlQuery);
|
|
292
306
|
// Skip cache if table is in cache context (will be cleared)
|
|
293
307
|
if (await (0, cacheContextUtils_1.isTableContainsTableInCacheContext)(sqlQuery.sql, options)) {
|
|
294
|
-
|
|
295
|
-
// eslint-disable-next-line no-console
|
|
296
|
-
console.warn(`Context contains value to clear. Skip getting from cache`);
|
|
297
|
-
}
|
|
308
|
+
debugLog("Context contains value to clear. Skip getting from cache", options);
|
|
298
309
|
return undefined;
|
|
299
310
|
}
|
|
300
311
|
try {
|
|
301
312
|
const cacheResult = await kvs_1.kvs.entity(options.cacheEntityName).get(key);
|
|
302
|
-
if (cacheResult
|
|
303
|
-
cacheResult[expirationName] >= getCurrentTime() &&
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
313
|
+
if (cacheResult) {
|
|
314
|
+
if (cacheResult[expirationName] >= getCurrentTime() &&
|
|
315
|
+
(0, cacheTableUtils_1.extractBacktickedValues)(sqlQuery.sql, options) === cacheResult[entityQueryName]) {
|
|
316
|
+
debugLog(`Get value from cache, cacheKey: ${key}`, options);
|
|
317
|
+
const results = cacheResult[dataName];
|
|
318
|
+
return JSON.parse(results);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
debugLog(`Expired cache entry still exists (will be automatically removed within 48 hours per Forge KVS TTL documentation), cacheKey: ${key}`, options);
|
|
308
322
|
}
|
|
309
|
-
const results = cacheResult[dataName];
|
|
310
|
-
return JSON.parse(results);
|
|
311
323
|
}
|
|
312
324
|
}
|
|
313
325
|
catch (error) {
|
|
@@ -319,11 +331,18 @@ async function getFromCache(query, options) {
|
|
|
319
331
|
/**
|
|
320
332
|
* Stores query results in cache with specified TTL.
|
|
321
333
|
*
|
|
334
|
+
* Uses Forge KVS TTL feature to set expiration. Note that expired data deletion is asynchronous:
|
|
335
|
+
* expired data is not removed immediately upon expiry. Deletion may take up to 48 hours.
|
|
336
|
+
* During this window, read operations may still return expired results. If your app requires
|
|
337
|
+
* strict expiry semantics, consider using the Clear Cache Scheduler Trigger to proactively
|
|
338
|
+
* clean up expired entries, especially if cache growth impacts INSERT/UPDATE performance.
|
|
339
|
+
*
|
|
322
340
|
* @param query - Query object with toSQL method
|
|
323
341
|
* @param options - ForgeSQL ORM options
|
|
324
342
|
* @param results - Data to cache
|
|
325
|
-
* @param cacheTtl - Time to live in seconds
|
|
343
|
+
* @param cacheTtl - Time to live in seconds (maximum TTL is 1 year from write time)
|
|
326
344
|
* @returns Promise that resolves when data is stored in cache
|
|
345
|
+
* @see https://developer.atlassian.com/platform/forge/runtime-reference/storage-api-basic-api/#ttl
|
|
327
346
|
*/
|
|
328
347
|
async function setCacheResult(query, options, results, cacheTtl) {
|
|
329
348
|
if (!options.cacheEntityName) {
|
|
@@ -336,10 +355,7 @@ async function setCacheResult(query, options, results, cacheTtl) {
|
|
|
336
355
|
const sqlQuery = query.toSQL();
|
|
337
356
|
// Skip cache if table is in cache context (will be cleared)
|
|
338
357
|
if (await (0, cacheContextUtils_1.isTableContainsTableInCacheContext)(sqlQuery.sql, options)) {
|
|
339
|
-
|
|
340
|
-
// eslint-disable-next-line no-console
|
|
341
|
-
console.warn(`Context contains value to clear. Skip setting from cache`);
|
|
342
|
-
}
|
|
358
|
+
debugLog("Context contains value to clear. Skip setting from cache", options);
|
|
343
359
|
return;
|
|
344
360
|
}
|
|
345
361
|
const key = hashKey(sqlQuery);
|
|
@@ -347,14 +363,11 @@ async function setCacheResult(query, options, results, cacheTtl) {
|
|
|
347
363
|
.transact()
|
|
348
364
|
.set(key, {
|
|
349
365
|
[entityQueryName]: (0, cacheTableUtils_1.extractBacktickedValues)(sqlQuery.sql, options),
|
|
350
|
-
[expirationName]: nowPlusSeconds(cacheTtl),
|
|
366
|
+
[expirationName]: nowPlusSeconds(cacheTtl + 2),
|
|
351
367
|
[dataName]: JSON.stringify(results),
|
|
352
|
-
}, { entityName: options.cacheEntityName })
|
|
368
|
+
}, { entityName: options.cacheEntityName }, { ttl: { value: cacheTtl, unit: "SECONDS" } })
|
|
353
369
|
.execute();
|
|
354
|
-
|
|
355
|
-
// eslint-disable-next-line no-console
|
|
356
|
-
console.warn(`Store value to cache, cacheKey: ${key}`);
|
|
357
|
-
}
|
|
370
|
+
debugLog(`Store value to cache, cacheKey: ${key}`, options);
|
|
358
371
|
}
|
|
359
372
|
catch (error) {
|
|
360
373
|
// eslint-disable-next-line no-console
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cacheUtils.js","sourceRoot":"","sources":["../../src/utils/cacheUtils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"cacheUtils.js","sourceRoot":"","sources":["../../src/utils/cacheUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import { ForgeSqlOrmOptions } from "../core/ForgeSQLQueryBuilder";
|
|
2
2
|
/**
|
|
3
|
-
* Scheduler trigger for clearing expired cache entries.
|
|
3
|
+
* Scheduler trigger for proactively clearing expired cache entries.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* **Why this trigger is needed:**
|
|
6
|
+
*
|
|
7
|
+
* While forge-sql-orm uses Forge KVS TTL feature to mark entries as expired, **actual deletion
|
|
8
|
+
* is asynchronous and may take up to 48 hours**. During this window, expired entries remain in
|
|
9
|
+
* storage and can impact INSERT/UPDATE performance if the cache grows large.
|
|
10
|
+
*
|
|
11
|
+
* This scheduler trigger proactively cleans up expired entries by querying the expiration index
|
|
12
|
+
* and deleting entries where expiration < now, preventing cache growth from impacting data
|
|
13
|
+
* modification operations.
|
|
14
|
+
*
|
|
15
|
+
* **When to use:**
|
|
16
|
+
* - Your cache grows large over time
|
|
17
|
+
* - INSERT/UPDATE operations are slowing down due to cache size
|
|
18
|
+
* - You need strict expiry semantics (immediate cleanup)
|
|
19
|
+
* - You want to reduce storage costs proactively
|
|
20
|
+
*
|
|
21
|
+
* **When optional:**
|
|
22
|
+
* - Small cache footprint
|
|
23
|
+
* - No performance impact on data modifications
|
|
24
|
+
* - You can tolerate expired entries being returned for up to 48 hours
|
|
7
25
|
*
|
|
8
26
|
* @note This function is automatically disabled in production environments and will return a 500 error if called.
|
|
9
27
|
*
|
|
@@ -26,7 +44,7 @@ import { ForgeSqlOrmOptions } from "../core/ForgeSQLQueryBuilder";
|
|
|
26
44
|
*
|
|
27
45
|
* @example
|
|
28
46
|
* ```yaml
|
|
29
|
-
* # In manifest.yml
|
|
47
|
+
* # In manifest.yml (optional - only if cache growth impacts INSERT/UPDATE performance)
|
|
30
48
|
* scheduledTrigger:
|
|
31
49
|
* - key: clear-cache-trigger
|
|
32
50
|
* function: clearCache
|
|
@@ -36,6 +54,8 @@ import { ForgeSqlOrmOptions } from "../core/ForgeSQLQueryBuilder";
|
|
|
36
54
|
* - key: clearCache
|
|
37
55
|
* handler: index.clearCache
|
|
38
56
|
* ```
|
|
57
|
+
*
|
|
58
|
+
* @see https://developer.atlassian.com/platform/forge/runtime-reference/storage-api-basic-api/#ttl
|
|
39
59
|
*/
|
|
40
60
|
export declare const clearCacheSchedulerTrigger: (options?: ForgeSqlOrmOptions) => Promise<{
|
|
41
61
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearCacheSchedulerTrigger.d.ts","sourceRoot":"","sources":["../../src/webtriggers/clearCacheSchedulerTrigger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE
|
|
1
|
+
{"version":3,"file":"clearCacheSchedulerTrigger.d.ts","sourceRoot":"","sources":["../../src/webtriggers/clearCacheSchedulerTrigger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,0BAA0B,GAAU,UAAU,kBAAkB;;;;;;;EAwC5E,CAAC"}
|
|
@@ -3,10 +3,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.clearCacheSchedulerTrigger = void 0;
|
|
4
4
|
const cacheUtils_1 = require("../utils/cacheUtils");
|
|
5
5
|
/**
|
|
6
|
-
* Scheduler trigger for clearing expired cache entries.
|
|
6
|
+
* Scheduler trigger for proactively clearing expired cache entries.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* **Why this trigger is needed:**
|
|
9
|
+
*
|
|
10
|
+
* While forge-sql-orm uses Forge KVS TTL feature to mark entries as expired, **actual deletion
|
|
11
|
+
* is asynchronous and may take up to 48 hours**. During this window, expired entries remain in
|
|
12
|
+
* storage and can impact INSERT/UPDATE performance if the cache grows large.
|
|
13
|
+
*
|
|
14
|
+
* This scheduler trigger proactively cleans up expired entries by querying the expiration index
|
|
15
|
+
* and deleting entries where expiration < now, preventing cache growth from impacting data
|
|
16
|
+
* modification operations.
|
|
17
|
+
*
|
|
18
|
+
* **When to use:**
|
|
19
|
+
* - Your cache grows large over time
|
|
20
|
+
* - INSERT/UPDATE operations are slowing down due to cache size
|
|
21
|
+
* - You need strict expiry semantics (immediate cleanup)
|
|
22
|
+
* - You want to reduce storage costs proactively
|
|
23
|
+
*
|
|
24
|
+
* **When optional:**
|
|
25
|
+
* - Small cache footprint
|
|
26
|
+
* - No performance impact on data modifications
|
|
27
|
+
* - You can tolerate expired entries being returned for up to 48 hours
|
|
10
28
|
*
|
|
11
29
|
* @note This function is automatically disabled in production environments and will return a 500 error if called.
|
|
12
30
|
*
|
|
@@ -29,7 +47,7 @@ const cacheUtils_1 = require("../utils/cacheUtils");
|
|
|
29
47
|
*
|
|
30
48
|
* @example
|
|
31
49
|
* ```yaml
|
|
32
|
-
* # In manifest.yml
|
|
50
|
+
* # In manifest.yml (optional - only if cache growth impacts INSERT/UPDATE performance)
|
|
33
51
|
* scheduledTrigger:
|
|
34
52
|
* - key: clear-cache-trigger
|
|
35
53
|
* function: clearCache
|
|
@@ -39,6 +57,8 @@ const cacheUtils_1 = require("../utils/cacheUtils");
|
|
|
39
57
|
* - key: clearCache
|
|
40
58
|
* handler: index.clearCache
|
|
41
59
|
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see https://developer.atlassian.com/platform/forge/runtime-reference/storage-api-basic-api/#ttl
|
|
42
62
|
*/
|
|
43
63
|
const clearCacheSchedulerTrigger = async (options) => {
|
|
44
64
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearCacheSchedulerTrigger.js","sourceRoot":"","sources":["../../src/webtriggers/clearCacheSchedulerTrigger.ts"],"names":[],"mappings":";;;AAAA,oDAAwD;AAGxD
|
|
1
|
+
{"version":3,"file":"clearCacheSchedulerTrigger.js","sourceRoot":"","sources":["../../src/webtriggers/clearCacheSchedulerTrigger.ts"],"names":[],"mappings":";;;AAAA,oDAAwD;AAGxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACI,MAAM,0BAA0B,GAAG,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC/E,IAAI,CAAC;QACH,MAAM,UAAU,GAAuB,OAAO,IAAI;YAChD,cAAc,EAAE,KAAK;YACrB,wBAAwB,EAAE,KAAK;YAC/B,QAAQ,EAAE,GAAG;YACb,eAAe,EAAE,OAAO;YACxB,oBAAoB,EAAE,KAAK;YAC3B,yBAAyB,EAAE,YAAY;YACvC,mBAAmB,EAAE,MAAM;SAC5B,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,IAAA,8BAAiB,EAAC,UAAU,CAAC,CAAC;QAEpC,OAAO;YACL,OAAO,EAAE,EAAE,cAAc,EAAE,CAAC,kBAAkB,CAAC,EAAE;YACjD,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,IAAI;YAChB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,sCAAsC;gBAC/C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACrE,OAAO;YACL,OAAO,EAAE,EAAE,cAAc,EAAE,CAAC,kBAAkB,CAAC,EAAE;YACjD,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,uBAAuB;YACnC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,oCAAoC;gBACpF,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAxCW,QAAA,0BAA0B,8BAwCrC"}
|