@twin.org/entity-storage-connector-mysql 0.0.3-next.13 → 0.0.3-next.14

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.
@@ -3,6 +3,7 @@
3
3
  import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
4
4
  import { BaseError, Coerce, ComponentFactory, GeneralError, Guards, HealthStatus, Is, ObjectHelper, SharedStore } from "@twin.org/core";
5
5
  import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, EntitySchemaPropertyType, LogicalOperator, SortDirection } from "@twin.org/entity";
6
+ import { EntityHelper } from "@twin.org/entity-storage-models";
6
7
  import { createPool } from "mysql2/promise";
7
8
  /**
8
9
  * Class for performing entity storage operations using MySql.
@@ -27,6 +28,11 @@ export class MySqlEntityStorageConnector {
27
28
  * @internal
28
29
  */
29
30
  static _PARTITION_KEY_VALUE = "root";
31
+ /**
32
+ * The name for the schema.
33
+ * @internal
34
+ */
35
+ _entitySchemaName;
30
36
  /**
31
37
  * The schema for the entity.
32
38
  * @internal
@@ -65,6 +71,7 @@ export class MySqlEntityStorageConnector {
65
71
  Guards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, "options.config.password", options.config.password);
66
72
  Guards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, "options.config.database", options.config.database);
67
73
  Guards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, "options.config.tableName", options.config.tableName);
74
+ this._entitySchemaName = options.entitySchema;
68
75
  this._entitySchema = EntitySchemaFactory.get(options.entitySchema);
69
76
  this._partitionContextIds = options.partitionContextIds;
70
77
  this._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
@@ -243,9 +250,10 @@ export class MySqlEntityStorageConnector {
243
250
  const query = `SELECT * FROM \`${this._config.database}\`.\`${this._config.tableName}\` WHERE ${whereClauses.join(" AND ")} LIMIT 1`;
244
251
  const [rows] = await pool.query(query, values);
245
252
  if (Is.array(rows) && rows.length === 1) {
246
- const item = ObjectHelper.removeEmptyProperties(rows[0], { removeNull: true });
247
- ObjectHelper.propertyDelete(item, MySqlEntityStorageConnector._PARTITION_KEY);
248
- return item;
253
+ const item = EntityHelper.unPrepareEntity(rows[0], [
254
+ MySqlEntityStorageConnector._PARTITION_KEY
255
+ ]);
256
+ return this.coerceEntityTypes(item);
249
257
  }
250
258
  }
251
259
  catch (err) {
@@ -265,8 +273,13 @@ export class MySqlEntityStorageConnector {
265
273
  Guards.object(MySqlEntityStorageConnector.CLASS_NAME, "entity", entity);
266
274
  const contextIds = await ContextIdStore.getContextIds();
267
275
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
268
- EntitySchemaHelper.validateEntity(entity, this._entitySchema);
269
- const id = entity[this._primaryKeyProperty.property];
276
+ const prepared = EntityHelper.prepareEntity(entity, this._entitySchema, [
277
+ {
278
+ property: MySqlEntityStorageConnector._PARTITION_KEY,
279
+ value: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE
280
+ }
281
+ ]);
282
+ const id = prepared[this._primaryKeyProperty.property];
270
283
  try {
271
284
  if (Is.arrayValue(conditions)) {
272
285
  const itemData = await this.get(id);
@@ -274,25 +287,25 @@ export class MySqlEntityStorageConnector {
274
287
  return;
275
288
  }
276
289
  }
277
- const finalEntity = ObjectHelper.clone(entity);
278
290
  const props = [...(this._entitySchema.properties ?? [])];
279
291
  props.unshift({
280
292
  property: MySqlEntityStorageConnector._PARTITION_KEY,
281
293
  type: EntitySchemaPropertyType.String
282
294
  });
283
- ObjectHelper.propertySet(finalEntity, MySqlEntityStorageConnector._PARTITION_KEY, partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);
284
295
  const keys = [];
285
296
  const values = [];
286
297
  for (const prop of props) {
287
- if (!(Is.empty(finalEntity[prop.property]) && (prop.optional ?? false))) {
288
- keys.push(prop.property);
289
- if (prop.type === EntitySchemaPropertyType.Object ||
290
- prop.type === EntitySchemaPropertyType.Array) {
291
- values.push(JSON.stringify(finalEntity[prop.property]));
292
- }
293
- else {
294
- values.push(finalEntity[prop.property]);
295
- }
298
+ keys.push(prop.property);
299
+ const val = prepared[prop.property];
300
+ if (val === null || val === undefined) {
301
+ values.push(null);
302
+ }
303
+ else if (prop.type === EntitySchemaPropertyType.Object ||
304
+ prop.type === EntitySchemaPropertyType.Array) {
305
+ values.push(JSON.stringify(val));
306
+ }
307
+ else {
308
+ values.push(val);
296
309
  }
297
310
  }
298
311
  let sql = `INSERT INTO \`${this._config.database}\`.\`${this._config.tableName}\``;
@@ -317,9 +330,12 @@ export class MySqlEntityStorageConnector {
317
330
  Guards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, "entities", entities);
318
331
  const contextIds = await ContextIdStore.getContextIds();
319
332
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
320
- for (const entity of entities) {
321
- EntitySchemaHelper.validateEntity(entity, this._entitySchema);
322
- }
333
+ const preparedEntities = entities.map(entity => EntityHelper.prepareEntity(entity, this._entitySchema, [
334
+ {
335
+ property: MySqlEntityStorageConnector._PARTITION_KEY,
336
+ value: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE
337
+ }
338
+ ]));
323
339
  try {
324
340
  const props = [...(this._entitySchema.properties ?? [])];
325
341
  props.unshift({
@@ -328,11 +344,9 @@ export class MySqlEntityStorageConnector {
328
344
  });
329
345
  const keys = props.map(p => p.property);
330
346
  const allValues = [];
331
- for (const entity of entities) {
332
- const finalEntity = ObjectHelper.clone(entity);
333
- ObjectHelper.propertySet(finalEntity, MySqlEntityStorageConnector._PARTITION_KEY, partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);
347
+ for (const prepared of preparedEntities) {
334
348
  for (const prop of props) {
335
- const val = finalEntity[prop.property];
349
+ const val = prepared[prop.property];
336
350
  if (prop.type === EntitySchemaPropertyType.Object ||
337
351
  prop.type === EntitySchemaPropertyType.Array) {
338
352
  allValues.push(Is.empty(val) ? null : JSON.stringify(val));
@@ -491,37 +505,27 @@ export class MySqlEntityStorageConnector {
491
505
  }
492
506
  orderByClause = `ORDER BY ${orderClauses.join(", ")}`;
493
507
  }
494
- const whereClauses = [];
495
- const values = [];
496
- const finalConditions = {
497
- conditions: [],
498
- logicalOperator: LogicalOperator.And
499
- };
500
- finalConditions.conditions.push({
501
- property: MySqlEntityStorageConnector._PARTITION_KEY,
502
- comparison: ComparisonOperator.Equals,
503
- value: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE
504
- });
505
- if (!Is.empty(conditions)) {
506
- finalConditions.conditions.push(conditions);
507
- }
508
- this.buildQueryParameters("", finalConditions, whereClauses, values);
508
+ const { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);
509
509
  const startIndex = Coerce.number(cursor) ?? 0;
510
510
  sql = `SELECT ${properties ? properties.map(p => `\`${String(p)}\``).join(", ") : "*"} FROM \`${this._config.database}\`.\`${this._config.tableName}\``;
511
- sql += ` WHERE ${whereClauses.join(" AND ")} ${orderByClause}`;
512
- sql += ` LIMIT ${returnSize} OFFSET ${startIndex}`;
511
+ if (whereClauses.length > 0) {
512
+ sql += ` WHERE ${whereClauses.join(" AND ")}`;
513
+ }
514
+ sql += ` ${orderByClause} LIMIT ${returnSize + 1} OFFSET ${startIndex}`;
513
515
  const pool = this.getPool();
514
516
  const [rows] = (await pool.query(sql, values)) ?? [];
515
- const entities = rows;
517
+ const hasMore = Is.array(rows) && rows.length > returnSize;
518
+ const resultRows = hasMore ? rows.slice(0, returnSize) : rows;
519
+ const entities = resultRows;
516
520
  for (let i = 0; i < entities.length; i++) {
517
- entities[i] = ObjectHelper.removeEmptyProperties(entities[i], { removeNull: true });
518
- ObjectHelper.propertyDelete(entities[i], MySqlEntityStorageConnector._PARTITION_KEY);
521
+ entities[i] = EntityHelper.unPrepareEntity(entities[i], [
522
+ MySqlEntityStorageConnector._PARTITION_KEY
523
+ ]);
524
+ entities[i] = this.coerceEntityTypes(entities[i]);
519
525
  }
520
526
  return {
521
527
  entities,
522
- cursor: Is.array(rows) && rows.length === returnSize
523
- ? Coerce.string(startIndex + returnSize)
524
- : undefined
528
+ cursor: hasMore ? Coerce.string(startIndex + returnSize) : undefined
525
529
  };
526
530
  }
527
531
  catch (err) {
@@ -530,19 +534,97 @@ export class MySqlEntityStorageConnector {
530
534
  }
531
535
  /**
532
536
  * Count all the entities which match the conditions.
537
+ * @param conditions The optional conditions to match for the entities.
533
538
  * @returns The total count of entities in the storage.
534
539
  */
