forge-sql-orm 2.0.30 → 2.1.0
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 +1090 -81
- package/dist/ForgeSQLORM.js +1080 -60
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +1063 -60
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLAnalyseOperations.d.ts +1 -1
- package/dist/core/ForgeSQLAnalyseOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLCacheOperations.d.ts +119 -0
- package/dist/core/ForgeSQLCacheOperations.d.ts.map +1 -0
- package/dist/core/ForgeSQLCrudOperations.d.ts +38 -22
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +104 -13
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +243 -15
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts +42 -0
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -0
- package/dist/utils/cacheContextUtils.d.ts +123 -0
- package/dist/utils/cacheContextUtils.d.ts.map +1 -0
- package/dist/utils/cacheUtils.d.ts +56 -0
- package/dist/utils/cacheUtils.d.ts.map +1 -0
- package/dist/utils/sqlUtils.d.ts +8 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts +46 -0
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts.map +1 -0
- package/dist/webtriggers/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/package.json +15 -12
- package/src/core/ForgeSQLAnalyseOperations.ts +1 -1
- package/src/core/ForgeSQLCacheOperations.ts +195 -0
- package/src/core/ForgeSQLCrudOperations.ts +49 -40
- package/src/core/ForgeSQLORM.ts +443 -34
- package/src/core/ForgeSQLQueryBuilder.ts +291 -20
- package/src/index.ts +1 -1
- package/src/lib/drizzle/extensions/additionalActions.ts +548 -0
- package/src/lib/drizzle/extensions/types.d.ts +68 -10
- package/src/utils/cacheContextUtils.ts +210 -0
- package/src/utils/cacheUtils.ts +403 -0
- package/src/utils/sqlUtils.ts +16 -0
- package/src/webtriggers/clearCacheSchedulerTrigger.ts +79 -0
- package/src/webtriggers/index.ts +1 -0
- package/dist/lib/drizzle/extensions/selectAliased.d.ts +0 -9
- package/dist/lib/drizzle/extensions/selectAliased.d.ts.map +0 -1
- package/src/lib/drizzle/extensions/selectAliased.ts +0 -72
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -1,18 +1,41 @@
|
|
|
1
1
|
import { ForgeSQLCrudOperations } from "./ForgeSQLCrudOperations";
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
VerioningModificationForgeSQL,
|
|
4
4
|
ForgeSqlOperation,
|
|
5
5
|
ForgeSqlOrmOptions,
|
|
6
6
|
SchemaAnalyzeForgeSql,
|
|
7
7
|
SchemaSqlForgeSql,
|
|
8
8
|
} from "./ForgeSQLQueryBuilder";
|
|
9
9
|
import { ForgeSQLSelectOperations } from "./ForgeSQLSelectOperations";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
drizzle,
|
|
12
|
+
MySqlRemoteDatabase,
|
|
13
|
+
MySqlRemotePreparedQueryHKT,
|
|
14
|
+
MySqlRemoteQueryResultHKT,
|
|
15
|
+
} from "drizzle-orm/mysql-proxy";
|
|
11
16
|
import { createForgeDriverProxy } from "../utils/forgeDriverProxy";
|
|
12
17
|
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
13
18
|
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
DeleteAndEvictCacheType,
|
|
21
|
+
InsertAndEvictCacheType,
|
|
22
|
+
patchDbWithSelectAliased,
|
|
23
|
+
SelectAliasedCacheableType,
|
|
24
|
+
SelectAliasedDistinctCacheableType,
|
|
25
|
+
SelectAliasedDistinctType,
|
|
26
|
+
SelectAliasedType,
|
|
27
|
+
UpdateAndEvictCacheType,
|
|
28
|
+
} from "../lib/drizzle/extensions/additionalActions";
|
|
15
29
|
import { ForgeSQLAnalyseOperation } from "./ForgeSQLAnalyseOperations";
|
|
30
|
+
import { ForgeSQLCacheOperations } from "./ForgeSQLCacheOperations";
|
|
31
|
+
import type { MySqlTable } from "drizzle-orm/mysql-core/table";
|
|
32
|
+
import {
|
|
33
|
+
MySqlDeleteBase,
|
|
34
|
+
MySqlInsertBuilder,
|
|
35
|
+
MySqlUpdateBuilder,
|
|
36
|
+
} from "drizzle-orm/mysql-core/query-builders";
|
|
37
|
+
import { cacheApplicationContext, localCacheApplicationContext } from "../utils/cacheContextUtils";
|
|
38
|
+
import { clearTablesCache } from "../utils/cacheUtils";
|
|
16
39
|
|
|
17
40
|
/**
|
|
18
41
|
* Implementation of ForgeSQLORM that uses Drizzle ORM for query building.
|
|
@@ -22,16 +45,22 @@ import { ForgeSQLAnalyseOperation } from "./ForgeSQLAnalyseOperations";
|
|
|
22
45
|
class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
23
46
|
private static instance: ForgeSQLORMImpl | null = null;
|
|
24
47
|
private readonly drizzle: MySqlRemoteDatabase<any> & {
|
|
25
|
-
selectAliased:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
48
|
+
selectAliased: SelectAliasedType;
|
|
49
|
+
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
50
|
+
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
51
|
+
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
52
|
+
insertWithCacheContext: InsertAndEvictCacheType;
|
|
53
|
+
insertAndEvictCache: InsertAndEvictCacheType;
|
|
54
|
+
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
55
|
+
updateWithCacheContext: UpdateAndEvictCacheType;
|
|
56
|
+
deleteAndEvictCache: DeleteAndEvictCacheType;
|
|
57
|
+
deleteWithCacheContext: DeleteAndEvictCacheType;
|
|
31
58
|
};
|
|
32
|
-
private readonly crudOperations:
|
|
59
|
+
private readonly crudOperations: VerioningModificationForgeSQL;
|
|
33
60
|
private readonly fetchOperations: SchemaSqlForgeSql;
|
|
34
61
|
private readonly analyzeOperations: SchemaAnalyzeForgeSql;
|
|
62
|
+
private readonly cacheOperations: ForgeSQLCacheOperations;
|
|
63
|
+
private readonly options: ForgeSqlOrmOptions;
|
|
35
64
|
|
|
36
65
|
/**
|
|
37
66
|
* Private constructor to enforce singleton behavior.
|
|
@@ -42,7 +71,13 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
42
71
|
const newOptions: ForgeSqlOrmOptions = options ?? {
|
|
43
72
|
logRawSqlQuery: false,
|
|
44
73
|
disableOptimisticLocking: false,
|
|
74
|
+
cacheWrapTable: true,
|
|
75
|
+
cacheTTL: 120,
|
|
76
|
+
cacheEntityQueryName: "sql",
|
|
77
|
+
cacheEntityExpirationName: "expiration",
|
|
78
|
+
cacheEntityDataName: "data",
|
|
45
79
|
};
|
|
80
|
+
this.options = newOptions;
|
|
46
81
|
if (newOptions.logRawSqlQuery) {
|
|
47
82
|
console.debug("Initializing ForgeSQLORM...");
|
|
48
83
|
}
|
|
@@ -50,21 +85,191 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
50
85
|
const proxiedDriver = createForgeDriverProxy(newOptions.hints, newOptions.logRawSqlQuery);
|
|
51
86
|
this.drizzle = patchDbWithSelectAliased(
|
|
52
87
|
drizzle(proxiedDriver, { logger: newOptions.logRawSqlQuery }),
|
|
88
|
+
newOptions,
|
|
53
89
|
);
|
|
54
90
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
55
91
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
56
92
|
this.analyzeOperations = new ForgeSQLAnalyseOperation(this);
|
|
93
|
+
this.cacheOperations = new ForgeSQLCacheOperations(newOptions, this);
|
|
57
94
|
} catch (error) {
|
|
58
95
|
console.error("ForgeSQLORM initialization failed:", error);
|
|
59
96
|
throw error;
|
|
60
97
|
}
|
|
61
98
|
}
|
|
62
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Executes operations within a cache context that collects cache eviction events.
|
|
102
|
+
* All clearCache calls within the context are collected and executed in batch at the end.
|
|
103
|
+
* Queries executed within this context will bypass cache for tables that were marked for clearing.
|
|
104
|
+
*
|
|
105
|
+
* This is useful for:
|
|
106
|
+
* - Batch operations that affect multiple tables
|
|
107
|
+
* - Transaction-like operations where you want to clear cache only at the end
|
|
108
|
+
* - Performance optimization by reducing cache clear operations
|
|
109
|
+
*
|
|
110
|
+
* @param cacheContext - Function containing operations that may trigger cache evictions
|
|
111
|
+
* @returns Promise that resolves when all operations and cache clearing are complete
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* await forgeSQL.executeWithCacheContext(async () => {
|
|
116
|
+
* await forgeSQL.modifyWithVersioning().insert(users, userData);
|
|
117
|
+
* await forgeSQL.modifyWithVersioning().insert(orders, orderData);
|
|
118
|
+
* // Cache for both users and orders tables will be cleared at the end
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
executeWithCacheContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
123
|
+
return this.executeWithCacheContextAndReturnValue<void>(cacheContext);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Executes operations within a cache context and returns a value.
|
|
128
|
+
* All clearCache calls within the context are collected and executed in batch at the end.
|
|
129
|
+
* Queries executed within this context will bypass cache for tables that were marked for clearing.
|
|
130
|
+
*
|
|
131
|
+
* @param cacheContext - Function containing operations that may trigger cache evictions
|
|
132
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const result = await forgeSQL.executeWithCacheContextAndReturnValue(async () => {
|
|
137
|
+
* await forgeSQL.modifyWithVersioning().insert(users, userData);
|
|
138
|
+
* return await forgeSQL.fetch().executeQueryOnlyOne(selectUserQuery);
|
|
139
|
+
* });
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
async executeWithCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
143
|
+
return await this.executeWithLocalCacheContextAndReturnValue(
|
|
144
|
+
async () =>
|
|
145
|
+
await cacheApplicationContext.run({ tables: new Set<string>() }, async () => {
|
|
146
|
+
try {
|
|
147
|
+
return await cacheContext();
|
|
148
|
+
} finally {
|
|
149
|
+
await clearTablesCache(
|
|
150
|
+
Array.from(cacheApplicationContext.getStore()?.tables ?? []),
|
|
151
|
+
this.options,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Executes operations within a local cache context and returns a value.
|
|
159
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
160
|
+
*
|
|
161
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
162
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
163
|
+
*/
|
|
164
|
+
async executeWithLocalCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
165
|
+
return await localCacheApplicationContext.run({ cache: {} }, async () => {
|
|
166
|
+
return await cacheContext();
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Executes operations within a local cache context.
|
|
172
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
173
|
+
*
|
|
174
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
175
|
+
* @returns Promise that resolves when all operations are complete
|
|
176
|
+
*/
|
|
177
|
+
executeWithLocalContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
178
|
+
return this.executeWithLocalCacheContextAndReturnValue<void>(cacheContext);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates an insert query builder.
|
|
182
|
+
*
|
|
183
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
184
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
185
|
+
*
|
|
186
|
+
* @param table - The table to insert into
|
|
187
|
+
* @returns Insert query builder (no versioning, no cache management)
|
|
188
|
+
*/
|
|
189
|
+
insert<TTable extends MySqlTable>(
|
|
190
|
+
table: TTable,
|
|
191
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
192
|
+
return this.drizzle.insertWithCacheContext(table);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Creates an insert query builder that automatically evicts cache after execution.
|
|
196
|
+
*
|
|
197
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
198
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
199
|
+
*
|
|
200
|
+
* @param table - The table to insert into
|
|
201
|
+
* @returns Insert query builder with automatic cache eviction (no versioning)
|
|
202
|
+
*/
|
|
203
|
+
insertAndEvictCache<TTable extends MySqlTable>(
|
|
204
|
+
table: TTable,
|
|
205
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
206
|
+
return this.drizzle.insertAndEvictCache(table);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Creates an update query builder that automatically evicts cache after execution.
|
|
211
|
+
*
|
|
212
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
213
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
214
|
+
*
|
|
215
|
+
* @param table - The table to update
|
|
216
|
+
* @returns Update query builder with automatic cache eviction (no versioning)
|
|
217
|
+
*/
|
|
218
|
+
updateAndEvictCache<TTable extends MySqlTable>(
|
|
219
|
+
table: TTable,
|
|
220
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
221
|
+
return this.drizzle.updateAndEvictCache(table);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates an update query builder.
|
|
226
|
+
*
|
|
227
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
228
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
229
|
+
*
|
|
230
|
+
* @param table - The table to update
|
|
231
|
+
* @returns Update query builder (no versioning, no cache management)
|
|
232
|
+
*/
|
|
233
|
+
update<TTable extends MySqlTable>(
|
|
234
|
+
table: TTable,
|
|
235
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
236
|
+
return this.drizzle.updateWithCacheContext(table);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Creates a delete query builder.
|
|
241
|
+
*
|
|
242
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
243
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
244
|
+
*
|
|
245
|
+
* @param table - The table to delete from
|
|
246
|
+
* @returns Delete query builder (no versioning, no cache management)
|
|
247
|
+
*/
|
|
248
|
+
delete<TTable extends MySqlTable>(
|
|
249
|
+
table: TTable,
|
|
250
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
251
|
+
return this.drizzle.deleteWithCacheContext(table);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Creates a delete query builder that automatically evicts cache after execution.
|
|
255
|
+
*
|
|
256
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
257
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
258
|
+
*
|
|
259
|
+
* @param table - The table to delete from
|
|
260
|
+
* @returns Delete query builder with automatic cache eviction (no versioning)
|
|
261
|
+
*/
|
|
262
|
+
deleteAndEvictCache<TTable extends MySqlTable>(
|
|
263
|
+
table: TTable,
|
|
264
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
265
|
+
return this.drizzle.deleteAndEvictCache(table);
|
|
266
|
+
}
|
|
267
|
+
|
|
63
268
|
/**
|
|
64
269
|
* Create the modify operations instance.
|
|
65
270
|
* @returns modify operations.
|
|
66
271
|
*/
|
|
67
|
-
|
|
272
|
+
modifyWithVersioning(): VerioningModificationForgeSQL {
|
|
68
273
|
return this.crudOperations;
|
|
69
274
|
}
|
|
70
275
|
|
|
@@ -78,14 +283,6 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
78
283
|
return ForgeSQLORMImpl.instance;
|
|
79
284
|
}
|
|
80
285
|
|
|
81
|
-
/**
|
|
82
|
-
* Retrieves the CRUD operations instance.
|
|
83
|
-
* @returns CRUD operations.
|
|
84
|
-
*/
|
|
85
|
-
crud(): CRUDForgeSQL {
|
|
86
|
-
return this.modify();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
286
|
/**
|
|
90
287
|
* Retrieves the fetch operations instance.
|
|
91
288
|
* @returns Fetch operations.
|
|
@@ -93,10 +290,29 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
93
290
|
fetch(): SchemaSqlForgeSql {
|
|
94
291
|
return this.fetchOperations;
|
|
95
292
|
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.
|
|
296
|
+
* @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance
|
|
297
|
+
*/
|
|
96
298
|
analyze(): SchemaAnalyzeForgeSql {
|
|
97
299
|
return this.analyzeOperations;
|
|
98
300
|
}
|
|
99
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Provides schema-level SQL operations with optimistic locking/versioning and automatic cache eviction.
|
|
304
|
+
*
|
|
305
|
+
* This method returns operations that use `modifyWithVersioning()` internally, providing:
|
|
306
|
+
* - Optimistic locking support
|
|
307
|
+
* - Automatic version field management
|
|
308
|
+
* - Cache eviction after successful operations
|
|
309
|
+
*
|
|
310
|
+
* @returns {ForgeSQLCacheOperations} Interface for executing versioned SQL operations with cache management
|
|
311
|
+
*/
|
|
312
|
+
modifyWithVersioningAndEvictCache(): ForgeSQLCacheOperations {
|
|
313
|
+
return this.cacheOperations;
|
|
314
|
+
}
|
|
315
|
+
|
|
100
316
|
/**
|
|
101
317
|
* Returns a Drizzle query builder instance.
|
|
102
318
|
*
|
|
@@ -106,7 +322,18 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
106
322
|
*
|
|
107
323
|
* @returns A Drizzle query builder instance for query construction only.
|
|
108
324
|
*/
|
|
109
|
-
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> {
|
|
325
|
+
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> & {
|
|
326
|
+
selectAliased: SelectAliasedType;
|
|
327
|
+
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
328
|
+
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
329
|
+
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
330
|
+
insertWithCacheContext: InsertAndEvictCacheType;
|
|
331
|
+
insertAndEvictCache: InsertAndEvictCacheType;
|
|
332
|
+
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
333
|
+
updateWithCacheContext: UpdateAndEvictCacheType;
|
|
334
|
+
deleteAndEvictCache: DeleteAndEvictCacheType;
|
|
335
|
+
deleteWithCacheContext: DeleteAndEvictCacheType;
|
|
336
|
+
} {
|
|
110
337
|
return this.drizzle;
|
|
111
338
|
}
|
|
112
339
|
|
|
@@ -159,6 +386,60 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
159
386
|
}
|
|
160
387
|
return this.drizzle.selectAliasedDistinct(fields);
|
|
161
388
|
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Creates a cacheable select query with unique field aliases to prevent field name collisions in joins.
|
|
392
|
+
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
393
|
+
*
|
|
394
|
+
* @template TSelection - The type of the selected fields
|
|
395
|
+
* @param {TSelection} fields - Object containing the fields to select, with table schemas as values
|
|
396
|
+
* @param {number} cacheTTL - cache ttl optional default is 60 sec.
|
|
397
|
+
* @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases
|
|
398
|
+
* @throws {Error} If fields parameter is empty
|
|
399
|
+
* @example
|
|
400
|
+
* ```typescript
|
|
401
|
+
* await forgeSQL
|
|
402
|
+
* .selectCacheable({user: users, order: orders},60)
|
|
403
|
+
* .from(orders)
|
|
404
|
+
* .innerJoin(users, eq(orders.userId, users.id));
|
|
405
|
+
* ```
|
|
406
|
+
*/
|
|
407
|
+
selectCacheable<TSelection extends SelectedFields>(
|
|
408
|
+
fields: TSelection,
|
|
409
|
+
cacheTTL?: number,
|
|
410
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
411
|
+
if (!fields) {
|
|
412
|
+
throw new Error("fields is empty");
|
|
413
|
+
}
|
|
414
|
+
return this.drizzle.selectAliasedCacheable(fields, cacheTTL);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Creates a cacheable distinct select query with unique field aliases to prevent field name collisions in joins.
|
|
419
|
+
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
420
|
+
*
|
|
421
|
+
* @template TSelection - The type of the selected fields
|
|
422
|
+
* @param {TSelection} fields - Object containing the fields to select, with table schemas as values
|
|
423
|
+
* @param {number} cacheTTL - cache ttl optional default is 60 sec.
|
|
424
|
+
* @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A distinct select query builder with unique field aliases
|
|
425
|
+
* @throws {Error} If fields parameter is empty
|
|
426
|
+
* @example
|
|
427
|
+
* ```typescript
|
|
428
|
+
* await forgeSQL
|
|
429
|
+
* .selectDistinctCacheable({user: users, order: orders}, 60)
|
|
430
|
+
* .from(orders)
|
|
431
|
+
* .innerJoin(users, eq(orders.userId, users.id));
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
selectDistinctCacheable<TSelection extends SelectedFields>(
|
|
435
|
+
fields: TSelection,
|
|
436
|
+
cacheTTL?: number,
|
|
437
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
438
|
+
if (!fields) {
|
|
439
|
+
throw new Error("fields is empty");
|
|
440
|
+
}
|
|
441
|
+
return this.drizzle.selectAliasedDistinctCacheable(fields, cacheTTL);
|
|
442
|
+
}
|
|
162
443
|
}
|
|
163
444
|
|
|
164
445
|
/**
|
|
@@ -172,6 +453,138 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
172
453
|
this.ormInstance = ForgeSQLORMImpl.getInstance(options);
|
|
173
454
|
}
|
|
174
455
|
|
|
456
|
+
selectCacheable<TSelection extends SelectedFields>(
|
|
457
|
+
fields: TSelection,
|
|
458
|
+
cacheTTL?: number,
|
|
459
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
460
|
+
return this.ormInstance.selectCacheable(fields, cacheTTL);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
selectDistinctCacheable<TSelection extends SelectedFields>(
|
|
464
|
+
fields: TSelection,
|
|
465
|
+
cacheTTL?: number,
|
|
466
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
467
|
+
return this.ormInstance.selectDistinctCacheable(fields, cacheTTL);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
executeWithCacheContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
471
|
+
return this.ormInstance.executeWithCacheContext(cacheContext);
|
|
472
|
+
}
|
|
473
|
+
executeWithCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
474
|
+
return this.ormInstance.executeWithCacheContextAndReturnValue(cacheContext);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Executes operations within a local cache context.
|
|
478
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
479
|
+
*
|
|
480
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
481
|
+
* @returns Promise that resolves when all operations are complete
|
|
482
|
+
*/
|
|
483
|
+
executeWithLocalContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
484
|
+
return this.ormInstance.executeWithLocalContext(cacheContext);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Executes operations within a local cache context and returns a value.
|
|
489
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
490
|
+
*
|
|
491
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
492
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
493
|
+
*/
|
|
494
|
+
executeWithLocalCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
495
|
+
return this.ormInstance.executeWithLocalCacheContextAndReturnValue(cacheContext);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Creates an insert query builder.
|
|
500
|
+
*
|
|
501
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
502
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
503
|
+
*
|
|
504
|
+
* @param table - The table to insert into
|
|
505
|
+
* @returns Insert query builder (no versioning, no cache management)
|
|
506
|
+
*/
|
|
507
|
+
insert<TTable extends MySqlTable>(
|
|
508
|
+
table: TTable,
|
|
509
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
510
|
+
return this.ormInstance.insert(table);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Creates an insert query builder that automatically evicts cache after execution.
|
|
515
|
+
*
|
|
516
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
517
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
518
|
+
*
|
|
519
|
+
* @param table - The table to insert into
|
|
520
|
+
* @returns Insert query builder with automatic cache eviction (no versioning)
|
|
521
|
+
*/
|
|
522
|
+
insertAndEvictCache<TTable extends MySqlTable>(
|
|
523
|
+
table: TTable,
|
|
524
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
525
|
+
return this.ormInstance.insertAndEvictCache(table);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Creates an update query builder.
|
|
530
|
+
*
|
|
531
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
532
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
533
|
+
*
|
|
534
|
+
* @param table - The table to update
|
|
535
|
+
* @returns Update query builder (no versioning, no cache management)
|
|
536
|
+
*/
|
|
537
|
+
update<TTable extends MySqlTable>(
|
|
538
|
+
table: TTable,
|
|
539
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
540
|
+
return this.ormInstance.update(table);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Creates an update query builder that automatically evicts cache after execution.
|
|
545
|
+
*
|
|
546
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
547
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
548
|
+
*
|
|
549
|
+
* @param table - The table to update
|
|
550
|
+
* @returns Update query builder with automatic cache eviction (no versioning)
|
|
551
|
+
*/
|
|
552
|
+
updateAndEvictCache<TTable extends MySqlTable>(
|
|
553
|
+
table: TTable,
|
|
554
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
555
|
+
return this.ormInstance.updateAndEvictCache(table);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Creates a delete query builder.
|
|
560
|
+
*
|
|
561
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
562
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
563
|
+
*
|
|
564
|
+
* @param table - The table to delete from
|
|
565
|
+
* @returns Delete query builder (no versioning, no cache management)
|
|
566
|
+
*/
|
|
567
|
+
delete<TTable extends MySqlTable>(
|
|
568
|
+
table: TTable,
|
|
569
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
570
|
+
return this.ormInstance.delete(table);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Creates a delete query builder that automatically evicts cache after execution.
|
|
575
|
+
*
|
|
576
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
577
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
578
|
+
*
|
|
579
|
+
* @param table - The table to delete from
|
|
580
|
+
* @returns Delete query builder with automatic cache eviction (no versioning)
|
|
581
|
+
*/
|
|
582
|
+
deleteAndEvictCache<TTable extends MySqlTable>(
|
|
583
|
+
table: TTable,
|
|
584
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
585
|
+
return this.ormInstance.deleteAndEvictCache(table);
|
|
586
|
+
}
|
|
587
|
+
|
|
175
588
|
/**
|
|
176
589
|
* Creates a select query with unique field aliases to prevent field name collisions in joins.
|
|
177
590
|
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
@@ -216,20 +629,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
216
629
|
return this.ormInstance.selectDistinct(fields);
|
|
217
630
|
}
|
|
218
631
|
|
|
219
|
-
/**
|
|
220
|
-
* Proxies the `crud` method from `ForgeSQLORMImpl`.
|
|
221
|
-
* @returns CRUD operations.
|
|
222
|
-
*/
|
|
223
|
-
crud(): CRUDForgeSQL {
|
|
224
|
-
return this.ormInstance.modify();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
632
|
/**
|
|
228
633
|
* Proxies the `modify` method from `ForgeSQLORMImpl`.
|
|
229
634
|
* @returns Modify operations.
|
|
230
635
|
*/
|
|
231
|
-
|
|
232
|
-
return this.ormInstance.
|
|
636
|
+
modifyWithVersioning(): VerioningModificationForgeSQL {
|
|
637
|
+
return this.ormInstance.modifyWithVersioning();
|
|
233
638
|
}
|
|
234
639
|
|
|
235
640
|
/**
|
|
@@ -248,13 +653,17 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
248
653
|
return this.ormInstance.analyze();
|
|
249
654
|
}
|
|
250
655
|
|
|
656
|
+
/**
|
|
657
|
+
* Provides schema-level SQL cacheable operations with type safety.
|
|
658
|
+
* @returns {ForgeSQLCacheOperations} Interface for executing schema-bound SQL queries
|
|
659
|
+
*/
|
|
660
|
+
modifyWithVersioningAndEvictCache(): ForgeSQLCacheOperations {
|
|
661
|
+
return this.ormInstance.modifyWithVersioningAndEvictCache();
|
|
662
|
+
}
|
|
663
|
+
|
|
251
664
|
/**
|
|
252
665
|
* Returns a Drizzle query builder instance.
|
|
253
666
|
*
|
|
254
|
-
* ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.
|
|
255
|
-
* The returned instance should NOT be used for direct database connections or query execution.
|
|
256
|
-
* All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.
|
|
257
|
-
*
|
|
258
667
|
* @returns A Drizzle query builder instance for query construction only.
|
|
259
668
|
*/
|
|
260
669
|
getDrizzleQueryBuilder() {
|