forge-sql-orm 2.0.27 → 2.0.28
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/dist/ForgeSQLORM.js +32 -4
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +32 -4
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/utils/sqlUtils.d.ts +11 -4
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/dropMigrationWebTrigger.d.ts +5 -5
- package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts +26 -0
- package/dist/webtriggers/dropTablesMigrationWebTrigger.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 +7 -7
- package/src/utils/sqlUtils.ts +22 -7
- package/src/webtriggers/dropMigrationWebTrigger.ts +6 -6
- package/src/webtriggers/dropTablesMigrationWebTrigger.ts +50 -0
- package/src/webtriggers/index.ts +1 -0
package/dist/ForgeSQLORM.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLORM.js","sources":["../src/utils/sqlUtils.ts","../src/core/ForgeSQLCrudOperations.ts","../src/core/ForgeSQLSelectOperations.ts","../src/utils/forgeDriver.ts","../src/utils/sqlHints.ts","../src/utils/forgeDriverProxy.ts","../src/lib/drizzle/extensions/selectAliased.ts","../src/core/ForgeSQLAnalyseOperations.ts","../src/core/ForgeSQLORM.ts","../src/core/ForgeSQLQueryBuilder.ts","../src/core/SystemTables.ts","../src/webtriggers/dropMigrationWebTrigger.ts","../src/webtriggers/applyMigrationsWebTrigger.ts","../src/webtriggers/fetchSchemaWebTrigger.ts","../src/webtriggers/index.ts"],"sourcesContent":["import moment from \"moment\";\nimport { AnyColumn, Column, isTable, SQL, sql, StringChunk } from \"drizzle-orm\";\nimport { AnyMySqlTable, MySqlCustomColumn } from \"drizzle-orm/mysql-core/index\";\nimport { PrimaryKeyBuilder } from \"drizzle-orm/mysql-core/primary-keys\";\nimport { AnyIndexBuilder } from \"drizzle-orm/mysql-core/indexes\";\nimport { CheckBuilder } from \"drizzle-orm/mysql-core/checks\";\nimport { ForeignKeyBuilder } from \"drizzle-orm/mysql-core/foreign-keys\";\nimport { UniqueConstraintBuilder } from \"drizzle-orm/mysql-core/unique-constraint\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { isSQLWrapper } from \"drizzle-orm/sql/sql\";\n\n/**\n * Interface representing table metadata information\n */\nexport interface MetadataInfo {\n /** The name of the table */\n tableName: string;\n /** Record of column names and their corresponding column definitions */\n columns: Record<string, AnyColumn>;\n /** Array of index builders */\n indexes: AnyIndexBuilder[];\n /** Array of check constraint builders */\n checks: CheckBuilder[];\n /** Array of foreign key builders */\n foreignKeys: ForeignKeyBuilder[];\n /** Array of primary key builders */\n primaryKeys: PrimaryKeyBuilder[];\n /** Array of unique constraint builders */\n uniqueConstraints: UniqueConstraintBuilder[];\n /** Array of all extra builders */\n extras: any[];\n}\n\n/**\n * Interface for config builder data\n */\ninterface ConfigBuilderData {\n value?: any;\n [key: string]: any;\n}\n\n/**\n * Parses a date string into a Date object using the specified format\n * @param value - The date string to parse\n * @param format - The format to use for parsing\n * @returns Date object\n */\nexport const parseDateTime = (value: string, format: string): Date => {\n let result: Date;\n const m = moment(value, format, true);\n if (!m.isValid()) {\n const momentDate = moment(value);\n if (momentDate.isValid()) {\n result = momentDate.toDate();\n } else {\n result = new Date(value);\n }\n } else {\n result = m.toDate();\n }\n if (isNaN(result.getTime())) {\n result = new Date(value);\n }\n return result;\n};\n\n/**\n * Gets primary keys from the schema.\n * @template T - The type of the table schema\n * @param {T} table - The table schema\n * @returns {[string, AnyColumn][]} Array of primary key name and column pairs\n */\nexport function getPrimaryKeys<T extends AnyMySqlTable>(table: T): [string, AnyColumn][] {\n const { columns, primaryKeys } = getTableMetadata(table);\n\n // First try to find primary keys in columns\n const columnPrimaryKeys = Object.entries(columns).filter(([, column]) => column.primary) as [\n string,\n AnyColumn,\n ][];\n\n if (columnPrimaryKeys.length > 0) {\n return columnPrimaryKeys;\n }\n\n // If no primary keys found in columns, check primary key builders\n if (Array.isArray(primaryKeys) && primaryKeys.length > 0) {\n // Collect all primary key columns from all primary key builders\n const primaryKeyColumns = new Set<[string, AnyColumn]>();\n\n primaryKeys.forEach((primaryKeyBuilder) => {\n // Get primary key columns from each builder\n Object.entries(columns)\n .filter(([, column]) => {\n // @ts-ignore - PrimaryKeyBuilder has internal columns property\n return primaryKeyBuilder.columns.includes(column);\n })\n .forEach(([name, column]) => {\n primaryKeyColumns.add([name, column]);\n });\n });\n\n return Array.from(primaryKeyColumns);\n }\n\n return [];\n}\n\n/**\n * Processes foreign keys from both foreignKeysSymbol and extraSymbol\n * @param table - The table schema\n * @param foreignKeysSymbol - Symbol for foreign keys\n * @param extraSymbol - Symbol for extra configuration\n * @returns Array of foreign key builders\n */\nfunction processForeignKeys(\n table: AnyMySqlTable,\n foreignKeysSymbol: symbol | undefined,\n extraSymbol: symbol | undefined,\n): ForeignKeyBuilder[] {\n const foreignKeys: ForeignKeyBuilder[] = [];\n\n // Process foreign keys from foreignKeysSymbol\n if (foreignKeysSymbol) {\n // @ts-ignore\n const fkArray: any[] = table[foreignKeysSymbol];\n if (fkArray) {\n fkArray.forEach((fk) => {\n if (fk.reference) {\n const item = fk.reference(fk);\n foreignKeys.push(item);\n }\n });\n }\n }\n\n // Process foreign keys from extraSymbol\n if (extraSymbol) {\n // @ts-ignore\n const extraConfigBuilder = table[extraSymbol];\n if (extraConfigBuilder && typeof extraConfigBuilder === \"function\") {\n const configBuilderData = extraConfigBuilder(table);\n if (configBuilderData) {\n const configBuilders = Array.isArray(configBuilderData)\n ? configBuilderData\n : Object.values(configBuilderData).map(\n (item) => (item as ConfigBuilderData).value ?? item,\n );\n\n configBuilders.forEach((builder) => {\n if (!builder?.constructor) return;\n\n const builderName = builder.constructor.name.toLowerCase();\n if (builderName.includes(\"foreignkeybuilder\")) {\n foreignKeys.push(builder);\n }\n });\n }\n }\n }\n\n return foreignKeys;\n}\n\n/**\n * Extracts table metadata from the schema.\n * @param {AnyMySqlTable} table - The table schema\n * @returns {MetadataInfo} Object containing table metadata\n */\nexport function getTableMetadata(table: AnyMySqlTable): MetadataInfo {\n const symbols = Object.getOwnPropertySymbols(table);\n const nameSymbol = symbols.find((s) => s.toString().includes(\"Name\"));\n const columnsSymbol = symbols.find((s) => s.toString().includes(\"Columns\"));\n const foreignKeysSymbol = symbols.find((s) => s.toString().includes(\"ForeignKeys)\"));\n const extraSymbol = symbols.find((s) => s.toString().includes(\"ExtraConfigBuilder\"));\n\n // Initialize builders arrays\n const builders = {\n indexes: [] as AnyIndexBuilder[],\n checks: [] as CheckBuilder[],\n foreignKeys: [] as ForeignKeyBuilder[],\n primaryKeys: [] as PrimaryKeyBuilder[],\n uniqueConstraints: [] as UniqueConstraintBuilder[],\n extras: [] as any[],\n };\n\n // Process foreign keys\n builders.foreignKeys = processForeignKeys(table, foreignKeysSymbol, extraSymbol);\n\n // Process extra configuration if available\n if (extraSymbol) {\n // @ts-ignore\n const extraConfigBuilder = table[extraSymbol];\n if (extraConfigBuilder && typeof extraConfigBuilder === \"function\") {\n const configBuilderData = extraConfigBuilder(table);\n if (configBuilderData) {\n // Convert configBuilderData to array if it's an object\n const configBuilders = Array.isArray(configBuilderData)\n ? configBuilderData\n : Object.values(configBuilderData).map(\n (item) => (item as ConfigBuilderData).value ?? item,\n );\n\n // Process each builder\n configBuilders.forEach((builder) => {\n if (!builder?.constructor) return;\n\n const builderName = builder.constructor.name.toLowerCase();\n\n // Map builder types to their corresponding arrays\n const builderMap = {\n indexbuilder: builders.indexes,\n checkbuilder: builders.checks,\n primarykeybuilder: builders.primaryKeys,\n uniqueconstraintbuilder: builders.uniqueConstraints,\n };\n\n // Add builder to appropriate array if it matches any type\n for (const [type, array] of Object.entries(builderMap)) {\n if (builderName.includes(type)) {\n array.push(builder);\n break;\n }\n }\n\n // Always add to extras array\n builders.extras.push(builder);\n });\n }\n }\n }\n\n return {\n tableName: nameSymbol ? (table as any)[nameSymbol] : \"\",\n columns: columnsSymbol ? ((table as any)[columnsSymbol] as Record<string, AnyColumn>) : {},\n ...builders,\n };\n}\n\n/**\n * Generates SQL statements to drop tables\n * @param tables - Array of table names\n * @returns Array of SQL statements for dropping tables\n */\nexport function generateDropTableStatements(tables: string[]): string[] {\n const dropStatements: string[] = [];\n\n tables.forEach((tableName) => {\n dropStatements.push(`DROP TABLE IF EXISTS \\`${tableName}\\`;`);\n dropStatements.push(`DROP SEQUENCE IF EXISTS \\`${tableName}\\`;`);\n });\n\n return dropStatements;\n}\n\ntype AliasColumnMap = Record<string, AnyColumn>;\n\nfunction mapSelectTableToAlias(\n table: MySqlTable,\n uniqPrefix: string,\n aliasMap: AliasColumnMap,\n): any {\n const { columns, tableName } = getTableMetadata(table);\n const selectionsTableFields: Record<string, unknown> = {};\n Object.keys(columns).forEach((name) => {\n const column = columns[name] as AnyColumn;\n const uniqName = `a_${uniqPrefix}_${tableName}_${column.name}`.toLowerCase();\n const fieldAlias = sql.raw(uniqName);\n selectionsTableFields[name] = sql`${column} as \\`${fieldAlias}\\``;\n aliasMap[uniqName] = column;\n });\n return selectionsTableFields;\n}\n\nfunction isDrizzleColumn(column: any): boolean {\n return column && typeof column === \"object\" && \"table\" in column;\n}\n\nexport function mapSelectAllFieldsToAlias(\n selections: any,\n name: string,\n uniqName: string,\n fields: any,\n aliasMap: AliasColumnMap,\n): any {\n if (isTable(fields)) {\n selections[name] = mapSelectTableToAlias(fields as MySqlTable, uniqName, aliasMap);\n } else if (isDrizzleColumn(fields)) {\n const column = fields as Column;\n const uniqAliasName = `a_${uniqName}_${column.name}`.toLowerCase();\n let aliasName = sql.raw(uniqAliasName);\n selections[name] = sql`${column} as \\`${aliasName}\\``;\n aliasMap[uniqAliasName] = column;\n } else if (isSQLWrapper(fields)) {\n selections[name] = fields;\n } else {\n const innerSelections: any = {};\n Object.entries(fields).forEach(([iname, ifields]) => {\n mapSelectAllFieldsToAlias(innerSelections, iname, `${uniqName}_${iname}`, ifields, aliasMap);\n });\n selections[name] = innerSelections;\n }\n return selections;\n}\nexport function mapSelectFieldsWithAlias<TSelection extends SelectedFields>(\n fields: TSelection,\n): { selections: TSelection; aliasMap: AliasColumnMap } {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n const aliasMap: AliasColumnMap = {};\n const selections: any = {};\n Object.entries(fields).forEach(([name, fields]) => {\n mapSelectAllFieldsToAlias(selections, name, name, fields, aliasMap);\n });\n return { selections, aliasMap };\n}\n\nfunction getAliasFromDrizzleAlias(value: unknown): string | undefined {\n const isSQL =\n value !== null && typeof value === \"object\" && isSQLWrapper(value) && \"queryChunks\" in value;\n if (isSQL) {\n const sql = value as SQL;\n const queryChunks = sql.queryChunks;\n if (queryChunks.length > 3) {\n const aliasNameChunk = queryChunks[queryChunks.length - 2];\n if (isSQLWrapper(aliasNameChunk) && \"queryChunks\" in aliasNameChunk) {\n const aliasNameChunkSql = aliasNameChunk as SQL;\n if (aliasNameChunkSql.queryChunks?.length === 1 && aliasNameChunkSql.queryChunks[0]) {\n const queryChunksStringChunc = aliasNameChunkSql.queryChunks[0];\n if (\"value\" in queryChunksStringChunc) {\n const values = (queryChunksStringChunc as StringChunk).value;\n if (values && values.length === 1) {\n return values[0];\n }\n }\n }\n }\n }\n }\n return undefined;\n}\n\nfunction transformValue(\n value: unknown,\n alias: string,\n aliasMap: Record<string, AnyColumn>,\n): unknown {\n const column = aliasMap[alias];\n if (!column) return value;\n\n let customColumn = column as MySqlCustomColumn<any>;\n // @ts-ignore\n const fromDriver = customColumn?.mapFrom;\n if (fromDriver && value !== null && value !== undefined) {\n return fromDriver(value);\n }\n return value;\n}\n\nfunction transformObject(\n obj: Record<string, unknown>,\n selections: Record<string, unknown>,\n aliasMap: Record<string, AnyColumn>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const selection = selections[key];\n const alias = getAliasFromDrizzleAlias(selection);\n if (alias && aliasMap[alias]) {\n result[key] = transformValue(value, alias, aliasMap);\n } else if (selection && typeof selection === \"object\" && !isSQLWrapper(selection)) {\n result[key] = transformObject(\n value as Record<string, unknown>,\n selection as Record<string, unknown>,\n aliasMap,\n );\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport function applyFromDriverTransform<T, TSelection>(\n rows: T[],\n selections: TSelection,\n aliasMap: Record<string, AnyColumn>,\n): T[] {\n return rows.map((row) => {\n const transformed = transformObject(\n row as Record<string, unknown>,\n selections as Record<string, unknown>,\n aliasMap,\n ) as Record<string, unknown>;\n\n return processNullBranches(transformed) as unknown as T;\n });\n}\n\nfunction processNullBranches(obj: Record<string, unknown>): Record<string, unknown> | null {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n // Skip built-in objects like Date, Array, etc.\n if (obj.constructor && obj.constructor.name !== \"Object\") {\n return obj;\n }\n\n const result: Record<string, unknown> = {};\n let allNull = true;\n\n for (const [key, value] of Object.entries(obj)) {\n if (value === null || value === undefined) {\n result[key] = null;\n continue;\n }\n\n if (typeof value === \"object\") {\n const processed = processNullBranches(value as Record<string, unknown>);\n result[key] = processed;\n if (processed !== null) {\n allNull = false;\n }\n } else {\n result[key] = value;\n allNull = false;\n }\n }\n\n return allNull ? null : result;\n}\n\nexport function formatLimitOffset(limitOrOffset: number): number {\n if (typeof limitOrOffset !== \"number\" || isNaN(limitOrOffset)) {\n throw new Error(\"limitOrOffset must be a valid number\");\n }\n return sql.raw(`${limitOrOffset}`) as unknown as number;\n}\n\nexport function nextVal(sequenceName: string): number {\n return sql.raw(`NEXTVAL(${sequenceName})`) as unknown as number;\n}\n","import { ForgeSqlOrmOptions } from \"..\";\nimport { CRUDForgeSQL, ForgeSqlOperation } from \"./ForgeSQLQueryBuilder\";\nimport { AnyMySqlTable } from \"drizzle-orm/mysql-core/index\";\nimport { AnyColumn, InferInsertModel } from \"drizzle-orm\";\nimport { eq, and } from \"drizzle-orm\";\nimport { SQL } from \"drizzle-orm\";\nimport { getPrimaryKeys, getTableMetadata } from \"../utils/sqlUtils\";\n\n/**\n * Class implementing CRUD operations for ForgeSQL ORM.\n * Provides methods for inserting, updating, and deleting records with support for optimistic locking.\n */\nexport class ForgeSQLCrudOperations implements CRUDForgeSQL {\n private readonly forgeOperations: ForgeSqlOperation;\n private readonly options: ForgeSqlOrmOptions;\n\n /**\n * Creates a new instance of ForgeSQLCrudOperations.\n * @param forgeSqlOperations - The ForgeSQL operations instance\n * @param options - Configuration options for the ORM\n */\n constructor(forgeSqlOperations: ForgeSqlOperation, options: ForgeSqlOrmOptions) {\n this.forgeOperations = forgeSqlOperations;\n this.options = options;\n }\n\n /**\n * Inserts records into the database with optional versioning support.\n * If a version field exists in the schema, versioning is applied.\n *\n * @template T - The type of the table schema\n * @param {T} schema - The entity schema\n * @param {Partial<InferInsertModel<T>>[]} models - Array of entities to insert\n * @param {boolean} [updateIfExists=false] - Whether to update existing records\n * @returns {Promise<number>} The number of inserted rows\n * @throws {Error} If the insert operation fails\n */\n async insert<T extends AnyMySqlTable>(\n schema: T,\n models: InferInsertModel<T>[],\n updateIfExists: boolean = false,\n ): Promise<number> {\n if (!models?.length) return 0;\n\n const { tableName, columns } = getTableMetadata(schema);\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Prepare models with version field if needed\n const preparedModels = models.map((model) =>\n this.prepareModelWithVersion(model, versionMetadata, columns),\n );\n\n // Build insert query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .insert(schema)\n .values(preparedModels);\n\n // Add onDuplicateKeyUpdate if needed\n const finalQuery = updateIfExists\n ? queryBuilder.onDuplicateKeyUpdate({\n set: Object.fromEntries(\n Object.keys(preparedModels[0]).map((key) => [key, (schema as any)[key]]),\n ) as any,\n })\n : queryBuilder;\n\n // Execute query\n const result = await finalQuery;\n return result[0].insertId;\n }\n\n /**\n * Deletes a record by its primary key with optional version check.\n * If versioning is enabled, ensures the record hasn't been modified since last read.\n *\n * @template T - The type of the table schema\n * @param {unknown} id - The ID of the record to delete\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If the delete operation fails\n * @throws {Error} If multiple primary keys are found\n */\n async deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number> {\n const { tableName, columns } = getTableMetadata(schema);\n const primaryKeys = this.getPrimaryKeys(schema);\n\n if (primaryKeys.length !== 1) {\n throw new Error(\"Only single primary key is supported\");\n }\n\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Build delete conditions\n const conditions: SQL<unknown>[] = [eq(primaryKeyColumn, id)];\n\n // Add version check if needed\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n const oldModel = await this.getOldModel({ [primaryKeyName]: id }, schema, [\n versionMetadata.fieldName,\n versionField,\n ]);\n conditions.push(eq(versionField, (oldModel as any)[versionMetadata.fieldName]));\n }\n }\n\n // Execute delete query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .delete(schema)\n .where(and(...conditions));\n\n const result = await queryBuilder;\n\n return result[0].affectedRows;\n }\n\n /**\n * Updates a record by its primary key with optimistic locking support.\n * If versioning is enabled:\n * - Retrieves the current version\n * - Checks for concurrent modifications\n * - Increments the version on successful update\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity with updated values\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If the primary key is not provided\n * @throws {Error} If optimistic locking check fails\n * @throws {Error} If multiple primary keys are found\n */\n async updateById<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n schema: T,\n ): Promise<number> {\n const { tableName, columns } = getTableMetadata(schema);\n const primaryKeys = this.getPrimaryKeys(schema);\n\n if (primaryKeys.length !== 1) {\n throw new Error(\"Only single primary key is supported\");\n }\n\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Validate primary key\n if (!(primaryKeyName in entity)) {\n throw new Error(`Primary key ${primaryKeyName} must be provided in the entity`);\n }\n\n // Get current version if needed\n const currentVersion = await this.getCurrentVersion(\n entity,\n primaryKeyName,\n versionMetadata,\n columns,\n schema,\n );\n\n // Prepare update data with version\n const updateData = this.prepareUpdateData(entity, versionMetadata, columns, currentVersion);\n\n // Build update conditions\n const conditions: SQL<unknown>[] = [\n eq(primaryKeyColumn, entity[primaryKeyName as keyof typeof entity]),\n ];\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n conditions.push(eq(versionField, currentVersion));\n }\n }\n\n // Execute update query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .update(schema)\n .set(updateData)\n .where(and(...conditions));\n\n const result = await queryBuilder;\n // Check optimistic locking\n if (versionMetadata && result[0].affectedRows === 0) {\n throw new Error(\n `Optimistic locking failed: record with primary key ${entity[primaryKeyName as keyof typeof entity]} has been modified`,\n );\n }\n\n return result[0].affectedRows;\n }\n\n /**\n * Updates specified fields of records based on provided conditions.\n * This method does not support versioning and should be used with caution.\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} updateData - The data to update\n * @param {T} schema - The entity schema\n * @param {SQL<unknown>} where - The WHERE conditions\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If WHERE conditions are not provided\n * @throws {Error} If the update operation fails\n */\n async updateFields<T extends AnyMySqlTable>(\n updateData: Partial<InferInsertModel<T>>,\n schema: T,\n where?: SQL<unknown>,\n ): Promise<number> {\n if (!where) {\n throw new Error(\"WHERE conditions must be provided\");\n }\n\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .update(schema)\n .set(updateData)\n .where(where);\n\n const result = await queryBuilder;\n return result[0].affectedRows;\n }\n\n // Helper methods\n\n /**\n * Gets primary keys from the schema.\n * @template T - The type of the table schema\n * @param {T} schema - The table schema\n * @returns {[string, AnyColumn][]} Array of primary key name and column pairs\n * @throws {Error} If no primary keys are found\n */\n private getPrimaryKeys<T extends AnyMySqlTable>(schema: T): [string, AnyColumn][] {\n const primaryKeys = getPrimaryKeys(schema);\n if (!primaryKeys) {\n throw new Error(`No primary keys found for schema: ${schema}`);\n }\n\n return primaryKeys;\n }\n\n /**\n * Validates and retrieves version field metadata.\n * @param {string} tableName - The name of the table\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @returns {Object | undefined} Version field metadata if valid, undefined otherwise\n */\n private validateVersionField(\n tableName: string,\n columns: Record<string, AnyColumn>,\n ): { fieldName: string; type: string } | undefined {\n if (this.options.disableOptimisticLocking) {\n return undefined;\n }\n const versionMetadata = this.options.additionalMetadata?.[tableName]?.versionField;\n if (!versionMetadata) return undefined;\n let fieldName = versionMetadata.fieldName;\n\n let versionField = columns[versionMetadata.fieldName];\n if (!versionField) {\n const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);\n if (find) {\n fieldName = find[0];\n versionField = find[1];\n }\n }\n if (!versionField) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" not found in table ${tableName}. Versioning will be skipped.`,\n );\n return undefined;\n }\n\n if (!versionField.notNull) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n return undefined;\n }\n\n const fieldType = versionField.getSQLType();\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n\n if (!isSupportedType) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n return undefined;\n }\n\n return { fieldName, type: fieldType };\n }\n\n /**\n * Gets the current version of an entity.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity\n * @param {string} primaryKeyName - The name of the primary key\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @param {T} schema - The table schema\n * @returns {Promise<unknown>} The current version value\n */\n private async getCurrentVersion<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n primaryKeyName: string,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n schema: T,\n ): Promise<unknown> {\n if (!versionMetadata || !columns) return undefined;\n\n const versionField = columns[versionMetadata.fieldName];\n if (!versionField) return undefined;\n\n if (versionMetadata.fieldName in entity) {\n return entity[versionMetadata.fieldName as keyof typeof entity];\n }\n\n const oldModel = await this.getOldModel(\n { [primaryKeyName]: entity[primaryKeyName as keyof typeof entity] },\n schema,\n [versionMetadata.fieldName, versionField],\n );\n\n return (oldModel as any)[versionMetadata.fieldName];\n }\n\n /**\n * Prepares a model for insertion with version field.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} model - The model to prepare\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @returns {InferInsertModel<T>} The prepared model\n */\n private prepareModelWithVersion<T extends AnyMySqlTable>(\n model: Partial<InferInsertModel<T>>,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n ): InferInsertModel<T> {\n if (!versionMetadata || !columns) return model as InferInsertModel<T>;\n let fieldName = versionMetadata.fieldName;\n let versionField = columns[versionMetadata.fieldName];\n if (!versionField) {\n const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);\n if (find) {\n fieldName = find[0];\n versionField = find[1];\n }\n }\n\n if (!versionField) return model as InferInsertModel<T>;\n\n const modelWithVersion = { ...model };\n const fieldType = versionField.getSQLType();\n const versionValue = fieldType === \"datetime\" || fieldType === \"timestamp\" ? new Date() : 1;\n modelWithVersion[fieldName as keyof typeof modelWithVersion] = versionValue as any;\n\n return modelWithVersion as InferInsertModel<T>;\n }\n\n /**\n * Prepares update data with version field.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity to update\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @param {unknown} currentVersion - The current version value\n * @returns {Partial<InferInsertModel<T>>} The prepared update data\n */\n private prepareUpdateData<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n currentVersion: unknown,\n ): Partial<InferInsertModel<T>> {\n const updateData = { ...entity };\n\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n const fieldType = versionField.getSQLType();\n updateData[versionMetadata.fieldName as keyof typeof updateData] =\n fieldType === \"datetime\" || fieldType === \"timestamp\"\n ? new Date()\n : (((currentVersion as number) + 1) as any);\n }\n }\n\n return updateData;\n }\n\n /**\n * Retrieves an existing model by primary key.\n * @template T - The type of the table schema\n * @param {Record<string, unknown>} primaryKeyValues - The primary key values\n * @param {T} schema - The table schema\n * @param {[string, AnyColumn]} versionField - The version field name and column\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} The existing model\n * @throws {Error} If the record is not found\n */\n private async getOldModel<T extends AnyMySqlTable>(\n primaryKeyValues: Record<string, unknown>,\n schema: T,\n versionField: [string, AnyColumn],\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n > {\n const [versionFieldName, versionFieldColumn] = versionField;\n const primaryKeys = this.getPrimaryKeys(schema);\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n\n const resultQuery = this.forgeOperations\n .getDrizzleQueryBuilder()\n .select({\n [primaryKeyName]: primaryKeyColumn as any,\n [versionFieldName]: versionFieldColumn as any,\n })\n .from(schema)\n .where(eq(primaryKeyColumn, primaryKeyValues[primaryKeyName]));\n\n const model = await this.forgeOperations.fetch().executeQueryOnlyOne(resultQuery);\n\n if (!model) {\n throw new Error(`Record not found in table ${schema}`);\n }\n\n return model as Awaited<T> extends Array<any> ? Awaited<T>[number] : Awaited<T>;\n }\n}\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport { ForgeSqlOrmOptions, SchemaSqlForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport {\n AnyMySqlSelectQueryBuilder,\n MySqlSelectDynamic,\n} from \"drizzle-orm/mysql-core/query-builders/select.types\";\n\n/**\n * Class implementing SQL select operations for ForgeSQL ORM.\n * Provides methods for executing queries and mapping results to entity types.\n */\nexport class ForgeSQLSelectOperations implements SchemaSqlForgeSql {\n private readonly options: ForgeSqlOrmOptions;\n\n /**\n * Creates a new instance of ForgeSQLSelectOperations.\n * @param {ForgeSqlOrmOptions} options - Configuration options for the ORM\n */\n constructor(options: ForgeSqlOrmOptions) {\n this.options = options;\n }\n\n /**\n * Executes a Drizzle query and returns a single result.\n * Throws an error if more than one record is returned.\n *\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} A single result object or undefined\n * @throws {Error} If more than one record is returned\n */\n async executeQueryOnlyOne<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n > {\n const results: Awaited<T> = await query;\n const datas = results as unknown[];\n if (!datas.length) {\n return undefined;\n }\n if (datas.length > 1) {\n throw new Error(`Expected 1 record but returned ${datas.length}`);\n }\n\n return datas[0] as Awaited<T> extends Array<any> ? Awaited<T>[number] : Awaited<T>;\n }\n\n /**\n * Executes a raw SQL query and returns the results.\n * Logs the query if logging is enabled.\n *\n * @template T - The type of the result objects\n * @param {string} query - The raw SQL query to execute\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<T[]>} A list of results as objects\n */\n async executeRawSQL<T extends object | unknown>(query: string, params?: unknown[]): Promise<T[]> {\n if (this.options.logRawSqlQuery) {\n const paramsStr = params ? `, with params: ${JSON.stringify(params)}` : \"\";\n console.debug(`Executing with SQL ${query}${paramsStr}`);\n }\n const sqlStatement = sql.prepare<T>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n const result = await sqlStatement.execute();\n return result.rows as T[];\n }\n\n /**\n * Executes a raw SQL update query.\n * @param {string} query - The raw SQL update query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<UpdateQueryResponse>} The update response containing affected rows\n */\n async executeRawUpdateSQL(query: string, params?: unknown[]): Promise<UpdateQueryResponse> {\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n if (this.options.logRawSqlQuery) {\n console.debug(\n `Executing Update with SQL ${query}` +\n (params ? `, with params: ${JSON.stringify(params)}` : \"\"),\n );\n }\n const updateQueryResponseResults = await sqlStatement.execute();\n return updateQueryResponseResults.rows;\n }\n}\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\n\ninterface ForgeSQLResult {\n rows: Record<string, unknown>[] | Record<string, unknown>;\n}\n\nexport const forgeDriver = async (\n query: string,\n params: any[],\n method: \"all\" | \"execute\",\n): Promise<{\n rows: any[];\n insertId?: number;\n affectedRows?: number;\n}> => {\n try {\n if (method == \"execute\") {\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n const updateQueryResponseResults = await sqlStatement.execute();\n let result = updateQueryResponseResults.rows as any;\n return { ...result, rows: [result] };\n } else {\n const sqlStatement = await sql.prepare<unknown>(query);\n if (params) {\n await sqlStatement.bindParams(...params);\n }\n const result = (await sqlStatement.execute()) as ForgeSQLResult;\n let rows;\n rows = (result.rows as any[]).map((r) => Object.values(r as Record<string, unknown>));\n return { rows: rows };\n }\n } catch (error) {\n console.error(\"SQL Error:\", JSON.stringify(error));\n throw error;\n }\n};\n","/**\n * Interface for SQL hints configuration\n */\nexport interface SqlHints {\n /** SQL hints for SELECT queries */\n select?: string[];\n /** SQL hints for INSERT queries */\n insert?: string[];\n /** SQL hints for UPDATE queries */\n update?: string[];\n /** SQL hints for DELETE queries */\n delete?: string[];\n}\n\n/**\n * Detects the type of SQL query and injects appropriate hints\n * @param query - The SQL query to analyze\n * @param hints - The hints configuration\n * @returns The modified query with injected hints\n */\nexport function injectSqlHints(query: string, hints?: SqlHints): string {\n if (!hints) {\n return query;\n }\n\n // Normalize the query for easier matching\n const normalizedQuery = query.trim().toUpperCase();\n\n // Get the appropriate hints based on query type\n let queryHints: string[] | undefined;\n\n if (normalizedQuery.startsWith(\"SELECT\")) {\n queryHints = hints.select;\n } else if (normalizedQuery.startsWith(\"INSERT\")) {\n queryHints = hints.insert;\n } else if (normalizedQuery.startsWith(\"UPDATE\")) {\n queryHints = hints.update;\n } else if (normalizedQuery.startsWith(\"DELETE\")) {\n queryHints = hints.delete;\n }\n\n // If no hints for this query type, return original query\n if (!queryHints || queryHints.length === 0) {\n return query;\n }\n\n // Join all hints with spaces\n const hintsString = queryHints.join(\" \");\n\n // Inject hints into the query\n if (normalizedQuery.startsWith(\"SELECT\")) {\n return `SELECT /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"INSERT\")) {\n return `INSERT /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"UPDATE\")) {\n return `UPDATE /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"DELETE\")) {\n return `DELETE /*+ ${hintsString} */ ${query.substring(6)}`;\n }\n\n // If no match found, return original query\n return query;\n}\n","import { forgeDriver } from \"./forgeDriver\";\nimport { injectSqlHints, SqlHints } from \"./sqlHints\";\n\n/**\n * Creates a proxy for the forgeDriver that injects SQL hints\n * @returns A proxied version of the forgeDriver\n */\nexport function createForgeDriverProxy(options?: SqlHints, logRawSqlQuery?: boolean) {\n return async (\n query: string,\n params: any[],\n method: \"all\" | \"execute\",\n ): Promise<{\n rows: any[];\n insertId?: number;\n affectedRows?: number;\n }> => {\n // Inject SQL hints into the query\n const modifiedQuery = injectSqlHints(query, options);\n\n if (options && logRawSqlQuery && modifiedQuery !== query) {\n console.warn(\"modified query: \" + modifiedQuery);\n }\n // Call the original forgeDriver with the modified query\n return forgeDriver(modifiedQuery, params, method);\n };\n}\n","import { MySqlRemoteDatabase } from \"drizzle-orm/mysql-proxy\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { applyFromDriverTransform, mapSelectFieldsWithAlias } from \"../../..\";\nimport { MySqlSelectBuilder } from \"drizzle-orm/mysql-core\";\nimport { MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy\";\n\nfunction createAliasedSelectBuilder<TSelection extends SelectedFields>(\n db: MySqlRemoteDatabase<any>,\n fields: TSelection,\n selectFn: (selections: any) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>,\n): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n const { selections, aliasMap } = mapSelectFieldsWithAlias(fields);\n const builder = selectFn(selections);\n\n const wrapBuilder = (rawBuilder: any): any => {\n return new Proxy(rawBuilder, {\n get(target, prop, receiver) {\n if (prop === \"execute\") {\n return async (...args: any[]) => {\n const rows = await target.execute(...args);\n return applyFromDriverTransform(rows, selections, aliasMap);\n };\n }\n\n if (prop === \"then\") {\n return (onfulfilled: any, onrejected: any) =>\n target.execute().then((rows: unknown[]) => {\n const transformed = applyFromDriverTransform(rows, selections, aliasMap);\n return onfulfilled?.(transformed);\n }, onrejected);\n }\n\n const value = Reflect.get(target, prop, receiver);\n\n if (typeof value === \"function\") {\n return (...args: any[]) => {\n const result = value.apply(target, args);\n\n if (typeof result === \"object\" && result !== null && \"execute\" in result) {\n return wrapBuilder(result);\n }\n\n return result;\n };\n }\n\n return value;\n },\n });\n };\n\n return wrapBuilder(builder);\n}\n\nexport function patchDbWithSelectAliased(db: MySqlRemoteDatabase<any>): MySqlRemoteDatabase<any> & {\n selectAliased: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n selectAliasedDistinct: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n} {\n db.selectAliased = function <TSelection extends SelectedFields>(fields: TSelection) {\n return createAliasedSelectBuilder(db, fields, (selections) => db.select(selections));\n };\n\n db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {\n return createAliasedSelectBuilder(db, fields, (selections) => db.selectDistinct(selections));\n };\n\n return db;\n}\n","import { ForgeSqlOperation, SchemaAnalyzeForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport { Query } from \"drizzle-orm\";\nimport {\n ClusterStatementRowCamelCase,\n ExplainAnalyzeRow,\n SlowQueryNormalized,\n} from \"./SystemTables\";\nimport { SqlParameters } from \"@forge/sql/out/sql-statement\";\nimport { AnyMySqlTable } from \"drizzle-orm/mysql-core/index\";\nimport { getTableName } from \"drizzle-orm/table\";\nimport moment from \"moment\";\n\n/**\n * Interface representing a row from the EXPLAIN ANALYZE output\n */\ninterface DecodedPlanRow {\n id: string;\n estRows?: string;\n estCost?: string;\n actRows?: string;\n task?: string;\n \"access object\"?: string;\n \"execution info\"?: string;\n \"operator info\"?: string;\n memory?: string;\n disk?: string;\n}\n\n/**\n * Interface representing a raw slow query row from the database\n */\ninterface SlowQueryRaw {\n Time: string;\n Txn_start_ts: number;\n User: string;\n Host: string;\n Conn_ID: number;\n DB: string;\n Query: string;\n Digest: string;\n Query_time: number;\n Compile_time: number;\n Optimize_time: number;\n Process_time: number;\n Wait_time: number;\n Parse_time: number;\n Rewrite_time: number;\n Cop_time: number;\n Cop_proc_avg: number;\n Cop_proc_max: number;\n Cop_proc_p90: number;\n Cop_proc_addr: string;\n Cop_wait_avg: number;\n Cop_wait_max: number;\n Cop_wait_p90: number;\n Cop_wait_addr: string;\n Mem_max: number;\n Disk_max: number;\n Total_keys: number;\n Process_keys: number;\n Request_count: number;\n KV_total: number;\n PD_total: number;\n Result_rows: number;\n Rocksdb_block_cache_hit_count: number;\n Rocksdb_block_read_count: number;\n Rocksdb_block_read_byte: number;\n Plan: string;\n Binary_plan: string;\n Plan_digest: string;\n}\n\n/**\n * Interface representing a row from the cluster statements table\n */\nexport interface ClusterStatementRow {\n INSTANCE: string;\n SUMMARY_BEGIN_TIME: string;\n SUMMARY_END_TIME: string;\n STMT_TYPE: string;\n SCHEMA_NAME: string;\n DIGEST: string;\n DIGEST_TEXT: string;\n TABLE_NAMES: string;\n INDEX_NAMES: string | null;\n SAMPLE_USER: string;\n EXEC_COUNT: number;\n SUM_ERRORS: number;\n SUM_WARNINGS: number;\n SUM_LATENCY: number;\n MAX_LATENCY: number;\n MIN_LATENCY: number;\n AVG_LATENCY: number;\n AVG_PARSE_LATENCY: number;\n MAX_PARSE_LATENCY: number;\n AVG_COMPILE_LATENCY: number;\n MAX_COMPILE_LATENCY: number;\n SUM_COP_TASK_NUM: number;\n MAX_COP_PROCESS_TIME: number;\n MAX_COP_PROCESS_ADDRESS: string;\n MAX_COP_WAIT_TIME: number;\n MAX_COP_WAIT_ADDRESS: string;\n AVG_PROCESS_TIME: number;\n MAX_PROCESS_TIME: number;\n AVG_WAIT_TIME: number;\n MAX_WAIT_TIME: number;\n AVG_BACKOFF_TIME: number;\n MAX_BACKOFF_TIME: number;\n AVG_TOTAL_KEYS: number;\n MAX_TOTAL_KEYS: number;\n AVG_PROCESSED_KEYS: number;\n MAX_PROCESSED_KEYS: number;\n AVG_ROCKSDB_DELETE_SKIPPED_COUNT: number;\n MAX_ROCKSDB_DELETE_SKIPPED_COUNT: number;\n AVG_ROCKSDB_KEY_SKIPPED_COUNT: number;\n MAX_ROCKSDB_KEY_SKIPPED_COUNT: number;\n AVG_ROCKSDB_BLOCK_CACHE_HIT_COUNT: number;\n MAX_ROCKSDB_BLOCK_CACHE_HIT_COUNT: number;\n AVG_ROCKSDB_BLOCK_READ_COUNT: number;\n MAX_ROCKSDB_BLOCK_READ_COUNT: number;\n AVG_ROCKSDB_BLOCK_READ_BYTE: number;\n MAX_ROCKSDB_BLOCK_READ_BYTE: number;\n AVG_PREWRITE_TIME: number;\n MAX_PREWRITE_TIME: number;\n AVG_COMMIT_TIME: number;\n MAX_COMMIT_TIME: number;\n AVG_GET_COMMIT_TS_TIME: number;\n MAX_GET_COMMIT_TS_TIME: number;\n AVG_COMMIT_BACKOFF_TIME: number;\n MAX_COMMIT_BACKOFF_TIME: number;\n AVG_RESOLVE_LOCK_TIME: number;\n MAX_RESOLVE_LOCK_TIME: number;\n AVG_LOCAL_LATCH_WAIT_TIME: number;\n MAX_LOCAL_LATCH_WAIT_TIME: number;\n AVG_WRITE_KEYS: number;\n MAX_WRITE_KEYS: number;\n AVG_WRITE_SIZE: number;\n MAX_WRITE_SIZE: number;\n AVG_PREWRITE_REGIONS: number;\n MAX_PREWRITE_REGIONS: number;\n AVG_TXN_RETRY: number;\n MAX_TXN_RETRY: number;\n SUM_EXEC_RETRY: number;\n SUM_EXEC_RETRY_TIME: number;\n SUM_BACKOFF_TIMES: number;\n BACKOFF_TYPES: string | null;\n AVG_MEM: number;\n MAX_MEM: number;\n AVG_DISK: number;\n MAX_DISK: number;\n AVG_KV_TIME: number;\n AVG_PD_TIME: number;\n AVG_BACKOFF_TOTAL_TIME: number;\n AVG_WRITE_SQL_RESP_TIME: number;\n AVG_TIDB_CPU_TIME: number;\n AVG_TIKV_CPU_TIME: number;\n MAX_RESULT_ROWS: number;\n MIN_RESULT_ROWS: number;\n AVG_RESULT_ROWS: number;\n PREPARED: number;\n AVG_AFFECTED_ROWS: number;\n FIRST_SEEN: string;\n LAST_SEEN: string;\n PLAN_IN_CACHE: number;\n PLAN_CACHE_HITS: number;\n PLAN_IN_BINDING: number;\n QUERY_SAMPLE_TEXT: string;\n PREV_SAMPLE_TEXT: string;\n PLAN_DIGEST: string;\n PLAN: string;\n BINARY_PLAN: string;\n CHARSET: string;\n COLLATION: string;\n PLAN_HINT: string;\n MAX_REQUEST_UNIT_READ: number;\n AVG_REQUEST_UNIT_READ: number;\n MAX_REQUEST_UNIT_WRITE: number;\n AVG_REQUEST_UNIT_WRITE: number;\n MAX_QUEUED_RC_TIME: number;\n AVG_QUEUED_RC_TIME: number;\n RESOURCE_GROUP: string;\n PLAN_CACHE_UNQUALIFIED: number;\n PLAN_CACHE_UNQUALIFIED_LAST_REASON: string;\n}\n\n/**\n * Class implementing SQL analysis operations for ForgeSQL ORM.\n * Provides methods for analyzing query performance, execution plans, and slow queries.\n */\nexport class ForgeSQLAnalyseOperation implements SchemaAnalyzeForgeSql {\n private readonly forgeOperations: ForgeSqlOperation;\n\n /**\n * Creates a new instance of ForgeSQLAnalizeOperation.\n * @param {ForgeSqlOperation} forgeOperations - The ForgeSQL operations instance\n */\n constructor(forgeOperations: ForgeSqlOperation) {\n this.forgeOperations = forgeOperations;\n this.mapToCamelCaseClusterStatement = this.mapToCamelCaseClusterStatement.bind(this);\n }\n\n /**\n * Executes EXPLAIN on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<DecodedPlanRow>(`EXPLAIN ${query}`, bindParams as SqlParameters);\n return results.map((row) => ({\n id: row.id,\n estRows: row.estRows,\n actRows: row.actRows,\n task: row.task,\n accessObject: row[\"access object\"],\n executionInfo: row[\"execution info\"],\n operatorInfo: row[\"operator info\"],\n memory: row.memory,\n disk: row.disk,\n }));\n }\n\n /**\n * Executes EXPLAIN on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explain(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]> {\n const { sql, params } = query.toSQL();\n return this.explainRaw(sql, params);\n }\n\n /**\n * Executes EXPLAIN ANALYZE on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainAnalyzeRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<DecodedPlanRow>(`EXPLAIN ANALYZE ${query}`, bindParams as SqlParameters);\n return results.map((row) => ({\n id: row.id,\n estRows: row.estRows,\n actRows: row.actRows,\n task: row.task,\n accessObject: row[\"access object\"],\n executionInfo: row[\"execution info\"],\n operatorInfo: row[\"operator info\"],\n memory: row.memory,\n disk: row.disk,\n }));\n }\n\n /**\n * Executes EXPLAIN ANALYZE on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainAnalyze(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]> {\n const { sql, params } = query.toSQL();\n return this.explainAnalyzeRaw(sql, params);\n }\n\n /**\n * Decodes a query execution plan from its string representation.\n * @param {string} input - The raw execution plan string\n * @returns {ExplainAnalyzeRow[]} The decoded execution plan rows\n */\n decodedPlan(input: string): ExplainAnalyzeRow[] {\n if (!input) {\n return [];\n }\n const lines = input.trim().split(\"\\n\");\n if (lines.length < 2) return [];\n\n const headersRaw = lines[0]\n .split(\"\\t\")\n .map((h) => h.trim())\n .filter(Boolean);\n const headers = headersRaw.map((h) => {\n return h\n .replace(/\\s+/g, \" \")\n .replace(/[-\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : \"\"))\n .replace(/^./, (s) => s.toLowerCase());\n });\n\n return lines.slice(1).map((line) => {\n const values = line\n .split(\"\\t\")\n .map((s) => s.trim())\n .filter(Boolean);\n const row: Record<string, string> = {};\n headers.forEach((key, i) => {\n row[key] = values[i] ?? \"\";\n });\n return row as unknown as ExplainAnalyzeRow;\n });\n }\n\n /**\n * Normalizes a raw slow query row into a more structured format.\n * @param {SlowQueryRaw} row - The raw slow query data\n * @returns {SlowQueryNormalized} The normalized slow query data\n */\n normalizeSlowQuery(row: SlowQueryRaw): SlowQueryNormalized {\n return {\n time: row.Time,\n txnStartTs: row.Txn_start_ts,\n user: row.User,\n host: row.Host,\n connId: row.Conn_ID,\n db: row.DB,\n query: row.Query,\n digest: row.Digest,\n queryTime: row.Query_time,\n compileTime: row.Compile_time,\n optimizeTime: row.Optimize_time,\n processTime: row.Process_time,\n waitTime: row.Wait_time,\n parseTime: row.Parse_time,\n rewriteTime: row.Rewrite_time,\n copTime: row.Cop_time,\n copProcAvg: row.Cop_proc_avg,\n copProcMax: row.Cop_proc_max,\n copProcP90: row.Cop_proc_p90,\n copProcAddr: row.Cop_proc_addr,\n copWaitAvg: row.Cop_wait_avg,\n copWaitMax: row.Cop_wait_max,\n copWaitP90: row.Cop_wait_p90,\n copWaitAddr: row.Cop_wait_addr,\n memMax: row.Mem_max,\n diskMax: row.Disk_max,\n totalKeys: row.Total_keys,\n processKeys: row.Process_keys,\n requestCount: row.Request_count,\n kvTotal: row.KV_total,\n pdTotal: row.PD_total,\n resultRows: row.Result_rows,\n rocksdbBlockCacheHitCount: row.Rocksdb_block_cache_hit_count,\n rocksdbBlockReadCount: row.Rocksdb_block_read_count,\n rocksdbBlockReadByte: row.Rocksdb_block_read_byte,\n plan: row.Plan,\n binaryPlan: row.Binary_plan,\n planDigest: row.Plan_digest,\n parsedPlan: this.decodedPlan(row.Plan),\n };\n }\n\n /**\n * Builds a SQL query for retrieving cluster statement history.\n * @param {string[]} tables - The tables to analyze\n * @param {Date} [from] - The start date for the analysis\n * @param {Date} [to] - The end date for the analysis\n * @returns {string} The SQL query for cluster statement history\n */\n buildClusterStatementQuery(tables: string[], from?: Date, to?: Date): string {\n const formatDateTime = (date: Date): string => moment(date).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n\n const tableConditions = tables\n .map((table) => `TABLE_NAMES LIKE CONCAT(SCHEMA_NAME, '.', '%', '${table}', '%')`)\n .join(\" OR \");\n\n const timeConditions: string[] = [];\n if (from) {\n timeConditions.push(`SUMMARY_BEGIN_TIME >= '${formatDateTime(from)}'`);\n }\n if (to) {\n timeConditions.push(`SUMMARY_END_TIME <= '${formatDateTime(to)}'`);\n }\n\n let whereClauses;\n if (tableConditions?.length) {\n whereClauses = [tableConditions ? `(${tableConditions})` : \"\", ...timeConditions];\n } else {\n whereClauses = timeConditions;\n }\n\n return `\n SELECT *\n FROM (\n SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY\n UNION ALL\n SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY\n ) AS combined\n ${whereClauses?.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\"}\n `;\n }\n\n /**\n * Retrieves and analyzes slow queries from the database.\n * @returns {Promise<SlowQueryNormalized[]>} The normalized slow query data\n */\n // CLUSTER_SLOW_QUERY STATISTICS\n async analyzeSlowQueries(): Promise<SlowQueryNormalized[]> {\n const results = await this.forgeOperations.fetch().executeRawSQL<SlowQueryRaw>(`\n SELECT *\n FROM information_schema.slow_query \n ORDER BY time DESC\n `);\n return results.map((row) => this.normalizeSlowQuery(row));\n }\n\n /**\n * Converts a cluster statement row to camelCase format.\n * @param {Record<string, any>} input - The input row data\n * @returns {ClusterStatementRowCamelCase} The converted row data\n */\n mapToCamelCaseClusterStatement(input: Record<string, any>): ClusterStatementRowCamelCase {\n if (!input) {\n return {} as ClusterStatementRowCamelCase;\n }\n\n const result: any = {};\n result.parsedPlan = this.decodedPlan(input[\"PLAN\"] ?? \"\");\n for (const key in input) {\n const camelKey = key.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n result[camelKey] = input[key];\n }\n\n return result as ClusterStatementRowCamelCase;\n }\n\n /**\n * Analyzes query history for specific tables using raw table names.\n * @param {string[]} tables - The table names to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n async analyzeQueriesHistoryRaw(\n tables: string[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<ClusterStatementRow>(\n this.buildClusterStatementQuery(tables ?? [], fromDate, toDate),\n );\n return results.map((r) => this.mapToCamelCaseClusterStatement(r));\n }\n\n /**\n * Analyzes query history for specific tables using Drizzle table objects.\n * @param {AnyMySqlTable[]} tables - The Drizzle table objects to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n async analyzeQueriesHistory(\n tables: AnyMySqlTable[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]> {\n const tableNames = tables?.map((table) => getTableName(table)) ?? [];\n return this.analyzeQueriesHistoryRaw(tableNames, fromDate, toDate);\n }\n}\n","import { ForgeSQLCrudOperations } from \"./ForgeSQLCrudOperations\";\nimport {\n CRUDForgeSQL,\n ForgeSqlOperation,\n ForgeSqlOrmOptions,\n SchemaAnalyzeForgeSql,\n SchemaSqlForgeSql,\n} from \"./ForgeSQLQueryBuilder\";\nimport { ForgeSQLSelectOperations } from \"./ForgeSQLSelectOperations\";\nimport { drizzle, MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy\";\nimport { createForgeDriverProxy } from \"../utils/forgeDriverProxy\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { MySqlSelectBuilder } from \"drizzle-orm/mysql-core\";\nimport { patchDbWithSelectAliased } from \"../lib/drizzle/extensions/selectAliased\";\nimport { ForgeSQLAnalyseOperation } from \"./ForgeSQLAnalyseOperations\";\n\n/**\n * Implementation of ForgeSQLORM that uses Drizzle ORM for query building.\n * This class provides a bridge between Forge SQL and Drizzle ORM, allowing\n * to use Drizzle's query builder while executing queries through Forge SQL.\n */\nclass ForgeSQLORMImpl implements ForgeSqlOperation {\n private static instance: ForgeSQLORMImpl | null = null;\n private readonly drizzle: MySqlRemoteDatabase<any> & {\n selectAliased: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n selectAliasedDistinct: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n };\n private readonly crudOperations: CRUDForgeSQL;\n private readonly fetchOperations: SchemaSqlForgeSql;\n private readonly analyzeOperations: SchemaAnalyzeForgeSql;\n\n /**\n * Private constructor to enforce singleton behavior.\n * @param options - Options for configuring ForgeSQL ORM behavior.\n */\n private constructor(options?: ForgeSqlOrmOptions) {\n try {\n const newOptions: ForgeSqlOrmOptions = options ?? {\n logRawSqlQuery: false,\n disableOptimisticLocking: false,\n };\n if (newOptions.logRawSqlQuery) {\n console.debug(\"Initializing ForgeSQLORM...\");\n }\n // Initialize Drizzle instance with our custom driver\n const proxiedDriver = createForgeDriverProxy(newOptions.hints, newOptions.logRawSqlQuery);\n this.drizzle = patchDbWithSelectAliased(\n drizzle(proxiedDriver, { logger: newOptions.logRawSqlQuery }),\n );\n this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);\n this.fetchOperations = new ForgeSQLSelectOperations(newOptions);\n this.analyzeOperations = new ForgeSQLAnalyseOperation(this);\n } catch (error) {\n console.error(\"ForgeSQLORM initialization failed:\", error);\n throw error;\n }\n }\n\n /**\n * Create the modify operations instance.\n * @returns modify operations.\n */\n modify(): CRUDForgeSQL {\n return this.crudOperations;\n }\n\n /**\n * Returns the singleton instance of ForgeSQLORMImpl.\n * @param options - Options for configuring ForgeSQL ORM behavior.\n * @returns The singleton instance of ForgeSQLORMImpl.\n */\n static getInstance(options?: ForgeSqlOrmOptions): ForgeSqlOperation {\n ForgeSQLORMImpl.instance ??= new ForgeSQLORMImpl(options);\n return ForgeSQLORMImpl.instance;\n }\n\n /**\n * Retrieves the CRUD operations instance.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.modify();\n }\n\n /**\n * Retrieves the fetch operations instance.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.fetchOperations;\n }\n analyze(): SchemaAnalyzeForgeSql {\n return this.analyzeOperations;\n }\n\n /**\n * Returns a Drizzle query builder instance.\n *\n * ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.\n * The returned instance should NOT be used for direct database connections or query execution.\n * All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.\n *\n * @returns A Drizzle query builder instance for query construction only.\n */\n getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> {\n return this.drizzle;\n }\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n return this.drizzle.selectAliased(fields);\n }\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n return this.drizzle.selectAliasedDistinct(fields);\n }\n}\n\n/**\n * Public class that acts as a wrapper around the private ForgeSQLORMImpl.\n * Provides a clean interface for working with Forge SQL and Drizzle ORM.\n */\nclass ForgeSQLORM implements ForgeSqlOperation {\n private readonly ormInstance: ForgeSqlOperation;\n\n constructor(options?: ForgeSqlOrmOptions) {\n this.ormInstance = ForgeSQLORMImpl.getInstance(options);\n }\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n return this.ormInstance.select(fields);\n }\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n return this.ormInstance.selectDistinct(fields);\n }\n\n /**\n * Proxies the `crud` method from `ForgeSQLORMImpl`.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.ormInstance.modify();\n }\n\n /**\n * Proxies the `modify` method from `ForgeSQLORMImpl`.\n * @returns Modify operations.\n */\n modify(): CRUDForgeSQL {\n return this.ormInstance.modify();\n }\n\n /**\n * Proxies the `fetch` method from `ForgeSQLORMImpl`.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.ormInstance.fetch();\n }\n\n /**\n * Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.\n * @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance\n */\n analyze(): SchemaAnalyzeForgeSql {\n return this.ormInstance.analyze();\n }\n\n /**\n * Returns a Drizzle query builder instance.\n *\n * ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.\n * The returned instance should NOT be used for direct database connections or query execution.\n * All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.\n *\n * @returns A Drizzle query builder instance for query construction only.\n */\n getDrizzleQueryBuilder() {\n return this.ormInstance.getDrizzleQueryBuilder();\n }\n}\n\nexport default ForgeSQLORM;\n","import { UpdateQueryResponse } from \"@forge/sql\";\nimport { SqlParameters } from \"@forge/sql/out/sql-statement\";\nimport {\n AnyMySqlSelectQueryBuilder,\n AnyMySqlTable,\n customType,\n MySqlSelectBuilder,\n} from \"drizzle-orm/mysql-core\";\nimport {\n MySqlSelectDynamic,\n type SelectedFields,\n} from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { InferInsertModel, Query, SQL } from \"drizzle-orm\";\nimport moment from \"moment/moment\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\nimport { MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy/index\";\nimport { SqlHints } from \"../utils/sqlHints\";\nimport {\n ClusterStatementRowCamelCase,\n ExplainAnalyzeRow,\n SlowQueryNormalized,\n} from \"./SystemTables\";\n\n/**\n * Core interface for ForgeSQL operations.\n * Provides access to CRUD operations, schema-level SQL operations, and query analysis capabilities.\n *\n * @interface ForgeSqlOperation\n * @extends {QueryBuilderForgeSql}\n */\nexport interface ForgeSqlOperation extends QueryBuilderForgeSql {\n /**\n * Provides CRUD (Create, Update, Delete) operations.\n * @deprecated Use modify() instead for better type safety and consistency\n * @returns {CRUDForgeSQL} Interface for performing CRUD operations\n */\n crud(): CRUDForgeSQL;\n\n /**\n * Provides modify (Create, Update, Delete) operations with optimistic locking support.\n * @returns {CRUDForgeSQL} Interface for performing CRUD operations\n */\n modify(): CRUDForgeSQL;\n\n /**\n * Provides schema-level SQL fetch operations with type safety.\n * @returns {SchemaSqlForgeSql} Interface for executing schema-bound SQL queries\n */\n fetch(): SchemaSqlForgeSql;\n\n /**\n * Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.\n * @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance\n */\n analyze(): SchemaAnalyzeForgeSql;\n}\n\n/**\n * Interface for Query Builder operations.\n * Provides access to the underlying Drizzle ORM query builder with enhanced functionality.\n *\n * @interface QueryBuilderForgeSql\n */\nexport interface QueryBuilderForgeSql {\n /**\n * Creates a new query builder for the given entity.\n * @returns {MySqlRemoteDatabase<Record<string, unknown>>} The Drizzle database instance for building queries\n */\n getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>>;\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n}\n\n/**\n * Interface for Modify (Create, Update, Delete) operations.\n * Provides methods for basic database operations with support for optimistic locking.\n *\n * @interface CRUDForgeSQL\n */\nexport interface CRUDForgeSQL {\n /**\n * Inserts multiple records into the database.\n * @template T - The type of the table schema\n * @param {T} schema - The entity schema\n * @param {InferInsertModel<T>[]} models - The list of entities to insert\n * @param {boolean} [updateIfExists] - Whether to update the row if it already exists (default: false)\n * @returns {Promise<number>} The number of inserted rows\n * @throws {Error} If the insert operation fails\n */\n insert<T extends AnyMySqlTable>(\n schema: T,\n models: InferInsertModel<T>[],\n updateIfExists?: boolean,\n ): Promise<number>;\n\n /**\n * Deletes a record by its ID.\n * @template T - The type of the table schema\n * @param {unknown} id - The ID of the record to delete\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} The number of rows affected\n * @throws {Error} If the delete operation fails\n */\n deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number>;\n\n /**\n * Updates a record by its ID with optimistic locking support.\n * If a version field is defined in the schema, versioning is applied:\n * - the current record version is retrieved\n * - checked for concurrent modifications\n * - and then incremented\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity with updated values\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} The number of rows affected\n * @throws {Error} If the primary key is not included in the update fields\n * @throws {Error} If optimistic locking check fails\n */\n updateById<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n schema: T,\n ): Promise<number>;\n\n /**\n * Updates specified fields of records based on provided conditions.\n * If the \"where\" parameter is not provided, the WHERE clause is built from the entity fields\n * that are not included in the list of fields to update.\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} updateData - The object containing values to update\n * @param {T} schema - The entity schema\n * @param {SQL<unknown>} [where] - Optional filtering conditions for the WHERE clause\n * @returns {Promise<number>} The number of affected rows\n * @throws {Error} If no filtering criteria are provided\n * @throws {Error} If the update operation fails\n */\n updateFields<T extends AnyMySqlTable>(\n updateData: Partial<InferInsertModel<T>>,\n schema: T,\n where?: SQL<unknown>,\n ): Promise<number>;\n}\n\n/**\n * Interface for schema analysis operations.\n * Provides methods for analyzing query performance and execution plans.\n *\n * @interface SchemaAnalyzeForgeSql\n */\nexport interface SchemaAnalyzeForgeSql {\n /**\n * Executes EXPLAIN on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explain(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN ANALYZE on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainAnalyze(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN ANALYZE on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainAnalyzeRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Analyzes slow queries from the database.\n * @returns {Promise<SlowQueryNormalized[]>} The normalized slow query data\n */\n analyzeSlowQueries(): Promise<SlowQueryNormalized[]>;\n\n /**\n * Analyzes query history for specific tables using Drizzle table objects.\n * @param {AnyMySqlTable[]} tables - The Drizzle table objects to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n analyzeQueriesHistory(\n tables: AnyMySqlTable[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]>;\n\n /**\n * Analyzes query history for specific tables using raw table names.\n * @param {string[]} tables - The table names to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n analyzeQueriesHistoryRaw(\n tables: string[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]>;\n}\n\n/**\n * Interface for schema-level SQL operations.\n * Provides methods for executing SQL queries with schema binding and type safety.\n *\n * @interface SchemaSqlForgeSql\n */\nexport interface SchemaSqlForgeSql {\n /**\n * Executes a Drizzle query and returns a single result.\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} A single result object or undefined\n * @throws {Error} If more than one record is returned\n * @throws {Error} If the query execution fails\n */\n executeQueryOnlyOne<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n >;\n\n /**\n * Executes a raw SQL query and returns the results.\n * @template T - The type of the result objects\n * @param {string} query - The raw SQL query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<T[]>} A list of results as objects\n * @throws {Error} If the query execution fails\n */\n executeRawSQL<T extends object | unknown>(query: string, params?: SqlParameters[]): Promise<T[]>;\n\n /**\n * Executes a raw SQL update query.\n * @param {string} query - The raw SQL update query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<UpdateQueryResponse>} The update response containing affected rows\n * @throws {Error} If the update operation fails\n */\n executeRawUpdateSQL(query: string, params?: unknown[]): Promise<UpdateQueryResponse>;\n}\n\n/**\n * Interface for version field metadata.\n * Defines the configuration for optimistic locking version fields.\n *\n * @interface VersionFieldMetadata\n */\nexport interface VersionFieldMetadata {\n /** Name of the version field */\n fieldName: string;\n}\n\n/**\n * Interface for table metadata.\n * Defines the configuration for a specific table.\n *\n * @interface TableMetadata\n */\nexport interface TableMetadata {\n /** Name of the table */\n tableName: string;\n /** Version field configuration for optimistic locking */\n versionField: VersionFieldMetadata;\n}\n\n/**\n * Type for additional metadata configuration.\n * Maps table names to their metadata configuration.\n *\n * @type {AdditionalMetadata}\n */\nexport type AdditionalMetadata = Record<string, TableMetadata>;\n\n/**\n * Interface for ForgeSQL ORM options\n *\n * @interface ForgeSqlOrmOptions\n */\nexport interface ForgeSqlOrmOptions {\n /** Whether to log raw SQL queries */\n logRawSqlQuery?: boolean;\n /** Whether to disable optimistic locking */\n disableOptimisticLocking?: boolean;\n /** SQL hints to be applied to queries */\n hints?: SqlHints;\n\n /**\n * Additional metadata for table configuration.\n * Allows specifying table-specific settings and behaviors.\n * @example\n * ```typescript\n * {\n * users: {\n * tableName: \"users\",\n * versionField: {\n * fieldName: \"updatedAt\",\n * type: \"datetime\",\n * nullable: false\n * }\n * }\n * }\n * ```\n */\n additionalMetadata?: AdditionalMetadata;\n}\n\n/**\n * Custom type for MySQL datetime fields.\n * Handles conversion between JavaScript Date objects and MySQL datetime strings.\n *\n * @type {CustomType}\n */\nexport const forgeDateTimeString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"datetime\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DDTHH:mm:ss.SSS\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL timestamp fields.\n * Handles conversion between JavaScript Date objects and MySQL timestamp strings.\n *\n * @type {CustomType}\n */\nexport const forgeTimestampString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"timestamp\";\n },\n toDriver(value: Date) {\n return moment(new Date(value)).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DDTHH:mm:ss.SSS\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL date fields.\n * Handles conversion between JavaScript Date objects and MySQL date strings.\n *\n * @type {CustomType}\n */\nexport const forgeDateString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"date\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"YYYY-MM-DD\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DD\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL time fields.\n * Handles conversion between JavaScript Date objects and MySQL time strings.\n *\n * @type {CustomType}\n */\nexport const forgeTimeString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"time\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"HH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n return parseDateTime(value as string, \"HH:mm:ss.SSS\");\n },\n});\n","import { bigint, mysqlTable, timestamp, varchar } from \"drizzle-orm/mysql-core\";\nimport { Table } from \"drizzle-orm\";\nimport { sql } from \"@forge/sql\";\n\nexport const migrations = mysqlTable(\"__migrations\", {\n id: bigint(\"id\", { mode: \"number\" }).primaryKey().autoincrement(),\n name: varchar(\"name\", { length: 255 }).notNull(),\n migratedAt: timestamp(\"migratedAt\").defaultNow().notNull(),\n});\n\nexport interface ExplainAnalyzeRow {\n id: string;\n estRows?: string;\n estCost?: string;\n actRows?: string;\n task?: string;\n accessObject?: string;\n executionInfo?: string;\n operatorInfo?: string;\n memory?: string;\n disk?: string;\n}\n\nexport interface SlowQueryNormalized {\n time: string;\n txnStartTs: number;\n user: string;\n host: string;\n connId: number;\n db: string;\n query: string;\n digest: string;\n queryTime: number;\n compileTime: number;\n optimizeTime: number;\n processTime: number;\n waitTime: number;\n parseTime: number;\n rewriteTime: number;\n copTime: number;\n copProcAvg: number;\n copProcMax: number;\n copProcP90: number;\n copProcAddr: string;\n copWaitAvg: number;\n copWaitMax: number;\n copWaitP90: number;\n copWaitAddr: string;\n memMax: number;\n diskMax: number;\n totalKeys: number;\n processKeys: number;\n requestCount: number;\n kvTotal: number;\n pdTotal: number;\n resultRows: number;\n rocksdbBlockCacheHitCount: number;\n rocksdbBlockReadCount: number;\n rocksdbBlockReadByte: number;\n plan: string;\n parsedPlan?: ExplainAnalyzeRow[];\n binaryPlan: string;\n planDigest: string;\n}\n\nexport interface ClusterStatementRowCamelCase {\n instance: string;\n summaryBeginTime: string;\n summaryEndTime: string;\n stmtType: string;\n schemaName: string;\n digest: string;\n digestText: string;\n tableNames: string;\n indexNames: string | null;\n sampleUser: string;\n execCount: number;\n sumErrors: number;\n sumWarnings: number;\n sumLatency: number;\n maxLatency: number;\n minLatency: number;\n avgLatency: number;\n avgParseLatency: number;\n maxParseLatency: number;\n avgCompileLatency: number;\n maxCompileLatency: number;\n sumCopTaskNum: number;\n maxCopProcessTime: number;\n maxCopProcessAddress: string;\n maxCopWaitTime: number;\n maxCopWaitAddress: string;\n avgProcessTime: number;\n maxProcessTime: number;\n avgWaitTime: number;\n maxWaitTime: number;\n avgBackoffTime: number;\n maxBackoffTime: number;\n avgTotalKeys: number;\n maxTotalKeys: number;\n avgProcessedKeys: number;\n maxProcessedKeys: number;\n avgRocksdbDeleteSkippedCount: number;\n maxRocksdbDeleteSkippedCount: number;\n avgRocksdbKeySkippedCount: number;\n maxRocksdbKeySkippedCount: number;\n avgRocksdbBlockCacheHitCount: number;\n maxRocksdbBlockCacheHitCount: number;\n avgRocksdbBlockReadCount: number;\n maxRocksdbBlockReadCount: number;\n avgRocksdbBlockReadByte: number;\n maxRocksdbBlockReadByte: number;\n avgPrewriteTime: number;\n maxPrewriteTime: number;\n avgCommitTime: number;\n maxCommitTime: number;\n avgGetCommitTsTime: number;\n maxGetCommitTsTime: number;\n avgCommitBackoffTime: number;\n maxCommitBackoffTime: number;\n avgResolveLockTime: number;\n maxResolveLockTime: number;\n avgLocalLatchWaitTime: number;\n maxLocalLatchWaitTime: number;\n avgWriteKeys: number;\n maxWriteKeys: number;\n avgWriteSize: number;\n maxWriteSize: number;\n avgPrewriteRegions: number;\n maxPrewriteRegions: number;\n avgTxnRetry: number;\n maxTxnRetry: number;\n sumExecRetry: number;\n sumExecRetryTime: number;\n sumBackoffTimes: number;\n backoffTypes: string | null;\n avgMem: number;\n maxMem: number;\n avgDisk: number;\n maxDisk: number;\n avgKvTime: number;\n avgPdTime: number;\n avgBackoffTotalTime: number;\n avgWriteSqlRespTime: number;\n avgTidbCpuTime: number;\n avgTikvCpuTime: number;\n maxResultRows: number;\n minResultRows: number;\n avgResultRows: number;\n prepared: number;\n avgAffectedRows: number;\n firstSeen: string;\n lastSeen: string;\n planInCache: number;\n planCacheHits: number;\n planInBinding: number;\n querySampleText: string;\n prevSampleText: string;\n planDigest: string;\n plan: string;\n binaryPlan: string;\n charset: string;\n collation: string;\n planHint: string;\n maxRequestUnitRead: number;\n avgRequestUnitRead: number;\n maxRequestUnitWrite: number;\n avgRequestUnitWrite: number;\n maxQueuedRcTime: number;\n avgQueuedRcTime: number;\n resourceGroup: string;\n planCacheUnqualified: number;\n planCacheUnqualifiedLastReason: string;\n parsedPlan?: ExplainAnalyzeRow[];\n}\n\n/**\n * Retrieves all tables from the database\n */\nexport async function getTables(): Promise<string[]> {\n const tables = await sql.executeDDL<string>(\"SHOW TABLES\");\n return tables.rows.flatMap((tableInfo) => Object.values(tableInfo));\n}\n\nexport const forgeSystemTables: Table[] = [migrations];\n","import { sql } from \"@forge/sql\";\nimport { generateDropTableStatements as generateStatements } from \"../utils/sqlUtils\";\nimport { getHttpResponse, TriggerResponse } from \"./index\";\nimport { getTables } from \"../core/SystemTables\";\n\n/**\n * ⚠️ DEVELOPMENT ONLY WEB TRIGGER ⚠️\n *\n * This web trigger is designed for development environments only and will permanently delete all data in the specified tables.\n * It generates and executes SQL statements to drop tables and their associated constraints.\n *\n * @warning This trigger should NEVER be used in production environments because:\n * - It permanently deletes all data in the specified tables\n * - The operation cannot be undone\n * - It may affect application functionality\n * - It could lead to data loss and system instability\n *\n * @returns {Promise<TriggerResponse<string>>} A response containing:\n * - On success: 200 status with warning message about permanent deletion\n * - On failure: 500 status with error message\n *\n * @example\n * ```typescript\n * // Example usage in development only\n * await dropSchemaMigrations();\n * // ⚠️ Warning: This will permanently delete all data in users and orders tables\n * ```\n */\nexport async function dropSchemaMigrations(): Promise<TriggerResponse<string>> {\n try {\n const tables = await getTables();\n // Generate drop statements\n const dropStatements = generateStatements(tables);\n\n // Execute each statement\n for (const statement of dropStatements) {\n console.warn(statement);\n await sql.executeDDL(statement);\n }\n\n return getHttpResponse<string>(\n 200,\n \"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone.\",\n );\n } catch (error: unknown) {\n console.error(error);\n const errorMessage = error instanceof Error ? error.message : \"Unknown error occurred\";\n return getHttpResponse<string>(500, errorMessage);\n }\n}\n","import { migrationRunner, sql } from \"@forge/sql\";\nimport { MigrationRunner } from \"@forge/sql/out/migration\";\n\n/**\n * Web trigger for applying database schema migrations in Atlassian Forge SQL.\n * This function handles the complete migration process including:\n * - Database provisioning\n * - Migration execution\n * - Migration history tracking\n *\n * @param migration - A function that takes a MigrationRunner instance and returns a Promise of MigrationRunner\n * This function should define the sequence of migrations to be applied\n * @returns {Promise<{\n * headers: { \"Content-Type\": [\"application/json\"] },\n * statusCode: number,\n * statusText: string,\n * body: string\n * }>} A response object containing:\n * - headers: Content-Type header set to application/json\n * - statusCode: 200 on success\n * - statusText: \"OK\" on success\n * - body: Success message or error details\n *\n * @throws {Error} If database provisioning fails\n * @throws {Error} If migration execution fails\n */\nexport const applySchemaMigrations = async (\n migration: (migrationRunner: MigrationRunner) => Promise<MigrationRunner>,\n) => {\n try {\n if (typeof migration !== \"function\") {\n throw new Error(\"migration is not a function\");\n }\n\n console.log(\"Provisioning the database\");\n await sql._provision();\n console.info(\"Running schema migrations\");\n const migrations = await migration(migrationRunner);\n const successfulMigrations = await migrations.run();\n console.info(\"Migrations applied:\", successfulMigrations);\n\n const migrationList = await migrationRunner.list();\n const migrationHistory =\n Array.isArray(migrationList) && migrationList.length > 0\n ? migrationList\n .sort((a, b) => a.migratedAt.getTime() - b.migratedAt.getTime())\n .map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`)\n .join(\"\\n\")\n : \"No migrations found\";\n\n console.info(\"Migrations history:\\nid, name, migrated_at\\n\", migrationHistory);\n\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode: 200,\n statusText: \"OK\",\n body: \"Migrations successfully executed\",\n };\n } catch (error) {\n try {\n console.error(\"Error during migration:\", JSON.stringify(error));\n } catch (e) {\n console.trace(\"Error stringify:\", e);\n console.error(\"Error during migration:\", error);\n }\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode: 500,\n statusText: \"Internal Server Error\",\n body: error instanceof Error ? error.message : \"Unknown error during migration\",\n };\n }\n};\n","import { sql } from \"@forge/sql\";\nimport { getHttpResponse, TriggerResponse } from \"./index\";\nimport { forgeSystemTables, getTables } from \"../core/SystemTables\";\nimport { getTableName } from \"drizzle-orm/table\";\n\ninterface CreateTableRow {\n Table: string;\n \"Create Table\": string;\n}\n\n/**\n * ⚠️ DEVELOPMENT ONLY WEB TRIGGER ⚠️\n *\n * This web trigger retrieves the current database schema from Atlassian Forge SQL.\n * It generates SQL statements that can be used to recreate the database structure.\n *\n * @warning This trigger should ONLY be used in development environments. It:\n * - Exposes your database structure\n * - Disables foreign key checks temporarily\n * - Generates SQL that could potentially be used maliciously\n * - May expose sensitive table names and structures\n *\n * @returns {Promise<TriggerResponse<string>>} A response containing SQL statements to recreate the database schema\n * - On success: Returns 200 status with SQL statements\n * - On failure: Returns 500 status with error message\n *\n * @example\n * ```typescript\n * // The response will contain SQL statements like:\n * // SET foreign_key_checks = 0;\n * // CREATE TABLE IF NOT EXISTS users (...);\n * // CREATE TABLE IF NOT EXISTS orders (...);\n * // SET foreign_key_checks = 1;\n * ```\n */\nexport async function fetchSchemaWebTrigger(): Promise<TriggerResponse<string>> {\n try {\n const tables = await getTables();\n const createTableStatements = await generateCreateTableStatements(tables);\n const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);\n\n return getHttpResponse<string>(200, sqlStatements.join(\";\\n\"));\n } catch (error: unknown) {\n console.error(JSON.stringify(error));\n const errorMessage = error instanceof Error ? error.message : \"Unknown error occurred\";\n return getHttpResponse<string>(500, errorMessage);\n }\n}\n\n/**\n * Generates CREATE TABLE statements for each table\n */\nasync function generateCreateTableStatements(tables: string[]): Promise<string[]> {\n const statements: string[] = [];\n\n for (const table of tables) {\n const createTableResult = await sql.executeDDL<CreateTableRow>(`SHOW CREATE TABLE \"${table}\"`);\n\n const createTableStatements = createTableResult.rows\n .filter((row) => !isSystemTable(row.Table))\n .map((row) => formatCreateTableStatement(row[\"Create Table\"]));\n\n statements.push(...createTableStatements);\n }\n\n return statements;\n}\n\n/**\n * Checks if the table is a system table\n */\nfunction isSystemTable(tableName: string): boolean {\n return forgeSystemTables.some((st) => getTableName(st) === tableName);\n}\n\n/**\n * Formats the CREATE TABLE statement\n */\nfunction formatCreateTableStatement(statement: string): string {\n return statement.replace(/\"/g, \"\").replace(\"CREATE TABLE\", \"CREATE TABLE IF NOT EXISTS\");\n}\n\n/**\n * Wraps the SQL statements with foreign key check controls\n */\nfunction wrapWithForeignKeyChecks(statements: string[]): string[] {\n return [\"SET foreign_key_checks = 0\", ...statements, \"SET foreign_key_checks = 1\"];\n}\n","export * from \"./dropMigrationWebTrigger\";\nexport * from \"./applyMigrationsWebTrigger\";\nexport * from \"./fetchSchemaWebTrigger\";\n\nexport interface TriggerResponse<BODY> {\n body?: BODY;\n headers?: Record<string, string[]>;\n statusCode: number;\n statusText?: string;\n}\n\nexport const getHttpResponse = <Body>(statusCode: number, body: Body): TriggerResponse<Body> => {\n let statusText = \"\";\n if (statusCode === 200) {\n statusText = \"Ok\";\n } else {\n statusText = \"Bad Request\";\n }\n\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode,\n statusText,\n body,\n };\n};\n"],"names":["table","sql","isTable","isSQLWrapper","fields","eq","and","getTableName","drizzle","customType","moment","mysqlTable","bigint","varchar","timestamp","generateStatements","migrations","migrationRunner"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ForgeSQLORM.js","sources":["../src/utils/sqlUtils.ts","../src/core/ForgeSQLCrudOperations.ts","../src/core/ForgeSQLSelectOperations.ts","../src/utils/forgeDriver.ts","../src/utils/sqlHints.ts","../src/utils/forgeDriverProxy.ts","../src/lib/drizzle/extensions/selectAliased.ts","../src/core/ForgeSQLAnalyseOperations.ts","../src/core/ForgeSQLORM.ts","../src/core/ForgeSQLQueryBuilder.ts","../src/core/SystemTables.ts","../src/webtriggers/dropMigrationWebTrigger.ts","../src/webtriggers/applyMigrationsWebTrigger.ts","../src/webtriggers/fetchSchemaWebTrigger.ts","../src/webtriggers/dropTablesMigrationWebTrigger.ts","../src/webtriggers/index.ts"],"sourcesContent":["import moment from \"moment\";\nimport { AnyColumn, Column, isTable, SQL, sql, StringChunk } from \"drizzle-orm\";\nimport { AnyMySqlTable, MySqlCustomColumn } from \"drizzle-orm/mysql-core/index\";\nimport { PrimaryKeyBuilder } from \"drizzle-orm/mysql-core/primary-keys\";\nimport { AnyIndexBuilder } from \"drizzle-orm/mysql-core/indexes\";\nimport { CheckBuilder } from \"drizzle-orm/mysql-core/checks\";\nimport { ForeignKeyBuilder } from \"drizzle-orm/mysql-core/foreign-keys\";\nimport { UniqueConstraintBuilder } from \"drizzle-orm/mysql-core/unique-constraint\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { isSQLWrapper } from \"drizzle-orm/sql/sql\";\n\n/**\n * Interface representing table metadata information\n */\nexport interface MetadataInfo {\n /** The name of the table */\n tableName: string;\n /** Record of column names and their corresponding column definitions */\n columns: Record<string, AnyColumn>;\n /** Array of index builders */\n indexes: AnyIndexBuilder[];\n /** Array of check constraint builders */\n checks: CheckBuilder[];\n /** Array of foreign key builders */\n foreignKeys: ForeignKeyBuilder[];\n /** Array of primary key builders */\n primaryKeys: PrimaryKeyBuilder[];\n /** Array of unique constraint builders */\n uniqueConstraints: UniqueConstraintBuilder[];\n /** Array of all extra builders */\n extras: any[];\n}\n\n/**\n * Interface for config builder data\n */\ninterface ConfigBuilderData {\n value?: any;\n [key: string]: any;\n}\n\n/**\n * Parses a date string into a Date object using the specified format\n * @param value - The date string to parse\n * @param format - The format to use for parsing\n * @returns Date object\n */\nexport const parseDateTime = (value: string, format: string): Date => {\n let result: Date;\n const m = moment(value, format, true);\n if (!m.isValid()) {\n const momentDate = moment(value);\n if (momentDate.isValid()) {\n result = momentDate.toDate();\n } else {\n result = new Date(value);\n }\n } else {\n result = m.toDate();\n }\n if (isNaN(result.getTime())) {\n result = new Date(value);\n }\n return result;\n};\n\n/**\n * Gets primary keys from the schema.\n * @template T - The type of the table schema\n * @param {T} table - The table schema\n * @returns {[string, AnyColumn][]} Array of primary key name and column pairs\n */\nexport function getPrimaryKeys<T extends AnyMySqlTable>(table: T): [string, AnyColumn][] {\n const { columns, primaryKeys } = getTableMetadata(table);\n\n // First try to find primary keys in columns\n const columnPrimaryKeys = Object.entries(columns).filter(([, column]) => column.primary) as [\n string,\n AnyColumn,\n ][];\n\n if (columnPrimaryKeys.length > 0) {\n return columnPrimaryKeys;\n }\n\n // If no primary keys found in columns, check primary key builders\n if (Array.isArray(primaryKeys) && primaryKeys.length > 0) {\n // Collect all primary key columns from all primary key builders\n const primaryKeyColumns = new Set<[string, AnyColumn]>();\n\n primaryKeys.forEach((primaryKeyBuilder) => {\n // Get primary key columns from each builder\n Object.entries(columns)\n .filter(([, column]) => {\n // @ts-ignore - PrimaryKeyBuilder has internal columns property\n return primaryKeyBuilder.columns.includes(column);\n })\n .forEach(([name, column]) => {\n primaryKeyColumns.add([name, column]);\n });\n });\n\n return Array.from(primaryKeyColumns);\n }\n\n return [];\n}\n\n/**\n * Processes foreign keys from both foreignKeysSymbol and extraSymbol\n * @param table - The table schema\n * @param foreignKeysSymbol - Symbol for foreign keys\n * @param extraSymbol - Symbol for extra configuration\n * @returns Array of foreign key builders\n */\nfunction processForeignKeys(\n table: AnyMySqlTable,\n foreignKeysSymbol: symbol | undefined,\n extraSymbol: symbol | undefined,\n): ForeignKeyBuilder[] {\n const foreignKeys: ForeignKeyBuilder[] = [];\n\n // Process foreign keys from foreignKeysSymbol\n if (foreignKeysSymbol) {\n // @ts-ignore\n const fkArray: any[] = table[foreignKeysSymbol];\n if (fkArray) {\n fkArray.forEach((fk) => {\n if (fk.reference) {\n const item = fk.reference(fk);\n foreignKeys.push(item);\n }\n });\n }\n }\n\n // Process foreign keys from extraSymbol\n if (extraSymbol) {\n // @ts-ignore\n const extraConfigBuilder = table[extraSymbol];\n if (extraConfigBuilder && typeof extraConfigBuilder === \"function\") {\n const configBuilderData = extraConfigBuilder(table);\n if (configBuilderData) {\n const configBuilders = Array.isArray(configBuilderData)\n ? configBuilderData\n : Object.values(configBuilderData).map(\n (item) => (item as ConfigBuilderData).value ?? item,\n );\n\n configBuilders.forEach((builder) => {\n if (!builder?.constructor) return;\n\n const builderName = builder.constructor.name.toLowerCase();\n if (builderName.includes(\"foreignkeybuilder\")) {\n foreignKeys.push(builder);\n }\n });\n }\n }\n }\n\n return foreignKeys;\n}\n\n/**\n * Extracts table metadata from the schema.\n * @param {AnyMySqlTable} table - The table schema\n * @returns {MetadataInfo} Object containing table metadata\n */\nexport function getTableMetadata(table: AnyMySqlTable): MetadataInfo {\n const symbols = Object.getOwnPropertySymbols(table);\n const nameSymbol = symbols.find((s) => s.toString().includes(\"Name\"));\n const columnsSymbol = symbols.find((s) => s.toString().includes(\"Columns\"));\n const foreignKeysSymbol = symbols.find((s) => s.toString().includes(\"ForeignKeys)\"));\n const extraSymbol = symbols.find((s) => s.toString().includes(\"ExtraConfigBuilder\"));\n\n // Initialize builders arrays\n const builders = {\n indexes: [] as AnyIndexBuilder[],\n checks: [] as CheckBuilder[],\n foreignKeys: [] as ForeignKeyBuilder[],\n primaryKeys: [] as PrimaryKeyBuilder[],\n uniqueConstraints: [] as UniqueConstraintBuilder[],\n extras: [] as any[],\n };\n\n // Process foreign keys\n builders.foreignKeys = processForeignKeys(table, foreignKeysSymbol, extraSymbol);\n\n // Process extra configuration if available\n if (extraSymbol) {\n // @ts-ignore\n const extraConfigBuilder = table[extraSymbol];\n if (extraConfigBuilder && typeof extraConfigBuilder === \"function\") {\n const configBuilderData = extraConfigBuilder(table);\n if (configBuilderData) {\n // Convert configBuilderData to array if it's an object\n const configBuilders = Array.isArray(configBuilderData)\n ? configBuilderData\n : Object.values(configBuilderData).map(\n (item) => (item as ConfigBuilderData).value ?? item,\n );\n\n // Process each builder\n configBuilders.forEach((builder) => {\n if (!builder?.constructor) return;\n\n const builderName = builder.constructor.name.toLowerCase();\n\n // Map builder types to their corresponding arrays\n const builderMap = {\n indexbuilder: builders.indexes,\n checkbuilder: builders.checks,\n primarykeybuilder: builders.primaryKeys,\n uniqueconstraintbuilder: builders.uniqueConstraints,\n };\n\n // Add builder to appropriate array if it matches any type\n for (const [type, array] of Object.entries(builderMap)) {\n if (builderName.includes(type)) {\n array.push(builder);\n break;\n }\n }\n\n // Always add to extras array\n builders.extras.push(builder);\n });\n }\n }\n }\n\n return {\n tableName: nameSymbol ? (table as any)[nameSymbol] : \"\",\n columns: columnsSymbol ? ((table as any)[columnsSymbol] as Record<string, AnyColumn>) : {},\n ...builders,\n };\n}\n\n/**\n * Generates SQL statements for dropping tables and/or their sequences.\n *\n * @param tables - List of table names to generate DROP statements for.\n * @param options - Configuration object:\n * - sequence: whether to drop associated sequences (default: true)\n * - table: whether to drop tables themselves (default: true)\n * @returns Array of SQL statements for dropping the specified objects\n */\nexport function generateDropTableStatements(\n tables: string[],\n options?: { sequence: boolean; table: boolean },\n): string[] {\n const dropStatements: string[] = [];\n const validOptions = options ?? { sequence: true, table: true };\n if (!validOptions.sequence && !validOptions.table) {\n console.warn('No drop operations requested: both \"table\" and \"sequence\" options are false');\n return [];\n }\n tables.forEach((tableName) => {\n if (validOptions.table) {\n dropStatements.push(`DROP TABLE IF EXISTS \\`${tableName}\\`;`);\n }\n if (validOptions.sequence) {\n dropStatements.push(`DROP SEQUENCE IF EXISTS \\`${tableName}\\`;`);\n }\n });\n\n return dropStatements;\n}\n\ntype AliasColumnMap = Record<string, AnyColumn>;\n\nfunction mapSelectTableToAlias(\n table: MySqlTable,\n uniqPrefix: string,\n aliasMap: AliasColumnMap,\n): any {\n const { columns, tableName } = getTableMetadata(table);\n const selectionsTableFields: Record<string, unknown> = {};\n Object.keys(columns).forEach((name) => {\n const column = columns[name] as AnyColumn;\n const uniqName = `a_${uniqPrefix}_${tableName}_${column.name}`.toLowerCase();\n const fieldAlias = sql.raw(uniqName);\n selectionsTableFields[name] = sql`${column} as \\`${fieldAlias}\\``;\n aliasMap[uniqName] = column;\n });\n return selectionsTableFields;\n}\n\nfunction isDrizzleColumn(column: any): boolean {\n return column && typeof column === \"object\" && \"table\" in column;\n}\n\nexport function mapSelectAllFieldsToAlias(\n selections: any,\n name: string,\n uniqName: string,\n fields: any,\n aliasMap: AliasColumnMap,\n): any {\n if (isTable(fields)) {\n selections[name] = mapSelectTableToAlias(fields as MySqlTable, uniqName, aliasMap);\n } else if (isDrizzleColumn(fields)) {\n const column = fields as Column;\n const uniqAliasName = `a_${uniqName}_${column.name}`.toLowerCase();\n let aliasName = sql.raw(uniqAliasName);\n selections[name] = sql`${column} as \\`${aliasName}\\``;\n aliasMap[uniqAliasName] = column;\n } else if (isSQLWrapper(fields)) {\n selections[name] = fields;\n } else {\n const innerSelections: any = {};\n Object.entries(fields).forEach(([iname, ifields]) => {\n mapSelectAllFieldsToAlias(innerSelections, iname, `${uniqName}_${iname}`, ifields, aliasMap);\n });\n selections[name] = innerSelections;\n }\n return selections;\n}\nexport function mapSelectFieldsWithAlias<TSelection extends SelectedFields>(\n fields: TSelection,\n): { selections: TSelection; aliasMap: AliasColumnMap } {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n const aliasMap: AliasColumnMap = {};\n const selections: any = {};\n Object.entries(fields).forEach(([name, fields]) => {\n mapSelectAllFieldsToAlias(selections, name, name, fields, aliasMap);\n });\n return { selections, aliasMap };\n}\n\nfunction getAliasFromDrizzleAlias(value: unknown): string | undefined {\n const isSQL =\n value !== null && typeof value === \"object\" && isSQLWrapper(value) && \"queryChunks\" in value;\n if (isSQL) {\n const sql = value as SQL;\n const queryChunks = sql.queryChunks;\n if (queryChunks.length > 3) {\n const aliasNameChunk = queryChunks[queryChunks.length - 2];\n if (isSQLWrapper(aliasNameChunk) && \"queryChunks\" in aliasNameChunk) {\n const aliasNameChunkSql = aliasNameChunk as SQL;\n if (aliasNameChunkSql.queryChunks?.length === 1 && aliasNameChunkSql.queryChunks[0]) {\n const queryChunksStringChunc = aliasNameChunkSql.queryChunks[0];\n if (\"value\" in queryChunksStringChunc) {\n const values = (queryChunksStringChunc as StringChunk).value;\n if (values && values.length === 1) {\n return values[0];\n }\n }\n }\n }\n }\n }\n return undefined;\n}\n\nfunction transformValue(\n value: unknown,\n alias: string,\n aliasMap: Record<string, AnyColumn>,\n): unknown {\n const column = aliasMap[alias];\n if (!column) return value;\n\n let customColumn = column as MySqlCustomColumn<any>;\n // @ts-ignore\n const fromDriver = customColumn?.mapFrom;\n if (fromDriver && value !== null && value !== undefined) {\n return fromDriver(value);\n }\n return value;\n}\n\nfunction transformObject(\n obj: Record<string, unknown>,\n selections: Record<string, unknown>,\n aliasMap: Record<string, AnyColumn>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const selection = selections[key];\n const alias = getAliasFromDrizzleAlias(selection);\n if (alias && aliasMap[alias]) {\n result[key] = transformValue(value, alias, aliasMap);\n } else if (selection && typeof selection === \"object\" && !isSQLWrapper(selection)) {\n result[key] = transformObject(\n value as Record<string, unknown>,\n selection as Record<string, unknown>,\n aliasMap,\n );\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport function applyFromDriverTransform<T, TSelection>(\n rows: T[],\n selections: TSelection,\n aliasMap: Record<string, AnyColumn>,\n): T[] {\n return rows.map((row) => {\n const transformed = transformObject(\n row as Record<string, unknown>,\n selections as Record<string, unknown>,\n aliasMap,\n ) as Record<string, unknown>;\n\n return processNullBranches(transformed) as unknown as T;\n });\n}\n\nfunction processNullBranches(obj: Record<string, unknown>): Record<string, unknown> | null {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n // Skip built-in objects like Date, Array, etc.\n if (obj.constructor && obj.constructor.name !== \"Object\") {\n return obj;\n }\n\n const result: Record<string, unknown> = {};\n let allNull = true;\n\n for (const [key, value] of Object.entries(obj)) {\n if (value === null || value === undefined) {\n result[key] = null;\n continue;\n }\n\n if (typeof value === \"object\") {\n const processed = processNullBranches(value as Record<string, unknown>);\n result[key] = processed;\n if (processed !== null) {\n allNull = false;\n }\n } else {\n result[key] = value;\n allNull = false;\n }\n }\n\n return allNull ? null : result;\n}\n\nexport function formatLimitOffset(limitOrOffset: number): number {\n if (typeof limitOrOffset !== \"number\" || isNaN(limitOrOffset)) {\n throw new Error(\"limitOrOffset must be a valid number\");\n }\n return sql.raw(`${limitOrOffset}`) as unknown as number;\n}\n\nexport function nextVal(sequenceName: string): number {\n return sql.raw(`NEXTVAL(${sequenceName})`) as unknown as number;\n}\n","import { ForgeSqlOrmOptions } from \"..\";\nimport { CRUDForgeSQL, ForgeSqlOperation } from \"./ForgeSQLQueryBuilder\";\nimport { AnyMySqlTable } from \"drizzle-orm/mysql-core/index\";\nimport { AnyColumn, InferInsertModel } from \"drizzle-orm\";\nimport { eq, and } from \"drizzle-orm\";\nimport { SQL } from \"drizzle-orm\";\nimport { getPrimaryKeys, getTableMetadata } from \"../utils/sqlUtils\";\n\n/**\n * Class implementing CRUD operations for ForgeSQL ORM.\n * Provides methods for inserting, updating, and deleting records with support for optimistic locking.\n */\nexport class ForgeSQLCrudOperations implements CRUDForgeSQL {\n private readonly forgeOperations: ForgeSqlOperation;\n private readonly options: ForgeSqlOrmOptions;\n\n /**\n * Creates a new instance of ForgeSQLCrudOperations.\n * @param forgeSqlOperations - The ForgeSQL operations instance\n * @param options - Configuration options for the ORM\n */\n constructor(forgeSqlOperations: ForgeSqlOperation, options: ForgeSqlOrmOptions) {\n this.forgeOperations = forgeSqlOperations;\n this.options = options;\n }\n\n /**\n * Inserts records into the database with optional versioning support.\n * If a version field exists in the schema, versioning is applied.\n *\n * @template T - The type of the table schema\n * @param {T} schema - The entity schema\n * @param {Partial<InferInsertModel<T>>[]} models - Array of entities to insert\n * @param {boolean} [updateIfExists=false] - Whether to update existing records\n * @returns {Promise<number>} The number of inserted rows\n * @throws {Error} If the insert operation fails\n */\n async insert<T extends AnyMySqlTable>(\n schema: T,\n models: InferInsertModel<T>[],\n updateIfExists: boolean = false,\n ): Promise<number> {\n if (!models?.length) return 0;\n\n const { tableName, columns } = getTableMetadata(schema);\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Prepare models with version field if needed\n const preparedModels = models.map((model) =>\n this.prepareModelWithVersion(model, versionMetadata, columns),\n );\n\n // Build insert query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .insert(schema)\n .values(preparedModels);\n\n // Add onDuplicateKeyUpdate if needed\n const finalQuery = updateIfExists\n ? queryBuilder.onDuplicateKeyUpdate({\n set: Object.fromEntries(\n Object.keys(preparedModels[0]).map((key) => [key, (schema as any)[key]]),\n ) as any,\n })\n : queryBuilder;\n\n // Execute query\n const result = await finalQuery;\n return result[0].insertId;\n }\n\n /**\n * Deletes a record by its primary key with optional version check.\n * If versioning is enabled, ensures the record hasn't been modified since last read.\n *\n * @template T - The type of the table schema\n * @param {unknown} id - The ID of the record to delete\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If the delete operation fails\n * @throws {Error} If multiple primary keys are found\n */\n async deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number> {\n const { tableName, columns } = getTableMetadata(schema);\n const primaryKeys = this.getPrimaryKeys(schema);\n\n if (primaryKeys.length !== 1) {\n throw new Error(\"Only single primary key is supported\");\n }\n\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Build delete conditions\n const conditions: SQL<unknown>[] = [eq(primaryKeyColumn, id)];\n\n // Add version check if needed\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n const oldModel = await this.getOldModel({ [primaryKeyName]: id }, schema, [\n versionMetadata.fieldName,\n versionField,\n ]);\n conditions.push(eq(versionField, (oldModel as any)[versionMetadata.fieldName]));\n }\n }\n\n // Execute delete query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .delete(schema)\n .where(and(...conditions));\n\n const result = await queryBuilder;\n\n return result[0].affectedRows;\n }\n\n /**\n * Updates a record by its primary key with optimistic locking support.\n * If versioning is enabled:\n * - Retrieves the current version\n * - Checks for concurrent modifications\n * - Increments the version on successful update\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity with updated values\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If the primary key is not provided\n * @throws {Error} If optimistic locking check fails\n * @throws {Error} If multiple primary keys are found\n */\n async updateById<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n schema: T,\n ): Promise<number> {\n const { tableName, columns } = getTableMetadata(schema);\n const primaryKeys = this.getPrimaryKeys(schema);\n\n if (primaryKeys.length !== 1) {\n throw new Error(\"Only single primary key is supported\");\n }\n\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n const versionMetadata = this.validateVersionField(tableName, columns);\n\n // Validate primary key\n if (!(primaryKeyName in entity)) {\n throw new Error(`Primary key ${primaryKeyName} must be provided in the entity`);\n }\n\n // Get current version if needed\n const currentVersion = await this.getCurrentVersion(\n entity,\n primaryKeyName,\n versionMetadata,\n columns,\n schema,\n );\n\n // Prepare update data with version\n const updateData = this.prepareUpdateData(entity, versionMetadata, columns, currentVersion);\n\n // Build update conditions\n const conditions: SQL<unknown>[] = [\n eq(primaryKeyColumn, entity[primaryKeyName as keyof typeof entity]),\n ];\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n conditions.push(eq(versionField, currentVersion));\n }\n }\n\n // Execute update query\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .update(schema)\n .set(updateData)\n .where(and(...conditions));\n\n const result = await queryBuilder;\n // Check optimistic locking\n if (versionMetadata && result[0].affectedRows === 0) {\n throw new Error(\n `Optimistic locking failed: record with primary key ${entity[primaryKeyName as keyof typeof entity]} has been modified`,\n );\n }\n\n return result[0].affectedRows;\n }\n\n /**\n * Updates specified fields of records based on provided conditions.\n * This method does not support versioning and should be used with caution.\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} updateData - The data to update\n * @param {T} schema - The entity schema\n * @param {SQL<unknown>} where - The WHERE conditions\n * @returns {Promise<number>} Number of affected rows\n * @throws {Error} If WHERE conditions are not provided\n * @throws {Error} If the update operation fails\n */\n async updateFields<T extends AnyMySqlTable>(\n updateData: Partial<InferInsertModel<T>>,\n schema: T,\n where?: SQL<unknown>,\n ): Promise<number> {\n if (!where) {\n throw new Error(\"WHERE conditions must be provided\");\n }\n\n const queryBuilder = this.forgeOperations\n .getDrizzleQueryBuilder()\n .update(schema)\n .set(updateData)\n .where(where);\n\n const result = await queryBuilder;\n return result[0].affectedRows;\n }\n\n // Helper methods\n\n /**\n * Gets primary keys from the schema.\n * @template T - The type of the table schema\n * @param {T} schema - The table schema\n * @returns {[string, AnyColumn][]} Array of primary key name and column pairs\n * @throws {Error} If no primary keys are found\n */\n private getPrimaryKeys<T extends AnyMySqlTable>(schema: T): [string, AnyColumn][] {\n const primaryKeys = getPrimaryKeys(schema);\n if (!primaryKeys) {\n throw new Error(`No primary keys found for schema: ${schema}`);\n }\n\n return primaryKeys;\n }\n\n /**\n * Validates and retrieves version field metadata.\n * @param {string} tableName - The name of the table\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @returns {Object | undefined} Version field metadata if valid, undefined otherwise\n */\n private validateVersionField(\n tableName: string,\n columns: Record<string, AnyColumn>,\n ): { fieldName: string; type: string } | undefined {\n if (this.options.disableOptimisticLocking) {\n return undefined;\n }\n const versionMetadata = this.options.additionalMetadata?.[tableName]?.versionField;\n if (!versionMetadata) return undefined;\n let fieldName = versionMetadata.fieldName;\n\n let versionField = columns[versionMetadata.fieldName];\n if (!versionField) {\n const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);\n if (find) {\n fieldName = find[0];\n versionField = find[1];\n }\n }\n if (!versionField) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" not found in table ${tableName}. Versioning will be skipped.`,\n );\n return undefined;\n }\n\n if (!versionField.notNull) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n return undefined;\n }\n\n const fieldType = versionField.getSQLType();\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n\n if (!isSupportedType) {\n console.warn(\n `Version field \"${versionMetadata.fieldName}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n return undefined;\n }\n\n return { fieldName, type: fieldType };\n }\n\n /**\n * Gets the current version of an entity.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity\n * @param {string} primaryKeyName - The name of the primary key\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @param {T} schema - The table schema\n * @returns {Promise<unknown>} The current version value\n */\n private async getCurrentVersion<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n primaryKeyName: string,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n schema: T,\n ): Promise<unknown> {\n if (!versionMetadata || !columns) return undefined;\n\n const versionField = columns[versionMetadata.fieldName];\n if (!versionField) return undefined;\n\n if (versionMetadata.fieldName in entity) {\n return entity[versionMetadata.fieldName as keyof typeof entity];\n }\n\n const oldModel = await this.getOldModel(\n { [primaryKeyName]: entity[primaryKeyName as keyof typeof entity] },\n schema,\n [versionMetadata.fieldName, versionField],\n );\n\n return (oldModel as any)[versionMetadata.fieldName];\n }\n\n /**\n * Prepares a model for insertion with version field.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} model - The model to prepare\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @returns {InferInsertModel<T>} The prepared model\n */\n private prepareModelWithVersion<T extends AnyMySqlTable>(\n model: Partial<InferInsertModel<T>>,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n ): InferInsertModel<T> {\n if (!versionMetadata || !columns) return model as InferInsertModel<T>;\n let fieldName = versionMetadata.fieldName;\n let versionField = columns[versionMetadata.fieldName];\n if (!versionField) {\n const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);\n if (find) {\n fieldName = find[0];\n versionField = find[1];\n }\n }\n\n if (!versionField) return model as InferInsertModel<T>;\n\n const modelWithVersion = { ...model };\n const fieldType = versionField.getSQLType();\n const versionValue = fieldType === \"datetime\" || fieldType === \"timestamp\" ? new Date() : 1;\n modelWithVersion[fieldName as keyof typeof modelWithVersion] = versionValue as any;\n\n return modelWithVersion as InferInsertModel<T>;\n }\n\n /**\n * Prepares update data with version field.\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity to update\n * @param {Object | undefined} versionMetadata - Version field metadata\n * @param {Record<string, AnyColumn>} columns - The table columns\n * @param {unknown} currentVersion - The current version value\n * @returns {Partial<InferInsertModel<T>>} The prepared update data\n */\n private prepareUpdateData<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n versionMetadata: { fieldName: string; type: string } | undefined,\n columns: Record<string, AnyColumn>,\n currentVersion: unknown,\n ): Partial<InferInsertModel<T>> {\n const updateData = { ...entity };\n\n if (versionMetadata && columns) {\n const versionField = columns[versionMetadata.fieldName];\n if (versionField) {\n const fieldType = versionField.getSQLType();\n updateData[versionMetadata.fieldName as keyof typeof updateData] =\n fieldType === \"datetime\" || fieldType === \"timestamp\"\n ? new Date()\n : (((currentVersion as number) + 1) as any);\n }\n }\n\n return updateData;\n }\n\n /**\n * Retrieves an existing model by primary key.\n * @template T - The type of the table schema\n * @param {Record<string, unknown>} primaryKeyValues - The primary key values\n * @param {T} schema - The table schema\n * @param {[string, AnyColumn]} versionField - The version field name and column\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} The existing model\n * @throws {Error} If the record is not found\n */\n private async getOldModel<T extends AnyMySqlTable>(\n primaryKeyValues: Record<string, unknown>,\n schema: T,\n versionField: [string, AnyColumn],\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n > {\n const [versionFieldName, versionFieldColumn] = versionField;\n const primaryKeys = this.getPrimaryKeys(schema);\n const [primaryKeyName, primaryKeyColumn] = primaryKeys[0];\n\n const resultQuery = this.forgeOperations\n .getDrizzleQueryBuilder()\n .select({\n [primaryKeyName]: primaryKeyColumn as any,\n [versionFieldName]: versionFieldColumn as any,\n })\n .from(schema)\n .where(eq(primaryKeyColumn, primaryKeyValues[primaryKeyName]));\n\n const model = await this.forgeOperations.fetch().executeQueryOnlyOne(resultQuery);\n\n if (!model) {\n throw new Error(`Record not found in table ${schema}`);\n }\n\n return model as Awaited<T> extends Array<any> ? Awaited<T>[number] : Awaited<T>;\n }\n}\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport { ForgeSqlOrmOptions, SchemaSqlForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport {\n AnyMySqlSelectQueryBuilder,\n MySqlSelectDynamic,\n} from \"drizzle-orm/mysql-core/query-builders/select.types\";\n\n/**\n * Class implementing SQL select operations for ForgeSQL ORM.\n * Provides methods for executing queries and mapping results to entity types.\n */\nexport class ForgeSQLSelectOperations implements SchemaSqlForgeSql {\n private readonly options: ForgeSqlOrmOptions;\n\n /**\n * Creates a new instance of ForgeSQLSelectOperations.\n * @param {ForgeSqlOrmOptions} options - Configuration options for the ORM\n */\n constructor(options: ForgeSqlOrmOptions) {\n this.options = options;\n }\n\n /**\n * Executes a Drizzle query and returns a single result.\n * Throws an error if more than one record is returned.\n *\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} A single result object or undefined\n * @throws {Error} If more than one record is returned\n */\n async executeQueryOnlyOne<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n > {\n const results: Awaited<T> = await query;\n const datas = results as unknown[];\n if (!datas.length) {\n return undefined;\n }\n if (datas.length > 1) {\n throw new Error(`Expected 1 record but returned ${datas.length}`);\n }\n\n return datas[0] as Awaited<T> extends Array<any> ? Awaited<T>[number] : Awaited<T>;\n }\n\n /**\n * Executes a raw SQL query and returns the results.\n * Logs the query if logging is enabled.\n *\n * @template T - The type of the result objects\n * @param {string} query - The raw SQL query to execute\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<T[]>} A list of results as objects\n */\n async executeRawSQL<T extends object | unknown>(query: string, params?: unknown[]): Promise<T[]> {\n if (this.options.logRawSqlQuery) {\n const paramsStr = params ? `, with params: ${JSON.stringify(params)}` : \"\";\n console.debug(`Executing with SQL ${query}${paramsStr}`);\n }\n const sqlStatement = sql.prepare<T>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n const result = await sqlStatement.execute();\n return result.rows as T[];\n }\n\n /**\n * Executes a raw SQL update query.\n * @param {string} query - The raw SQL update query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<UpdateQueryResponse>} The update response containing affected rows\n */\n async executeRawUpdateSQL(query: string, params?: unknown[]): Promise<UpdateQueryResponse> {\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n if (this.options.logRawSqlQuery) {\n console.debug(\n `Executing Update with SQL ${query}` +\n (params ? `, with params: ${JSON.stringify(params)}` : \"\"),\n );\n }\n const updateQueryResponseResults = await sqlStatement.execute();\n return updateQueryResponseResults.rows;\n }\n}\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\n\ninterface ForgeSQLResult {\n rows: Record<string, unknown>[] | Record<string, unknown>;\n}\n\nexport const forgeDriver = async (\n query: string,\n params: any[],\n method: \"all\" | \"execute\",\n): Promise<{\n rows: any[];\n insertId?: number;\n affectedRows?: number;\n}> => {\n try {\n if (method == \"execute\") {\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n if (params) {\n sqlStatement.bindParams(...params);\n }\n const updateQueryResponseResults = await sqlStatement.execute();\n let result = updateQueryResponseResults.rows as any;\n return { ...result, rows: [result] };\n } else {\n const sqlStatement = await sql.prepare<unknown>(query);\n if (params) {\n await sqlStatement.bindParams(...params);\n }\n const result = (await sqlStatement.execute()) as ForgeSQLResult;\n let rows;\n rows = (result.rows as any[]).map((r) => Object.values(r as Record<string, unknown>));\n return { rows: rows };\n }\n } catch (error) {\n console.error(\"SQL Error:\", JSON.stringify(error));\n throw error;\n }\n};\n","/**\n * Interface for SQL hints configuration\n */\nexport interface SqlHints {\n /** SQL hints for SELECT queries */\n select?: string[];\n /** SQL hints for INSERT queries */\n insert?: string[];\n /** SQL hints for UPDATE queries */\n update?: string[];\n /** SQL hints for DELETE queries */\n delete?: string[];\n}\n\n/**\n * Detects the type of SQL query and injects appropriate hints\n * @param query - The SQL query to analyze\n * @param hints - The hints configuration\n * @returns The modified query with injected hints\n */\nexport function injectSqlHints(query: string, hints?: SqlHints): string {\n if (!hints) {\n return query;\n }\n\n // Normalize the query for easier matching\n const normalizedQuery = query.trim().toUpperCase();\n\n // Get the appropriate hints based on query type\n let queryHints: string[] | undefined;\n\n if (normalizedQuery.startsWith(\"SELECT\")) {\n queryHints = hints.select;\n } else if (normalizedQuery.startsWith(\"INSERT\")) {\n queryHints = hints.insert;\n } else if (normalizedQuery.startsWith(\"UPDATE\")) {\n queryHints = hints.update;\n } else if (normalizedQuery.startsWith(\"DELETE\")) {\n queryHints = hints.delete;\n }\n\n // If no hints for this query type, return original query\n if (!queryHints || queryHints.length === 0) {\n return query;\n }\n\n // Join all hints with spaces\n const hintsString = queryHints.join(\" \");\n\n // Inject hints into the query\n if (normalizedQuery.startsWith(\"SELECT\")) {\n return `SELECT /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"INSERT\")) {\n return `INSERT /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"UPDATE\")) {\n return `UPDATE /*+ ${hintsString} */ ${query.substring(6)}`;\n } else if (normalizedQuery.startsWith(\"DELETE\")) {\n return `DELETE /*+ ${hintsString} */ ${query.substring(6)}`;\n }\n\n // If no match found, return original query\n return query;\n}\n","import { forgeDriver } from \"./forgeDriver\";\nimport { injectSqlHints, SqlHints } from \"./sqlHints\";\n\n/**\n * Creates a proxy for the forgeDriver that injects SQL hints\n * @returns A proxied version of the forgeDriver\n */\nexport function createForgeDriverProxy(options?: SqlHints, logRawSqlQuery?: boolean) {\n return async (\n query: string,\n params: any[],\n method: \"all\" | \"execute\",\n ): Promise<{\n rows: any[];\n insertId?: number;\n affectedRows?: number;\n }> => {\n // Inject SQL hints into the query\n const modifiedQuery = injectSqlHints(query, options);\n\n if (options && logRawSqlQuery && modifiedQuery !== query) {\n console.warn(\"modified query: \" + modifiedQuery);\n }\n // Call the original forgeDriver with the modified query\n return forgeDriver(modifiedQuery, params, method);\n };\n}\n","import { MySqlRemoteDatabase } from \"drizzle-orm/mysql-proxy\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { applyFromDriverTransform, mapSelectFieldsWithAlias } from \"../../..\";\nimport { MySqlSelectBuilder } from \"drizzle-orm/mysql-core\";\nimport { MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy\";\n\nfunction createAliasedSelectBuilder<TSelection extends SelectedFields>(\n db: MySqlRemoteDatabase<any>,\n fields: TSelection,\n selectFn: (selections: any) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>,\n): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n const { selections, aliasMap } = mapSelectFieldsWithAlias(fields);\n const builder = selectFn(selections);\n\n const wrapBuilder = (rawBuilder: any): any => {\n return new Proxy(rawBuilder, {\n get(target, prop, receiver) {\n if (prop === \"execute\") {\n return async (...args: any[]) => {\n const rows = await target.execute(...args);\n return applyFromDriverTransform(rows, selections, aliasMap);\n };\n }\n\n if (prop === \"then\") {\n return (onfulfilled: any, onrejected: any) =>\n target.execute().then((rows: unknown[]) => {\n const transformed = applyFromDriverTransform(rows, selections, aliasMap);\n return onfulfilled?.(transformed);\n }, onrejected);\n }\n\n const value = Reflect.get(target, prop, receiver);\n\n if (typeof value === \"function\") {\n return (...args: any[]) => {\n const result = value.apply(target, args);\n\n if (typeof result === \"object\" && result !== null && \"execute\" in result) {\n return wrapBuilder(result);\n }\n\n return result;\n };\n }\n\n return value;\n },\n });\n };\n\n return wrapBuilder(builder);\n}\n\nexport function patchDbWithSelectAliased(db: MySqlRemoteDatabase<any>): MySqlRemoteDatabase<any> & {\n selectAliased: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n selectAliasedDistinct: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n} {\n db.selectAliased = function <TSelection extends SelectedFields>(fields: TSelection) {\n return createAliasedSelectBuilder(db, fields, (selections) => db.select(selections));\n };\n\n db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {\n return createAliasedSelectBuilder(db, fields, (selections) => db.selectDistinct(selections));\n };\n\n return db;\n}\n","import { ForgeSqlOperation, SchemaAnalyzeForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport { Query } from \"drizzle-orm\";\nimport {\n ClusterStatementRowCamelCase,\n ExplainAnalyzeRow,\n SlowQueryNormalized,\n} from \"./SystemTables\";\nimport { SqlParameters } from \"@forge/sql/out/sql-statement\";\nimport { AnyMySqlTable } from \"drizzle-orm/mysql-core/index\";\nimport { getTableName } from \"drizzle-orm/table\";\nimport moment from \"moment\";\n\n/**\n * Interface representing a row from the EXPLAIN ANALYZE output\n */\ninterface DecodedPlanRow {\n id: string;\n estRows?: string;\n estCost?: string;\n actRows?: string;\n task?: string;\n \"access object\"?: string;\n \"execution info\"?: string;\n \"operator info\"?: string;\n memory?: string;\n disk?: string;\n}\n\n/**\n * Interface representing a raw slow query row from the database\n */\ninterface SlowQueryRaw {\n Time: string;\n Txn_start_ts: number;\n User: string;\n Host: string;\n Conn_ID: number;\n DB: string;\n Query: string;\n Digest: string;\n Query_time: number;\n Compile_time: number;\n Optimize_time: number;\n Process_time: number;\n Wait_time: number;\n Parse_time: number;\n Rewrite_time: number;\n Cop_time: number;\n Cop_proc_avg: number;\n Cop_proc_max: number;\n Cop_proc_p90: number;\n Cop_proc_addr: string;\n Cop_wait_avg: number;\n Cop_wait_max: number;\n Cop_wait_p90: number;\n Cop_wait_addr: string;\n Mem_max: number;\n Disk_max: number;\n Total_keys: number;\n Process_keys: number;\n Request_count: number;\n KV_total: number;\n PD_total: number;\n Result_rows: number;\n Rocksdb_block_cache_hit_count: number;\n Rocksdb_block_read_count: number;\n Rocksdb_block_read_byte: number;\n Plan: string;\n Binary_plan: string;\n Plan_digest: string;\n}\n\n/**\n * Interface representing a row from the cluster statements table\n */\nexport interface ClusterStatementRow {\n INSTANCE: string;\n SUMMARY_BEGIN_TIME: string;\n SUMMARY_END_TIME: string;\n STMT_TYPE: string;\n SCHEMA_NAME: string;\n DIGEST: string;\n DIGEST_TEXT: string;\n TABLE_NAMES: string;\n INDEX_NAMES: string | null;\n SAMPLE_USER: string;\n EXEC_COUNT: number;\n SUM_ERRORS: number;\n SUM_WARNINGS: number;\n SUM_LATENCY: number;\n MAX_LATENCY: number;\n MIN_LATENCY: number;\n AVG_LATENCY: number;\n AVG_PARSE_LATENCY: number;\n MAX_PARSE_LATENCY: number;\n AVG_COMPILE_LATENCY: number;\n MAX_COMPILE_LATENCY: number;\n SUM_COP_TASK_NUM: number;\n MAX_COP_PROCESS_TIME: number;\n MAX_COP_PROCESS_ADDRESS: string;\n MAX_COP_WAIT_TIME: number;\n MAX_COP_WAIT_ADDRESS: string;\n AVG_PROCESS_TIME: number;\n MAX_PROCESS_TIME: number;\n AVG_WAIT_TIME: number;\n MAX_WAIT_TIME: number;\n AVG_BACKOFF_TIME: number;\n MAX_BACKOFF_TIME: number;\n AVG_TOTAL_KEYS: number;\n MAX_TOTAL_KEYS: number;\n AVG_PROCESSED_KEYS: number;\n MAX_PROCESSED_KEYS: number;\n AVG_ROCKSDB_DELETE_SKIPPED_COUNT: number;\n MAX_ROCKSDB_DELETE_SKIPPED_COUNT: number;\n AVG_ROCKSDB_KEY_SKIPPED_COUNT: number;\n MAX_ROCKSDB_KEY_SKIPPED_COUNT: number;\n AVG_ROCKSDB_BLOCK_CACHE_HIT_COUNT: number;\n MAX_ROCKSDB_BLOCK_CACHE_HIT_COUNT: number;\n AVG_ROCKSDB_BLOCK_READ_COUNT: number;\n MAX_ROCKSDB_BLOCK_READ_COUNT: number;\n AVG_ROCKSDB_BLOCK_READ_BYTE: number;\n MAX_ROCKSDB_BLOCK_READ_BYTE: number;\n AVG_PREWRITE_TIME: number;\n MAX_PREWRITE_TIME: number;\n AVG_COMMIT_TIME: number;\n MAX_COMMIT_TIME: number;\n AVG_GET_COMMIT_TS_TIME: number;\n MAX_GET_COMMIT_TS_TIME: number;\n AVG_COMMIT_BACKOFF_TIME: number;\n MAX_COMMIT_BACKOFF_TIME: number;\n AVG_RESOLVE_LOCK_TIME: number;\n MAX_RESOLVE_LOCK_TIME: number;\n AVG_LOCAL_LATCH_WAIT_TIME: number;\n MAX_LOCAL_LATCH_WAIT_TIME: number;\n AVG_WRITE_KEYS: number;\n MAX_WRITE_KEYS: number;\n AVG_WRITE_SIZE: number;\n MAX_WRITE_SIZE: number;\n AVG_PREWRITE_REGIONS: number;\n MAX_PREWRITE_REGIONS: number;\n AVG_TXN_RETRY: number;\n MAX_TXN_RETRY: number;\n SUM_EXEC_RETRY: number;\n SUM_EXEC_RETRY_TIME: number;\n SUM_BACKOFF_TIMES: number;\n BACKOFF_TYPES: string | null;\n AVG_MEM: number;\n MAX_MEM: number;\n AVG_DISK: number;\n MAX_DISK: number;\n AVG_KV_TIME: number;\n AVG_PD_TIME: number;\n AVG_BACKOFF_TOTAL_TIME: number;\n AVG_WRITE_SQL_RESP_TIME: number;\n AVG_TIDB_CPU_TIME: number;\n AVG_TIKV_CPU_TIME: number;\n MAX_RESULT_ROWS: number;\n MIN_RESULT_ROWS: number;\n AVG_RESULT_ROWS: number;\n PREPARED: number;\n AVG_AFFECTED_ROWS: number;\n FIRST_SEEN: string;\n LAST_SEEN: string;\n PLAN_IN_CACHE: number;\n PLAN_CACHE_HITS: number;\n PLAN_IN_BINDING: number;\n QUERY_SAMPLE_TEXT: string;\n PREV_SAMPLE_TEXT: string;\n PLAN_DIGEST: string;\n PLAN: string;\n BINARY_PLAN: string;\n CHARSET: string;\n COLLATION: string;\n PLAN_HINT: string;\n MAX_REQUEST_UNIT_READ: number;\n AVG_REQUEST_UNIT_READ: number;\n MAX_REQUEST_UNIT_WRITE: number;\n AVG_REQUEST_UNIT_WRITE: number;\n MAX_QUEUED_RC_TIME: number;\n AVG_QUEUED_RC_TIME: number;\n RESOURCE_GROUP: string;\n PLAN_CACHE_UNQUALIFIED: number;\n PLAN_CACHE_UNQUALIFIED_LAST_REASON: string;\n}\n\n/**\n * Class implementing SQL analysis operations for ForgeSQL ORM.\n * Provides methods for analyzing query performance, execution plans, and slow queries.\n */\nexport class ForgeSQLAnalyseOperation implements SchemaAnalyzeForgeSql {\n private readonly forgeOperations: ForgeSqlOperation;\n\n /**\n * Creates a new instance of ForgeSQLAnalizeOperation.\n * @param {ForgeSqlOperation} forgeOperations - The ForgeSQL operations instance\n */\n constructor(forgeOperations: ForgeSqlOperation) {\n this.forgeOperations = forgeOperations;\n this.mapToCamelCaseClusterStatement = this.mapToCamelCaseClusterStatement.bind(this);\n }\n\n /**\n * Executes EXPLAIN on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<DecodedPlanRow>(`EXPLAIN ${query}`, bindParams as SqlParameters);\n return results.map((row) => ({\n id: row.id,\n estRows: row.estRows,\n actRows: row.actRows,\n task: row.task,\n accessObject: row[\"access object\"],\n executionInfo: row[\"execution info\"],\n operatorInfo: row[\"operator info\"],\n memory: row.memory,\n disk: row.disk,\n }));\n }\n\n /**\n * Executes EXPLAIN on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explain(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]> {\n const { sql, params } = query.toSQL();\n return this.explainRaw(sql, params);\n }\n\n /**\n * Executes EXPLAIN ANALYZE on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainAnalyzeRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<DecodedPlanRow>(`EXPLAIN ANALYZE ${query}`, bindParams as SqlParameters);\n return results.map((row) => ({\n id: row.id,\n estRows: row.estRows,\n actRows: row.actRows,\n task: row.task,\n accessObject: row[\"access object\"],\n executionInfo: row[\"execution info\"],\n operatorInfo: row[\"operator info\"],\n memory: row.memory,\n disk: row.disk,\n }));\n }\n\n /**\n * Executes EXPLAIN ANALYZE on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n async explainAnalyze(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]> {\n const { sql, params } = query.toSQL();\n return this.explainAnalyzeRaw(sql, params);\n }\n\n /**\n * Decodes a query execution plan from its string representation.\n * @param {string} input - The raw execution plan string\n * @returns {ExplainAnalyzeRow[]} The decoded execution plan rows\n */\n decodedPlan(input: string): ExplainAnalyzeRow[] {\n if (!input) {\n return [];\n }\n const lines = input.trim().split(\"\\n\");\n if (lines.length < 2) return [];\n\n const headersRaw = lines[0]\n .split(\"\\t\")\n .map((h) => h.trim())\n .filter(Boolean);\n const headers = headersRaw.map((h) => {\n return h\n .replace(/\\s+/g, \" \")\n .replace(/[-\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : \"\"))\n .replace(/^./, (s) => s.toLowerCase());\n });\n\n return lines.slice(1).map((line) => {\n const values = line\n .split(\"\\t\")\n .map((s) => s.trim())\n .filter(Boolean);\n const row: Record<string, string> = {};\n headers.forEach((key, i) => {\n row[key] = values[i] ?? \"\";\n });\n return row as unknown as ExplainAnalyzeRow;\n });\n }\n\n /**\n * Normalizes a raw slow query row into a more structured format.\n * @param {SlowQueryRaw} row - The raw slow query data\n * @returns {SlowQueryNormalized} The normalized slow query data\n */\n normalizeSlowQuery(row: SlowQueryRaw): SlowQueryNormalized {\n return {\n time: row.Time,\n txnStartTs: row.Txn_start_ts,\n user: row.User,\n host: row.Host,\n connId: row.Conn_ID,\n db: row.DB,\n query: row.Query,\n digest: row.Digest,\n queryTime: row.Query_time,\n compileTime: row.Compile_time,\n optimizeTime: row.Optimize_time,\n processTime: row.Process_time,\n waitTime: row.Wait_time,\n parseTime: row.Parse_time,\n rewriteTime: row.Rewrite_time,\n copTime: row.Cop_time,\n copProcAvg: row.Cop_proc_avg,\n copProcMax: row.Cop_proc_max,\n copProcP90: row.Cop_proc_p90,\n copProcAddr: row.Cop_proc_addr,\n copWaitAvg: row.Cop_wait_avg,\n copWaitMax: row.Cop_wait_max,\n copWaitP90: row.Cop_wait_p90,\n copWaitAddr: row.Cop_wait_addr,\n memMax: row.Mem_max,\n diskMax: row.Disk_max,\n totalKeys: row.Total_keys,\n processKeys: row.Process_keys,\n requestCount: row.Request_count,\n kvTotal: row.KV_total,\n pdTotal: row.PD_total,\n resultRows: row.Result_rows,\n rocksdbBlockCacheHitCount: row.Rocksdb_block_cache_hit_count,\n rocksdbBlockReadCount: row.Rocksdb_block_read_count,\n rocksdbBlockReadByte: row.Rocksdb_block_read_byte,\n plan: row.Plan,\n binaryPlan: row.Binary_plan,\n planDigest: row.Plan_digest,\n parsedPlan: this.decodedPlan(row.Plan),\n };\n }\n\n /**\n * Builds a SQL query for retrieving cluster statement history.\n * @param {string[]} tables - The tables to analyze\n * @param {Date} [from] - The start date for the analysis\n * @param {Date} [to] - The end date for the analysis\n * @returns {string} The SQL query for cluster statement history\n */\n buildClusterStatementQuery(tables: string[], from?: Date, to?: Date): string {\n const formatDateTime = (date: Date): string => moment(date).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n\n const tableConditions = tables\n .map((table) => `TABLE_NAMES LIKE CONCAT(SCHEMA_NAME, '.', '%', '${table}', '%')`)\n .join(\" OR \");\n\n const timeConditions: string[] = [];\n if (from) {\n timeConditions.push(`SUMMARY_BEGIN_TIME >= '${formatDateTime(from)}'`);\n }\n if (to) {\n timeConditions.push(`SUMMARY_END_TIME <= '${formatDateTime(to)}'`);\n }\n\n let whereClauses;\n if (tableConditions?.length) {\n whereClauses = [tableConditions ? `(${tableConditions})` : \"\", ...timeConditions];\n } else {\n whereClauses = timeConditions;\n }\n\n return `\n SELECT *\n FROM (\n SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY\n UNION ALL\n SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY\n ) AS combined\n ${whereClauses?.length > 0 ? `WHERE ${whereClauses.join(\" AND \")}` : \"\"}\n `;\n }\n\n /**\n * Retrieves and analyzes slow queries from the database.\n * @returns {Promise<SlowQueryNormalized[]>} The normalized slow query data\n */\n // CLUSTER_SLOW_QUERY STATISTICS\n async analyzeSlowQueries(): Promise<SlowQueryNormalized[]> {\n const results = await this.forgeOperations.fetch().executeRawSQL<SlowQueryRaw>(`\n SELECT *\n FROM information_schema.slow_query \n ORDER BY time DESC\n `);\n return results.map((row) => this.normalizeSlowQuery(row));\n }\n\n /**\n * Converts a cluster statement row to camelCase format.\n * @param {Record<string, any>} input - The input row data\n * @returns {ClusterStatementRowCamelCase} The converted row data\n */\n mapToCamelCaseClusterStatement(input: Record<string, any>): ClusterStatementRowCamelCase {\n if (!input) {\n return {} as ClusterStatementRowCamelCase;\n }\n\n const result: any = {};\n result.parsedPlan = this.decodedPlan(input[\"PLAN\"] ?? \"\");\n for (const key in input) {\n const camelKey = key.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n result[camelKey] = input[key];\n }\n\n return result as ClusterStatementRowCamelCase;\n }\n\n /**\n * Analyzes query history for specific tables using raw table names.\n * @param {string[]} tables - The table names to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n async analyzeQueriesHistoryRaw(\n tables: string[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]> {\n const results = await this.forgeOperations\n .fetch()\n .executeRawSQL<ClusterStatementRow>(\n this.buildClusterStatementQuery(tables ?? [], fromDate, toDate),\n );\n return results.map((r) => this.mapToCamelCaseClusterStatement(r));\n }\n\n /**\n * Analyzes query history for specific tables using Drizzle table objects.\n * @param {AnyMySqlTable[]} tables - The Drizzle table objects to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n async analyzeQueriesHistory(\n tables: AnyMySqlTable[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]> {\n const tableNames = tables?.map((table) => getTableName(table)) ?? [];\n return this.analyzeQueriesHistoryRaw(tableNames, fromDate, toDate);\n }\n}\n","import { ForgeSQLCrudOperations } from \"./ForgeSQLCrudOperations\";\nimport {\n CRUDForgeSQL,\n ForgeSqlOperation,\n ForgeSqlOrmOptions,\n SchemaAnalyzeForgeSql,\n SchemaSqlForgeSql,\n} from \"./ForgeSQLQueryBuilder\";\nimport { ForgeSQLSelectOperations } from \"./ForgeSQLSelectOperations\";\nimport { drizzle, MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy\";\nimport { createForgeDriverProxy } from \"../utils/forgeDriverProxy\";\nimport type { SelectedFields } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { MySqlSelectBuilder } from \"drizzle-orm/mysql-core\";\nimport { patchDbWithSelectAliased } from \"../lib/drizzle/extensions/selectAliased\";\nimport { ForgeSQLAnalyseOperation } from \"./ForgeSQLAnalyseOperations\";\n\n/**\n * Implementation of ForgeSQLORM that uses Drizzle ORM for query building.\n * This class provides a bridge between Forge SQL and Drizzle ORM, allowing\n * to use Drizzle's query builder while executing queries through Forge SQL.\n */\nclass ForgeSQLORMImpl implements ForgeSqlOperation {\n private static instance: ForgeSQLORMImpl | null = null;\n private readonly drizzle: MySqlRemoteDatabase<any> & {\n selectAliased: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n selectAliasedDistinct: <TSelection extends SelectedFields>(\n fields: TSelection,\n ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n };\n private readonly crudOperations: CRUDForgeSQL;\n private readonly fetchOperations: SchemaSqlForgeSql;\n private readonly analyzeOperations: SchemaAnalyzeForgeSql;\n\n /**\n * Private constructor to enforce singleton behavior.\n * @param options - Options for configuring ForgeSQL ORM behavior.\n */\n private constructor(options?: ForgeSqlOrmOptions) {\n try {\n const newOptions: ForgeSqlOrmOptions = options ?? {\n logRawSqlQuery: false,\n disableOptimisticLocking: false,\n };\n if (newOptions.logRawSqlQuery) {\n console.debug(\"Initializing ForgeSQLORM...\");\n }\n // Initialize Drizzle instance with our custom driver\n const proxiedDriver = createForgeDriverProxy(newOptions.hints, newOptions.logRawSqlQuery);\n this.drizzle = patchDbWithSelectAliased(\n drizzle(proxiedDriver, { logger: newOptions.logRawSqlQuery }),\n );\n this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);\n this.fetchOperations = new ForgeSQLSelectOperations(newOptions);\n this.analyzeOperations = new ForgeSQLAnalyseOperation(this);\n } catch (error) {\n console.error(\"ForgeSQLORM initialization failed:\", error);\n throw error;\n }\n }\n\n /**\n * Create the modify operations instance.\n * @returns modify operations.\n */\n modify(): CRUDForgeSQL {\n return this.crudOperations;\n }\n\n /**\n * Returns the singleton instance of ForgeSQLORMImpl.\n * @param options - Options for configuring ForgeSQL ORM behavior.\n * @returns The singleton instance of ForgeSQLORMImpl.\n */\n static getInstance(options?: ForgeSqlOrmOptions): ForgeSqlOperation {\n ForgeSQLORMImpl.instance ??= new ForgeSQLORMImpl(options);\n return ForgeSQLORMImpl.instance;\n }\n\n /**\n * Retrieves the CRUD operations instance.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.modify();\n }\n\n /**\n * Retrieves the fetch operations instance.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.fetchOperations;\n }\n analyze(): SchemaAnalyzeForgeSql {\n return this.analyzeOperations;\n }\n\n /**\n * Returns a Drizzle query builder instance.\n *\n * ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.\n * The returned instance should NOT be used for direct database connections or query execution.\n * All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.\n *\n * @returns A Drizzle query builder instance for query construction only.\n */\n getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> {\n return this.drizzle;\n }\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n return this.drizzle.selectAliased(fields);\n }\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n if (!fields) {\n throw new Error(\"fields is empty\");\n }\n return this.drizzle.selectAliasedDistinct(fields);\n }\n}\n\n/**\n * Public class that acts as a wrapper around the private ForgeSQLORMImpl.\n * Provides a clean interface for working with Forge SQL and Drizzle ORM.\n */\nclass ForgeSQLORM implements ForgeSqlOperation {\n private readonly ormInstance: ForgeSqlOperation;\n\n constructor(options?: ForgeSqlOrmOptions) {\n this.ormInstance = ForgeSQLORMImpl.getInstance(options);\n }\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n return this.ormInstance.select(fields);\n }\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {\n return this.ormInstance.selectDistinct(fields);\n }\n\n /**\n * Proxies the `crud` method from `ForgeSQLORMImpl`.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.ormInstance.modify();\n }\n\n /**\n * Proxies the `modify` method from `ForgeSQLORMImpl`.\n * @returns Modify operations.\n */\n modify(): CRUDForgeSQL {\n return this.ormInstance.modify();\n }\n\n /**\n * Proxies the `fetch` method from `ForgeSQLORMImpl`.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.ormInstance.fetch();\n }\n\n /**\n * Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.\n * @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance\n */\n analyze(): SchemaAnalyzeForgeSql {\n return this.ormInstance.analyze();\n }\n\n /**\n * Returns a Drizzle query builder instance.\n *\n * ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.\n * The returned instance should NOT be used for direct database connections or query execution.\n * All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.\n *\n * @returns A Drizzle query builder instance for query construction only.\n */\n getDrizzleQueryBuilder() {\n return this.ormInstance.getDrizzleQueryBuilder();\n }\n}\n\nexport default ForgeSQLORM;\n","import { UpdateQueryResponse } from \"@forge/sql\";\nimport { SqlParameters } from \"@forge/sql/out/sql-statement\";\nimport {\n AnyMySqlSelectQueryBuilder,\n AnyMySqlTable,\n customType,\n MySqlSelectBuilder,\n} from \"drizzle-orm/mysql-core\";\nimport {\n MySqlSelectDynamic,\n type SelectedFields,\n} from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { InferInsertModel, Query, SQL } from \"drizzle-orm\";\nimport moment from \"moment/moment\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\nimport { MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from \"drizzle-orm/mysql-proxy/index\";\nimport { SqlHints } from \"../utils/sqlHints\";\nimport {\n ClusterStatementRowCamelCase,\n ExplainAnalyzeRow,\n SlowQueryNormalized,\n} from \"./SystemTables\";\n\n/**\n * Core interface for ForgeSQL operations.\n * Provides access to CRUD operations, schema-level SQL operations, and query analysis capabilities.\n *\n * @interface ForgeSqlOperation\n * @extends {QueryBuilderForgeSql}\n */\nexport interface ForgeSqlOperation extends QueryBuilderForgeSql {\n /**\n * Provides CRUD (Create, Update, Delete) operations.\n * @deprecated Use modify() instead for better type safety and consistency\n * @returns {CRUDForgeSQL} Interface for performing CRUD operations\n */\n crud(): CRUDForgeSQL;\n\n /**\n * Provides modify (Create, Update, Delete) operations with optimistic locking support.\n * @returns {CRUDForgeSQL} Interface for performing CRUD operations\n */\n modify(): CRUDForgeSQL;\n\n /**\n * Provides schema-level SQL fetch operations with type safety.\n * @returns {SchemaSqlForgeSql} Interface for executing schema-bound SQL queries\n */\n fetch(): SchemaSqlForgeSql;\n\n /**\n * Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.\n * @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance\n */\n analyze(): SchemaAnalyzeForgeSql;\n}\n\n/**\n * Interface for Query Builder operations.\n * Provides access to the underlying Drizzle ORM query builder with enhanced functionality.\n *\n * @interface QueryBuilderForgeSql\n */\nexport interface QueryBuilderForgeSql {\n /**\n * Creates a new query builder for the given entity.\n * @returns {MySqlRemoteDatabase<Record<string, unknown>>} The Drizzle database instance for building queries\n */\n getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>>;\n\n /**\n * Creates a select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .select({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n select<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n\n /**\n * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.\n * This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.\n *\n * @template TSelection - The type of the selected fields\n * @param {TSelection} fields - Object containing the fields to select, with table schemas as values\n * @returns {MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>} A distinct select query builder with unique field aliases\n * @throws {Error} If fields parameter is empty\n * @example\n * ```typescript\n * await forgeSQL\n * .selectDistinct({user: users, order: orders})\n * .from(orders)\n * .innerJoin(users, eq(orders.userId, users.id));\n * ```\n */\n selectDistinct<TSelection extends SelectedFields>(\n fields: TSelection,\n ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;\n}\n\n/**\n * Interface for Modify (Create, Update, Delete) operations.\n * Provides methods for basic database operations with support for optimistic locking.\n *\n * @interface CRUDForgeSQL\n */\nexport interface CRUDForgeSQL {\n /**\n * Inserts multiple records into the database.\n * @template T - The type of the table schema\n * @param {T} schema - The entity schema\n * @param {InferInsertModel<T>[]} models - The list of entities to insert\n * @param {boolean} [updateIfExists] - Whether to update the row if it already exists (default: false)\n * @returns {Promise<number>} The number of inserted rows\n * @throws {Error} If the insert operation fails\n */\n insert<T extends AnyMySqlTable>(\n schema: T,\n models: InferInsertModel<T>[],\n updateIfExists?: boolean,\n ): Promise<number>;\n\n /**\n * Deletes a record by its ID.\n * @template T - The type of the table schema\n * @param {unknown} id - The ID of the record to delete\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} The number of rows affected\n * @throws {Error} If the delete operation fails\n */\n deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number>;\n\n /**\n * Updates a record by its ID with optimistic locking support.\n * If a version field is defined in the schema, versioning is applied:\n * - the current record version is retrieved\n * - checked for concurrent modifications\n * - and then incremented\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} entity - The entity with updated values\n * @param {T} schema - The entity schema\n * @returns {Promise<number>} The number of rows affected\n * @throws {Error} If the primary key is not included in the update fields\n * @throws {Error} If optimistic locking check fails\n */\n updateById<T extends AnyMySqlTable>(\n entity: Partial<InferInsertModel<T>>,\n schema: T,\n ): Promise<number>;\n\n /**\n * Updates specified fields of records based on provided conditions.\n * If the \"where\" parameter is not provided, the WHERE clause is built from the entity fields\n * that are not included in the list of fields to update.\n *\n * @template T - The type of the table schema\n * @param {Partial<InferInsertModel<T>>} updateData - The object containing values to update\n * @param {T} schema - The entity schema\n * @param {SQL<unknown>} [where] - Optional filtering conditions for the WHERE clause\n * @returns {Promise<number>} The number of affected rows\n * @throws {Error} If no filtering criteria are provided\n * @throws {Error} If the update operation fails\n */\n updateFields<T extends AnyMySqlTable>(\n updateData: Partial<InferInsertModel<T>>,\n schema: T,\n where?: SQL<unknown>,\n ): Promise<number>;\n}\n\n/**\n * Interface for schema analysis operations.\n * Provides methods for analyzing query performance and execution plans.\n *\n * @interface SchemaAnalyzeForgeSql\n */\nexport interface SchemaAnalyzeForgeSql {\n /**\n * Executes EXPLAIN on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explain(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN ANALYZE on a Drizzle query.\n * @param {{ toSQL: () => Query }} query - The Drizzle query to analyze\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainAnalyze(query: { toSQL: () => Query }): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Executes EXPLAIN ANALYZE on a raw SQL query.\n * @param {string} query - The SQL query to analyze\n * @param {unknown[]} bindParams - The query parameters\n * @returns {Promise<ExplainAnalyzeRow[]>} The execution plan analysis results\n */\n explainAnalyzeRaw(query: string, bindParams: unknown[]): Promise<ExplainAnalyzeRow[]>;\n\n /**\n * Analyzes slow queries from the database.\n * @returns {Promise<SlowQueryNormalized[]>} The normalized slow query data\n */\n analyzeSlowQueries(): Promise<SlowQueryNormalized[]>;\n\n /**\n * Analyzes query history for specific tables using Drizzle table objects.\n * @param {AnyMySqlTable[]} tables - The Drizzle table objects to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n analyzeQueriesHistory(\n tables: AnyMySqlTable[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]>;\n\n /**\n * Analyzes query history for specific tables using raw table names.\n * @param {string[]} tables - The table names to analyze\n * @param {Date} [fromDate] - The start date for the analysis\n * @param {Date} [toDate] - The end date for the analysis\n * @returns {Promise<ClusterStatementRowCamelCase[]>} The analyzed query history\n */\n analyzeQueriesHistoryRaw(\n tables: string[],\n fromDate?: Date,\n toDate?: Date,\n ): Promise<ClusterStatementRowCamelCase[]>;\n}\n\n/**\n * Interface for schema-level SQL operations.\n * Provides methods for executing SQL queries with schema binding and type safety.\n *\n * @interface SchemaSqlForgeSql\n */\nexport interface SchemaSqlForgeSql {\n /**\n * Executes a Drizzle query and returns a single result.\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} A single result object or undefined\n * @throws {Error} If more than one record is returned\n * @throws {Error} If the query execution fails\n */\n executeQueryOnlyOne<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<\n Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined\n >;\n\n /**\n * Executes a raw SQL query and returns the results.\n * @template T - The type of the result objects\n * @param {string} query - The raw SQL query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<T[]>} A list of results as objects\n * @throws {Error} If the query execution fails\n */\n executeRawSQL<T extends object | unknown>(query: string, params?: SqlParameters[]): Promise<T[]>;\n\n /**\n * Executes a raw SQL update query.\n * @param {string} query - The raw SQL update query\n * @param {SqlParameters[]} [params] - Optional SQL parameters\n * @returns {Promise<UpdateQueryResponse>} The update response containing affected rows\n * @throws {Error} If the update operation fails\n */\n executeRawUpdateSQL(query: string, params?: unknown[]): Promise<UpdateQueryResponse>;\n}\n\n/**\n * Interface for version field metadata.\n * Defines the configuration for optimistic locking version fields.\n *\n * @interface VersionFieldMetadata\n */\nexport interface VersionFieldMetadata {\n /** Name of the version field */\n fieldName: string;\n}\n\n/**\n * Interface for table metadata.\n * Defines the configuration for a specific table.\n *\n * @interface TableMetadata\n */\nexport interface TableMetadata {\n /** Name of the table */\n tableName: string;\n /** Version field configuration for optimistic locking */\n versionField: VersionFieldMetadata;\n}\n\n/**\n * Type for additional metadata configuration.\n * Maps table names to their metadata configuration.\n *\n * @type {AdditionalMetadata}\n */\nexport type AdditionalMetadata = Record<string, TableMetadata>;\n\n/**\n * Interface for ForgeSQL ORM options\n *\n * @interface ForgeSqlOrmOptions\n */\nexport interface ForgeSqlOrmOptions {\n /** Whether to log raw SQL queries */\n logRawSqlQuery?: boolean;\n /** Whether to disable optimistic locking */\n disableOptimisticLocking?: boolean;\n /** SQL hints to be applied to queries */\n hints?: SqlHints;\n\n /**\n * Additional metadata for table configuration.\n * Allows specifying table-specific settings and behaviors.\n * @example\n * ```typescript\n * {\n * users: {\n * tableName: \"users\",\n * versionField: {\n * fieldName: \"updatedAt\",\n * type: \"datetime\",\n * nullable: false\n * }\n * }\n * }\n * ```\n */\n additionalMetadata?: AdditionalMetadata;\n}\n\n/**\n * Custom type for MySQL datetime fields.\n * Handles conversion between JavaScript Date objects and MySQL datetime strings.\n *\n * @type {CustomType}\n */\nexport const forgeDateTimeString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"datetime\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DDTHH:mm:ss.SSS\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL timestamp fields.\n * Handles conversion between JavaScript Date objects and MySQL timestamp strings.\n *\n * @type {CustomType}\n */\nexport const forgeTimestampString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"timestamp\";\n },\n toDriver(value: Date) {\n return moment(new Date(value)).format(\"YYYY-MM-DDTHH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DDTHH:mm:ss.SSS\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL date fields.\n * Handles conversion between JavaScript Date objects and MySQL date strings.\n *\n * @type {CustomType}\n */\nexport const forgeDateString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"date\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"YYYY-MM-DD\");\n },\n fromDriver(value: unknown) {\n const format = \"YYYY-MM-DD\";\n return parseDateTime(value as string, format);\n },\n});\n\n/**\n * Custom type for MySQL time fields.\n * Handles conversion between JavaScript Date objects and MySQL time strings.\n *\n * @type {CustomType}\n */\nexport const forgeTimeString = customType<{\n data: Date;\n driver: string;\n config: { format?: string };\n}>({\n dataType() {\n return \"time\";\n },\n toDriver(value: Date) {\n return moment(value as Date).format(\"HH:mm:ss.SSS\");\n },\n fromDriver(value: unknown) {\n return parseDateTime(value as string, \"HH:mm:ss.SSS\");\n },\n});\n","import { bigint, mysqlTable, timestamp, varchar } from \"drizzle-orm/mysql-core\";\nimport { Table } from \"drizzle-orm\";\nimport { sql } from \"@forge/sql\";\n\nexport const migrations = mysqlTable(\"__migrations\", {\n id: bigint(\"id\", { mode: \"number\" }).primaryKey().autoincrement(),\n name: varchar(\"name\", { length: 255 }).notNull(),\n migratedAt: timestamp(\"migratedAt\").defaultNow().notNull(),\n});\n\nexport interface ExplainAnalyzeRow {\n id: string;\n estRows?: string;\n estCost?: string;\n actRows?: string;\n task?: string;\n accessObject?: string;\n executionInfo?: string;\n operatorInfo?: string;\n memory?: string;\n disk?: string;\n}\n\nexport interface SlowQueryNormalized {\n time: string;\n txnStartTs: number;\n user: string;\n host: string;\n connId: number;\n db: string;\n query: string;\n digest: string;\n queryTime: number;\n compileTime: number;\n optimizeTime: number;\n processTime: number;\n waitTime: number;\n parseTime: number;\n rewriteTime: number;\n copTime: number;\n copProcAvg: number;\n copProcMax: number;\n copProcP90: number;\n copProcAddr: string;\n copWaitAvg: number;\n copWaitMax: number;\n copWaitP90: number;\n copWaitAddr: string;\n memMax: number;\n diskMax: number;\n totalKeys: number;\n processKeys: number;\n requestCount: number;\n kvTotal: number;\n pdTotal: number;\n resultRows: number;\n rocksdbBlockCacheHitCount: number;\n rocksdbBlockReadCount: number;\n rocksdbBlockReadByte: number;\n plan: string;\n parsedPlan?: ExplainAnalyzeRow[];\n binaryPlan: string;\n planDigest: string;\n}\n\nexport interface ClusterStatementRowCamelCase {\n instance: string;\n summaryBeginTime: string;\n summaryEndTime: string;\n stmtType: string;\n schemaName: string;\n digest: string;\n digestText: string;\n tableNames: string;\n indexNames: string | null;\n sampleUser: string;\n execCount: number;\n sumErrors: number;\n sumWarnings: number;\n sumLatency: number;\n maxLatency: number;\n minLatency: number;\n avgLatency: number;\n avgParseLatency: number;\n maxParseLatency: number;\n avgCompileLatency: number;\n maxCompileLatency: number;\n sumCopTaskNum: number;\n maxCopProcessTime: number;\n maxCopProcessAddress: string;\n maxCopWaitTime: number;\n maxCopWaitAddress: string;\n avgProcessTime: number;\n maxProcessTime: number;\n avgWaitTime: number;\n maxWaitTime: number;\n avgBackoffTime: number;\n maxBackoffTime: number;\n avgTotalKeys: number;\n maxTotalKeys: number;\n avgProcessedKeys: number;\n maxProcessedKeys: number;\n avgRocksdbDeleteSkippedCount: number;\n maxRocksdbDeleteSkippedCount: number;\n avgRocksdbKeySkippedCount: number;\n maxRocksdbKeySkippedCount: number;\n avgRocksdbBlockCacheHitCount: number;\n maxRocksdbBlockCacheHitCount: number;\n avgRocksdbBlockReadCount: number;\n maxRocksdbBlockReadCount: number;\n avgRocksdbBlockReadByte: number;\n maxRocksdbBlockReadByte: number;\n avgPrewriteTime: number;\n maxPrewriteTime: number;\n avgCommitTime: number;\n maxCommitTime: number;\n avgGetCommitTsTime: number;\n maxGetCommitTsTime: number;\n avgCommitBackoffTime: number;\n maxCommitBackoffTime: number;\n avgResolveLockTime: number;\n maxResolveLockTime: number;\n avgLocalLatchWaitTime: number;\n maxLocalLatchWaitTime: number;\n avgWriteKeys: number;\n maxWriteKeys: number;\n avgWriteSize: number;\n maxWriteSize: number;\n avgPrewriteRegions: number;\n maxPrewriteRegions: number;\n avgTxnRetry: number;\n maxTxnRetry: number;\n sumExecRetry: number;\n sumExecRetryTime: number;\n sumBackoffTimes: number;\n backoffTypes: string | null;\n avgMem: number;\n maxMem: number;\n avgDisk: number;\n maxDisk: number;\n avgKvTime: number;\n avgPdTime: number;\n avgBackoffTotalTime: number;\n avgWriteSqlRespTime: number;\n avgTidbCpuTime: number;\n avgTikvCpuTime: number;\n maxResultRows: number;\n minResultRows: number;\n avgResultRows: number;\n prepared: number;\n avgAffectedRows: number;\n firstSeen: string;\n lastSeen: string;\n planInCache: number;\n planCacheHits: number;\n planInBinding: number;\n querySampleText: string;\n prevSampleText: string;\n planDigest: string;\n plan: string;\n binaryPlan: string;\n charset: string;\n collation: string;\n planHint: string;\n maxRequestUnitRead: number;\n avgRequestUnitRead: number;\n maxRequestUnitWrite: number;\n avgRequestUnitWrite: number;\n maxQueuedRcTime: number;\n avgQueuedRcTime: number;\n resourceGroup: string;\n planCacheUnqualified: number;\n planCacheUnqualifiedLastReason: string;\n parsedPlan?: ExplainAnalyzeRow[];\n}\n\n/**\n * Retrieves all tables from the database\n */\nexport async function getTables(): Promise<string[]> {\n const tables = await sql.executeDDL<string>(\"SHOW TABLES\");\n return tables.rows.flatMap((tableInfo) => Object.values(tableInfo));\n}\n\nexport const forgeSystemTables: Table[] = [migrations];\n","import { sql } from \"@forge/sql\";\nimport { generateDropTableStatements as generateStatements } from \"../utils/sqlUtils\";\nimport { getHttpResponse, TriggerResponse } from \"./index\";\nimport { getTables } from \"../core/SystemTables\";\n\n/**\n * ⚠️ DEVELOPMENT ONLY WEB TRIGGER ⚠️\n *\n * This web trigger is designed for development environments only and will permanently delete all data in the specified tables and sequences.\n * It generates and executes SQL statements to drop tables, their associated constraints, and sequences.\n *\n * @warning This trigger should NEVER be used in production environments because:\n * - It permanently deletes all data in the specified tables and sequences\n * - The operation cannot be undone\n * - It may affect application functionality\n * - It could lead to data loss and system instability\n *\n * @returns {Promise<TriggerResponse<string>>} A response containing:\n * - On success: 200 status with warning message about permanent deletion of tables and sequences\n * - On failure: 500 status with error message\n *\n * @example\n * ```typescript\n * // Example usage in development only\n * await dropSchemaMigrations();\n * // ⚠️ Warning: This will permanently delete all data in users and orders tables and their sequences\n * ```\n */\nexport async function dropSchemaMigrations(): Promise<TriggerResponse<string>> {\n try {\n const tables = await getTables();\n // Generate drop statements\n const dropStatements = generateStatements(tables, { sequence: true, table: true });\n\n // Execute each statement\n for (const statement of dropStatements) {\n console.warn(statement);\n await sql.executeDDL(statement);\n }\n\n return getHttpResponse<string>(\n 200,\n \"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone.\",\n );\n } catch (error: unknown) {\n console.error(error);\n const errorMessage = error instanceof Error ? error.message : \"Unknown error occurred\";\n return getHttpResponse<string>(500, errorMessage);\n }\n}\n","import { migrationRunner, sql } from \"@forge/sql\";\nimport { MigrationRunner } from \"@forge/sql/out/migration\";\n\n/**\n * Web trigger for applying database schema migrations in Atlassian Forge SQL.\n * This function handles the complete migration process including:\n * - Database provisioning\n * - Migration execution\n * - Migration history tracking\n *\n * @param migration - A function that takes a MigrationRunner instance and returns a Promise of MigrationRunner\n * This function should define the sequence of migrations to be applied\n * @returns {Promise<{\n * headers: { \"Content-Type\": [\"application/json\"] },\n * statusCode: number,\n * statusText: string,\n * body: string\n * }>} A response object containing:\n * - headers: Content-Type header set to application/json\n * - statusCode: 200 on success\n * - statusText: \"OK\" on success\n * - body: Success message or error details\n *\n * @throws {Error} If database provisioning fails\n * @throws {Error} If migration execution fails\n */\nexport const applySchemaMigrations = async (\n migration: (migrationRunner: MigrationRunner) => Promise<MigrationRunner>,\n) => {\n try {\n if (typeof migration !== \"function\") {\n throw new Error(\"migration is not a function\");\n }\n\n console.log(\"Provisioning the database\");\n await sql._provision();\n console.info(\"Running schema migrations\");\n const migrations = await migration(migrationRunner);\n const successfulMigrations = await migrations.run();\n console.info(\"Migrations applied:\", successfulMigrations);\n\n const migrationList = await migrationRunner.list();\n const migrationHistory =\n Array.isArray(migrationList) && migrationList.length > 0\n ? migrationList\n .sort((a, b) => a.migratedAt.getTime() - b.migratedAt.getTime())\n .map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`)\n .join(\"\\n\")\n : \"No migrations found\";\n\n console.info(\"Migrations history:\\nid, name, migrated_at\\n\", migrationHistory);\n\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode: 200,\n statusText: \"OK\",\n body: \"Migrations successfully executed\",\n };\n } catch (error) {\n try {\n console.error(\"Error during migration:\", JSON.stringify(error));\n } catch (e) {\n console.trace(\"Error stringify:\", e);\n console.error(\"Error during migration:\", error);\n }\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode: 500,\n statusText: \"Internal Server Error\",\n body: error instanceof Error ? error.message : \"Unknown error during migration\",\n };\n }\n};\n","import { sql } from \"@forge/sql\";\nimport { getHttpResponse, TriggerResponse } from \"./index\";\nimport { forgeSystemTables, getTables } from \"../core/SystemTables\";\nimport { getTableName } from \"drizzle-orm/table\";\n\ninterface CreateTableRow {\n Table: string;\n \"Create Table\": string;\n}\n\n/**\n * ⚠️ DEVELOPMENT ONLY WEB TRIGGER ⚠️\n *\n * This web trigger retrieves the current database schema from Atlassian Forge SQL.\n * It generates SQL statements that can be used to recreate the database structure.\n *\n * @warning This trigger should ONLY be used in development environments. It:\n * - Exposes your database structure\n * - Disables foreign key checks temporarily\n * - Generates SQL that could potentially be used maliciously\n * - May expose sensitive table names and structures\n *\n * @returns {Promise<TriggerResponse<string>>} A response containing SQL statements to recreate the database schema\n * - On success: Returns 200 status with SQL statements\n * - On failure: Returns 500 status with error message\n *\n * @example\n * ```typescript\n * // The response will contain SQL statements like:\n * // SET foreign_key_checks = 0;\n * // CREATE TABLE IF NOT EXISTS users (...);\n * // CREATE TABLE IF NOT EXISTS orders (...);\n * // SET foreign_key_checks = 1;\n * ```\n */\nexport async function fetchSchemaWebTrigger(): Promise<TriggerResponse<string>> {\n try {\n const tables = await getTables();\n const createTableStatements = await generateCreateTableStatements(tables);\n const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);\n\n return getHttpResponse<string>(200, sqlStatements.join(\";\\n\"));\n } catch (error: unknown) {\n console.error(JSON.stringify(error));\n const errorMessage = error instanceof Error ? error.message : \"Unknown error occurred\";\n return getHttpResponse<string>(500, errorMessage);\n }\n}\n\n/**\n * Generates CREATE TABLE statements for each table\n */\nasync function generateCreateTableStatements(tables: string[]): Promise<string[]> {\n const statements: string[] = [];\n\n for (const table of tables) {\n const createTableResult = await sql.executeDDL<CreateTableRow>(`SHOW CREATE TABLE \"${table}\"`);\n\n const createTableStatements = createTableResult.rows\n .filter((row) => !isSystemTable(row.Table))\n .map((row) => formatCreateTableStatement(row[\"Create Table\"]));\n\n statements.push(...createTableStatements);\n }\n\n return statements;\n}\n\n/**\n * Checks if the table is a system table\n */\nfunction isSystemTable(tableName: string): boolean {\n return forgeSystemTables.some((st) => getTableName(st) === tableName);\n}\n\n/**\n * Formats the CREATE TABLE statement\n */\nfunction formatCreateTableStatement(statement: string): string {\n return statement.replace(/\"/g, \"\").replace(\"CREATE TABLE\", \"CREATE TABLE IF NOT EXISTS\");\n}\n\n/**\n * Wraps the SQL statements with foreign key check controls\n */\nfunction wrapWithForeignKeyChecks(statements: string[]): string[] {\n return [\"SET foreign_key_checks = 0\", ...statements, \"SET foreign_key_checks = 1\"];\n}\n","import { sql } from \"@forge/sql\";\nimport { generateDropTableStatements as generateStatements } from \"../utils/sqlUtils\";\nimport { getHttpResponse, TriggerResponse } from \"./index\";\nimport { getTables } from \"../core/SystemTables\";\n\n/**\n * ⚠️ DEVELOPMENT ONLY WEB TRIGGER ⚠️\n *\n * This web trigger is designed for development environments only and will permanently delete all data in the specified tables.\n * It generates and executes SQL statements to drop tables and their associated constraints.\n *\n * @warning This trigger should NEVER be used in production environments because:\n * - It permanently deletes all data in the specified tables\n * - The operation cannot be undone\n * - It may affect application functionality\n * - It could lead to data loss and system instability\n *\n * @returns {Promise<TriggerResponse<string>>} A response containing:\n * - On success: 200 status with warning message about permanent deletion\n * - On failure: 500 status with error message\n *\n * @example\n * ```typescript\n * // Example usage in development only\n * await dropTableSchemaMigrations();\n * // ⚠️ Warning: This will permanently delete all data in users and orders tables\n * ```\n */\nexport async function dropTableSchemaMigrations(): Promise<TriggerResponse<string>> {\n try {\n const tables = await getTables();\n // Generate drop statements\n const dropStatements = generateStatements(tables, { sequence: false, table: true });\n\n // Execute each statement\n for (const statement of dropStatements) {\n console.warn(statement);\n await sql.executeDDL(statement);\n }\n\n return getHttpResponse<string>(\n 200,\n \"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone.\",\n );\n } catch (error: unknown) {\n console.error(error);\n const errorMessage = error instanceof Error ? error.message : \"Unknown error occurred\";\n return getHttpResponse<string>(500, errorMessage);\n }\n}\n","export * from \"./dropMigrationWebTrigger\";\nexport * from \"./applyMigrationsWebTrigger\";\nexport * from \"./fetchSchemaWebTrigger\";\nexport * from \"./dropTablesMigrationWebTrigger\";\n\nexport interface TriggerResponse<BODY> {\n body?: BODY;\n headers?: Record<string, string[]>;\n statusCode: number;\n statusText?: string;\n}\n\nexport const getHttpResponse = <Body>(statusCode: number, body: Body): TriggerResponse<Body> => {\n let statusText = \"\";\n if (statusCode === 200) {\n statusText = \"Ok\";\n } else {\n statusText = \"Bad Request\";\n }\n\n return {\n headers: { \"Content-Type\": [\"application/json\"] },\n statusCode,\n statusText,\n body,\n };\n};\n"],"names":["table","sql","isTable","isSQLWrapper","fields","eq","and","getTableName","drizzle","customType","moment","mysqlTable","bigint","varchar","timestamp","generateStatements","migrations","migrationRunner"],"mappings":"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"}
|