forge-sql-orm 1.0.29 → 1.0.30
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 +3 -23
- package/dist/ForgeSQLORM.js +64 -1
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +65 -2
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ComplexQuerySchemaBuilder.d.ts +38 -0
- package/dist/core/ComplexQuerySchemaBuilder.d.ts.map +1 -0
- package/dist/core/ForgeSQLQueryBuilder.d.ts +23 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts +9 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist-cli/forgeSqlOrmCLI.js +7 -12
- package/package.json +5 -5
- package/src/core/ComplexQuerySchemaBuilder.ts +63 -0
- package/src/core/ForgeSQLQueryBuilder.ts +25 -1
- package/src/core/ForgeSQLSelectOperations.ts +22 -11
- package/src/utils/sqlUtils.ts +1 -1
package/README.md
CHANGED
|
@@ -14,12 +14,6 @@
|
|
|
14
14
|
- ✅ **Automatic migration generation** from MySQL/tidb databases.
|
|
15
15
|
- ✅ **Optimistic Locking** Ensures data consistency by preventing conflicts when multiple users update the same record.
|
|
16
16
|
|
|
17
|
-
🚀 **Development in Progress** 🚀
|
|
18
|
-
I am currently working on implementing the following features:
|
|
19
|
-
- 🗑️ **Soft Deletion Support** – Allows marking records as deleted without actually removing them from the database, enabling easy recovery.
|
|
20
|
-
- 🏗️ **Complex Query Handling** _(JOIN, GROUP BY, etc.) without requiring an EntitySchema_ – Simplifies the execution of advanced SQL queries without the need to define additional schemas.
|
|
21
|
-
---
|
|
22
|
-
|
|
23
17
|
## Installation
|
|
24
18
|
|
|
25
19
|
Forge-SQL-ORM is designed to work with @forge/sql and requires some additional setup to ensure compatibility within Atlassian Forge.
|
|
@@ -157,19 +151,9 @@ const users = (await forgeSQL.fetch().executeRawSQL) < Users > "SELECT * FROM us
|
|
|
157
151
|
|
|
158
152
|
```js
|
|
159
153
|
// Define schema for join result
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export const innerJoinSchema = new EntitySchema<InnerJoinResult>({
|
|
166
|
-
class: InnerJoinResult,
|
|
167
|
-
properties: {
|
|
168
|
-
name: { type: "string", fieldName: "name" },
|
|
169
|
-
product: { type: "string", fieldName: "product" }
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
innerJoinSchema.init();
|
|
154
|
+
const innerJoinSchema = forgeSQL.fetch().createComplexQuerySchema();
|
|
155
|
+
schemaBuilder.addField(Users.meta.properties.name);
|
|
156
|
+
schemaBuilder.addField(Orders.meta.properties.product);
|
|
173
157
|
|
|
174
158
|
// Execute query
|
|
175
159
|
const query = forgeSQL.createQueryBuilder(Orders, "order")
|
|
@@ -616,10 +600,6 @@ const duplicateResult = await forgeSQL
|
|
|
616
600
|
|
|
617
601
|
---
|
|
618
602
|
|
|
619
|
-
Below is the plain text version of the additional section for Optimistic Locking. You can copy and paste it directly into your README:
|
|
620
|
-
|
|
621
|
-
---
|
|
622
|
-
|
|
623
603
|
## Optimistic Locking
|
|
624
604
|
|
|
625
605
|
Optimistic locking is a concurrency control mechanism that prevents data conflicts when multiple transactions attempt to update the same record concurrently. Instead of using locks, this technique relies on a version field in your entity models. Each time an update occurs, the current version is checked, and if it doesn't match the stored version, the update is rejected. This ensures data consistency and helps avoid accidental overwrites.
|
package/dist/ForgeSQLORM.js
CHANGED
|
@@ -463,11 +463,74 @@ class ForgeSQLCrudOperations {
|
|
|
463
463
|
return true;
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
|
+
class DynamicEntity {
|
|
467
|
+
/**
|
|
468
|
+
* Retrieves a schema field by its original entity property.
|
|
469
|
+
* @param field - The entity property to search for.
|
|
470
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
471
|
+
*/
|
|
472
|
+
getSchemaBySchemaField(field) {
|
|
473
|
+
return this[field.name];
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Retrieves a schema field by its alias.
|
|
477
|
+
* @param alias - The alias of the field.
|
|
478
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
479
|
+
*/
|
|
480
|
+
getSchemaByAliasField(alias) {
|
|
481
|
+
return this[alias];
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
class EntitySchemaBuilder {
|
|
485
|
+
constructor(entityClass) {
|
|
486
|
+
this.entityClass = entityClass;
|
|
487
|
+
}
|
|
488
|
+
properties = {};
|
|
489
|
+
/**
|
|
490
|
+
* Adds a field to the schema definition.
|
|
491
|
+
* @param field - The entity property to add.
|
|
492
|
+
* @param alias - (Optional) Custom alias for the field name.
|
|
493
|
+
* @returns The current instance of EntitySchemaBuilder for method chaining.
|
|
494
|
+
*/
|
|
495
|
+
addField(field, alias) {
|
|
496
|
+
const fieldName = alias || field.name;
|
|
497
|
+
const fieldNameType = fieldName;
|
|
498
|
+
this.properties[fieldNameType] = { ...field, name: fieldNameType };
|
|
499
|
+
return this;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Creates and initializes a new EntitySchema based on the added fields.
|
|
503
|
+
* @returns A new EntitySchema<T> instance.
|
|
504
|
+
*/
|
|
505
|
+
createSchema() {
|
|
506
|
+
const es = new mysql.EntitySchema({
|
|
507
|
+
class: this.entityClass,
|
|
508
|
+
// @ts-ignore
|
|
509
|
+
properties: this.properties
|
|
510
|
+
});
|
|
511
|
+
es.init();
|
|
512
|
+
return es;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
class DynamicEntitySchemaBuilder extends EntitySchemaBuilder {
|
|
516
|
+
constructor() {
|
|
517
|
+
super(DynamicEntity);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
466
520
|
class ForgeSQLSelectOperations {
|
|
467
521
|
options;
|
|
468
522
|
constructor(options) {
|
|
469
523
|
this.options = options;
|
|
470
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
527
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
528
|
+
* may not be known at compile time.
|
|
529
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
530
|
+
*/
|
|
531
|
+
createComplexQuerySchema() {
|
|
532
|
+
return new DynamicEntitySchemaBuilder();
|
|
533
|
+
}
|
|
471
534
|
async executeSchemaSQLOnlyOne(query, schema) {
|
|
472
535
|
const results = await this.executeSchemaSQL(query, schema);
|
|
473
536
|
if (!results || results.length === 0) {
|
|
@@ -489,7 +552,7 @@ class ForgeSQLSelectOperations {
|
|
|
489
552
|
if (!datas.length) return [];
|
|
490
553
|
return datas.map((r) => {
|
|
491
554
|
const rawModel = r;
|
|
492
|
-
const newModel =
|
|
555
|
+
const newModel = Object.create(schema.meta.prototype);
|
|
493
556
|
schema.meta.props.filter((p) => p.kind === "scalar").forEach((p) => {
|
|
494
557
|
const fieldName = p.name;
|
|
495
558
|
const fieldNames = p.fieldNames;
|
package/dist/ForgeSQLORM.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLORM.js","sources":["../src/utils/sqlUtils.ts","../src/core/ForgeSQLCrudOperations.ts","../src/core/ForgeSQLSelectOperations.ts","../src/core/ForgeSQLORM.ts"],"sourcesContent":["import { types } from \"@mikro-orm/core/types\";\nimport moment from \"moment\";\nimport { AnyString } from \"@mikro-orm/core/typings\";\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 { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport type { EntitySchema } from \"@mikro-orm/core/metadata/EntitySchema\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\nimport { ForgeSqlOrmOptions, SchemaSqlForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport {SqlParameters} from \"@forge/sql/out/sql-statement\";\n\nexport class ForgeSQLSelectOperations implements SchemaSqlForgeSql {\n private readonly options: ForgeSqlOrmOptions;\n\n constructor(options: ForgeSqlOrmOptions) {\n this.options = options;\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: Record<string, unknown> = {};\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\n switch (p.type) {\n case \"datetime\":\n newModel[fieldName] = parseDateTime(\n rawModel[rawFieldName] as string,\n \"YYYY-MM-DDTHH:mm:ss.SSS\",\n );\n break;\n case \"date\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"YYYY-MM-DD\");\n break;\n case \"time\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"HH:mm:ss.SSS\");\n break;\n default:\n newModel[fieldName] = rawModel[rawFieldName];\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 console.debug(\"Initializing ForgeSQLORM...\");\n\n try {\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 const newOptions: ForgeSqlOrmOptions = options ?? { logRawSqlQuery: false, disableOptimisticLocking: false };\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":["sql","MikroORM","NullCacheAdapter","MemoryCacheAdapter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ForgeSQLORM.js","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 console.debug(\"Initializing ForgeSQLORM...\");\n\n try {\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 const newOptions: ForgeSqlOrmOptions = options ?? { logRawSqlQuery: false, disableOptimisticLocking: false };\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":["sql","EntitySchema","MikroORM","NullCacheAdapter","MemoryCacheAdapter"],"mappings":"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"}
|
package/dist/ForgeSQLORM.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MikroORM, MemoryCacheAdapter, NullCacheAdapter } from "@mikro-orm/mysql";
|
|
1
|
+
import { EntitySchema, MikroORM, MemoryCacheAdapter, NullCacheAdapter } from "@mikro-orm/mysql";
|
|
2
2
|
export * from "@mikro-orm/mysql";
|
|
3
3
|
import { sql } from "@forge/sql";
|
|
4
4
|
import moment from "moment";
|
|
@@ -462,11 +462,74 @@ class ForgeSQLCrudOperations {
|
|
|
462
462
|
return true;
|
|
463
463
|
}
|
|
464
464
|
}
|
|
465
|
+
class DynamicEntity {
|
|
466
|
+
/**
|
|
467
|
+
* Retrieves a schema field by its original entity property.
|
|
468
|
+
* @param field - The entity property to search for.
|
|
469
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
470
|
+
*/
|
|
471
|
+
getSchemaBySchemaField(field) {
|
|
472
|
+
return this[field.name];
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Retrieves a schema field by its alias.
|
|
476
|
+
* @param alias - The alias of the field.
|
|
477
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
478
|
+
*/
|
|
479
|
+
getSchemaByAliasField(alias) {
|
|
480
|
+
return this[alias];
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
class EntitySchemaBuilder {
|
|
484
|
+
constructor(entityClass) {
|
|
485
|
+
this.entityClass = entityClass;
|
|
486
|
+
}
|
|
487
|
+
properties = {};
|
|
488
|
+
/**
|
|
489
|
+
* Adds a field to the schema definition.
|
|
490
|
+
* @param field - The entity property to add.
|
|
491
|
+
* @param alias - (Optional) Custom alias for the field name.
|
|
492
|
+
* @returns The current instance of EntitySchemaBuilder for method chaining.
|
|
493
|
+
*/
|
|
494
|
+
addField(field, alias) {
|
|
495
|
+
const fieldName = alias || field.name;
|
|
496
|
+
const fieldNameType = fieldName;
|
|
497
|
+
this.properties[fieldNameType] = { ...field, name: fieldNameType };
|
|
498
|
+
return this;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Creates and initializes a new EntitySchema based on the added fields.
|
|
502
|
+
* @returns A new EntitySchema<T> instance.
|
|
503
|
+
*/
|
|
504
|
+
createSchema() {
|
|
505
|
+
const es = new EntitySchema({
|
|
506
|
+
class: this.entityClass,
|
|
507
|
+
// @ts-ignore
|
|
508
|
+
properties: this.properties
|
|
509
|
+
});
|
|
510
|
+
es.init();
|
|
511
|
+
return es;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
class DynamicEntitySchemaBuilder extends EntitySchemaBuilder {
|
|
515
|
+
constructor() {
|
|
516
|
+
super(DynamicEntity);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
465
519
|
class ForgeSQLSelectOperations {
|
|
466
520
|
options;
|
|
467
521
|
constructor(options) {
|
|
468
522
|
this.options = options;
|
|
469
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
526
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
527
|
+
* may not be known at compile time.
|
|
528
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
529
|
+
*/
|
|
530
|
+
createComplexQuerySchema() {
|
|
531
|
+
return new DynamicEntitySchemaBuilder();
|
|
532
|
+
}
|
|
470
533
|
async executeSchemaSQLOnlyOne(query, schema) {
|
|
471
534
|
const results = await this.executeSchemaSQL(query, schema);
|
|
472
535
|
if (!results || results.length === 0) {
|
|
@@ -488,7 +551,7 @@ class ForgeSQLSelectOperations {
|
|
|
488
551
|
if (!datas.length) return [];
|
|
489
552
|
return datas.map((r) => {
|
|
490
553
|
const rawModel = r;
|
|
491
|
-
const newModel =
|
|
554
|
+
const newModel = Object.create(schema.meta.prototype);
|
|
492
555
|
schema.meta.props.filter((p) => p.kind === "scalar").forEach((p) => {
|
|
493
556
|
const fieldName = p.name;
|
|
494
557
|
const fieldNames = p.fieldNames;
|
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/ForgeSQLSelectOperations.ts","../src/core/ForgeSQLORM.ts"],"sourcesContent":["import { types } from \"@mikro-orm/core/types\";\nimport moment from \"moment\";\nimport { AnyString } from \"@mikro-orm/core/typings\";\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 { sql, UpdateQueryResponse } from \"@forge/sql\";\nimport type { EntitySchema } from \"@mikro-orm/core/metadata/EntitySchema\";\nimport { parseDateTime } from \"../utils/sqlUtils\";\nimport { ForgeSqlOrmOptions, SchemaSqlForgeSql } from \"./ForgeSQLQueryBuilder\";\nimport {SqlParameters} from \"@forge/sql/out/sql-statement\";\n\nexport class ForgeSQLSelectOperations implements SchemaSqlForgeSql {\n private readonly options: ForgeSqlOrmOptions;\n\n constructor(options: ForgeSqlOrmOptions) {\n this.options = options;\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: Record<string, unknown> = {};\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\n switch (p.type) {\n case \"datetime\":\n newModel[fieldName] = parseDateTime(\n rawModel[rawFieldName] as string,\n \"YYYY-MM-DDTHH:mm:ss.SSS\",\n );\n break;\n case \"date\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"YYYY-MM-DD\");\n break;\n case \"time\":\n newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, \"HH:mm:ss.SSS\");\n break;\n default:\n newModel[fieldName] = rawModel[rawFieldName];\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 console.debug(\"Initializing ForgeSQLORM...\");\n\n try {\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 const newOptions: ForgeSqlOrmOptions = options ?? { logRawSqlQuery: false, disableOptimisticLocking: false };\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/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 console.debug(\"Initializing ForgeSQLORM...\");\n\n try {\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 const newOptions: ForgeSqlOrmOptions = options ?? { logRawSqlQuery: false, disableOptimisticLocking: false };\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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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { EntitySchema, EntityProperty } from "..";
|
|
2
|
+
import { ComplexQuerySchemaBuilder } from "./ForgeSQLQueryBuilder";
|
|
3
|
+
export declare class DynamicEntity {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
/**
|
|
6
|
+
* Retrieves a schema field by its original entity property.
|
|
7
|
+
* @param field - The entity property to search for.
|
|
8
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
9
|
+
*/
|
|
10
|
+
getSchemaBySchemaField<TYPE>(field: EntityProperty): TYPE | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Retrieves a schema field by its alias.
|
|
13
|
+
* @param alias - The alias of the field.
|
|
14
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
15
|
+
*/
|
|
16
|
+
getSchemaByAliasField<TYPE>(alias: string): TYPE | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare class EntitySchemaBuilder<T> implements ComplexQuerySchemaBuilder<T> {
|
|
19
|
+
private entityClass;
|
|
20
|
+
private properties;
|
|
21
|
+
constructor(entityClass: new () => T);
|
|
22
|
+
/**
|
|
23
|
+
* Adds a field to the schema definition.
|
|
24
|
+
* @param field - The entity property to add.
|
|
25
|
+
* @param alias - (Optional) Custom alias for the field name.
|
|
26
|
+
* @returns The current instance of EntitySchemaBuilder for method chaining.
|
|
27
|
+
*/
|
|
28
|
+
addField<K>(field: Partial<EntityProperty<K>>, alias?: string): this;
|
|
29
|
+
/**
|
|
30
|
+
* Creates and initializes a new EntitySchema based on the added fields.
|
|
31
|
+
* @returns A new EntitySchema<T> instance.
|
|
32
|
+
*/
|
|
33
|
+
createSchema(): EntitySchema<T>;
|
|
34
|
+
}
|
|
35
|
+
export declare class DynamicEntitySchemaBuilder extends EntitySchemaBuilder<DynamicEntity> {
|
|
36
|
+
constructor();
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ComplexQuerySchemaBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComplexQuerySchemaBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ComplexQuerySchemaBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAa,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAC,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AAEjE,qBAAa,aAAa;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAEvB;;;;OAIG;IACH,sBAAsB,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS;IAIrE;;;;OAIG;IACH,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;CAG/D;AAED,qBAAa,mBAAmB,CAAC,CAAC,CAAE,YAAW,yBAAyB,CAAC,CAAC,CAAC;IAG3D,OAAO,CAAC,WAAW;IAF/B,OAAO,CAAC,UAAU,CAAyC;gBAEvC,WAAW,EAAE,UAAU,CAAC;IAE5C;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAOpE;;;OAGG;IACH,YAAY,IAAI,YAAY,CAAC,CAAC,CAAC;CASlC;AAED,qBAAa,0BAA2B,SAAQ,mBAAmB,CAAC,aAAa,CAAC;;CAIjF"}
|
|
@@ -3,8 +3,9 @@ import type { EntityName, LoggingOptions, QBFilterQuery } from "..";
|
|
|
3
3
|
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
4
4
|
import type { QueryBuilder } from "@mikro-orm/knex/query";
|
|
5
5
|
import type { Knex } from "knex";
|
|
6
|
-
import { EntityKey } from "@mikro-orm/core";
|
|
6
|
+
import { EntityKey, EntityProperty } from "@mikro-orm/core";
|
|
7
7
|
import { SqlParameters } from "@forge/sql/out/sql-statement";
|
|
8
|
+
import { DynamicEntity } from "./ComplexQuerySchemaBuilder";
|
|
8
9
|
/**
|
|
9
10
|
* Interface representing the main ForgeSQL operations.
|
|
10
11
|
*/
|
|
@@ -62,6 +63,13 @@ export interface SchemaSqlForgeSql {
|
|
|
62
63
|
* @returns The update response containing affected rows.
|
|
63
64
|
*/
|
|
64
65
|
executeRawUpdateSQL(query: string, params?: SqlParameters[]): Promise<UpdateQueryResponse>;
|
|
66
|
+
/**
|
|
67
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
68
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
69
|
+
* may not be known at compile time.
|
|
70
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
71
|
+
*/
|
|
72
|
+
createComplexQuerySchema(): ComplexQuerySchemaBuilder<DynamicEntity>;
|
|
65
73
|
}
|
|
66
74
|
/**
|
|
67
75
|
* Interface for CRUD (Create, Read, Update, Delete) operations.
|
|
@@ -139,4 +147,18 @@ export interface QueryBuilderForgeSql {
|
|
|
139
147
|
*/
|
|
140
148
|
getKnex(): Knex<any, any[]>;
|
|
141
149
|
}
|
|
150
|
+
export interface ComplexQuerySchemaBuilder<T> {
|
|
151
|
+
/**
|
|
152
|
+
* Adds a field from an entity schema to the builder.
|
|
153
|
+
* @param field - The entity property to be added.
|
|
154
|
+
* @param alias - (Optional) Alias for the field name.
|
|
155
|
+
* @returns The updated instance of the builder.
|
|
156
|
+
*/
|
|
157
|
+
addField<K>(field: Partial<EntityProperty<K>>, alias?: string): this;
|
|
158
|
+
/**
|
|
159
|
+
* Creates and returns a new entity schema based on the added fields.
|
|
160
|
+
* @returns A new EntitySchema<T> instance.
|
|
161
|
+
*/
|
|
162
|
+
createSchema(): EntitySchema<T>;
|
|
163
|
+
}
|
|
142
164
|
//# sourceMappingURL=ForgeSQLQueryBuilder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLQueryBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLQueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"ForgeSQLQueryBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLQueryBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { UpdateQueryResponse } from "@forge/sql";
|
|
2
2
|
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
3
|
-
import { ForgeSqlOrmOptions, SchemaSqlForgeSql } from "./ForgeSQLQueryBuilder";
|
|
3
|
+
import { ComplexQuerySchemaBuilder, ForgeSqlOrmOptions, SchemaSqlForgeSql } from "./ForgeSQLQueryBuilder";
|
|
4
4
|
import { SqlParameters } from "@forge/sql/out/sql-statement";
|
|
5
|
+
import { DynamicEntity } from "./ComplexQuerySchemaBuilder";
|
|
5
6
|
export declare class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
|
|
6
7
|
private readonly options;
|
|
7
8
|
constructor(options: ForgeSqlOrmOptions);
|
|
9
|
+
/**
|
|
10
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
11
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
12
|
+
* may not be known at compile time.
|
|
13
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
14
|
+
*/
|
|
15
|
+
createComplexQuerySchema(): ComplexQuerySchemaBuilder<DynamicEntity>;
|
|
8
16
|
executeSchemaSQLOnlyOne<T extends object>(query: string, schema: EntitySchema<T>): Promise<T | undefined>;
|
|
9
17
|
/**
|
|
10
18
|
* Executes a schema-based SQL query and maps the result to the entity schema.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLSelectOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLSelectOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ForgeSQLSelectOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLSelectOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAE1E,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AACzG,OAAO,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAC,aAAa,EAA6B,MAAM,6BAA6B,CAAC;AAGtF,qBAAa,wBAAyB,YAAW,iBAAiB;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,kBAAkB;IAIvC;;;;;OAKG;IACH,wBAAwB,IAAI,yBAAyB,CAAC,aAAa,CAAC;IAIhE,uBAAuB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAC,SAAS,CAAC;IAW7G;;;;;OAKG;IACG,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAmC9F;;;;OAIG;IACG,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ5E;;;;;OAKG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAQjG"}
|
package/dist/utils/sqlUtils.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/sqlUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sqlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/sqlUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAC,KAAK,EAAC,MAAM,IAAI,CAAC;AAMzB,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,OAAO;IACvC,IAAI,EAAE,MAAM,OAAO,KAAK,GAAG,SAAS,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC;CACV,EAAE,YAAW,OAAe,KAAG,CAc/B,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,IAM7D,CAAC"}
|
|
@@ -10,15 +10,10 @@ const args = process.argv.slice(2).join(" ");
|
|
|
10
10
|
// Resolve the path to cli.ts (your TypeScript entry file)
|
|
11
11
|
const cliPath = path.resolve(__dirname, "cli.js");
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
runCommand(`npx --yes tsm --no-warnings ${cliPath} ${args}`);
|
|
13
|
+
try {
|
|
14
|
+
execSync(`npx --yes tsm --no-warnings ${cliPath} ${args}`, { stdio: "inherit", shell: true });
|
|
15
|
+
process.exit(0);
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error("⚠️ Command execution failed:", e.message);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-sql-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Mikro-ORM integration for Forge-SQL in Atlassian Forge applications.",
|
|
5
5
|
"main": "dist/ForgeSQLORM.js",
|
|
6
6
|
"module": "dist/ForgeSQLORM.mjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@eslint/js": "^9.22.0",
|
|
32
32
|
"@mikro-orm/cli": "^6.4.9",
|
|
33
|
-
"inquirer": "^12.
|
|
33
|
+
"inquirer": "^12.5.0",
|
|
34
34
|
"@mikro-orm/entity-generator": "^6.4.9",
|
|
35
35
|
"@mikro-orm/reflection": "^6.4.9",
|
|
36
36
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"tsup": "^8.4.0",
|
|
53
53
|
"typescript": "^5.8.2",
|
|
54
54
|
"typescript-eslint": "^8.26.1",
|
|
55
|
-
"vite": "^6.2.
|
|
55
|
+
"vite": "^6.2.2",
|
|
56
56
|
"vite-plugin-static-copy": "^2.3.0",
|
|
57
57
|
"vitest": "^3.0.8"
|
|
58
58
|
},
|
|
@@ -84,13 +84,13 @@
|
|
|
84
84
|
"README.md"
|
|
85
85
|
],
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@forge/resolver": "^1.6.
|
|
87
|
+
"@forge/resolver": "^1.6.8",
|
|
88
88
|
"@mikro-orm/core": "6.4.9",
|
|
89
89
|
"@mikro-orm/mysql": "6.4.9",
|
|
90
90
|
"moment": "^2.30.1"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
|
-
"@forge/sql": "^2.4.
|
|
93
|
+
"@forge/sql": "^2.4.1"
|
|
94
94
|
},
|
|
95
95
|
"bin": {
|
|
96
96
|
"forge-sql-orm": "dist-cli/forgeSqlOrmCLI.js"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { EntitySchema, EntityProperty, EntityKey } from "..";
|
|
2
|
+
import {ComplexQuerySchemaBuilder} from "./ForgeSQLQueryBuilder";
|
|
3
|
+
|
|
4
|
+
export class DynamicEntity {
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Retrieves a schema field by its original entity property.
|
|
9
|
+
* @param field - The entity property to search for.
|
|
10
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
11
|
+
*/
|
|
12
|
+
getSchemaBySchemaField<TYPE>(field: EntityProperty): TYPE | undefined {
|
|
13
|
+
return this[field.name] as TYPE | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves a schema field by its alias.
|
|
18
|
+
* @param alias - The alias of the field.
|
|
19
|
+
* @returns The corresponding schema field or undefined if not found.
|
|
20
|
+
*/
|
|
21
|
+
getSchemaByAliasField<TYPE>(alias: string): TYPE | undefined {
|
|
22
|
+
return this[alias] as TYPE | undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class EntitySchemaBuilder<T> implements ComplexQuerySchemaBuilder<T> {
|
|
27
|
+
private properties: Record<string, EntityProperty<T>> = {};
|
|
28
|
+
|
|
29
|
+
constructor(private entityClass: new () => T) {}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Adds a field to the schema definition.
|
|
33
|
+
* @param field - The entity property to add.
|
|
34
|
+
* @param alias - (Optional) Custom alias for the field name.
|
|
35
|
+
* @returns The current instance of EntitySchemaBuilder for method chaining.
|
|
36
|
+
*/
|
|
37
|
+
addField<K>(field: Partial<EntityProperty<K>>, alias?: string): this {
|
|
38
|
+
const fieldName = alias || field.name;
|
|
39
|
+
const fieldNameType = fieldName as unknown as EntityKey<T>;
|
|
40
|
+
this.properties[fieldNameType] = { ...field, name: fieldNameType } as unknown as EntityProperty<T>;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Creates and initializes a new EntitySchema based on the added fields.
|
|
46
|
+
* @returns A new EntitySchema<T> instance.
|
|
47
|
+
*/
|
|
48
|
+
createSchema(): EntitySchema<T> {
|
|
49
|
+
const es = new EntitySchema<T>({
|
|
50
|
+
class: this.entityClass,
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
properties: this.properties,
|
|
53
|
+
});
|
|
54
|
+
es.init();
|
|
55
|
+
return es;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class DynamicEntitySchemaBuilder extends EntitySchemaBuilder<DynamicEntity> {
|
|
60
|
+
constructor() {
|
|
61
|
+
super(DynamicEntity);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -3,8 +3,9 @@ import type { EntityName, LoggingOptions, QBFilterQuery } from "..";
|
|
|
3
3
|
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
4
4
|
import type { QueryBuilder } from "@mikro-orm/knex/query";
|
|
5
5
|
import type { Knex } from "knex";
|
|
6
|
-
import {
|
|
6
|
+
import {EntityKey, EntityProperty} from "@mikro-orm/core";
|
|
7
7
|
import {SqlParameters} from "@forge/sql/out/sql-statement";
|
|
8
|
+
import {DynamicEntity} from "./ComplexQuerySchemaBuilder";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Interface representing the main ForgeSQL operations.
|
|
@@ -70,6 +71,13 @@ export interface SchemaSqlForgeSql {
|
|
|
70
71
|
*/
|
|
71
72
|
executeRawUpdateSQL(query: string, params?: SqlParameters[]): Promise<UpdateQueryResponse>;
|
|
72
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
76
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
77
|
+
* may not be known at compile time.
|
|
78
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
79
|
+
*/
|
|
80
|
+
createComplexQuerySchema():ComplexQuerySchemaBuilder<DynamicEntity>
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
/**
|
|
@@ -171,3 +179,19 @@ export interface QueryBuilderForgeSql {
|
|
|
171
179
|
*/
|
|
172
180
|
getKnex(): Knex<any, any[]>;
|
|
173
181
|
}
|
|
182
|
+
|
|
183
|
+
export interface ComplexQuerySchemaBuilder<T> {
|
|
184
|
+
/**
|
|
185
|
+
* Adds a field from an entity schema to the builder.
|
|
186
|
+
* @param field - The entity property to be added.
|
|
187
|
+
* @param alias - (Optional) Alias for the field name.
|
|
188
|
+
* @returns The updated instance of the builder.
|
|
189
|
+
*/
|
|
190
|
+
addField<K>(field: Partial<EntityProperty<K>>, alias?: string): this
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Creates and returns a new entity schema based on the added fields.
|
|
194
|
+
* @returns A new EntitySchema<T> instance.
|
|
195
|
+
*/
|
|
196
|
+
createSchema(): EntitySchema<T>;
|
|
197
|
+
}
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { sql, UpdateQueryResponse } from "@forge/sql";
|
|
2
2
|
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
3
3
|
import { parseDateTime } from "../utils/sqlUtils";
|
|
4
|
-
import { ForgeSqlOrmOptions, SchemaSqlForgeSql
|
|
4
|
+
import { ComplexQuerySchemaBuilder, ForgeSqlOrmOptions, SchemaSqlForgeSql} from "./ForgeSQLQueryBuilder";
|
|
5
5
|
import {SqlParameters} from "@forge/sql/out/sql-statement";
|
|
6
|
+
import {DynamicEntity, DynamicEntitySchemaBuilder} from "./ComplexQuerySchemaBuilder";
|
|
7
|
+
import {EntityKey} from "@mikro-orm/core";
|
|
6
8
|
|
|
7
9
|
export class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
|
|
8
|
-
|
|
10
|
+
private readonly options: ForgeSqlOrmOptions;
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
constructor(options: ForgeSqlOrmOptions) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a builder for constructing complex query schemas dynamically.
|
|
18
|
+
* This method is useful when working with dynamic entity structures where fields
|
|
19
|
+
* may not be known at compile time.
|
|
20
|
+
* @returns An instance of ComplexQuerySchemaBuilder configured for dynamic entities.
|
|
21
|
+
*/
|
|
22
|
+
createComplexQuerySchema(): ComplexQuerySchemaBuilder<DynamicEntity> {
|
|
23
|
+
return new DynamicEntitySchemaBuilder();
|
|
24
|
+
}
|
|
13
25
|
|
|
14
26
|
async executeSchemaSQLOnlyOne<T extends object>(query: string, schema: EntitySchema<T>): Promise<T|undefined> {
|
|
15
27
|
const results = await this.executeSchemaSQL(query, schema);
|
|
@@ -34,7 +46,7 @@ export class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
|
|
|
34
46
|
|
|
35
47
|
return datas.map((r) => {
|
|
36
48
|
const rawModel = r as Record<string, unknown>;
|
|
37
|
-
|
|
49
|
+
const newModel = Object.create(schema.meta.prototype) as T;
|
|
38
50
|
|
|
39
51
|
schema.meta.props
|
|
40
52
|
.filter((p) => p.kind === "scalar")
|
|
@@ -42,22 +54,21 @@ export class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
|
|
|
42
54
|
const fieldName = p.name;
|
|
43
55
|
const fieldNames = p.fieldNames;
|
|
44
56
|
const rawFieldName = fieldNames && Array.isArray(fieldNames) ? fieldNames[0] : p.name;
|
|
45
|
-
|
|
46
57
|
switch (p.type) {
|
|
47
58
|
case "datetime":
|
|
48
59
|
newModel[fieldName] = parseDateTime(
|
|
49
60
|
rawModel[rawFieldName] as string,
|
|
50
61
|
"YYYY-MM-DDTHH:mm:ss.SSS",
|
|
51
|
-
);
|
|
62
|
+
) as unknown as T[EntityKey<T>];
|
|
52
63
|
break;
|
|
53
64
|
case "date":
|
|
54
|
-
newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, "YYYY-MM-DD");
|
|
65
|
+
newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, "YYYY-MM-DD") as unknown as T[EntityKey<T>];
|
|
55
66
|
break;
|
|
56
67
|
case "time":
|
|
57
|
-
newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, "HH:mm:ss.SSS");
|
|
68
|
+
newModel[fieldName] = parseDateTime(rawModel[rawFieldName] as string, "HH:mm:ss.SSS") as unknown as T[EntityKey<T>];
|
|
58
69
|
break;
|
|
59
70
|
default:
|
|
60
|
-
newModel[fieldName] = rawModel[rawFieldName];
|
|
71
|
+
newModel[fieldName] = rawModel[rawFieldName] as unknown as T[EntityKey<T>];
|
|
61
72
|
}
|
|
62
73
|
});
|
|
63
74
|
return newModel as T;
|
package/src/utils/sqlUtils.ts
CHANGED