forge-sql-orm
Version:
Drizzle ORM integration for Atlassian @forge/sql. Provides a custom driver, schema migration, two levels of caching (local and global via @forge/kvs), optimistic locking, and query analysis.
136 lines • 5.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.forgeDriver = void 0;
exports.isUpdateQueryResponse = isUpdateQueryResponse;
const sql_1 = require("@forge/sql");
const metadataContextUtils_1 = require("./metadataContextUtils");
const requestTypeContextUtils_1 = require("./requestTypeContextUtils");
const sqlUtils_1 = require("./sqlUtils");
const sql_2 = require("@forge/sql/out/sql");
const timeoutMs = 10000;
const timeoutMessage = `Atlassian @forge/sql did not return a response within ${timeoutMs}ms (${timeoutMs / 1000} seconds), so the request is blocked. Possible causes: slow query, network issues, or exceeding Forge SQL limits.`;
/**
* Type guard to check if an object is an UpdateQueryResponse.
*
* @param obj - The object to check
* @returns True if the object is an UpdateQueryResponse
*/
function isUpdateQueryResponse(obj) {
return (obj !== null &&
typeof obj === "object" &&
typeof obj.affectedRows === "number" &&
typeof obj.insertId === "number");
}
/**
* Processes DDL query results and saves metadata to the execution context.
*
* @param query - The SQL query string
* @param params - Query parameters
* @param method - Execution method ("all" or "execute")
* @param result - The DDL query result
* @returns Processed result for Drizzle ORM
*/
async function processDDLResult(query, params, method, result) {
if (result.metadata) {
await (0, metadataContextUtils_1.saveMetaDataToContext)(query, params, result.metadata);
}
if (!result?.rows) {
return { rows: [] };
}
if (isUpdateQueryResponse(result.rows)) {
const oneRow = result.rows;
return { ...oneRow, rows: [oneRow] };
}
if (Array.isArray(result.rows)) {
if (method === "execute") {
return { rows: [result.rows] };
}
else {
const rows = result.rows.map((r) => Object.values(r));
return { rows };
}
}
return { rows: [] };
}
/**
* Processes execute method results (UPDATE, INSERT, DELETE) and saves metadata to the execution context.
*
* @param query - The SQL query string
* @param params - Query parameters (may be undefined)
* @returns Processed result for Drizzle ORM
*/
async function processExecuteMethod(query, params) {
const sqlStatement = sql_1.sql.prepare(query);
if (params) {
sqlStatement.bindParams(...params);
}
const result = await (0, sqlUtils_1.withTimeout)(sqlStatement.execute(), timeoutMessage, timeoutMs);
await (0, metadataContextUtils_1.saveMetaDataToContext)(query, params ?? [], result.metadata);
if (!result.rows) {
return { rows: [[]] };
}
return { rows: [result.rows] };
}
/**
* Processes all method results (SELECT queries) and saves metadata to the execution context.
*
* @param query - The SQL query string
* @param params - Query parameters (may be undefined)
* @returns Processed result for Drizzle ORM
*/
async function processAllMethod(query, params) {
const sqlStatement = sql_1.sql.prepare(query);
if (params) {
sqlStatement.bindParams(...params);
}
const result = await (0, sqlUtils_1.withTimeout)(sqlStatement.execute(), timeoutMessage, timeoutMs);
await (0, metadataContextUtils_1.saveMetaDataToContext)(query, params ?? [], result.metadata);
if (!result.rows) {
return { rows: [] };
}
const rows = result.rows.map((r) => Object.values(r));
return { rows };
}
/**
* Main Forge SQL driver function for Drizzle ORM integration.
* Handles DDL operations, execute operations (UPDATE/INSERT/DELETE), and select operations.
* Automatically saves query execution metadata to the context for performance monitoring.
*
* @param query - The SQL query to execute
* @param params - Query parameters (may be undefined or empty array)
* @param method - Execution method ("all" for SELECT, "execute" for UPDATE/INSERT/DELETE)
* @returns Promise with query results compatible with Drizzle ORM
*
* @throws {Error} When DDL operations are called with parameters
*
* @example
* ```typescript
* // DDL operation
* await forgeDriver("CREATE TABLE users (id INT)", [], "all");
*
* // SELECT operation
* await forgeDriver("SELECT * FROM users WHERE id = ?", [1], "all");
*
* // UPDATE operation
* await forgeDriver("UPDATE users SET name = ? WHERE id = ?", ["John", 1], "execute");
* ```
*/
const forgeDriver = async (query, params, method) => {
const operationType = await (0, requestTypeContextUtils_1.getOperationType)();
// Handle DDL operations
if (operationType === "DDL") {
const result = await (0, sqlUtils_1.withTimeout)(sql_1.sql
.prepare(query, sql_2.SQL_API_ENDPOINTS.EXECUTE_DDL)
.bindParams(params ?? [])
.execute(), timeoutMessage, timeoutMs);
return await processDDLResult(query, params ?? [], method, result);
}
// Handle execute method (UPDATE, INSERT, DELETE)
if (method === "execute") {
return await processExecuteMethod(query, params);
}
// Handle all method (SELECT)
return await processAllMethod(query, params);
};
exports.forgeDriver = forgeDriver;
//# sourceMappingURL=forgeDriver.js.map