forge-sql-orm 2.1.5 → 2.1.7

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.
Files changed (41) hide show
  1. package/README.md +135 -53
  2. package/dist/ForgeSQLORM.js +572 -231
  3. package/dist/ForgeSQLORM.js.map +1 -1
  4. package/dist/ForgeSQLORM.mjs +572 -231
  5. package/dist/ForgeSQLORM.mjs.map +1 -1
  6. package/dist/core/ForgeSQLORM.d.ts +91 -3
  7. package/dist/core/ForgeSQLORM.d.ts.map +1 -1
  8. package/dist/core/ForgeSQLQueryBuilder.d.ts +89 -2
  9. package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
  10. package/dist/core/SystemTables.d.ts +3654 -0
  11. package/dist/core/SystemTables.d.ts.map +1 -1
  12. package/dist/lib/drizzle/extensions/additionalActions.d.ts +2 -2
  13. package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
  14. package/dist/utils/forgeDriver.d.ts +61 -14
  15. package/dist/utils/forgeDriver.d.ts.map +1 -1
  16. package/dist/utils/metadataContextUtils.d.ts +1 -1
  17. package/dist/utils/metadataContextUtils.d.ts.map +1 -1
  18. package/dist/utils/requestTypeContextUtils.d.ts +8 -0
  19. package/dist/utils/requestTypeContextUtils.d.ts.map +1 -0
  20. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +90 -65
  21. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -1
  22. package/package.json +9 -9
  23. package/src/core/ForgeSQLCrudOperations.ts +3 -3
  24. package/src/core/ForgeSQLORM.ts +334 -124
  25. package/src/core/ForgeSQLQueryBuilder.ts +116 -20
  26. package/src/core/ForgeSQLSelectOperations.ts +2 -2
  27. package/src/core/SystemTables.ts +16 -0
  28. package/src/lib/drizzle/extensions/additionalActions.ts +24 -22
  29. package/src/utils/cacheContextUtils.ts +2 -2
  30. package/src/utils/cacheUtils.ts +12 -12
  31. package/src/utils/forgeDriver.ts +219 -40
  32. package/src/utils/forgeDriverProxy.ts +2 -2
  33. package/src/utils/metadataContextUtils.ts +11 -13
  34. package/src/utils/requestTypeContextUtils.ts +11 -0
  35. package/src/utils/sqlUtils.ts +1 -1
  36. package/src/webtriggers/applyMigrationsWebTrigger.ts +9 -9
  37. package/src/webtriggers/clearCacheSchedulerTrigger.ts +1 -1
  38. package/src/webtriggers/dropMigrationWebTrigger.ts +2 -2
  39. package/src/webtriggers/dropTablesMigrationWebTrigger.ts +2 -2
  40. package/src/webtriggers/fetchSchemaWebTrigger.ts +1 -1
  41. package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +511 -308
package/README.md CHANGED
@@ -19,12 +19,12 @@
19
19
  - ✅ **Custom Drizzle Driver** for direct integration with @forge/sql
20
20
  - ✅ **Local Cache System (Level 1)** for in-memory query optimization within single resolver invocation scope