535
- async count() {
540
+ async count(conditions) {
541
+ let sql;
536
542
  try {
543
+ const pool = this.getPool();
537
544
  const contextIds = await ContextIdStore.getContextIds();
538
545
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
539
- const pool = this.getPool();
540
- const [rows] = await pool.query(`SELECT COUNT(*) AS count FROM \`${this._config.database}\`.\`${this._config.tableName}\` WHERE \`${MySqlEntityStorageConnector._PARTITION_KEY}\` = ?`, [partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]);
546
+ const { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);
547
+ sql = `SELECT COUNT(*) AS count FROM \`${this._config.database}\`.\`${this._config.tableName}\``;
548
+ if (whereClauses.length > 0) {
549
+ sql += ` WHERE ${whereClauses.join(" AND ")}`;
550
+ }
551
+ const [rows] = await pool.query(sql, values);
541
552
  return Number(rows[0].count);
542
553
  }
543
554
  catch (err) {
544
- throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "countFailed", undefined, err);
555
+ throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "countFailed", { sql }, err);
556
+ }
557
+ }
558
+ /**
559
+ * Get all unique partition context ids present in the table.
560
+ * @returns An array of context id objects, one per unique partition.
561
+ */
562
+ async getPartitionContextIds() {
563
+ if (!Is.arrayValue(this._partitionContextIds)) {
564
+ return [];
565
+ }
566
+ try {
567
+ const pool = this.getPool();
568
+ const [rows] = await pool.query(`SELECT DISTINCT \`${MySqlEntityStorageConnector._PARTITION_KEY}\` FROM \`${this._config.database}\`.\`${this._config.tableName}\``);
569
+ return rows
570
+ .map(row => row[MySqlEntityStorageConnector._PARTITION_KEY])
571
+ .filter((id) => Is.stringValue(id))
572
+ .map(id => ContextIdHelper.shortSplit(this._partitionContextIds ?? [], id));
573
+ }
574
+ catch (err) {
575
+ throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "getPartitionContextIdsFailed", undefined, err);
576
+ }
577
+ }
578
+ /**
579
+ * Create the target connector for performing the migration using a temporary table.
580
+ * @param newEntitySchema The name of the new entity schema to create the connector for.
581
+ * @returns Connector for performing the migration.
582
+ */
583
+ async createTargetConnector(newEntitySchema) {
584
+ const migrationTableName = `${this._config.tableName}Migration${Date.now()}`;
585
+ return new MySqlEntityStorageConnector({
586
+ entitySchema: newEntitySchema,
587
+ config: {
588
+ ...this._config,
589
+ tableName: migrationTableName
590
+ },
591
+ partitionContextIds: this._partitionContextIds
592
+ });
593
+ }
594
+ /**
595
+ * Finalize the migration by dropping the source table and renaming the migration table to the original name.
596
+ * @param targetConnector The connector holding the migrated data in a temporary table.
597
+ * @param options The options to control how the migration is finalized.
598
+ * @param loggingComponentType The logging component type to use during finalization.
599
+ * @returns The final connector using the original table name with the new schema.
600
+ */
601
+ async finalizeMigration(targetConnector, options, loggingComponentType) {
602
+ // Teardown the existing table with the original name to free up the name for the new table
603
+ await this.teardown(loggingComponentType);
604
+ // RENAME TABLE is an atomic metadata-only operation in MySQL — no data copying needed.
605
+ const pool = this.getPool();
606
+ await pool.query(`RENAME TABLE \`${targetConnector._config.database}\`.\`${targetConnector._config.tableName}\` TO \`${this._config.database}\`.\`${this._config.tableName}\``);
607
+ const finalConnector = new MySqlEntityStorageConnector({
608
+ entitySchema: targetConnector._entitySchemaName,
609
+ config: this._config,
610
+ partitionContextIds: this._partitionContextIds
611
+ });
612
+ if (await finalConnector.bootstrap(loggingComponentType)) {
613
+ await targetConnector.stop();
614
+ return finalConnector;
545
615
  }
616
+ throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "finalizeMigrationFailedBootstrap", undefined);
617
+ }
618
+ /**
619
+ * Cleanup a failed or aborted migration by dropping the temporary migration table.
620
+ * @param targetConnector The target connector to cleanup.
621
+ * @param options The options to control how the migration is cleaned up.
622
+ * @param loggingComponentType The optional component type to use for logging.
623
+ * @returns A promise that resolves when the cleanup is complete.
624
+ */
625
+ async cleanupMigration(targetConnector, options, loggingComponentType) {
626
+ // If something failed the only thing to cleanup is the migration table
627
+ await targetConnector?.teardown?.(loggingComponentType);
546
628
  }
547
629
  /**
548
630
  * Check if the database exists.
@@ -558,6 +640,45 @@ export class MySqlEntityStorageConnector {
558
640
  return false;
559
641
  }
560
642
  }
643
+ /**
644
+ * Close the connection pool and release all connections.
645
+ * Should be called when the connector is no longer needed.
646
+ * @returns Nothing.
647
+ */
648
+ async close() {
649
+ if (this._pool) {
650
+ const poolConfig = this.createPoolConfig();
651
+ const poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;
652
+ let sharedPools = SharedStore.get("mySqlPools");
653
+ sharedPools ??= {};
654
+ if (sharedPools[poolId]) {
655
+ // Decrease the use counter and close the pool if no longer used
656
+ sharedPools[poolId].useCounter--;
657
+ if (sharedPools[poolId].useCounter <= 0) {
658
+ await this._pool.end();
659
+ delete sharedPools[poolId];
660
+ }
661
+ SharedStore.set("mySqlPools", sharedPools);
662
+ }
663
+ this._pool = undefined;
664
+ }
665
+ }
666
+ /**
667
+ * Coerce MySQL raw row values back to proper TypeScript types based on the entity schema.
668
+ * MySQL returns TINYINT(1) as 0/1 rather than false/true; this method converts those.
669
+ * @param entity The raw entity row from MySQL.
670
+ * @returns The entity with schema-correct types.
671
+ * @internal
672
+ */
673
+ coerceEntityTypes(entity) {
674
+ for (const prop of this._entitySchema.properties ?? []) {
675
+ const value = entity[prop.property];
676
+ if (prop.type === EntitySchemaPropertyType.Boolean && !Is.empty(value)) {
677
+ ObjectHelper.propertySet(entity, prop.property, Boolean(value));
678
+ }
679
+ }
680
+ return entity;
681
+ }
561
682
  /**
562
683
  * Wait for a database to exist.
563
684
  * @returns Nothing.
@@ -664,6 +785,31 @@ export class MySqlEntityStorageConnector {
664
785
  queueLimit: poolConfig.queueLimit ?? 0
665
786
  };
666
787
  }
788
+ /**
789
+ * Build where clause arrays for a query, combining partition key and optional conditions.
790
+ * @param conditions The optional entity conditions to include.
791
+ * @param partitionKey The partition key value.
792
+ * @returns The where clauses and bound values.
793
+ * @internal
794
+ */
795
+ buildWhereClause(conditions, partitionKey) {
796
+ const whereClauses = [];
797
+ const values = [];
798
+ const finalConditions = {
799
+ conditions: [],
800
+ logicalOperator: LogicalOperator.And
801
+ };
802
+ finalConditions.conditions.push({
803
+ property: MySqlEntityStorageConnector._PARTITION_KEY,
804
+ comparison: ComparisonOperator.Equals,
805
+ value: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE
806
+ });
807
+ if (!Is.empty(conditions)) {
808
+ finalConditions.conditions.push(conditions);
809
+ }
810
+ this.buildQueryParameters("", finalConditions, whereClauses, values);
811
+ return { whereClauses, values };
812
+ }
667
813
  /**
668
814
  * Create an SQL condition clause.
669
815
  * @param objectPath The path for the nested object.
@@ -796,6 +942,14 @@ export class MySqlEntityStorageConnector {
796
942
  }
797
943
  return `JSON_CONTAINS(\`${prop}\`, ?)`;
798
944
  }
945
+ case ComparisonOperator.NotIncludes: {
946
+ if (type === EntitySchemaPropertyType.String) {
947
+ values.pop();
948
+ values.push(`%${String(comparator.value).toLowerCase()}%`);
949
+ return `LOWER(\`${prop}\`) NOT LIKE ?`;
950
+ }
951
+ return `NOT JSON_CONTAINS(\`${prop}\`, ?)`;
952
+ }
799
953
  default:
800
954
  throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
801
955
  comparison: comparator.comparison
@@ -820,7 +974,7 @@ export class MySqlEntityStorageConnector {
820
974
  return Number(value);
821
975
  }
822
976
  else if (type === "boolean") {
823
- return Boolean(value);
977
+ return value ? 1 : 0;
824
978
  }
825
979
  return value;
826
980
  }
@@ -852,10 +1006,12 @@ export class MySqlEntityStorageConnector {
852
1006
  }
853
1007
  /**
854
1008
  * Map entity schema properties to SQL properties.
1009
+ * @param schema The schema to use, defaults to the connector's own schema.
855
1010
  * @returns The SQL properties as a string.
856
1011
  * @throws GeneralError if the entity properties do not exist.
857
1012
  */
