forge-sql-orm 1.0.31 → 1.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -695
- package/dist/ForgeSQLORM.js +538 -567
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +536 -554
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts +101 -130
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +11 -10
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +271 -113
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts +65 -22
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/core/SystemTables.d.ts +59 -0
- package/dist/core/SystemTables.d.ts.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +53 -6
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist-cli/cli.js +471 -397
- package/dist-cli/cli.js.map +1 -1
- package/dist-cli/cli.mjs +471 -397
- package/dist-cli/cli.mjs.map +1 -1
- package/package.json +21 -22
- package/src/core/ForgeSQLCrudOperations.ts +360 -473
- package/src/core/ForgeSQLORM.ts +38 -79
- package/src/core/ForgeSQLQueryBuilder.ts +250 -133
- package/src/core/ForgeSQLSelectOperations.ts +182 -72
- package/src/core/SystemTables.ts +7 -0
- package/src/index.ts +1 -2
- package/src/utils/sqlUtils.ts +155 -23
- package/dist/core/ComplexQuerySchemaBuilder.d.ts +0 -38
- package/dist/core/ComplexQuerySchemaBuilder.d.ts.map +0 -1
- package/dist/knex/index.d.ts +0 -4
- package/dist/knex/index.d.ts.map +0 -1
- package/src/core/ComplexQuerySchemaBuilder.ts +0 -63
- package/src/knex/index.ts +0 -4
package/dist/ForgeSQLORM.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLORM.mjs","sources":["../src/utils/sqlUtils.ts","../src/core/ForgeSQLCrudOperations.ts","../src/core/ComplexQuerySchemaBuilder.ts","../src/core/ForgeSQLSelectOperations.ts","../src/core/ForgeSQLORM.ts"],"sourcesContent":["import moment from \"moment\";\nimport { AnyString } from \"@mikro-orm/core/typings\";\nimport {types} from \"..\";\n\nconst wrapIfNeeded=(data:string, wrap:boolean):string => {\n return wrap?`'${data}'`:data;\n}\n\nexport const transformValue = <U>(value: {\n type: keyof typeof types | AnyString;\n value: U;\n}, wrapValue: boolean = false): U => {\n switch (value.type) {\n case \"text\":\n case \"string\":\n return <U>wrapIfNeeded(`${value.value}`,wrapValue);\n case \"datetime\":\n return <U>wrapIfNeeded(`${moment(value.value as Date).format(\"YYYY-MM-DDTHH:mm:ss.SSS\")}`,wrapValue);\n case \"date\":\n return <U>wrapIfNeeded(`${moment(value.value as Date).format(\"YYYY-MM-DD\")}`, wrapValue);\n case \"time\":\n return <U>wrapIfNeeded(`${moment(value.value as Date).format(\"HH:mm:ss.SSS\")}`,wrapValue);\n default:\n return value.value;\n }\n};\n\nexport const parseDateTime = (value: string, format: string): Date => {\n const m = moment(value, format, true);\n if (!m.isValid()) {\n return moment(value).toDate();\n }\n return m.toDate();\n};\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport { EntityProperty, EntitySchema, ForgeSqlOrmOptions } from \"..\";\nimport type { types } from \"@mikro-orm/core/types\";\nimport { transformValue } from \"../utils/sqlUtils\";\nimport { CRUDForgeSQL, ForgeSqlOperation } from \"./ForgeSQLQueryBuilder\";\nimport { EntityKey, QBFilterQuery } from \"..\";\nimport Knex from \"../knex\";\n\nexport class ForgeSQLCrudOperations implements CRUDForgeSQL {\n private readonly forgeOperations: ForgeSqlOperation;\n private readonly options: ForgeSqlOrmOptions;\n\n constructor(forgeSqlOperations: ForgeSqlOperation, options: ForgeSqlOrmOptions) {\n this.forgeOperations = forgeSqlOperations;\n this.options = options;\n }\n\n /**\n * Generates an SQL INSERT statement for the provided models.\n * If a version field exists in the schema, its value is set accordingly.\n *\n * @param schema - The entity schema.\n * @param models - The list of entities to insert.\n * @param updateIfExists - Whether to update the row if it already exists.\n * @returns An object containing the SQL query, column names, and values.\n */\n private async generateInsertScript<T extends object>(\n schema: EntitySchema<T>,\n models: T[],\n updateIfExists: boolean,\n ): Promise<{\n sql: string;\n query: string;\n fields: string[];\n values: { type: keyof typeof types; value: unknown }[];\n }> {\n const columnNames = new Set<string>();\n const modelFieldValues: Record<string, { type: keyof typeof types; value: unknown }>[] = [];\n\n // Build field values for each model.\n models.forEach((model) => {\n const fieldValues: Record<string, { type: keyof typeof types; value: unknown }> = {};\n schema.meta.props.forEach((prop) => {\n const value = model[prop.name];\n if (prop.kind === \"scalar\" && value !== undefined) {\n const columnName = this.getRealFieldNameFromSchema(prop);\n columnNames.add(columnName);\n fieldValues[columnName] = { type: prop.type as keyof typeof types, value };\n }\n });\n modelFieldValues.push(fieldValues);\n });\n\n // If a version field exists, set or update its value.\n const versionField = this.getVersionField(schema);\n if (versionField) {\n modelFieldValues.forEach((mv) => {\n const versionRealName = this.getRealFieldNameFromSchema(versionField);\n if (mv[versionRealName]) {\n mv[versionRealName].value = transformValue(\n { value: this.createVersionField(versionField), type: versionField.name },\n true,\n );\n } else {\n mv[versionRealName] = {\n type: versionField.type as keyof typeof types,\n value: transformValue(\n { value: this.createVersionField(versionField), type: versionField.name },\n true,\n ),\n };\n columnNames.add(versionField.name);\n }\n });\n }\n\n const columns = Array.from(columnNames);\n\n // Flatten values for each row in the order of columns.\n const values = modelFieldValues.flatMap((fieldValueMap) =>\n columns.map(\n (column) =>\n fieldValueMap[column] || {\n type: \"string\",\n value: null,\n },\n ),\n );\n\n // Build the VALUES clause.\n const insertValues = modelFieldValues\n .map((fieldValueMap) => {\n const rowValues = columns\n .map((column) =>\n transformValue(\n fieldValueMap[column] || { type: \"string\", value: null },\n true,\n ),\n )\n .join(\",\");\n return `(${rowValues})`;\n })\n .join(\", \");\n // Build the VALUES ? clause.\n const insertEmptyValues = modelFieldValues\n .map(() => {\n const rowValues = columns\n .map(() =>\n '?',\n )\n .join(\",\");\n return `(${rowValues})`;\n })\n .join(\", \");\n\n const updateClause = updateIfExists\n ? ` ON DUPLICATE KEY UPDATE ${columns.map((col) => `${col} = VALUES(${col})`).join(\",\")}`\n : \"\";\n\n return {\n sql: `INSERT INTO ${schema.meta.collection} (${columns.join(\",\")}) VALUES ${insertValues}${updateClause}`,\n query: `INSERT INTO ${schema.meta.collection} (${columns.join(\",\")}) VALUES ${insertEmptyValues}${updateClause}`,\n fields: columns,\n values,\n };\n }\n\n /**\n * Inserts records into the database.\n * If a version field exists in the schema, versioning is applied.\n *\n * @param schema - The entity schema.\n * @param models - The list of entities to insert.\n * @param updateIfExists - Whether to update the row if it already exists.\n * @returns The ID of the inserted row.\n */\n async insert<T extends object>(\n schema: EntitySchema<T>,\n models: T[],\n updateIfExists: boolean = false,\n ): Promise<number> {\n if (!models || models.length === 0) return 0;\n\n const query = await this.generateInsertScript(schema, models, updateIfExists);\n if (this.options?.logRawSqlQuery) {\n console.debug(\"INSERT SQL: \" + query.query);\n }\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query.sql);\n const result = await sqlStatement.execute();\n return result.rows.insertId;\n }\n\n /**\n * Retrieves the primary key properties from the entity schema.\n *\n * @param schema - The entity schema.\n * @returns An array of primary key properties.\n * @throws If no primary keys are found.\n */\n private getPrimaryKeys<T extends object>(schema: EntitySchema<T>): EntityProperty<T, unknown>[] {\n const primaryKeys = schema.meta.props.filter((prop) => prop.primary);\n if (!primaryKeys.length) {\n throw new Error(`No primary keys found for schema: ${schema.meta.className}`);\n }\n return primaryKeys;\n }\n\n /**\n * Deletes a record by its primary key.\n *\n * @param id - The ID of the record to delete.\n * @param schema - The entity schema.\n * @returns The number of rows affected.\n * @throws If the entity has more than one primary key.\n */\n async deleteById<T extends object>(id: unknown, schema: EntitySchema<T>): Promise<number> {\n const primaryKeys = this.getPrimaryKeys(schema);\n if (primaryKeys.length > 1) {\n throw new Error(\"Only one primary key is supported\");\n }\n\n const primaryKey = primaryKeys[0];\n const queryBuilder = this.forgeOperations.createQueryBuilder(schema.meta.class).delete();\n queryBuilder.andWhere({ [primaryKey.name]: { $eq: id } });\n\n const query = queryBuilder.getFormattedQuery();\n if (this.options?.logRawSqlQuery) {\n console.debug(\"DELETE SQL: \" + queryBuilder.getQuery());\n }\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n const result = await sqlStatement.execute();\n return result.rows.affectedRows;\n }\n\n /**\n * Retrieves the version field from the entity schema.\n * The version field must be of type datetime, integer, or decimal, not a primary key, and not nullable.\n *\n * @param schema - The entity schema.\n * @returns The version field property if it exists.\n */\n getVersionField<T>(schema: EntitySchema<T>) {\n if (this.options.disableOptimisticLocking){\n return undefined;\n }\n return schema.meta.props\n .filter((prop) => prop.version)\n .filter((prop) => {\n const validType =\n prop.type === \"datetime\" || prop.type === \"integer\" || prop.type === \"decimal\";\n if (!validType) {\n console.warn(\n `Version field \"${prop.name}\" in table ${schema.meta.tableName} must be datetime, integer, or decimal, but is \"${prop.type}\"`,\n );\n }\n return validType;\n })\n .filter((prop) => {\n if (prop.primary) {\n console.warn(\n `Version field \"${prop.name}\" in table ${schema.meta.tableName} cannot be a primary key`,\n );\n return false;\n }\n return true;\n })\n .find((prop) => {\n if (prop.nullable) {\n console.warn(\n `Version field \"${prop.name}\" in table ${schema.meta.tableName} should not be nullable`,\n );\n return false;\n }\n return true;\n });\n }\n\n /**\n * Increments the version field of an entity.\n * For datetime types, sets the current date; for numeric types, increments by 1.\n *\n * @param versionField - The version field property.\n * @param updateModel - The entity to update.\n */\n incrementVersionField<T>(versionField: EntityProperty<T, any>, updateModel: T): void {\n const key = versionField.name as keyof T;\n switch (versionField.type) {\n case \"datetime\": {\n updateModel[key] = new Date() as unknown as T[keyof T];\n break;\n }\n case \"decimal\":\n case \"integer\": {\n updateModel[key] = ((updateModel[key] as number) + 1) as unknown as T[keyof T];\n break;\n }\n default:\n throw new Error(`Unsupported version field type: ${versionField.type}`);\n }\n }\n\n /**\n * Creates the initial version field value for an entity.\n * For datetime types, returns the current date; for numeric types, returns 0.\n *\n * @param versionField - The version field property.\n */\n createVersionField<T>(versionField: EntityProperty<T>): unknown {\n switch (versionField.type) {\n case \"datetime\": {\n return new Date() as unknown as T[keyof T];\n }\n case \"decimal\":\n case \"integer\": {\n return 0;\n }\n default:\n throw new Error(`Unsupported version field type: ${versionField.type}`);\n }\n }\n\n /**\n * Updates a record by its primary key using the provided entity data.\n *\n * @param entity - The entity with updated values.\n * @param schema - The entity schema.\n */\n async updateById<T extends object>(entity: Partial<T>, schema: EntitySchema<T>): Promise<void> {\n const fields = schema.meta.props\n .filter((prop) => prop.kind === \"scalar\")\n .map((prop) => prop.name);\n await this.updateFieldById(entity as T, fields, schema);\n }\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 * @param entity - The object containing values to update and potential criteria for filtering.\n * @param fields - Array of field names to update.\n * @param schema - The entity schema.\n * @param where - Optional filtering conditions for the WHERE clause.\n * @returns The number of affected rows.\n * @throws If no filtering criteria are provided (either via \"where\" or from the remaining entity fields).\n */\n async updateFields<T extends object>(\n entity: Partial<T>,\n fields: EntityKey<T>[],\n schema: EntitySchema<T>,\n where?: QBFilterQuery<T>,\n ): Promise<number> {\n // Extract update data from the entity based on the provided fields.\n const updateData = this.filterEntityFields(entity, fields);\n const updateModel = this.modifyModel(updateData as T, schema);\n\n // Create the query builder for the entity.\n let queryBuilder = this.forgeOperations\n .createQueryBuilder(schema.meta.class)\n .getKnexQuery();\n\n // Set the update data.\n queryBuilder.update(updateModel as T);\n\n // Use the provided \"where\" conditions if available; otherwise, build conditions from the remaining entity fields.\n if (where) {\n queryBuilder.where(where);\n } else {\n const filterCriteria = (Object.keys(entity) as Array<keyof T>)\n .filter((key: keyof T) => !fields.includes(key as EntityKey<T>))\n .reduce((criteria, key) => {\n if (entity[key] !== undefined) {\n // Cast key to string to use it as an object key.\n criteria[key as string] = entity[key];\n }\n return criteria;\n }, {} as Record<string, unknown>);\n\n\n if (Object.keys(filterCriteria).length === 0) {\n throw new Error(\n \"Filtering criteria (WHERE clause) must be provided either via the 'where' parameter or through non-updated entity fields\"\n );\n }\n queryBuilder.where(filterCriteria);\n }\n\n if (this.options?.logRawSqlQuery) {\n console.debug(\"UPDATE SQL (updateFields): \" + queryBuilder.toSQL().sql);\n }\n\n // Execute the update query.\n const sqlQuery = queryBuilder.toQuery();\n const updateQueryResponse = await this.forgeOperations.fetch().executeRawUpdateSQL(sqlQuery);\n return updateQueryResponse.affectedRows;\n }\n\n\n /**\n * Updates specific fields of a record identified by its primary key.\n * If a version field exists in the schema, versioning is applied.\n *\n * @param entity - The entity with updated values.\n * @param fields - The list of field names to update.\n * @param schema - The entity schema.\n * @throws If the primary key is not included in the update fields.\n */\n async updateFieldById<T extends object>(\n entity: T,\n fields: EntityKey<T>[],\n schema: EntitySchema<T>,\n ): Promise<void> {\n const primaryKeys = this.getPrimaryKeys(schema);\n primaryKeys.forEach((pk) => {\n if (!fields.includes(pk.name)) {\n throw new Error(\"Update fields must include primary key: \" + pk.name);\n }\n });\n\n // Prepare updated entity and query builder.\n const updatedEntity = this.filterEntityFields(entity, fields);\n let queryBuilder = this.forgeOperations.createQueryBuilder(schema.meta.class).getKnexQuery();\n const versionField = this.getVersionField(schema);\n const useVersion = Boolean(versionField);\n let updateModel = { ...updatedEntity };\n\n if (useVersion && versionField) {\n // If the version field is missing from the entity, load the old record.\n let oldModel = entity;\n if (entity[versionField.name] === undefined || entity[versionField.name] === null) {\n oldModel = await this.getOldModel(primaryKeys, entity, schema, versionField);\n }\n const primaryFieldNames = primaryKeys.map((pk) => pk.name);\n const fieldsToRetain = primaryFieldNames.concat(versionField.name);\n const fromEntries = Object.fromEntries(fieldsToRetain.map((key) => [key, oldModel[key]]));\n updateModel = { ...updatedEntity, ...fromEntries };\n\n // Increment the version field.\n this.incrementVersionField(versionField, updateModel as T);\n\n updateModel = this.modifyModel(updateModel as T, schema);\n queryBuilder.update(updateModel as T);\n if (oldModel[versionField.name]!==undefined || oldModel[versionField.name]!==null && this.isValid(oldModel[versionField.name])) {\n queryBuilder.andWhere(this.optWhere(oldModel, versionField));\n }\n } else {\n updateModel = this.modifyModel(updatedEntity as T, schema);\n queryBuilder.update(updateModel as T);\n }\n\n this.addPrimaryWhere(queryBuilder as unknown as Knex.QueryBuilder<any, any>, primaryKeys, updateModel as T);\n const sqlQuery = queryBuilder.toQuery();\n\n if (this.options?.logRawSqlQuery) {\n console.debug(\"UPDATE SQL: \" + queryBuilder.toSQL().sql);\n }\n const updateQueryResponse = await this.forgeOperations.fetch().executeRawUpdateSQL(sqlQuery);\n if (versionField && !updateQueryResponse.affectedRows) {\n throw new Error(\n \"Optimistic locking failed: the record with primary key(s) \" +\n primaryKeys.map((p) => updateModel[p.name]).join(\", \") +\n \" has been modified by another process.\",\n );\n }\n }\n\n /**\n * Constructs an optional WHERE clause for the version field.\n *\n * @param updateModel - The model containing the current version field value.\n * @param versionField - The version field property.\n * @returns A filter query for the version field.\n */\n private optWhere<T>(\n updateModel: T,\n versionField: EntityProperty<T>,\n ): QBFilterQuery<unknown> {\n const currentVersionValue = transformValue(\n { value: updateModel[versionField.name], type: versionField.type },\n false,\n );\n return { [versionField.name]: currentVersionValue };\n }\n\n /**\n * Retrieves the current state of a record from the database.\n *\n * @param primaryKeys - The primary key properties.\n * @param entity - The entity with updated values.\n * @param schema - The entity schema.\n * @param versionField - The version field property.\n * @returns The existing record from the database.\n * @throws If the record does not exist or if multiple records are found.\n */\n private async getOldModel<T>(\n primaryKeys: EntityProperty<T, unknown>[],\n entity: T,\n schema: EntitySchema<T>,\n versionField: EntityProperty<T>,\n ): Promise<T> {\n const primaryFieldNames = primaryKeys.map((pk) => pk.name);\n const fieldsToSelect = primaryFieldNames.concat(versionField.name);\n const queryBuilder = this.forgeOperations\n .createQueryBuilder(schema as EntitySchema)\n .select(fieldsToSelect);\n this.addPrimaryWhere(queryBuilder, primaryKeys, entity);\n const formattedQuery = queryBuilder.getFormattedQuery();\n const models: T[] = await this.forgeOperations.fetch().executeSchemaSQL(formattedQuery, schema as EntitySchema);\n\n if (!models || models.length === 0) {\n throw new Error(`Cannot modify record because it does not exist in table ${schema.meta.tableName}`);\n }\n if (models.length > 1) {\n throw new Error(\n `Cannot modify record because multiple rows with the same ID were found in table ${schema.meta.tableName}. Please verify the table metadata.`,\n );\n }\n return models[0];\n }\n\n /**\n * Adds primary key conditions to the query builder.\n *\n * @param queryBuilder - The Knex query builder instance.\n * @param primaryKeys - The primary key properties.\n * @param entity - The entity containing primary key values.\n * @throws If any primary key value is missing.\n */\n private addPrimaryWhere<T>(\n queryBuilder: Knex.QueryBuilder<any, any>,\n primaryKeys: EntityProperty<T, unknown>[],\n entity: T,\n ) {\n primaryKeys.forEach((pk) => {\n const fieldName = this.getRealFieldNameFromSchema(pk);\n const value = entity[fieldName];\n if (value === null || value === undefined) {\n throw new Error(`Primary key ${fieldName} must exist in the model`);\n }\n queryBuilder.andWhere({ [fieldName]: value });\n });\n }\n\n /**\n * Filters the entity to include only the specified fields.\n *\n * @param entity - The original entity.\n * @param fields - The list of fields to retain.\n * @returns A partial entity object containing only the specified fields.\n */\n filterEntityFields = <T extends object>(entity: T, fields: (keyof T)[]): Partial<T> =>\n fields.reduce((result, field) => {\n if (field in entity) {\n result[field] = entity[field];\n }\n return result;\n }, {} as Partial<T>);\n\n /**\n * Transforms and modifies the updated entity model based on the schema.\n *\n * @param updatedEntity - The updated entity.\n * @param schema - The entity schema.\n * @returns The modified entity.\n */\n private modifyModel<T>(updatedEntity: T, schema: EntitySchema<T>): T {\n const modifiedModel: Record<string, any> = {};\n schema.meta.props\n .filter((p) => p.kind === \"scalar\")\n .forEach((p) => {\n const value = updatedEntity[p.name];\n if (value !== undefined && value !== null) {\n const fieldName = this.getRealFieldNameFromSchema(p);\n modifiedModel[fieldName] = transformValue({ value, type: p.type }, false);\n }\n });\n return modifiedModel as T;\n }\n\n /**\n * Returns the real field name from the entity property based on the schema.\n *\n * @param p - The entity property.\n * @returns The real field name.\n */\n private getRealFieldNameFromSchema<T>(p: EntityProperty<T>): EntityKey<T> {\n return p.fieldNames && p.fieldNames.length\n ? (p.fieldNames[0] as EntityKey<T>)\n : p.name;\n }\n\n /**\n * Validates the provided value.\n *\n * @param value - The value to validate.\n * @returns True if the value is valid, false otherwise.\n */\n isValid(value: any): boolean {\n if (value instanceof Date) {\n return !isNaN(value.getTime());\n }\n return true;\n }\n}\n","import { EntitySchema, EntityProperty, EntityKey } from \"..\";\nimport {ComplexQuerySchemaBuilder} from \"./ForgeSQLQueryBuilder\";\n\nexport class DynamicEntity {\n [key: string]: unknown;\n\n /**\n * Retrieves a schema field by its original entity property.\n * @param field - The entity property to search for.\n * @returns The corresponding schema field or undefined if not found.\n */\n getSchemaBySchemaField<TYPE>(field: EntityProperty): TYPE | undefined {\n return this[field.name] as TYPE | undefined;\n }\n\n /**\n * Retrieves a schema field by its alias.\n * @param alias - The alias of the field.\n * @returns The corresponding schema field or undefined if not found.\n */\n getSchemaByAliasField<TYPE>(alias: string): TYPE | undefined {\n return this[alias] as TYPE | undefined;\n }\n}\n\nexport class EntitySchemaBuilder<T> implements ComplexQuerySchemaBuilder<T> {\n private properties: Record<string, EntityProperty<T>> = {};\n\n constructor(private entityClass: new () => T) {}\n\n /**\n * Adds a field to the schema definition.\n * @param field - The entity property to add.\n * @param alias - (Optional) Custom alias for the field name.\n * @returns The current instance of EntitySchemaBuilder for method chaining.\n */\n addField<K>(field: Partial<EntityProperty<K>>, alias?: string): this {\n const fieldName = alias || field.name;\n const fieldNameType = fieldName as unknown as EntityKey<T>;\n this.properties[fieldNameType] = { ...field, name: fieldNameType } as unknown as EntityProperty<T>;\n return this;\n }\n\n /**\n * Creates and initializes a new EntitySchema based on the added fields.\n * @returns A new EntitySchema<T> instance.\n */\n createSchema(): EntitySchema<T> {\n const es = new EntitySchema<T>({\n class: this.entityClass,\n // @ts-ignore\n properties: this.properties,\n });\n es.init();\n return es;\n }\n}\n\nexport class DynamicEntitySchemaBuilder extends EntitySchemaBuilder<DynamicEntity> {\n constructor() {\n super(DynamicEntity);\n }\n}\n","import { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport type { EntitySchema } from \"@mikro-orm/core/metadata/EntitySchema\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\nimport { ComplexQuerySchemaBuilder, ForgeSqlOrmOptions, SchemaSqlForgeSql} from \"./ForgeSQLQueryBuilder\";\nimport {SqlParameters} from \"@forge/sql/out/sql-statement\";\nimport {DynamicEntity, DynamicEntitySchemaBuilder} from \"./ComplexQuerySchemaBuilder\";\nimport {EntityKey} from \"@mikro-orm/core\";\n\nexport class ForgeSQLSelectOperations implements SchemaSqlForgeSql {\n private readonly options: ForgeSqlOrmOptions;\n\n constructor(options: ForgeSqlOrmOptions) {\n this.options = options;\n }\n\n /**\n * Creates a builder for constructing complex query schemas dynamically.\n * This method is useful when working with dynamic entity structures where fields\n * may not be known at compile time.\n * @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.\n */\n createComplexQuerySchema(): ComplexQuerySchemaBuilder<DynamicEntity> {\n return new DynamicEntitySchemaBuilder();\n }\n\n async executeSchemaSQLOnlyOne<T extends object>(query: string, schema: EntitySchema<T>): Promise<T|undefined> {\n const results = await this.executeSchemaSQL(query, schema);\n if (!results || results.length === 0){\n return undefined;\n }\n if (results.length>1){\n throw new Error('Expected 1 record but returned '+results.length)\n }\n return results[0];\n }\n\n /**\n * Executes a schema-based SQL query and maps the result to the entity schema.\n * @param query - The SQL query to execute.\n * @param schema - The entity schema defining the structure.\n * @returns A list of mapped entity objects.\n */\n async executeSchemaSQL<T extends object>(query: string, schema: EntitySchema<T>): Promise<T[]> {\n const datas = await this.executeRawSQL<unknown>(query);\n if (!datas.length) return [];\n\n return datas.map((r) => {\n const rawModel = r as Record<string, unknown>;\n const newModel = Object.create(schema.meta.prototype) as T;\n\n schema.meta.props\n .filter((p) => p.kind === \"scalar\")\n .forEach((p) => {\n const fieldName = p.name;\n const fieldNames = p.fieldNames;\n const rawFieldName = fieldNames && Array.isArray(fieldNames) ? fieldNames[0] : p.name;\n switch (p.type) {\n case \"datetime\":\n newModel[fieldName] = parseDateTime(\n rawModel[rawFieldName] as string,\n \"YYYY-MM-DDTHH:mm:ss.SSS\",\n ) as unknown as T[EntityKey<T>];\n break;\n case \"date\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"YYYY-MM-DD\") as unknown as T[EntityKey<T>];\n break;\n case \"time\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"HH:mm:ss.SSS\") as unknown as T[EntityKey<T>];\n break;\n default:\n newModel[fieldName] = rawModel[rawFieldName] as unknown as T[EntityKey<T>];\n }\n });\n return newModel as T;\n });\n }\n\n /**\n * Executes a raw SQL query and returns the results.\n * @param query - The raw SQL query to execute.\n * @returns A list of results as objects.\n */\n async executeRawSQL<T extends object | unknown>(query: string): Promise<T[]> {\n if (this.options.logRawSqlQuery) {\n console.debug(\"Executing raw SQL: \" + query);\n }\n const sqlStatement = await sql.prepare<T>(query).execute();\n return sqlStatement.rows as T[];\n }\n\n /**\n * Executes a raw SQL update query.\n * @param query - The raw SQL update query.\n * @param params - sql parameters.\n * @returns The update response containing affected rows.\n */\n async executeRawUpdateSQL(query: string, params?: SqlParameters[]): Promise<UpdateQueryResponse> {\n const sqlStatement = sql.prepare<UpdateQueryResponse>(query);\n if (params) {\n sqlStatement.bindParams(params);\n }\n const updateQueryResponseResults = await sqlStatement.execute();\n return updateQueryResponseResults.rows;\n }\n}\n","import type { EntityName, LoggingOptions } from \"..\";\nimport type { EntitySchema } from \"@mikro-orm/core/metadata/EntitySchema\";\nimport type { AnyEntity, EntityClass, EntityClassGroup } from \"@mikro-orm/core/typings\";\nimport type { QueryBuilder } from \"@mikro-orm/knex/query\";\nimport { MemoryCacheAdapter, MikroORM, NullCacheAdapter } from \"@mikro-orm/mysql\";\nimport { ForgeSQLCrudOperations } from \"./ForgeSQLCrudOperations\";\nimport {\n CRUDForgeSQL,\n ForgeSqlOperation,\n ForgeSqlOrmOptions,\n SchemaSqlForgeSql,\n} from \"./ForgeSQLQueryBuilder\";\nimport { ForgeSQLSelectOperations } from \"./ForgeSQLSelectOperations\";\nimport type { Knex } from \"knex\";\n\n/**\n * Implementation of ForgeSQLORM that interacts with MikroORM.\n */\nclass ForgeSQLORMImpl implements ForgeSqlOperation {\n private static instance: ForgeSQLORMImpl | null = null;\n private readonly mikroORM: MikroORM;\n private readonly crudOperations: CRUDForgeSQL;\n private readonly fetchOperations: SchemaSqlForgeSql;\n\n /**\n * Private constructor to enforce singleton behavior.\n * @param entities - The list of entities for ORM initialization.\n * @param options - Options for configuring ForgeSQL ORM behavior.\n */\n private constructor(\n entities: (EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[],\n options?: ForgeSqlOrmOptions,\n ) {\n\n try {\n const newOptions: ForgeSqlOrmOptions = options ?? { logRawSqlQuery: false, disableOptimisticLocking: false };\n if (newOptions.logRawSqlQuery){\n console.debug(\"Initializing ForgeSQLORM...\");\n }\n this.mikroORM = MikroORM.initSync({\n dbName: \"inmemory\",\n schemaGenerator: {\n disableForeignKeys: false,\n },\n discovery: {\n warnWhenNoEntities: true,\n },\n resultCache: {\n adapter: NullCacheAdapter,\n },\n metadataCache: {\n enabled: false,\n adapter: MemoryCacheAdapter,\n },\n entities: entities,\n preferTs: false,\n debug: false,\n });\n\n this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);\n this.fetchOperations = new ForgeSQLSelectOperations(newOptions);\n } catch (error) {\n console.error(\"ForgeSQLORM initialization failed:\", error);\n throw error; // Prevents inconsistent state\n }\n }\n\n /**\n * Returns the singleton instance of ForgeSQLORMImpl.\n * @param entities - List of entities (required only on first initialization).\n * @param options - Options for configuring ForgeSQL ORM behavior.\n * @returns The singleton instance of ForgeSQLORMImpl.\n */\n static getInstance(\n entities: (EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[],\n options?: ForgeSqlOrmOptions,\n ): ForgeSqlOperation {\n if (!ForgeSQLORMImpl.instance) {\n ForgeSQLORMImpl.instance = new ForgeSQLORMImpl(entities, options);\n }\n return ForgeSQLORMImpl.instance;\n }\n\n /**\n * Retrieves the CRUD operations instance.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.crudOperations;\n }\n\n /**\n * Retrieves the fetch operations instance.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.fetchOperations;\n }\n\n /**\n * Creates a new query builder for the given entity.\n * @param entityName - The entity name or an existing query builder.\n * @param alias - The alias for the entity.\n * @param loggerContext - Logging options.\n * @returns The query builder instance.\n */\n createQueryBuilder<Entity extends object, RootAlias extends string = never>(\n entityName: EntityName<Entity> | QueryBuilder<Entity>,\n alias?: RootAlias,\n loggerContext?: LoggingOptions,\n ): QueryBuilder<Entity, RootAlias> {\n return this.mikroORM.em.createQueryBuilder(entityName, alias, undefined, loggerContext);\n }\n\n /**\n * Provides access to the underlying Knex instance for building complex query parts.\n * enabling advanced query customization and performance tuning.\n * @returns The Knex instance, which can be used for query building.\n */\n getKnex(): Knex<any, any[]> {\n return this.mikroORM.em.getKnex();\n }\n}\n\n/**\n * Public class that acts as a wrapper around the private ForgeSQLORMImpl.\n */\nclass ForgeSQLORM {\n private readonly ormInstance: ForgeSqlOperation;\n\n constructor(\n entities: (EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[],\n options?: ForgeSqlOrmOptions,\n ) {\n this.ormInstance = ForgeSQLORMImpl.getInstance(entities, options);\n }\n\n /**\n * Proxies the `crud` method from `ForgeSQLORMImpl`.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.ormInstance.crud();\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 getKnex(): Knex<any, any[]> {\n return this.ormInstance.getKnex();\n }\n\n /**\n * Proxies the `createQueryBuilder` method from `ForgeSQLORMImpl`.\n * @returns A new query builder instance.\n */\n createQueryBuilder<Entity extends object, RootAlias extends string = never>(\n entityName: EntityName<Entity> | QueryBuilder<Entity>,\n alias?: RootAlias,\n loggerContext?: LoggingOptions,\n ): QueryBuilder<Entity, RootAlias> {\n return this.ormInstance.createQueryBuilder(entityName, alias, loggerContext);\n }\n}\n\nexport default ForgeSQLORM;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ForgeSQLORM.mjs","sources":["../src/utils/sqlUtils.ts","../src/core/ForgeSQLCrudOperations.ts","../src/core/ForgeSQLSelectOperations.ts","../src/core/ForgeSQLORM.ts","../src/core/ForgeSQLQueryBuilder.ts"],"sourcesContent":["import moment from \"moment\";\nimport { AnyColumn } from \"drizzle-orm\";\nimport { AnyMySqlTable } from \"drizzle-orm/mysql-core/index\";\nimport { PrimaryKeyBuilder } from \"drizzle-orm/mysql-core/primary-keys\";\nimport { AnyIndexBuilder, IndexBuilder } 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\";\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 * 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 const m = moment(value, format, true);\n if (!m.isValid()) {\n return moment(value).toDate();\n }\n return m.toDate();\n};\n\n/**\n * Extracts the alias from a SQL query\n * @param query - The SQL query to extract the alias from\n * @returns The extracted alias or the original query if no alias found\n */\nexport function extractAlias(query: string): string {\n const match = query.match(/\\bas\\s+(['\"`]?)([\\w*]+)\\1$/i);\n return match ? match[2] : query;\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][] | undefined} Array of primary key name and column pairs or undefined if no primary keys found\n */\nexport function getPrimaryKeys<T extends AnyMySqlTable>(\n table: T,\n): [string, AnyColumn][] | undefined {\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 const result = Array.from(primaryKeyColumns);\n return result.length > 0 ? result : undefined;\n }\n\n return undefined;\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 extraSymbol = symbols.find((s) => s.toString().includes(\"ExtraConfigBuilder\"));\n const foreignKeysSymbol = symbols.find((s) => s.toString().includes(\"MySqlInlineForeignKeys)\"));\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 if (foreignKeysSymbol) {\n // @ts-ignore\n const foreignKeys: any[] = table[foreignKeysSymbol];\n if (foreignKeys) {\n for (const foreignKey of foreignKeys) {\n builders.foreignKeys.push(foreignKey);\n }\n }\n }\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 configBuilders = extraConfigBuilder(table);\n let configBuildersArray: any[] = [];\n if (!Array.isArray(configBuilders)) {\n configBuildersArray = Object.values(configBuilders);\n } else {\n configBuildersArray = configBuilders as any[];\n }\n configBuildersArray.forEach((builder) => {\n if (builder instanceof IndexBuilder) {\n builders.indexes.push(builder);\n } else if (builder instanceof CheckBuilder) {\n builders.checks.push(builder);\n } else if (builder instanceof ForeignKeyBuilder) {\n builders.foreignKeys.push(builder);\n } else if (builder instanceof PrimaryKeyBuilder) {\n builders.primaryKeys.push(builder);\n } else if (builder instanceof UniqueConstraintBuilder) {\n builders.uniqueConstraints.push(builder);\n }\n builders.extras.push(builder);\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","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: Partial<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 query = finalQuery.toSQL();\n if (this.options?.logRawSqlQuery) {\n console.debug(\"INSERT SQL:\", query.sql);\n }\n\n const result = await this.forgeOperations.fetch().executeRawUpdateSQL(query.sql, query.params);\n\n return result.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 if (this.options?.logRawSqlQuery) {\n console.debug(\"DELETE SQL:\", queryBuilder.toSQL().sql);\n }\n\n const result = await this.forgeOperations\n .fetch()\n .executeRawUpdateSQL(queryBuilder.toSQL().sql, queryBuilder.toSQL().params);\n\n return result.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 if (this.options?.logRawSqlQuery) {\n console.debug(\"UPDATE SQL:\", queryBuilder.toSQL().sql);\n }\n\n const result = await this.forgeOperations\n .fetch()\n .executeRawUpdateSQL(queryBuilder.toSQL().sql, queryBuilder.toSQL().params);\n\n // Check optimistic locking\n if (versionMetadata && result.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.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 if (this.options?.logRawSqlQuery) {\n console.debug(\"UPDATE SQL:\", queryBuilder.toSQL().sql);\n }\n\n const result = await this.forgeOperations\n .fetch()\n .executeRawUpdateSQL(queryBuilder.toSQL().sql, queryBuilder.toSQL().params);\n\n return result.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\n const versionField = columns[versionMetadata.fieldName];\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: versionMetadata.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\n const versionField = columns[versionMetadata.fieldName];\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[versionMetadata.fieldName as keyof typeof modelWithVersion] =\n 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 { extractAlias, parseDateTime } from \"../utils/sqlUtils\";\nimport { ForgeSqlOrmOptions, SchemaSqlForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport { AnyMySqlSelect } from \"drizzle-orm/mysql-core\";\nimport {\n AnyMySqlSelectQueryBuilder,\n MySqlSelectDynamic,\n} from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { Column, SQL, SQLChunk, StringChunk } from \"drizzle-orm\";\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 the results.\n * Maps the raw database results to the appropriate entity types.\n *\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T>>} The query results mapped to entity types\n */\n async executeQuery<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<Awaited<T>> {\n const queryType = <AnyMySqlSelect>query;\n const querySql = queryType.toSQL();\n const datas = await this.executeRawSQL<unknown>(querySql.sql, querySql.params);\n\n if (!datas.length) return [] as Awaited<T>;\n\n return datas.map((r) => {\n const rawModel = r as Record<string, unknown>;\n const newModel: any = {};\n\n // @ts-ignore - Drizzle internal property\n const columns = queryType.config.fields;\n\n Object.entries(columns).forEach(([name, column]: [string, any]) => {\n const { realColumn, aliasName } = this.extractColumnInfo(column);\n const value = rawModel[aliasName];\n\n if (value === null || value === undefined) {\n newModel[name] = value;\n return;\n }\n\n newModel[name] = this.parseColumnValue(realColumn, value);\n });\n\n return newModel;\n }) as Awaited<T>;\n }\n\n /**\n * Extracts column information and alias name from a column definition.\n * @param {any} column - The column definition from Drizzle\n * @returns {Object} Object containing the real column and its alias name\n */\n private extractColumnInfo(column: any): { realColumn: Column; aliasName: string } {\n if (column instanceof SQL) {\n const realColumnSql = <SQL>column;\n const realColumn = realColumnSql.queryChunks.find(\n (q: SQLChunk) => q instanceof Column,\n ) as Column;\n\n let stringChunk = this.findAliasChunk(realColumnSql);\n let withoutAlias = false;\n\n if (!realColumn && (!stringChunk || !stringChunk.value || !stringChunk.value?.length)) {\n stringChunk = realColumnSql.queryChunks\n .filter((q: SQLChunk) => q instanceof StringChunk)\n .find((q: SQLChunk) => (q as StringChunk).value[0]) as StringChunk;\n withoutAlias = true;\n }\n\n const aliasName = this.resolveAliasName(stringChunk, realColumn, withoutAlias);\n\n return { realColumn, aliasName };\n }\n\n return { realColumn: column, aliasName: column.name };\n }\n\n /**\n * Finds the alias chunk in SQL query chunks.\n * @param {SQL} realColumnSql - The SQL query chunks\n * @returns {StringChunk | undefined} The string chunk containing the alias or undefined\n */\n private findAliasChunk(realColumnSql: SQL): StringChunk | undefined {\n return realColumnSql.queryChunks\n .filter((q: SQLChunk) => q instanceof StringChunk)\n .find((q: SQLChunk) =>\n (q as StringChunk).value.find((f) => f.toLowerCase().includes(\"as\")),\n ) as StringChunk;\n }\n\n /**\n * Resolves the alias name from the string chunk or column.\n * @param {StringChunk | undefined} stringChunk - The string chunk containing the alias\n * @param {Column | undefined} realColumn - The real column definition\n * @param {boolean} withoutAlias - Whether the column has no alias\n * @returns {string} The resolved alias name\n */\n private resolveAliasName(\n stringChunk: StringChunk | undefined,\n realColumn: Column | undefined,\n withoutAlias: boolean,\n ): string {\n if (stringChunk) {\n if (withoutAlias) {\n return stringChunk.value[0];\n }\n const asClause = stringChunk.value.find((f) => f.toLowerCase().includes(\"as\"));\n return asClause ? extractAlias(asClause.trim()) : realColumn?.name || \"\";\n }\n return realColumn?.name || \"\";\n }\n\n /**\n * Parses a column value based on its SQL type.\n * Handles datetime, date, and time types with appropriate formatting.\n *\n * @param {Column} column - The column definition\n * @param {unknown} value - The raw value to parse\n * @returns {unknown} The parsed value\n */\n private parseColumnValue(column: Column, value: unknown): unknown {\n if (!column) return value;\n\n switch (column.getSQLType()) {\n case \"datetime\":\n return parseDateTime(value as string, \"YYYY-MM-DDTHH:mm:ss.SSS\");\n case \"date\":\n return parseDateTime(value as string, \"YYYY-MM-DD\");\n case \"time\":\n return parseDateTime(value as string, \"HH:mm:ss.SSS\");\n default:\n return value;\n }\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 this.executeQuery<T>(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 console.debug(\"Executing raw SQL: \" + query);\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 const updateQueryResponseResults = await sqlStatement.execute();\n return updateQueryResponseResults.rows;\n }\n}\n","import { ForgeSQLCrudOperations } from \"./ForgeSQLCrudOperations\";\nimport {\n CRUDForgeSQL,\n ForgeSqlOperation,\n ForgeSqlOrmOptions,\n SchemaSqlForgeSql,\n} from \"./ForgeSQLQueryBuilder\";\nimport { ForgeSQLSelectOperations } from \"./ForgeSQLSelectOperations\";\nimport { drizzle } from \"drizzle-orm/mysql2\";\nimport { MySql2Database } from \"drizzle-orm/mysql2/driver\";\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: MySql2Database<Record<string, unknown>>;\n private readonly crudOperations: CRUDForgeSQL;\n private readonly fetchOperations: SchemaSqlForgeSql;\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 for query building only\n // This instance should not be used for direct database connections\n this.drizzle = drizzle(\"\");\n this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);\n this.fetchOperations = new ForgeSQLSelectOperations(newOptions);\n } catch (error) {\n console.error(\"ForgeSQLORM initialization failed:\", error);\n throw error; // Prevents inconsistent state\n }\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 if (!ForgeSQLORMImpl.instance) {\n ForgeSQLORMImpl.instance = new ForgeSQLORMImpl(options);\n }\n return ForgeSQLORMImpl.instance;\n }\n\n /**\n * Retrieves the CRUD operations instance.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.crudOperations;\n }\n\n /**\n * Retrieves the fetch operations instance.\n * @returns Fetch operations.\n */\n fetch(): SchemaSqlForgeSql {\n return this.fetchOperations;\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(): MySql2Database<Record<string, unknown>> {\n return this.drizzle;\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 {\n private readonly ormInstance: ForgeSqlOperation;\n\n constructor(options?: ForgeSqlOrmOptions) {\n this.ormInstance = ForgeSQLORMImpl.getInstance(options);\n }\n\n /**\n * Proxies the `crud` method from `ForgeSQLORMImpl`.\n * @returns CRUD operations.\n */\n crud(): CRUDForgeSQL {\n return this.ormInstance.crud();\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 * 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(): MySql2Database<Record<string, unknown>> {\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 { MySql2Database } from \"drizzle-orm/mysql2/driver\";\nimport { AnyMySqlSelectQueryBuilder, AnyMySqlTable, customType } from \"drizzle-orm/mysql-core\";\nimport { MySqlSelectDynamic } from \"drizzle-orm/mysql-core/query-builders/select.types\";\nimport { InferInsertModel, SQL } from \"drizzle-orm\";\nimport moment from \"moment/moment\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\n\n// ============= Core Types =============\n\n/**\n * Interface representing the main ForgeSQL operations.\n * Provides access to CRUD operations and schema-level SQL operations.\n */\nexport interface ForgeSqlOperation extends QueryBuilderForgeSql {\n /**\n * Provides CRUD (Create, Read, Update, Delete) operations.\n * @returns {CRUDForgeSQL} Interface for performing CRUD operations\n */\n crud(): CRUDForgeSQL;\n\n /**\n * Provides schema-level SQL fetch operations.\n * @returns {SchemaSqlForgeSql} Interface for executing schema-bound SQL queries\n */\n fetch(): SchemaSqlForgeSql;\n}\n\n/**\n * Interface for Query Builder operations.\n * Provides access to the underlying Drizzle ORM query builder.\n */\nexport interface QueryBuilderForgeSql {\n /**\n * Creates a new query builder for the given entity.\n * @returns {MySql2Database<Record<string, unknown>>} The Drizzle database instance for building queries\n */\n getDrizzleQueryBuilder(): MySql2Database<Record<string, unknown>>;\n}\n\n// ============= CRUD Operations =============\n\n/**\n * Interface for CRUD (Create, Read, Update, Delete) operations.\n * Provides methods for basic database operations with support for optimistic locking.\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 {Partial<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: Partial<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// ============= Schema SQL Operations =============\n\n/**\n * Interface for schema-level SQL operations.\n * Provides methods for executing SQL queries with schema binding and type safety.\n */\nexport interface SchemaSqlForgeSql {\n /**\n * Executes a Drizzle query and returns the result.\n * @template T - The type of the query builder\n * @param {T} query - The Drizzle query to execute\n * @returns {Promise<Awaited<T>>} The query result\n * @throws {Error} If the query execution fails\n */\n executeQuery<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(\n query: T,\n ): Promise<Awaited<T>>;\n\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// ============= Configuration Types =============\n\n/**\n * Interface for version field metadata.\n * Defines the configuration for optimistic locking version fields.\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 */\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 */\nexport type AdditionalMetadata = Record<string, TableMetadata>;\n\n/**\n * Options for configuring ForgeSQL ORM behavior.\n */\nexport interface ForgeSqlOrmOptions {\n /**\n * Enables logging of raw SQL queries in the Atlassian Forge Developer Console.\n * Useful for debugging and monitoring SQL operations.\n * @default false\n */\n logRawSqlQuery?: boolean;\n\n /**\n * Disables optimistic locking for all operations.\n * When enabled, version checks are skipped during updates.\n * @default false\n */\n disableOptimisticLocking?: boolean;\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// ============= Custom Types =============\n\n/**\n * Custom type for MySQL datetime fields.\n * Handles conversion between JavaScript Date objects and MySQL datetime strings.\n */\nexport const mySqlDateTimeString = 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 */\nexport const mySqlTimestampString = 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(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 date fields.\n * Handles conversion between JavaScript Date objects and MySQL date strings.\n */\nexport const mySqlDateString = 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 */\nexport const mySqlTimeString = 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"],"names":["moment"],"mappings":"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"}
|
|
@@ -1,157 +1,128 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ForgeSqlOrmOptions } from "..";
|
|
2
2
|
import { CRUDForgeSQL, ForgeSqlOperation } from "./ForgeSQLQueryBuilder";
|
|
3
|
-
import {
|
|
3
|
+
import { AnyMySqlTable } from "drizzle-orm/mysql-core/index";
|
|
4
|
+
import { InferInsertModel } from "drizzle-orm";
|
|
5
|
+
import { SQL } from "drizzle-orm";
|
|
6
|
+
/**
|
|
7
|
+
* Class implementing CRUD operations for ForgeSQL ORM.
|
|
8
|
+
* Provides methods for inserting, updating, and deleting records with support for optimistic locking.
|
|
9
|
+
*/
|
|
4
10
|
export declare class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
5
11
|
private readonly forgeOperations;
|
|
6
12
|
private readonly options;
|
|
7
|
-
constructor(forgeSqlOperations: ForgeSqlOperation, options: ForgeSqlOrmOptions);
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* @param schema - The entity schema.
|
|
13
|
-
* @param models - The list of entities to insert.
|
|
14
|
-
* @param updateIfExists - Whether to update the row if it already exists.
|
|
15
|
-
* @returns An object containing the SQL query, column names, and values.
|
|
14
|
+
* Creates a new instance of ForgeSQLCrudOperations.
|
|
15
|
+
* @param forgeSqlOperations - The ForgeSQL operations instance
|
|
16
|
+
* @param options - Configuration options for the ORM
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
+
constructor(forgeSqlOperations: ForgeSqlOperation, options: ForgeSqlOrmOptions);
|
|
18
19
|
/**
|
|
19
|
-
* Inserts records into the database.
|
|
20
|
+
* Inserts records into the database with optional versioning support.
|
|
20
21
|
* If a version field exists in the schema, versioning is applied.
|
|
21
22
|
*
|
|
22
|
-
* @
|
|
23
|
-
* @param
|
|
24
|
-
* @param
|
|
25
|
-
* @
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Retrieves the primary key properties from the entity schema.
|
|
30
|
-
*
|
|
31
|
-
* @param schema - The entity schema.
|
|
32
|
-
* @returns An array of primary key properties.
|
|
33
|
-
* @throws If no primary keys are found.
|
|
34
|
-
*/
|
|
35
|
-
private getPrimaryKeys;
|
|
36
|
-
/**
|
|
37
|
-
* Deletes a record by its primary key.
|
|
38
|
-
*
|
|
39
|
-
* @param id - The ID of the record to delete.
|
|
40
|
-
* @param schema - The entity schema.
|
|
41
|
-
* @returns The number of rows affected.
|
|
42
|
-
* @throws If the entity has more than one primary key.
|
|
23
|
+
* @template T - The type of the table schema
|
|
24
|
+
* @param {T} schema - The entity schema
|
|
25
|
+
* @param {Partial<InferInsertModel<T>>[]} models - Array of entities to insert
|
|
26
|
+
* @param {boolean} [updateIfExists=false] - Whether to update existing records
|
|
27
|
+
* @returns {Promise<number>} The number of inserted rows
|
|
28
|
+
* @throws {Error} If the insert operation fails
|
|
43
29
|
*/
|
|
44
|
-
|
|
30
|
+
insert<T extends AnyMySqlTable>(schema: T, models: Partial<InferInsertModel<T>>[], updateIfExists?: boolean): Promise<number>;
|
|
45
31
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
32
|
+
* Deletes a record by its primary key with optional version check.
|
|
33
|
+
* If versioning is enabled, ensures the record hasn't been modified since last read.
|
|
48
34
|
*
|
|
49
|
-
* @
|
|
50
|
-
* @
|
|
35
|
+
* @template T - The type of the table schema
|
|
36
|
+
* @param {unknown} id - The ID of the record to delete
|
|
37
|
+
* @param {T} schema - The entity schema
|
|
38
|
+
* @returns {Promise<number>} Number of affected rows
|
|
39
|
+
* @throws {Error} If the delete operation fails
|
|
40
|
+
* @throws {Error} If multiple primary keys are found
|
|
51
41
|
*/
|
|
52
|
-
|
|
42
|
+
deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number>;
|
|
53
43
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
44
|
+
* Updates a record by its primary key with optimistic locking support.
|
|
45
|
+
* If versioning is enabled:
|
|
46
|
+
* - Retrieves the current version
|
|
47
|
+
* - Checks for concurrent modifications
|
|
48
|
+
* - Increments the version on successful update
|
|
56
49
|
*
|
|
57
|
-
* @
|
|
58
|
-
* @param
|
|
50
|
+
* @template T - The type of the table schema
|
|
51
|
+
* @param {Partial<InferInsertModel<T>>} entity - The entity with updated values
|
|
52
|
+
* @param {T} schema - The entity schema
|
|
53
|
+
* @returns {Promise<number>} Number of affected rows
|
|
54
|
+
* @throws {Error} If the primary key is not provided
|
|
55
|
+
* @throws {Error} If optimistic locking check fails
|
|
56
|
+
* @throws {Error} If multiple primary keys are found
|
|
59
57
|
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Creates the initial version field value for an entity.
|
|
63
|
-
* For datetime types, returns the current date; for numeric types, returns 0.
|
|
64
|
-
*
|
|
65
|
-
* @param versionField - The version field property.
|
|
66
|
-
*/
|
|
67
|
-
createVersionField<T>(versionField: EntityProperty<T>): unknown;
|
|
68
|
-
/**
|
|
69
|
-
* Updates a record by its primary key using the provided entity data.
|
|
70
|
-
*
|
|
71
|
-
* @param entity - The entity with updated values.
|
|
72
|
-
* @param schema - The entity schema.
|
|
73
|
-
*/
|
|
74
|
-
updateById<T extends object>(entity: Partial<T>, schema: EntitySchema<T>): Promise<void>;
|
|
58
|
+
updateById<T extends AnyMySqlTable>(entity: Partial<InferInsertModel<T>>, schema: T): Promise<number>;
|
|
75
59
|
/**
|
|
76
60
|
* Updates specified fields of records based on provided conditions.
|
|
77
|
-
*
|
|
78
|
-
* that are not included in the list of fields to update.
|
|
79
|
-
*
|
|
80
|
-
* @param entity - The object containing values to update and potential criteria for filtering.
|
|
81
|
-
* @param fields - Array of field names to update.
|
|
82
|
-
* @param schema - The entity schema.
|
|
83
|
-
* @param where - Optional filtering conditions for the WHERE clause.
|
|
84
|
-
* @returns The number of affected rows.
|
|
85
|
-
* @throws If no filtering criteria are provided (either via "where" or from the remaining entity fields).
|
|
86
|
-
*/
|
|
87
|
-
updateFields<T extends object>(entity: Partial<T>, fields: EntityKey<T>[], schema: EntitySchema<T>, where?: QBFilterQuery<T>): Promise<number>;
|
|
88
|
-
/**
|
|
89
|
-
* Updates specific fields of a record identified by its primary key.
|
|
90
|
-
* If a version field exists in the schema, versioning is applied.
|
|
61
|
+
* This method does not support versioning and should be used with caution.
|
|
91
62
|
*
|
|
92
|
-
* @
|
|
93
|
-
* @param
|
|
94
|
-
* @param schema - The entity schema
|
|
95
|
-
* @
|
|
63
|
+
* @template T - The type of the table schema
|
|
64
|
+
* @param {Partial<InferInsertModel<T>>} updateData - The data to update
|
|
65
|
+
* @param {T} schema - The entity schema
|
|
66
|
+
* @param {SQL<unknown>} where - The WHERE conditions
|
|
67
|
+
* @returns {Promise<number>} Number of affected rows
|
|
68
|
+
* @throws {Error} If WHERE conditions are not provided
|
|
69
|
+
* @throws {Error} If the update operation fails
|
|
96
70
|
*/
|
|
97
|
-
|
|
71
|
+
updateFields<T extends AnyMySqlTable>(updateData: Partial<InferInsertModel<T>>, schema: T, where?: SQL<unknown>): Promise<number>;
|
|
98
72
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* @param
|
|
102
|
-
* @
|
|
103
|
-
* @
|
|
73
|
+
* Gets primary keys from the schema.
|
|
74
|
+
* @template T - The type of the table schema
|
|
75
|
+
* @param {T} schema - The table schema
|
|
76
|
+
* @returns {[string, AnyColumn][]} Array of primary key name and column pairs
|
|
77
|
+
* @throws {Error} If no primary keys are found
|
|
104
78
|
*/
|
|
105
|
-
private
|
|
79
|
+
private getPrimaryKeys;
|
|
106
80
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* @param
|
|
110
|
-
* @
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
*
|
|
81
|
+
* Validates and retrieves version field metadata.
|
|
82
|
+
* @param {string} tableName - The name of the table
|
|
83
|
+
* @param {Record<string, AnyColumn>} columns - The table columns
|
|
84
|
+
* @returns {Object | undefined} Version field metadata if valid, undefined otherwise
|
|
85
|
+
*/
|
|
86
|
+
private validateVersionField;
|
|
87
|
+
/**
|
|
88
|
+
* Gets the current version of an entity.
|
|
89
|
+
* @template T - The type of the table schema
|
|
90
|
+
* @param {Partial<InferInsertModel<T>>} entity - The entity
|
|
91
|
+
* @param {string} primaryKeyName - The name of the primary key
|
|
92
|
+
* @param {Object | undefined} versionMetadata - Version field metadata
|
|
93
|
+
* @param {Record<string, AnyColumn>} columns - The table columns
|
|
94
|
+
* @param {T} schema - The table schema
|
|
95
|
+
* @returns {Promise<unknown>} The current version value
|
|
96
|
+
*/
|
|
97
|
+
private getCurrentVersion;
|
|
98
|
+
/**
|
|
99
|
+
* Prepares a model for insertion with version field.
|
|
100
|
+
* @template T - The type of the table schema
|
|
101
|
+
* @param {Partial<InferInsertModel<T>>} model - The model to prepare
|
|
102
|
+
* @param {Object | undefined} versionMetadata - Version field metadata
|
|
103
|
+
* @param {Record<string, AnyColumn>} columns - The table columns
|
|
104
|
+
* @returns {InferInsertModel<T>} The prepared model
|
|
105
|
+
*/
|
|
106
|
+
private prepareModelWithVersion;
|
|
107
|
+
/**
|
|
108
|
+
* Prepares update data with version field.
|
|
109
|
+
* @template T - The type of the table schema
|
|
110
|
+
* @param {Partial<InferInsertModel<T>>} entity - The entity to update
|
|
111
|
+
* @param {Object | undefined} versionMetadata - Version field metadata
|
|
112
|
+
* @param {Record<string, AnyColumn>} columns - The table columns
|
|
113
|
+
* @param {unknown} currentVersion - The current version value
|
|
114
|
+
* @returns {Partial<InferInsertModel<T>>} The prepared update data
|
|
115
|
+
*/
|
|
116
|
+
private prepareUpdateData;
|
|
117
|
+
/**
|
|
118
|
+
* Retrieves an existing model by primary key.
|
|
119
|
+
* @template T - The type of the table schema
|
|
120
|
+
* @param {Record<string, unknown>} primaryKeyValues - The primary key values
|
|
121
|
+
* @param {T} schema - The table schema
|
|
122
|
+
* @param {[string, AnyColumn]} versionField - The version field name and column
|
|
123
|
+
* @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} The existing model
|
|
124
|
+
* @throws {Error} If the record is not found
|
|
115
125
|
*/
|
|
116
126
|
private getOldModel;
|
|
117
|
-
/**
|
|
118
|
-
* Adds primary key conditions to the query builder.
|
|
119
|
-
*
|
|
120
|
-
* @param queryBuilder - The Knex query builder instance.
|
|
121
|
-
* @param primaryKeys - The primary key properties.
|
|
122
|
-
* @param entity - The entity containing primary key values.
|
|
123
|
-
* @throws If any primary key value is missing.
|
|
124
|
-
*/
|
|
125
|
-
private addPrimaryWhere;
|
|
126
|
-
/**
|
|
127
|
-
* Filters the entity to include only the specified fields.
|
|
128
|
-
*
|
|
129
|
-
* @param entity - The original entity.
|
|
130
|
-
* @param fields - The list of fields to retain.
|
|
131
|
-
* @returns A partial entity object containing only the specified fields.
|
|
132
|
-
*/
|
|
133
|
-
filterEntityFields: <T extends object>(entity: T, fields: (keyof T)[]) => Partial<T>;
|
|
134
|
-
/**
|
|
135
|
-
* Transforms and modifies the updated entity model based on the schema.
|
|
136
|
-
*
|
|
137
|
-
* @param updatedEntity - The updated entity.
|
|
138
|
-
* @param schema - The entity schema.
|
|
139
|
-
* @returns The modified entity.
|
|
140
|
-
*/
|
|
141
|
-
private modifyModel;
|
|
142
|
-
/**
|
|
143
|
-
* Returns the real field name from the entity property based on the schema.
|
|
144
|
-
*
|
|
145
|
-
* @param p - The entity property.
|
|
146
|
-
* @returns The real field name.
|
|
147
|
-
*/
|
|
148
|
-
private getRealFieldNameFromSchema;
|
|
149
|
-
/**
|
|
150
|
-
* Validates the provided value.
|
|
151
|
-
*
|
|
152
|
-
* @param value - The value to validate.
|
|
153
|
-
* @returns True if the value is valid, false otherwise.
|
|
154
|
-
*/
|
|
155
|
-
isValid(value: any): boolean;
|
|
156
127
|
}
|
|
157
128
|
//# sourceMappingURL=ForgeSQLCrudOperations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLCrudOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLCrudOperations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ForgeSQLCrudOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLCrudOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAa,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,YAAY;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C;;;;OAIG;gBACS,kBAAkB,EAAE,iBAAiB,EAAE,OAAO,EAAE,kBAAkB;IAK9E;;;;;;;;;;OAUG;IACG,MAAM,CAAC,CAAC,SAAS,aAAa,EAClC,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EACtC,cAAc,GAAE,OAAe,GAC9B,OAAO,CAAC,MAAM,CAAC;IAqClB;;;;;;;;;;OAUG;IACG,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IA2ClF;;;;;;;;;;;;;;OAcG;IACG,UAAU,CAAC,CAAC,SAAS,aAAa,EACtC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,MAAM,CAAC;IAgElB;;;;;;;;;;;OAWG;IACG,YAAY,CAAC,CAAC,SAAS,aAAa,EACxC,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,CAAC,EACT,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GACnB,OAAO,CAAC,MAAM,CAAC;IAwBlB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAStB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IA4C5B;;;;;;;;;OASG;YACW,iBAAiB;IAyB/B;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;;;;OAQG;YACW,WAAW;CA4B1B"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import type { EntityName, LoggingOptions } from "..";
|
|
2
|
-
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
3
|
-
import type { AnyEntity, EntityClass, EntityClassGroup } from "@mikro-orm/core/typings";
|
|
4
|
-
import type { QueryBuilder } from "@mikro-orm/knex/query";
|
|
5
1
|
import { CRUDForgeSQL, ForgeSqlOrmOptions, SchemaSqlForgeSql } from "./ForgeSQLQueryBuilder";
|
|
6
|
-
import
|
|
2
|
+
import { MySql2Database } from "drizzle-orm/mysql2/driver";
|
|
7
3
|
/**
|
|
8
4
|
* Public class that acts as a wrapper around the private ForgeSQLORMImpl.
|
|
5
|
+
* Provides a clean interface for working with Forge SQL and Drizzle ORM.
|
|
9
6
|
*/
|
|
10
7
|
declare class ForgeSQLORM {
|
|
11
8
|
private readonly ormInstance;
|
|
12
|
-
constructor(
|
|
9
|
+
constructor(options?: ForgeSqlOrmOptions);
|
|
13
10
|
/**
|
|
14
11
|
* Proxies the `crud` method from `ForgeSQLORMImpl`.
|
|
15
12
|
* @returns CRUD operations.
|
|
@@ -20,12 +17,16 @@ declare class ForgeSQLORM {
|
|
|
20
17
|
* @returns Fetch operations.
|
|
21
18
|
*/
|
|
22
19
|
fetch(): SchemaSqlForgeSql;
|
|
23
|
-
getKnex(): Knex<any, any[]>;
|
|
24
20
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
21
|
+
* Returns a Drizzle query builder instance.
|
|
22
|
+
*
|
|
23
|
+
* ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.
|
|
24
|
+
* The returned instance should NOT be used for direct database connections or query execution.
|
|
25
|
+
* All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.
|
|
26
|
+
*
|
|
27
|
+
* @returns A Drizzle query builder instance for query construction only.
|
|
27
28
|
*/
|
|
28
|
-
|
|
29
|
+
getDrizzleQueryBuilder(): MySql2Database<Record<string, unknown>>;
|
|
29
30
|
}
|
|
30
31
|
export default ForgeSQLORM;
|
|
31
32
|
//# sourceMappingURL=ForgeSQLORM.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLORM.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLORM.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ForgeSQLORM.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLORM.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EAEZ,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AA+E3D;;;GAGG;AACH,cAAM,WAAW;IACf,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;gBAEpC,OAAO,CAAC,EAAE,kBAAkB;IAIxC;;;OAGG;IACH,IAAI,IAAI,YAAY;IAIpB;;;OAGG;IACH,KAAK,IAAI,iBAAiB;IAI1B;;;;;;;;OAQG;IACH,sBAAsB,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAGlE;AAED,eAAe,WAAW,CAAC"}
|