21
21
  - ✅ **Global Cache System (Level 2)** with cross-invocation caching, automatic cache invalidation and context-aware operations (using [@forge/kvs](https://developer.atlassian.com/platform/forge/storage-reference/storage-api-custom-entities/) )
22
- - ✅ **Memory Usage Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
22
+ - ✅ **Performance Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
23
23
  - ✅ **Type-Safe Query Building**: Write SQL queries with full TypeScript support
24
24
  - ✅ **Supports complex SQL queries** with joins and filtering using Drizzle ORM
25
25
  - ✅ **Advanced Query Methods**: `selectFrom()`, `selectDistinctFrom()`, `selectCacheableFrom()`, `selectDistinctCacheableFrom()` for all-column queries with field aliasing
26
- - ✅ **Raw SQL Execution**: `execute()` and `executeCacheable()` methods for direct SQL queries with local and global caching
27
26
  - ✅ **Query Execution with Metadata**: `executeWithMetadata()` method for capturing detailed execution metrics including database execution time, response size, and Forge SQL metadata
27
+ - ✅ **Raw SQL Execution**: `execute()`, `executeCacheable()`, `executeDDL()`, and `executeDDLActions()` methods for direct SQL queries with local and global caching
28
28
  - ✅ **Common Table Expressions (CTEs)**: `with()` method for complex queries with subqueries
29
29
  - ✅ **Schema migration support**, allowing automatic schema evolution
30
30
  - ✅ **Automatic entity generation** from MySQL/tidb databases
@@ -65,7 +65,7 @@
65
65
  ### 🔒 Advanced Features
66
66
  - [Optimistic Locking](#optimistic-locking)
67
67
  - [Query Analysis and Performance Optimization](#query-analysis-and-performance-optimization)
68
- - [Memory Usage Monitoring](#memory-usage-monitoring)
68
+ - [Performance Monitoring](#performance-monitoring)
69
69
  - [Date and Time Types](#date-and-time-types)
70
70
 
71
71
  ### 🛠️ Development Tools
@@ -82,7 +82,7 @@
82
82
  - [Query Analysis Example](examples/forge-sql-orm-example-query-analyses)
83
83
  - [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker)
84
84
  - [Checklist Example](examples/forge-sql-orm-example-checklist)
85
- - [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` memory monitoring
85
+ - [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` performance monitoring
86
86
 
87
87
  ### 📚 Reference
88
88
  - [ForgeSqlOrmOptions](#forgesqlormoptions)
@@ -344,6 +344,32 @@ const usersWithMetadata = await forgeSQL.executeWithMetadata(
344
344
  }
345
345
  );
346
346
 
347
+ // DDL operations for schema modifications
348
+ await forgeSQL.executeDDL(`
349
+ CREATE TABLE users (
350
+ id INT PRIMARY KEY AUTO_INCREMENT,
351
+ name VARCHAR(255) NOT NULL,
352
+ email VARCHAR(255) UNIQUE
353
+ )
354
+ `);
355
+
356
+ // Execute regular SQL queries in DDL context for performance monitoring
357
+ await forgeSQL.executeDDLActions(async () => {
358
+ // Execute regular SQL queries in DDL context for monitoring
359
+ const slowQueries = await forgeSQL.execute(`
360
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
361
+ WHERE AVG_LATENCY > 1000000
362
+ `);
363
+
364
+ // Execute complex analysis queries in DDL context
365
+ const performanceData = await forgeSQL.execute(`
366
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
367
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
368
+ `);
369
+
370
+ return { slowQueries, performanceData };
371
+ });
372
+
347
373
  // Common Table Expressions (CTEs)
348
374
  const userStats = await forgeSQL
349
375
  .with(
@@ -778,6 +804,8 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
778
804
  | `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
779
805
  | `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
780
806
  | `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
807
+ | `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
808
+ | `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
781
809
  | `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
782
810
 
783
811
 
@@ -799,6 +827,8 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
799
827
  | `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
800
828
  | `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
801
829
  | `executeWithMetadata()` | Raw SQL queries with execution metrics capture | ❌ No | Local Cache |
830
+ | `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
831
+ | `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
802
832
  | `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
803
833
  where Cache context - allows you to batch cache invalidation events and bypass cache reads for affected tables.
804
834
 
@@ -1187,14 +1217,48 @@ const users = await forgeSQL
1187
1217
 
1188
1218
  // Using executeWithMetadata() for capturing execution metrics
1189
1219
  const usersWithMetadata = await forgeSQL
1190
- .executeWithMetadata(
1191
- async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
1192
- (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
1193
- console.log(`DB execution time: ${totalDbExecutionTime}ms`);
1194
- console.log(`Response size: ${totalResponseSize} bytes`);
1195
- console.log('Forge metadata:', forgeMetadata);
1196
- }
1197
- );
1220
+ .executeWithMetadata(
1221
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
1222
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
1223
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
1224
+ console.log(`Response size: ${totalResponseSize} bytes`);
1225
+ console.log('Forge metadata:', forgeMetadata);
1226
+ }
1227
+ );
1228
+
1229
+ // Using executeDDL() for DDL operations (CREATE, ALTER, DROP, etc.)
1230
+ await forgeSQL.executeDDL(`
1231
+ CREATE TABLE users (
1232
+ id INT PRIMARY KEY AUTO_INCREMENT,
1233
+ name VARCHAR(255) NOT NULL,
1234
+ email VARCHAR(255) UNIQUE
1235
+ )
1236
+ `);
1237
+
1238
+ await forgeSQL.executeDDL(sql`
1239
+ ALTER TABLE users
1240
+ ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
1241
+ `);
1242
+
1243
+ await forgeSQL.executeDDL("DROP TABLE IF EXISTS old_users");
1244
+
1245
+ // Using executeDDLActions() for executing regular SQL queries in DDL context
1246
+ // This method executes a series of actions within a DDL operation context for monitoring
1247
+ await forgeSQL.executeDDLActions(async () => {
1248
+ // Execute regular SQL queries in DDL context for performance monitoring
1249
+ const slowQueries = await forgeSQL.execute(`
1250
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
1251
+ WHERE AVG_LATENCY > 1000000
1252
+ `);
1253
+
1254
+ // Execute complex analysis queries in DDL context
1255
+ const performanceData = await forgeSQL.execute(`
1256
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
1257
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
1258
+ `);
1259
+
1260
+ return { slowQueries, performanceData };
1261
+ });
1198
1262
 
1199
1263
  // Using execute() with complex queries
1200
1264
  const userStats = await forgeSQL
@@ -2074,13 +2138,13 @@ This analysis provides insights into:
2074
2138
  - Resource usage at each step
2075
2139
  - Performance optimization opportunities
2076
2140
 
2077
- ## Memory Usage Monitoring
2141
+ ## Performance Monitoring
2078
2142
 
2079
2143
  [↑ Back to Top](#table-of-contents)
2080
2144
 
2081
- Forge-SQL-ORM provides automated memory usage monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
2145
+ Forge-SQL-ORM provides automated performance monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
2082
2146
 
2083
- ### Why Memory Monitoring is Critical
2147
+ ### Why Performance Monitoring is Critical
2084
2148
 
2085
2149
  Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow query detection (which is available in the Forge Developer Console), there's **no built-in way to monitor memory usage** of your queries. This monitoring system fills that gap by:
2086
2150
 
@@ -2092,7 +2156,7 @@ Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow
2092
2156
 
2093
2157
  ### Overview
2094
2158
 
2095
- The memory monitoring system:
2159
+ The performance monitoring system:
2096
2160
  - **Automatically detects memory-intensive queries** based on configurable memory thresholds
2097
2161
  - **Provides detailed memory metrics** including execution time, memory usage, and execution plans
2098
2162
  - **Logs memory issues** to the Forge Developer Console for easy debugging
@@ -2101,7 +2165,7 @@ The memory monitoring system:
2101
2165
 
2102
2166
  ### Key Features
2103
2167
 
2104
- - **Memory-Focused Monitoring**: Primary focus on memory usage with configurable thresholds
2168
+ - **Memory-Focused Performance Monitoring**: Primary focus on memory usage with configurable thresholds
2105
2169
  - **Atlassian 16 MiB Limit Awareness**: Designed specifically for Forge SQL's memory constraints
2106
2170
  - **Execution Plan Analysis**: Shows detailed query plans to help optimize memory consumption
2107
2171
  - **Configurable Thresholds**: Set custom memory usage thresholds (default: 4MB warning)
@@ -2125,18 +2189,18 @@ import ForgeSQL, { topSlowestStatementLastHourTrigger } from 'forge-sql-orm';
2125
2189
  const forgeSQL = new ForgeSQL();
2126
2190
 
2127
2191
  // Basic usage with default thresholds (300ms latency, 8MB memory warning)
2128
- export const memoryUsageTrigger = () =>
2192
+ export const performanceTrigger = () =>
2129
2193
  topSlowestStatementLastHourTrigger(forgeSQL);
2130
2194
 
2131
- // Conservative memory monitoring: 4MB warning (well below 16MB limit)
2195
+ // Conservative performance monitoring: 4MB warning (well below 16MB limit)
2132
2196
  export const conservativeMemoryTrigger = () =>
2133
2197
  topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 4 * 1024 * 1024 });
2134
2198
 
2135
- // Aggressive memory monitoring: 12MB warning (75% of 16MB limit)
2199
+ // Aggressive performance monitoring: 12MB warning (75% of 16MB limit)
2136
2200
  export const aggressiveMemoryTrigger = () =>
2137
2201
  topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 12 * 1024 * 1024 });
2138
2202
 
2139
- // Memory-only monitoring: Only trigger on memory usage (latency effectively disabled)
2203
+ // Memory-only performance monitoring: Only trigger on memory usage (latency effectively disabled)
2140
2204
  export const memoryOnlyTrigger = () =>
2141
2205
  topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 10000, memoryThresholdBytes: 4 * 1024 * 1024 });
2142
2206
 
@@ -2145,55 +2209,40 @@ export const latencyOnlyTrigger = () =>
2145
2209
  topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 500, memoryThresholdBytes: 16 * 1024 * 1024 });
2146
2210
 
2147
2211
  // With execution plan in logs
2148
- export const withPlanTrigger = () =>
2212
+ export const performanceWithPlanTrigger = () =>
2149
2213
  topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true });
2150
-
2151
- // With cache logging enabled
2152
- export const withCacheLoggingTrigger = () =>
2153
- topSlowestStatementLastHourTrigger(forgeSQL, { logCache: true });
2154
-
2155
- // With both execution plan and cache logging
2156
- export const withFullLoggingTrigger = () =>
2157
- topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true, logCache: true });
2158
-
2159
- // With custom ORM options for debugging
2160
- const forgeSQL = new ForgeSQL({
2161
- logRawSqlQuery: true,
2162
- logCache: true,
2163
- cacheEntityName: "cache"
2164
- });
2165
-
2214
+ ```
2166
2215
 
2167
2216
  #### 3. Configure in manifest.yml
2168
2217
 
2169
2218
  **As Scheduler Trigger (Recommended for Production):**
2170
2219
  ```yaml
2171
2220
  scheduledTrigger:
2172
- - key: memory-usage-trigger
2173
- function: memoryUsageTrigger
2221
+ - key: performance-trigger
2222
+ function: perfTrigger
2174
2223
  interval: hour # Required: only hour interval is supported
2175
2224
 
2176
2225
  function:
2177
- - key: memoryUsageTrigger
2178
- handler: index.memoryUsageTrigger
2226
+ - key: perfTrigger
2227
+ handler: index.performanceTrigger
2179
2228
  ```
2180
2229
 
2181
2230
  **As Web Trigger (Development Only):**
2182
2231
  ```yaml
2183
2232
  webtrigger:
2184
2233
  - key: print-slowest-queries
2185
- function: memoryUsageTrigger
2234
+ function: perfTrigger
2186
2235
 
2187
2236
  function:
2188
- - key: memoryUsageTrigger
2189
- handler: index.memoryUsageTrigger
2237
+ - key: perfTrigger
2238
+ handler: index.performanceTrigger
2190
2239
  ```
2191
2240
 
2192
2241
  > **⚠️ Important**: Web triggers are not recommended for production as they violate the "run-on-atlassian" principle. Use scheduler triggers for production monitoring.
2193
2242
 
2194
2243
  ### How It Works
2195
2244
 
2196
- The memory monitoring trigger works differently depending on how it's configured:
2245
+ The performance monitoring trigger works differently depending on how it's configured:
2197
2246
 
2198
2247
  #### Scheduler Trigger Mode (Production)
2199
2248
 
@@ -2279,7 +2328,7 @@ The monitoring uses **OR logic** - if **either** threshold is exceeded, the quer
2279
2328
  - No need to exceed both thresholds simultaneously
2280
2329
 
2281
2330
  **💡 Pro Tips:**
2282
- - **Memory-only monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
2331
+ - **Memory-only performance monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
2283
2332
  - **Latency-only monitoring**: Set `memoryThresholdBytes` to 16MB (16 * 1024 * 1024) to trigger only on latency
2284
2333
  - **Combined monitoring**: Use both thresholds for comprehensive monitoring
2285
2334
  - **Execution plan analysis**: Set `showPlan: true` to include detailed execution plans in logs (useful for debugging)
@@ -2352,6 +2401,8 @@ This section covers the breaking changes introduced in version 2.1.x and how to
2352
2401
  - `forgeSQL.selectDistinctCacheableFrom()` - Distinct all-column queries with field aliasing and caching
2353
2402
  - `forgeSQL.execute()` - Raw SQL queries with local caching
2354
2403
  - `forgeSQL.executeCacheable()` - Raw SQL queries with local and global caching
2404
+ - `forgeSQL.executeDDL()` - DDL operations (CREATE, ALTER, DROP, etc.)
2405
+ - `forgeSQL.executeDDLActions()` - Execute actions within DDL operation context
2355
2406
  - `forgeSQL.with()` - Common Table Expressions (CTEs)
2356
2407
 
2357
2408
  **Optional Migration:**
@@ -2390,14 +2441,45 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
2390
2441
 
2391
2442
  // ✅ Raw SQL execution with metadata capture
2392
2443
  const usersWithMetadata = await forgeSQL.executeWithMetadata(
2393
- async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
2394
- (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
2395
- console.log(`DB execution time: ${totalDbExecutionTime}ms`);
2396
- console.log(`Response size: ${totalResponseSize} bytes`);
2397
- console.log('Forge metadata:', forgeMetadata);
2398
- }
2444
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
2445
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
2446
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
2447
+ console.log(`Response size: ${totalResponseSize} bytes`);
2448
+ console.log('Forge metadata:', forgeMetadata);
2449
+ }
2399
2450
  );
2400
2451
 
2452
+ // ✅ DDL operations for schema modifications
2453
+ await forgeSQL.executeDDL(`
2454
+ CREATE TABLE users (
2455
+ id INT PRIMARY KEY AUTO_INCREMENT,
2456
+ name VARCHAR(255) NOT NULL,
2457
+ email VARCHAR(255) UNIQUE
2458
+ )
2459
+ `);
2460
+
2461
+ await forgeSQL.executeDDL(sql`
2462
+ ALTER TABLE users
2463
+ ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2464
+ `);
2465
+
2466
+ // ✅ Execute regular SQL queries in DDL context for performance monitoring
2467
+ await forgeSQL.executeDDLActions(async () => {
2468
+ // Execute regular SQL queries in DDL context for monitoring
2469
+ const slowQueries = await forgeSQL.execute(`
2470
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
2471
+ WHERE AVG_LATENCY > 1000000
2472
+ `);
2473
+
2474
+ // Execute complex analysis queries in DDL context
2475
+ const performanceData = await forgeSQL.execute(`
2476
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
2477
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
2478
+ `);
2479
+
2480
+ return { slowQueries, performanceData };
2481
+ });
2482
+
2401
2483
  // ✅ Common Table Expressions (CTEs)
2402
2484
  const userStats = await forgeSQL
2403
2485
  .with(