858
- mapMySqlProperties() {
1013
+ mapMySqlProperties(schema) {
1014
+ const entitySchema = schema ?? this._entitySchema;
859
1015
  const sqlTypeMap = {
860
1016
  [EntitySchemaPropertyType.String]: "LONGTEXT",
861
1017
  [EntitySchemaPropertyType.Number]: "FLOAT",
@@ -864,11 +1020,11 @@ export class MySqlEntityStorageConnector {
864
1020
  [EntitySchemaPropertyType.Array]: "JSON",
865
1021
  [EntitySchemaPropertyType.Boolean]: "TINYINT(1)"
866
1022
  };
867
- if (!this._entitySchema.properties) {
1023
+ if (!entitySchema.properties) {
868
1024
  throw new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, "entitySchemaPropertiesUndefined");
869
1025
  }
870
1026
  const primaryKeys = [];
871
- const props = [...this._entitySchema.properties];
1027
+ const props = [...entitySchema.properties];
872
1028
  props.unshift({
873
1029
  property: MySqlEntityStorageConnector._PARTITION_KEY,
874
1030
  type: EntitySchemaPropertyType.String,
@@ -879,7 +1035,7 @@ export class MySqlEntityStorageConnector {
879
1035
  let sqlType = sqlTypeMap[prop.type] || "TEXT";
880
1036
  if (prop.format) {
881
1037
  switch (prop.type) {
882
- case "string":
1038
+ case EntitySchemaPropertyType.String:
883
1039
  sqlType = "LONGTEXT";
884
1040
  switch (prop.format) {
885
1041
  case "uuid":
@@ -891,7 +1047,7 @@ export class MySqlEntityStorageConnector {
891
1047
  break;
892
1048
  }
893
1049
  break;
894
- case "number":
1050
+ case EntitySchemaPropertyType.Number:
895
1051
  sqlType = "FLOAT";
896
1052
  switch (prop.format) {
897
1053
  case "float":
@@ -902,7 +1058,7 @@ export class MySqlEntityStorageConnector {
902
1058
  break;
903
1059
  }
904
1060
  break;
905
- case "integer":
1061
+ case EntitySchemaPropertyType.Integer:
906
1062
  sqlType = "INT";
907
1063
  switch (prop.format) {
908
1064
  case "int8":
@@ -1 +1 @@
1
- {"version":3,"file":"mysqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/mysqlEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\tIs,\n\tObjectHelper,\n\tSharedStore,\n\ttype IHealth\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport type { IEntityStorageConnector } from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type Pool, type PoolOptions, createPool } from \"mysql2/promise\";\nimport type { IMySqlEntityStorageConnectorConfig } from \"./models/IMySqlEntityStorageConnectorConfig.js\";\nimport type { IMySqlEntityStorageConnectorConstructorOptions } from \"./models/IMySqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using MySql.\n */\nexport class MySqlEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MySqlEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IMySqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The connection pool for MySql.\n\t * @internal\n\t */\n\tprivate _pool?: Pool;\n\n\t/**\n\t * The primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * Create a new instance of MySqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMySqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MySqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMySqlEntityStorageConnectorConfig>(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.host),\n\t\t\toptions.config.host\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.user),\n\t\t\toptions.config.user\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.password),\n\t\t\toptions.config.password\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.database),\n\t\t\toptions.config.database\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MySqlEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the health of the component.\n\t * @returns The health of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tawait this.getPool().query(\n\t\t\t\t`SELECT 1 FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` LIMIT 0`\n\t\t\t);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Initialize the MySql environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (!databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait pool.query(`CREATE DATABASE IF NOT EXISTS \\`${this._config.database}\\``);\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait pool.query(\n\t\t\t\t\t`CREATE TABLE IF NOT EXISTS \\`${this._config.database}\\`.\\`${this._config.tableName}\\` (${this.mapMySqlProperties()})`\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForTableExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tlet sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\"\n\t\t\t);\n\t\t\tsharedPools ??= {};\n\t\t\tif (sharedPools[poolId]) {\n\t\t\t\t// Decrease the use counter and close the pool if no longer used\n\t\t\t\tsharedPools[poolId].useCounter--;\n\t\t\t\tif (sharedPools[poolId].useCounter <= 0) {\n\t\t\t\t\tawait this._pool.end();\n\t\t\t\t\tdelete sharedPools[poolId];\n\t\t\t\t}\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\n\t\t\tthis._pool = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Get an entity from MySql.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\\`${String(secondaryIndex)}\\` = ?`);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\\`${String(this._primaryKeyProperty.property)}\\` = ?`);\n\t\t\t}\n\t\t\tvalues.push(id);\n\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\twhereClauses.push(`\\`${String(condition.property)}\\` = ?`);\n\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query = `SELECT * FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\t\t\tconst [rows] = await pool.query(query, values);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tconst item = ObjectHelper.removeEmptyProperties(rows[0] as T, { removeNull: true });\n\t\t\t\tObjectHelper.propertyDelete(item, MySqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t\treturn item;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MySqlEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntitySchemaHelper.validateEntity(entity, this._entitySchema);\n\n\t\tconst id = entity[this._primaryKeyProperty.property] as unknown as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst itemData = await this.get(id);\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst finalEntity = ObjectHelper.clone(entity);\n\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tObjectHelper.propertySet(\n\t\t\t\tfinalEntity,\n\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values = [];\n\n\t\t\tfor (const prop of props) {\n\t\t\t\tif (!(Is.empty(finalEntity[prop.property]) && (prop.optional ?? false))) {\n\t\t\t\t\tkeys.push(prop.property as string);\n\t\t\t\t\tif (\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t\t) {\n\t\t\t\t\t\tvalues.push(JSON.stringify(finalEntity[prop.property]));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalues.push(finalEntity[prop.property]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map(() => \"?\").join(\", \")})`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, values);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tfor (const entity of entities) {\n\t\t\tEntitySchemaHelper.validateEntity(entity, this._entitySchema);\n\t\t}\n\n\t\ttry {\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys = props.map(p => p.property as string);\n\t\t\tconst allValues: unknown[] = [];\n\n\t\t\tfor (const entity of entities) {\n\t\t\t\tconst finalEntity = ObjectHelper.clone(entity);\n\t\t\t\tObjectHelper.propertySet(\n\t\t\t\t\tfinalEntity,\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t);\n\t\t\t\tfor (const prop of props) {\n\t\t\t\t\tconst val = finalEntity[prop.property];\n\t\t\t\t\tif (\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t\t) {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : JSON.stringify(val));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rowPlaceholder = `(${keys.map(() => \"?\").join(\", \")})`;\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES ${entities.map(() => rowPlaceholder).join(\", \")}`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, allValues);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(\n\t\t\t\t`DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`,\n\t\t\t\t[partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst itemData = await this.get(id, undefined, conditions);\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tconst values: unknown[] = [];\n\t\t\t\tconst whereClauses: string[] = [];\n\n\t\t\t\twhereClauses.push(`\\`${this._primaryKeyProperty.property as string}\\` = ?`);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\t\twhereClauses.push(\n\t\t\t\t\t\t...conditions.map(condition => {\n\t\t\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t\t\t\treturn `\\`${String(condition.property)}\\` = ?`;\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst query = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait pool.query(query, values);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the entity storage by dropping the table.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDropping\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tif (await this.tableExists()) {\n\t\t\t\tconst pool = this.getPool();\n\t\t\t\tawait pool.query(`DROP TABLE \\`${this._config.database}\\`.\\`${this._config.tableName}\\`;`);\n\t\t\t\tawait this.waitForTableNotExists();\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDropped\",\n\t\t\t\tdata: { tableName: this._config.tableName }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by their primary key IDs.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst sql = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ? AND \\`${String(this._primaryKeyProperty.property)}\\` IN (?)`;\n\t\t\tawait pool.query(sql, [\n\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\tids\n\t\t\t]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tlet sql = \"\";\n\t\ttry {\n\t\t\tconst returnSize = limit ?? MySqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.array(sortProperties)) {\n\t\t\t\tconst orderClauses: string[] = [];\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"ASC\" : \"DESC\";\n\t\t\t\t\torderClauses.push(`\\`${String(sortProperty.property)}\\` ${direction}`);\n\t\t\t\t}\n\t\t\t\torderByClause = `ORDER BY ${orderClauses.join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\t\tconditions: [],\n\t\t\t\tlogicalOperator: LogicalOperator.And\n\t\t\t};\n\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t});\n\n\t\t\tif (!Is.empty(conditions)) {\n\t\t\t\tfinalConditions.conditions.push(conditions);\n\t\t\t}\n\n\t\t\tthis.buildQueryParameters(\"\", finalConditions, whereClauses, values);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `\\`${String(p)}\\``).join(\", \") : \"*\"} FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")} ${orderByClause}`;\n\t\t\tsql += ` LIMIT ${returnSize} OFFSET ${startIndex}`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = (await pool.query(sql, values)) ?? [];\n\n\t\t\tconst entities = rows as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tentities[i] = ObjectHelper.removeEmptyProperties(entities[i], { removeNull: true });\n\t\t\t\tObjectHelper.propertyDelete(entities[i], MySqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tentities,\n\t\t\t\tcursor:\n\t\t\t\t\tIs.array(rows) && rows.length === returnSize\n\t\t\t\t\t\t? Coerce.string(startIndex + returnSize)\n\t\t\t\t\t\t: undefined\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"queryFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(): Promise<number> {\n\t\ttry {\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\n\t\t\t\t`SELECT COUNT(*) AS count FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`,\n\t\t\t\t[partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]\n\t\t\t);\n\t\t\treturn Number((rows as { count: number }[])[0].count);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"countFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t */\n\tpublic async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW DATABASES LIKE ?;\", [this._config.database]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @returns True if the table exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async tableExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW TABLES FROM ?? LIKE ?\", [\n\t\t\t\tthis._config.database,\n\t\t\t\tthis._config.tableName\n\t\t\t]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to not exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableNotExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the connection pool.\n\t * @returns The MySql connection pool.\n\t * @internal\n\t */\n\tprivate getPool(): Pool {\n\t\tif (!this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tlet sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\"\n\t\t\t);\n\t\t\tsharedPools ??= {};\n\n\t\t\t// If there is no pool for the id, create it\n\t\t\tif (!sharedPools[poolId]) {\n\t\t\t\tsharedPools[poolId] = {\n\t\t\t\t\tpool: createPool(poolConfig),\n\t\t\t\t\tuseCounter: 0\n\t\t\t\t};\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\t\t\t// Increase the use counter and return the pool\n\t\t\tsharedPools[poolId].useCounter++;\n\t\t\tthis._pool = sharedPools[poolId].pool;\n\t\t}\n\t\treturn this._pool;\n\t}\n\n\t/**\n\t * Create the connection pool configuration.\n\t * @returns The MySql pool configuration.\n\t * @internal\n\t */\n\tprivate createPoolConfig(): PoolOptions {\n\t\tconst poolConfig = this._config.pool ?? {};\n\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 3306,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password,\n\n\t\t\tconnectionLimit: poolConfig.connectionLimit ?? 10,\n\t\t\tmaxIdle: poolConfig.maxIdle ?? 10,\n\t\t\tidleTimeout: poolConfig.idleTimeout ?? 60000,\n\t\t\tenableKeepAlive: poolConfig.enableKeepAlive ?? true,\n\t\t\tkeepAliveInitialDelay: 0,\n\t\t\twaitForConnections: poolConfig.waitForConnections ?? true,\n\t\t\tqueueLimit: poolConfig.queueLimit ?? 0\n\t\t};\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param whereClauses The where clauses to use in the query.\n\t * @param values The values to use in the query.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\twhereClauses: string[],\n\t\tvalues: unknown[]\n\t): void {\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c => {\n\t\t\t\tconst subWhereClauses: string[] = [];\n\t\t\t\tconst subValues: unknown[] = [];\n\t\t\t\tthis.buildQueryParameters(objectPath, c, subWhereClauses, subValues);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\treturn subWhereClauses.join(\" AND \");\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions.filter(j => j.length > 0).join(` ${logicalOperator} `);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\twhereClauses.push(`(${queryClause})`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\t\tconst comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, values);\n\t\twhereClauses.push(comparison);\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in MySQL.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param values The values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tvalues: unknown[]\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\n\t\tprop += comparator.property;\n\n\t\tif (comparator.comparison === ComparisonOperator.In) {\n\t\t\tconst inValues = Is.array(comparator.value) ? comparator.value : [comparator.value];\n\t\t\tvalues.push(...inValues.map(val => this.propertyToDbValue(val, type)));\n\t\t\tconst placeholders = inValues.map(() => \"?\").join(\", \");\n\t\t\treturn `\\`${prop}\\` IN (${placeholders})`;\n\t\t}\n\n\t\t// null/undefined must use IS NULL / IS NOT NULL — never a parameterised placeholder.\n\t\t// Passing undefined through propertyToDbValue() coerces it to NaN for number fields\n\t\t// (Number(undefined) === NaN), and null coerces to 0 (Number(null) === 0), both of\n\t\t// which produce semantically wrong or invalid SQL.\n\t\tif (comparator.value === null || comparator.value === undefined) {\n\t\t\tif (\n\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t) {\n\t\t\t\tconst nullCheck =\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ? \"IS NULL\" : \"IS NOT NULL\";\n\n\t\t\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\t\t\t\t\treturn `${jsonExpr} ${nullCheck}`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` ${nullCheck}`;\n\t\t\t}\n\t\t}\n\n\t\tconst dbValue = this.propertyToDbValue(comparator.value, type);\n\t\tvalues.push(dbValue);\n\n\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\n\t\t\tswitch (comparator.comparison) {\n\t\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(${jsonExpr}) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\t\treturn `${jsonExpr} <> ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\t\treturn `${jsonExpr} > ?`;\n\t\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\t\treturn `${jsonExpr} < ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} >= ?`;\n\t\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} <= ?`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${jsonExpr} = ?`;\n\t\t\t}\n\t\t}\n\n\t\tswitch (comparator.comparison) {\n\t\t\tcase ComparisonOperator.Equals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` = ?`;\n\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` <> ?`;\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn `\\`${prop}\\` > ?`;\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn `\\`${prop}\\` < ?`;\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` >= ?`;\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` <= ?`;\n\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) LIKE ?`;\n\t\t\t\t}\n\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\t\t\tcomparison: comparator.comparison\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn String(value);\n\t\t} else if (type === \"number\") {\n\t\t\treturn Number(value);\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn Boolean(value);\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in MySQL.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Map entity schema properties to SQL properties.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t */\n\tprivate mapMySqlProperties(): string {\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"LONGTEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"FLOAT\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INT\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"TINYINT(1)\"\n\t\t};\n\n\t\tif (!this._entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"entitySchemaPropertiesUndefined\"\n\t\t\t);\n\t\t}\n\n\t\tconst primaryKeys: string[] = [];\n\n\t\tconst props: IEntitySchemaProperty<T>[] = [...this._entitySchema.properties];\n\n\t\tprops.unshift({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tlet sqlType = sqlTypeMap[prop.type] || \"TEXT\";\n\t\t\t\tif (prop.format) {\n\t\t\t\t\tswitch (prop.type) {\n\t\t\t\t\t\tcase \"string\":\n\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"uuid\":\n\t\t\t\t\t\t\t\t\tsqlType = \"CHAR(36)\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"date\":\n\t\t\t\t\t\t\t\tcase \"date-time\":\n\t\t\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"number\":\n\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"float\":\n\t\t\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"double\":\n\t\t\t\t\t\t\t\t\tsqlType = \"DOUBLE\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"integer\":\n\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"int8\":\n\t\t\t\t\t\t\t\tcase \"uint8\":\n\t\t\t\t\t\t\t\t\tsqlType = \"TINYINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int16\":\n\t\t\t\t\t\t\t\tcase \"uint16\":\n\t\t\t\t\t\t\t\t\tsqlType = \"SMALLINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int32\":\n\t\t\t\t\t\t\t\tcase \"uint32\":\n\t\t\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int64\":\n\t\t\t\t\t\t\t\tcase \"uint64\":\n\t\t\t\t\t\t\t\t\tsqlType = \"BIGINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst columnName = String(prop.property);\n\t\t\t\tconst nullable = prop.optional ? \" NULL\" : \" NOT NULL\";\n\n\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\tif (sqlType === \"LONGTEXT\" || sqlType === \"TEXT\") {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\`(255)`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\``);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn `\\`${columnName}\\` ${sqlType}${nullable}`;\n\t\t\t})\n\t\t\t.join(\", \");\n\n\t\tconst primaryKeyDefinition =\n\t\t\tprimaryKeys.length > 0 ? `, PRIMARY KEY (${primaryKeys.join(\", \")})` : \"\";\n\t\treturn columnDefinitions + primaryKeyDefinition;\n\t}\n}\n"]}
1
+ {"version":3,"file":"mysqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/mysqlEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\tObjectHelper,\n\tSharedStore\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type Pool, type PoolOptions, createPool } from \"mysql2/promise\";\nimport type { IMySqlEntityStorageConnectorConfig } from \"./models/IMySqlEntityStorageConnectorConfig.js\";\nimport type { IMySqlEntityStorageConnectorConstructorOptions } from \"./models/IMySqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using MySql.\n */\nexport class MySqlEntityStorageConnector<\n\tT = unknown\n> implements IEntityStorageMigrationConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MySqlEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The name for the schema.\n\t * @internal\n\t */\n\tprivate readonly _entitySchemaName: string;\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IMySqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The connection pool for MySql.\n\t * @internal\n\t */\n\tprivate _pool?: Pool;\n\n\t/**\n\t * The primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * Create a new instance of MySqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMySqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MySqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMySqlEntityStorageConnectorConfig>(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.host),\n\t\t\toptions.config.host\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.user),\n\t\t\toptions.config.user\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.password),\n\t\t\toptions.config.password\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.database),\n\t\t\toptions.config.database\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKeyProperty = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MySqlEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the health of the component.\n\t * @returns The health of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tawait this.getPool().query(\n\t\t\t\t`SELECT 1 FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` LIMIT 0`\n\t\t\t);\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { database: this._config.database, tableName: this._config.tableName }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Initialize the MySql environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (!databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tawait pool.query(`CREATE DATABASE IF NOT EXISTS \\`${this._config.database}\\``);\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait pool.query(\n\t\t\t\t\t`CREATE TABLE IF NOT EXISTS \\`${this._config.database}\\`.\\`${this._config.tableName}\\` (${this.mapMySqlProperties()})`\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForTableExists();\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseName: this._config.database\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tlet sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\"\n\t\t\t);\n\t\t\tsharedPools ??= {};\n\t\t\tif (sharedPools[poolId]) {\n\t\t\t\t// Decrease the use counter and close the pool if no longer used\n\t\t\t\tsharedPools[poolId].useCounter--;\n\t\t\t\tif (sharedPools[poolId].useCounter <= 0) {\n\t\t\t\t\tawait this._pool.end();\n\t\t\t\t\tdelete sharedPools[poolId];\n\t\t\t\t}\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\n\t\t\tthis._pool = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Get an entity from MySql.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\\`${String(secondaryIndex)}\\` = ?`);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\\`${String(this._primaryKeyProperty.property)}\\` = ?`);\n\t\t\t}\n\t\t\tvalues.push(id);\n\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const condition of conditions) {\n\t\t\t\t\twhereClauses.push(`\\`${String(condition.property)}\\` = ?`);\n\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query = `SELECT * FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\t\t\tconst [rows] = await pool.query(query, values);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tconst item = EntityHelper.unPrepareEntity<T>(rows[0] as T, [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\treturn this.coerceEntityTypes(item) as T;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MySqlEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst prepared = EntityHelper.prepareEntity(entity, this._entitySchema, [\n\t\t\t{\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t}\n\t\t]);\n\n\t\tconst id = prepared[this._primaryKeyProperty.property] as unknown as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst itemData = await this.get(id);\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values = [];\n\n\t\t\tfor (const prop of props) {\n\t\t\t\tkeys.push(prop.property as string);\n\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\tif (val === null || val === undefined) {\n\t\t\t\t\tvalues.push(null);\n\t\t\t\t} else if (\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t) {\n\t\t\t\t\tvalues.push(JSON.stringify(val));\n\t\t\t\t} else {\n\t\t\t\t\tvalues.push(val);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map(() => \"?\").join(\", \")})`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, values);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst preparedEntities = entities.map(entity =>\n\t\t\tEntityHelper.prepareEntity(entity, this._entitySchema, [\n\t\t\t\t{\n\t\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t])\n\t\t);\n\n\t\ttry {\n\t\t\tconst props = [...(this._entitySchema.properties ?? [])];\n\t\t\tprops.unshift({\n\t\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\ttype: EntitySchemaPropertyType.String\n\t\t\t});\n\n\t\t\tconst keys = props.map(p => p.property as string);\n\t\t\tconst allValues: unknown[] = [];\n\n\t\t\tfor (const prepared of preparedEntities) {\n\t\t\t\tfor (const prop of props) {\n\t\t\t\t\tconst val = prepared[prop.property];\n\t\t\t\t\tif (\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array\n\t\t\t\t\t) {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : JSON.stringify(val));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tallValues.push(Is.empty(val) ? null : val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst rowPlaceholder = `(${keys.map(() => \"?\").join(\", \")})`;\n\t\t\tlet sql = `INSERT INTO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tsql += ` (${keys.map(key => `\\`${key}\\``).join(\", \")})`;\n\t\t\tsql += ` VALUES ${entities.map(() => rowPlaceholder).join(\", \")}`;\n\t\t\tsql += ` ON DUPLICATE KEY UPDATE ${keys.map(key => `\\`${key}\\` = VALUES(\\`${key}\\`)`).join(\", \")};`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(sql, allValues);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tawait pool.query(\n\t\t\t\t`DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`,\n\t\t\t\t[partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE]\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"emptyFailed\", undefined, err);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst itemData = await this.get(id, undefined, conditions);\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tconst values: unknown[] = [];\n\t\t\t\tconst whereClauses: string[] = [];\n\n\t\t\t\twhereClauses.push(`\\`${this._primaryKeyProperty.property as string}\\` = ?`);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(`\\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ?`);\n\t\t\t\tvalues.push(partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\t\twhereClauses.push(\n\t\t\t\t\t\t...conditions.map(condition => {\n\t\t\t\t\t\t\tvalues.push(condition.value);\n\t\t\t\t\t\t\treturn `\\`${String(condition.property)}\\` = ?`;\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst query = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait pool.query(query, values);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the entity storage by dropping the table.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDropping\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tif (await this.tableExists()) {\n\t\t\t\tconst pool = this.getPool();\n\t\t\t\tawait pool.query(`DROP TABLE \\`${this._config.database}\\`.\\`${this._config.tableName}\\`;`);\n\t\t\t\tawait this.waitForTableNotExists();\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDropped\",\n\t\t\t\tdata: { tableName: this._config.tableName }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: MySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by their primary key IDs.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MySqlEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst sql = `DELETE FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\` WHERE \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` = ? AND \\`${String(this._primaryKeyProperty.property)}\\` IN (?)`;\n\t\t\tawait pool.query(sql, [\n\t\t\t\tpartitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\tids\n\t\t\t]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tlet sql = \"\";\n\t\ttry {\n\t\t\tconst returnSize = limit ?? MySqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.array(sortProperties)) {\n\t\t\t\tconst orderClauses: string[] = [];\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"ASC\" : \"DESC\";\n\t\t\t\t\torderClauses.push(`\\`${String(sortProperty.property)}\\` ${direction}`);\n\t\t\t\t}\n\t\t\t\torderByClause = `ORDER BY ${orderClauses.join(\", \")}`;\n\t\t\t}\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `\\`${String(p)}\\``).join(\", \") : \"*\"} FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\t\t\tsql += ` ${orderByClause} LIMIT ${returnSize + 1} OFFSET ${startIndex}`;\n\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = (await pool.query(sql, values)) ?? [];\n\n\t\t\tconst hasMore = Is.array(rows) && rows.length > returnSize;\n\t\t\tconst resultRows = hasMore ? (rows as unknown[]).slice(0, returnSize) : rows;\n\t\t\tconst entities = resultRows as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tentities[i] = EntityHelper.unPrepareEntity(entities[i], [\n\t\t\t\t\tMySqlEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t\tentities[i] = this.coerceEntityTypes(entities[i]);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tentities,\n\t\t\t\tcursor: hasMore ? Coerce.string(startIndex + returnSize) : undefined\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"queryFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tlet sql: string | undefined;\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst { whereClauses, values } = this.buildWhereClause(conditions, partitionKey);\n\n\t\t\tsql = `SELECT COUNT(*) AS count FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``;\n\t\t\tif (whereClauses.length > 0) {\n\t\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t}\n\n\t\t\tconst [rows] = await pool.query(sql, values);\n\t\t\treturn Number((rows as { count: number }[])[0].count);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"countFailed\", { sql }, err);\n\t\t}\n\t}\n\n\t/**\n\t * Get all unique partition context ids present in the table.\n\t * @returns An array of context id objects, one per unique partition.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\tif (!Is.arrayValue(this._partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\n\t\t\t\t`SELECT DISTINCT \\`${MySqlEntityStorageConnector._PARTITION_KEY}\\` FROM \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t\t);\n\t\t\treturn (rows as { [key: string]: string }[])\n\t\t\t\t.map(row => row[MySqlEntityStorageConnector._PARTITION_KEY])\n\t\t\t\t.filter((id): id is string => Is.stringValue(id))\n\t\t\t\t.map(id => ContextIdHelper.shortSplit(this._partitionContextIds ?? [], id));\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getPartitionContextIdsFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration using a temporary table.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\tconst migrationTableName = `${this._config.tableName}Migration${Date.now()}`;\n\t\treturn new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: {\n\t\t\t\t...this._config,\n\t\t\t\ttableName: migrationTableName\n\t\t\t},\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by dropping the source table and renaming the migration table to the original name.\n\t * @param targetConnector The connector holding the migrated data in a temporary table.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The logging component type to use during finalization.\n\t * @returns The final connector using the original table name with the new schema.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: MySqlEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<MySqlEntityStorageConnector<U>> {\n\t\t// Teardown the existing table with the original name to free up the name for the new table\n\t\tawait this.teardown(loggingComponentType);\n\n\t\t// RENAME TABLE is an atomic metadata-only operation in MySQL — no data copying needed.\n\t\tconst pool = this.getPool();\n\t\tawait pool.query(\n\t\t\t`RENAME TABLE \\`${targetConnector._config.database}\\`.\\`${targetConnector._config.tableName}\\` TO \\`${this._config.database}\\`.\\`${this._config.tableName}\\``\n\t\t);\n\n\t\tconst finalConnector = new MySqlEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\n\t\tif (await finalConnector.bootstrap(loggingComponentType)) {\n\t\t\tawait targetConnector.stop();\n\t\t\treturn finalConnector;\n\t\t}\n\n\t\tthrow new GeneralError(\n\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\",\n\t\t\tundefined\n\t\t);\n\t}\n\n\t/**\n\t * Cleanup a failed or aborted migration by dropping the temporary migration table.\n\t * @param targetConnector The target connector to cleanup.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging.\n\t * @returns A promise that resolves when the cleanup is complete.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t */\n\tpublic async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW DATABASES LIKE ?;\", [this._config.database]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Close the connection pool and release all connections.\n\t * Should be called when the connector is no longer needed.\n\t * @returns Nothing.\n\t */\n\tpublic async close(): Promise<void> {\n\t\tif (this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tlet sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\"\n\t\t\t);\n\t\t\tsharedPools ??= {};\n\t\t\tif (sharedPools[poolId]) {\n\t\t\t\t// Decrease the use counter and close the pool if no longer used\n\t\t\t\tsharedPools[poolId].useCounter--;\n\t\t\t\tif (sharedPools[poolId].useCounter <= 0) {\n\t\t\t\t\tawait this._pool.end();\n\t\t\t\t\tdelete sharedPools[poolId];\n\t\t\t\t}\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\n\t\t\tthis._pool = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Coerce MySQL raw row values back to proper TypeScript types based on the entity schema.\n\t * MySQL returns TINYINT(1) as 0/1 rather than false/true; this method converts those.\n\t * @param entity The raw entity row from MySQL.\n\t * @returns The entity with schema-correct types.\n\t * @internal\n\t */\n\tprivate coerceEntityTypes(entity: Partial<T>): Partial<T> {\n\t\tfor (const prop of this._entitySchema.properties ?? []) {\n\t\t\tconst value = entity[prop.property];\n\t\t\tif (prop.type === EntitySchemaPropertyType.Boolean && !Is.empty(value)) {\n\t\t\t\tObjectHelper.propertySet(entity, prop.property as string, Boolean(value));\n\t\t\t}\n\t\t}\n\t\treturn entity;\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @returns True if the table exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async tableExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst pool = this.getPool();\n\t\t\tconst [rows] = await pool.query(\"SHOW TABLES FROM ?? LIKE ?\", [\n\t\t\t\tthis._config.database,\n\t\t\t\tthis._config.tableName\n\t\t\t]);\n\t\t\treturn Is.arrayValue(rows);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a table to not exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForTableNotExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the connection pool.\n\t * @returns The MySql connection pool.\n\t * @internal\n\t */\n\tprivate getPool(): Pool {\n\t\tif (!this._pool) {\n\t\t\tconst poolConfig = this.createPoolConfig();\n\t\t\tconst poolId = `${poolConfig.host}|${poolConfig.port}|${poolConfig.user}`;\n\n\t\t\tlet sharedPools = SharedStore.get<{ [id: string]: { pool: Pool; useCounter: number } }>(\n\t\t\t\t\"mySqlPools\"\n\t\t\t);\n\t\t\tsharedPools ??= {};\n\n\t\t\t// If there is no pool for the id, create it\n\t\t\tif (!sharedPools[poolId]) {\n\t\t\t\tsharedPools[poolId] = {\n\t\t\t\t\tpool: createPool(poolConfig),\n\t\t\t\t\tuseCounter: 0\n\t\t\t\t};\n\t\t\t\tSharedStore.set(\"mySqlPools\", sharedPools);\n\t\t\t}\n\t\t\t// Increase the use counter and return the pool\n\t\t\tsharedPools[poolId].useCounter++;\n\t\t\tthis._pool = sharedPools[poolId].pool;\n\t\t}\n\t\treturn this._pool;\n\t}\n\n\t/**\n\t * Create the connection pool configuration.\n\t * @returns The MySql pool configuration.\n\t * @internal\n\t */\n\tprivate createPoolConfig(): PoolOptions {\n\t\tconst poolConfig = this._config.pool ?? {};\n\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 3306,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password,\n\n\t\t\tconnectionLimit: poolConfig.connectionLimit ?? 10,\n\t\t\tmaxIdle: poolConfig.maxIdle ?? 10,\n\t\t\tidleTimeout: poolConfig.idleTimeout ?? 60000,\n\t\t\tenableKeepAlive: poolConfig.enableKeepAlive ?? true,\n\t\t\tkeepAliveInitialDelay: 0,\n\t\t\twaitForConnections: poolConfig.waitForConnections ?? true,\n\t\t\tqueueLimit: poolConfig.queueLimit ?? 0\n\t\t};\n\t}\n\n\t/**\n\t * Build where clause arrays for a query, combining partition key and optional conditions.\n\t * @param conditions The optional entity conditions to include.\n\t * @param partitionKey The partition key value.\n\t * @returns The where clauses and bound values.\n\t * @internal\n\t */\n\tprivate buildWhereClause(\n\t\tconditions: EntityCondition<T> | undefined,\n\t\tpartitionKey: string | undefined\n\t): { whereClauses: string[]; values: unknown[] } {\n\t\tconst whereClauses: string[] = [];\n\t\tconst values: unknown[] = [];\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tfinalConditions.conditions.push({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY,\n\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\tvalue: partitionKey ?? MySqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t});\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(conditions);\n\t\t}\n\n\t\tthis.buildQueryParameters(\"\", finalConditions, whereClauses, values);\n\n\t\treturn { whereClauses, values };\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param whereClauses The where clauses to use in the query.\n\t * @param values The values to use in the query.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\twhereClauses: string[],\n\t\tvalues: unknown[]\n\t): void {\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c => {\n\t\t\t\tconst subWhereClauses: string[] = [];\n\t\t\t\tconst subValues: unknown[] = [];\n\t\t\t\tthis.buildQueryParameters(objectPath, c, subWhereClauses, subValues);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\treturn subWhereClauses.join(\" AND \");\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions.filter(j => j.length > 0).join(` ${logicalOperator} `);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\twhereClauses.push(`(${queryClause})`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\t\tconst comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, values);\n\t\twhereClauses.push(comparison);\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in MySQL.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param values The values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tvalues: unknown[]\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\n\t\tprop += comparator.property;\n\n\t\tif (comparator.comparison === ComparisonOperator.In) {\n\t\t\tconst inValues = Is.array(comparator.value) ? comparator.value : [comparator.value];\n\t\t\tvalues.push(...inValues.map(val => this.propertyToDbValue(val, type)));\n\t\t\tconst placeholders = inValues.map(() => \"?\").join(\", \");\n\t\t\treturn `\\`${prop}\\` IN (${placeholders})`;\n\t\t}\n\n\t\t// null/undefined must use IS NULL / IS NOT NULL — never a parameterised placeholder.\n\t\t// Passing undefined through propertyToDbValue() coerces it to NaN for number fields\n\t\t// (Number(undefined) === NaN), and null coerces to 0 (Number(null) === 0), both of\n\t\t// which produce semantically wrong or invalid SQL.\n\t\tif (comparator.value === null || comparator.value === undefined) {\n\t\t\tif (\n\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t) {\n\t\t\t\tconst nullCheck =\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ? \"IS NULL\" : \"IS NOT NULL\";\n\n\t\t\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\t\t\t\t\treturn `${jsonExpr} ${nullCheck}`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` ${nullCheck}`;\n\t\t\t}\n\t\t}\n\n\t\tconst dbValue = this.propertyToDbValue(comparator.value, type);\n\t\tvalues.push(dbValue);\n\n\t\tif (comparator.property.split(\".\").length > 1) {\n\t\t\tconst rootProp = comparator.property.split(\".\")[0];\n\t\t\tconst nestedPath = comparator.property.split(\".\").slice(1).join(\".\");\n\t\t\tconst rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);\n\t\t\tconst isArray = rootSchema?.type === EntitySchemaPropertyType.Array;\n\t\t\tconst jsonPath = isArray ? `$[*].${nestedPath}` : `$.${nestedPath}`;\n\t\t\tconst jsonExpr = `JSON_UNQUOTE(JSON_EXTRACT(\\`${rootProp}\\`, '${jsonPath}'))`;\n\n\t\t\tswitch (comparator.comparison) {\n\t\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(${jsonExpr}) LIKE ?`;\n\t\t\t\t}\n\t\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\t\treturn `${jsonExpr} <> ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\t\treturn `${jsonExpr} > ?`;\n\t\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\t\treturn `${jsonExpr} < ?`;\n\t\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} >= ?`;\n\t\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\t\treturn `${jsonExpr} <= ?`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${jsonExpr} = ?`;\n\t\t\t}\n\t\t}\n\n\t\tswitch (comparator.comparison) {\n\t\t\tcase ComparisonOperator.Equals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` = ?`;\n\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t\t}\n\t\t\t\treturn `\\`${prop}\\` <> ?`;\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn `\\`${prop}\\` > ?`;\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn `\\`${prop}\\` < ?`;\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` >= ?`;\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn `\\`${prop}\\` <= ?`;\n\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) LIKE ?`;\n\t\t\t\t}\n\t\t\t\treturn `JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tcase ComparisonOperator.NotIncludes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\tvalues.pop();\n\t\t\t\t\tvalues.push(`%${String(comparator.value).toLowerCase()}%`);\n\t\t\t\t\treturn `LOWER(\\`${prop}\\`) NOT LIKE ?`;\n\t\t\t\t}\n\t\t\t\treturn `NOT JSON_CONTAINS(\\`${prop}\\`, ?)`;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\t\t\tcomparison: comparator.comparison\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\treturn JSON.stringify(value);\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn String(value);\n\t\t} else if (type === \"number\") {\n\t\t\treturn Number(value);\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn value ? 1 : 0;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in MySQL.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(MySqlEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Map entity schema properties to SQL properties.\n\t * @param schema The schema to use, defaults to the connector's own schema.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t */\n\tprivate mapMySqlProperties(schema?: IEntitySchema<T>): string {\n\t\tconst entitySchema = schema ?? this._entitySchema;\n\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"LONGTEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"FLOAT\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INT\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSON\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"TINYINT(1)\"\n\t\t};\n\n\t\tif (!entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tMySqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"entitySchemaPropertiesUndefined\"\n\t\t\t);\n\t\t}\n\n\t\tconst primaryKeys: string[] = [];\n\n\t\tconst props: IEntitySchemaProperty<T>[] = [...entitySchema.properties];\n\n\t\tprops.unshift({\n\t\t\tproperty: MySqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tlet sqlType = sqlTypeMap[prop.type] || \"TEXT\";\n\t\t\t\tif (prop.format) {\n\t\t\t\t\tswitch (prop.type) {\n\t\t\t\t\t\tcase EntitySchemaPropertyType.String:\n\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"uuid\":\n\t\t\t\t\t\t\t\t\tsqlType = \"CHAR(36)\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"date\":\n\t\t\t\t\t\t\t\tcase \"date-time\":\n\t\t\t\t\t\t\t\t\tsqlType = \"LONGTEXT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Number:\n\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"float\":\n\t\t\t\t\t\t\t\t\tsqlType = \"FLOAT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"double\":\n\t\t\t\t\t\t\t\t\tsqlType = \"DOUBLE\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EntitySchemaPropertyType.Integer:\n\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\tswitch (prop.format) {\n\t\t\t\t\t\t\t\tcase \"int8\":\n\t\t\t\t\t\t\t\tcase \"uint8\":\n\t\t\t\t\t\t\t\t\tsqlType = \"TINYINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int16\":\n\t\t\t\t\t\t\t\tcase \"uint16\":\n\t\t\t\t\t\t\t\t\tsqlType = \"SMALLINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int32\":\n\t\t\t\t\t\t\t\tcase \"uint32\":\n\t\t\t\t\t\t\t\t\tsqlType = \"INT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase \"int64\":\n\t\t\t\t\t\t\t\tcase \"uint64\":\n\t\t\t\t\t\t\t\t\tsqlType = \"BIGINT\";\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst columnName = String(prop.property);\n\t\t\t\tconst nullable = prop.optional ? \" NULL\" : \" NOT NULL\";\n\n\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\tif (sqlType === \"LONGTEXT\" || sqlType === \"TEXT\") {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\`(255)`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprimaryKeys.push(`\\`${columnName}\\``);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn `\\`${columnName}\\` ${sqlType}${nullable}`;\n\t\t\t})\n\t\t\t.join(\", \");\n\n\t\tconst primaryKeyDefinition =\n\t\t\tprimaryKeys.length > 0 ? `, PRIMARY KEY (${primaryKeys.join(\", \")})` : \"\";\n\t\treturn columnDefinitions + primaryKeyDefinition;\n\t}\n}\n"]}
@@ -1,11 +1,12 @@
1
+ import { type IContextIds } from "@twin.org/context";
1
2
  import { type IHealth } from "@twin.org/core";
2
3
  import { type EntityCondition, type IEntitySchema, SortDirection } from "@twin.org/entity";
3
- import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
4
+ import { type IEntityStorageConnector, type IEntityStorageMigrationConnector, type IMigrationOptions } from "@twin.org/entity-storage-models";
4
5
  import type { IMySqlEntityStorageConnectorConstructorOptions } from "./models/IMySqlEntityStorageConnectorConstructorOptions.js";
5
6
  /**
6
7
  * Class for performing entity storage operations using MySql.
7
8
  */
8
- export declare class MySqlEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {
9
+ export declare class MySqlEntityStorageConnector<T = unknown> implements IEntityStorageMigrationConnector<T> {
9
10
  /**
10
11
  * Runtime name for the class.
11
12
  */
@@ -115,16 +116,51 @@ export declare class MySqlEntityStorageConnector<T = unknown> implements IEntity
115
116
  }>;
116
117
  /**
117
118
  * Count all the entities which match the conditions.
119
+ * @param conditions The optional conditions to match for the entities.
118
120
  * @returns The total count of entities in the storage.
119
121
  */
120
- count(): Promise<number>;
122
+ count(conditions?: EntityCondition<T>): Promise<number>;
123
+ /**
124
+ * Get all unique partition context ids present in the table.
125
+ * @returns An array of context id objects, one per unique partition.
126
+ */
127
+ getPartitionContextIds(): Promise<IContextIds[]>;
128
+ /**
129
+ * Create the target connector for performing the migration using a temporary table.
130
+ * @param newEntitySchema The name of the new entity schema to create the connector for.
131
+ * @returns Connector for performing the migration.
132
+ */
133
+ createTargetConnector<U>(newEntitySchema: string): Promise<IEntityStorageConnector<U>>;
134
+ /**
135
+ * Finalize the migration by dropping the source table and renaming the migration table to the original name.
136
+ * @param targetConnector The connector holding the migrated data in a temporary table.
137
+ * @param options The options to control how the migration is finalized.
138
+ * @param loggingComponentType The logging component type to use during finalization.
139
+ * @returns The final connector using the original table name with the new schema.
140
+ */
141
+ finalizeMigration<U>(targetConnector: MySqlEntityStorageConnector<U>, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<MySqlEntityStorageConnector<U>>;
142
+ /**
143
+ * Cleanup a failed or aborted migration by dropping the temporary migration table.
144
+ * @param targetConnector The target connector to cleanup.
145
+ * @param options The options to control how the migration is cleaned up.
146
+ * @param loggingComponentType The optional component type to use for logging.
147
+ * @returns A promise that resolves when the cleanup is complete.
148
+ */
149
+ cleanupMigration<U>(targetConnector: IEntityStorageConnector<U> | undefined, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<void>;
121
150
  /**
122
151
  * Check if the database exists.
123
152
  * @returns True if the database exists, false otherwise.
124
153
  */
125
154
  databaseExists(): Promise<boolean>;
155
+ /**
156
+ * Close the connection pool and release all connections.
157
+ * Should be called when the connector is no longer needed.
158
+ * @returns Nothing.
159
+ */
160
+ close(): Promise<void>;
126
161
  /**
127
162
  * Map entity schema properties to SQL properties.
163
+ * @param schema The schema to use, defaults to the connector's own schema.
128
164
  * @returns The SQL properties as a string.
129
165
  * @throws GeneralError if the entity properties do not exist.
130
166
  */
package/docs/changelog.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.14](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-mysql-v0.0.3-next.13...entity-storage-connector-mysql-v0.0.3-next.14) (2026-05-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * adding schema migration functionality to all the connectors ([#85](https://github.com/iotaledger/twin-entity-storage/issues/85)) ([fd1555a](https://github.com/iotaledger/twin-entity-storage/commit/fd1555a34380158214a577586dafae821e72a578))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/entity-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
16
+ * devDependencies
17
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.13 to 0.0.3-next.14
18
+
3
19
  ## [0.0.3-next.13](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-mysql-v0.0.3-next.12...entity-storage-connector-mysql-v0.0.3-next.13) (2026-05-13)
4
20
 
5
21
 
@@ -10,7 +10,7 @@ Class for performing entity storage operations using MySql.
10
10
 
11
11
  ## Implements
12
12
 
13
- - `IEntityStorageConnector`\<`T`\>
13
+ - `IEntityStorageMigrationConnector`\<`T`\>
14
14
 
15
15
  ## Constructors
16
16
 
@@ -56,7 +56,7 @@ The class name of the component.
56
56
 
57
57
  #### Implementation of
58
58
 
59
- `IEntityStorageConnector.className`
59
+ `IEntityStorageMigrationConnector.className`
60
60
 
61
61
  ***
62
62
 
@@ -74,7 +74,7 @@ The health of the component.
74
74
 
75
75
  #### Implementation of
76
76
 
77
- `IEntityStorageConnector.health`
77
+ `IEntityStorageMigrationConnector.health`
78
78
 
79
79
  ***
80
80
 
@@ -92,7 +92,7 @@ The schema for the entities.
92
92
 
93
93
  #### Implementation of
94
94
 
95
- `IEntityStorageConnector.getSchema`
95
+ `IEntityStorageMigrationConnector.getSchema`
96
96
 
97
97
  ***
98
98
 
@@ -118,7 +118,7 @@ A promise that resolves to a boolean indicating success.
118
118
 
119
119
  #### Implementation of
120
120
 
121
- `IEntityStorageConnector.bootstrap`
121
+ `IEntityStorageMigrationConnector.bootstrap`
122
122
 
123
123
  ***
124
124
 
@@ -144,7 +144,7 @@ Nothing.
144
144
 
145
145
  #### Implementation of
146
146
 
147
- `IEntityStorageConnector.stop`
147
+ `IEntityStorageMigrationConnector.stop`
148
148
 
149
149
  ***
150
150
 
@@ -182,7 +182,7 @@ The object if it can be found or undefined.
182
182
 
183
183
  #### Implementation of
184
184
 
185
- `IEntityStorageConnector.get`
185
+ `IEntityStorageMigrationConnector.get`
186
186
 
187
187
  ***
188
188
 
@@ -214,7 +214,7 @@ The id of the entity.
214
214
 
215
215
  #### Implementation of
216
216
 
217
- `IEntityStorageConnector.set`
217
+ `IEntityStorageMigrationConnector.set`
218
218
 
219
219
  ***
220
220
 
@@ -240,7 +240,7 @@ Nothing.
240
240
 
241
241
  #### Implementation of
242
242
 
243
- `IEntityStorageConnector.setBatch`
243
+ `IEntityStorageMigrationConnector.setBatch`
244
244
 
245
245
  ***
246
246
 
@@ -258,7 +258,7 @@ Nothing.
258
258
 
259
259
  #### Implementation of
260
260
 
261
- `IEntityStorageConnector.empty`
261
+ `IEntityStorageMigrationConnector.empty`
262
262
 
263
263
  ***
264
264
 
@@ -290,7 +290,7 @@ Nothing.
290
290
 
291
291
  #### Implementation of
292
292
 
293
- `IEntityStorageConnector.remove`
293
+ `IEntityStorageMigrationConnector.remove`
294
294
 
295
295
  ***
296
296
 
@@ -316,7 +316,7 @@ True if the teardown process was successful.
316
316
 
317
317
  #### Implementation of
318
318
 
319
- `IEntityStorageConnector.teardown`
319
+ `IEntityStorageMigrationConnector.teardown`
320
320
 
321
321
  ***
322
322
 
@@ -342,7 +342,7 @@ Nothing.
342
342
 
343
343
  #### Implementation of
344
344
 
345
- `IEntityStorageConnector.removeBatch`
345
+ `IEntityStorageMigrationConnector.removeBatch`
346
346
 
347
347
  ***
348
348
 
@@ -393,16 +393,24 @@ and a cursor which can be used to request more entities.
393
393
 
394
394
  #### Implementation of
395
395
 
396
- `IEntityStorageConnector.query`
396
+ `IEntityStorageMigrationConnector.query`
397
397
 
398
398
  ***
399
399
 
400
400
  ### count() {#count}
401
401
 
402
- > **count**(): `Promise`\<`number`\>
402
+ > **count**(`conditions?`): `Promise`\<`number`\>
403
403
 
404
404
  Count all the entities which match the conditions.
405
405
 
406
+ #### Parameters
407
+
408
+ ##### conditions?
409
+
410
+ `EntityCondition`\<`T`\>
411
+
412
+ The optional conditions to match for the entities.
413
+
406
414
  #### Returns
407
415
 
408
416
  `Promise`\<`number`\>
@@ -411,7 +419,145 @@ The total count of entities in the storage.
411
419
 
412
420
  #### Implementation of
413
421
 
414
- `IEntityStorageConnector.count`
422
+ `IEntityStorageMigrationConnector.count`
423
+
424
+ ***
425
+
426
+ ### getPartitionContextIds() {#getpartitioncontextids}
427
+
428
+ > **getPartitionContextIds**(): `Promise`\<`IContextIds`[]\>
429
+
430
+ Get all unique partition context ids present in the table.
431
+
432
+ #### Returns
433
+
434
+ `Promise`\<`IContextIds`[]\>
435
+
436
+ An array of context id objects, one per unique partition.
437
+
438
+ #### Implementation of
439
+
440
+ `IEntityStorageMigrationConnector.getPartitionContextIds`
441
+
442
+ ***
443
+
444
+ ### createTargetConnector() {#createtargetconnector}
445
+
446
+ > **createTargetConnector**\<`U`\>(`newEntitySchema`): `Promise`\<`IEntityStorageConnector`\<`U`\>\>
447
+
448
+ Create the target connector for performing the migration using a temporary table.
449
+
450
+ #### Type Parameters
451
+
452
+ ##### U
453
+
454
+ `U`
455
+
456
+ #### Parameters
457
+
458
+ ##### newEntitySchema
459
+
460
+ `string`
461
+
462
+ The name of the new entity schema to create the connector for.
463
+
464
+ #### Returns
465
+
466
+ `Promise`\<`IEntityStorageConnector`\<`U`\>\>
467
+
468
+ Connector for performing the migration.
469
+
470
+ #### Implementation of
471
+
472
+ `IEntityStorageMigrationConnector.createTargetConnector`
473
+
474
+ ***
475
+
476
+ ### finalizeMigration() {#finalizemigration}
477
+
478
+ > **finalizeMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`MySqlEntityStorageConnector`\<`U`\>\>
479
+
480
+ Finalize the migration by dropping the source table and renaming the migration table to the original name.
481
+
482
+ #### Type Parameters
483
+
484
+ ##### U
485
+
486
+ `U`
487
+
488
+ #### Parameters
489
+
490
+ ##### targetConnector
491
+
492
+ `MySqlEntityStorageConnector`\<`U`\>
493
+
494
+ The connector holding the migrated data in a temporary table.
495
+
496
+ ##### options?
497
+
498
+ `IMigrationOptions`\<`T`, `U`\>
499
+
500
+ The options to control how the migration is finalized.
501
+
502
+ ##### loggingComponentType?
503
+
504
+ `string`
505
+
506
+ The logging component type to use during finalization.
507
+
508
+ #### Returns
509
+
510
+ `Promise`\<`MySqlEntityStorageConnector`\<`U`\>\>
511
+
512
+ The final connector using the original table name with the new schema.
513
+
514
+ #### Implementation of
515
+
516
+ `IEntityStorageMigrationConnector.finalizeMigration`
517
+
518
+ ***
519
+
520
+ ### cleanupMigration() {#cleanupmigration}
521
+
522
+ > **cleanupMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`void`\>
523
+
524
+ Cleanup a failed or aborted migration by dropping the temporary migration table.
525
+
526
+ #### Type Parameters
527
+
528
+ ##### U
529
+
530
+ `U`
531
+
532
+ #### Parameters
533
+
534
+ ##### targetConnector
535
+
536
+ `IEntityStorageConnector`\<`U`\> \| `undefined`
537
+
538
+ The target connector to cleanup.
539
+
540
+ ##### options?
541
+
542
+ `IMigrationOptions`\<`T`, `U`\>
543
+
544
+ The options to control how the migration is cleaned up.
545
+
546
+ ##### loggingComponentType?
547
+
548
+ `string`
549
+
550
+ The optional component type to use for logging.
551
+
552
+ #### Returns
553
+
554
+ `Promise`\<`void`\>
555
+
556
+ A promise that resolves when the cleanup is complete.
557
+
558
+ #### Implementation of
559
+
560
+ `IEntityStorageMigrationConnector.cleanupMigration`
415
561
 
416
562
  ***
417
563
 
@@ -426,3 +572,18 @@ Check if the database exists.
426
572
  `Promise`\<`boolean`\>
427
573
 
428
574
  True if the database exists, false otherwise.
575
+
576
+ ***
577
+
578
+ ### close() {#close}
579
+
580
+ > **close**(): `Promise`\<`void`\>
581
+
582
+ Close the connection pool and release all connections.
583
+ Should be called when the connector is no longer needed.
584
+
585
+ #### Returns
586
+
587
+ `Promise`\<`void`\>
588
+
589
+ Nothing.
package/locales/en.json CHANGED
@@ -23,7 +23,9 @@
23
23
  "countFailed": "Unable to count entities",
24
24
  "emptyFailed": "Unable to empty entity storage",
25
25
  "removeBatchFailed": "Unable to remove batch of entities",
26
- "teardownFailed": "Unable to teardown entity storage"
26
+ "teardownFailed": "Unable to teardown entity storage",
27
+ "getPartitionContextIdsFailed": "Unable to get partition context ids",
28
+ "finalizeMigrationFailedBootstrap": "Finalizing migration failed during bootstrap phase"
27
29
  }
28
30
  },
29
31
  "health": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-mysql",
3
- "version": "0.0.3-next.13",
3
+ "version": "0.0.3-next.14",
4
4
  "description": "MySQL connector for relational persistence with SQL querying.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/data-json-ld": "next",
20
20
  "@twin.org/entity": "next",
21
- "@twin.org/entity-storage-models": "0.0.3-next.13",
21
+ "@twin.org/entity-storage-models": "0.0.3-next.14",
22
22
  "@twin.org/logging-models": "next",
23
23
  "@twin.org/nameof": "next",
24
24
  "mysql2": "3.22.3"