@twin.org/entity-storage-connector-postgresql 0.0.3-next.6 → 0.0.3-next.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # TWIN Entity Storage Connector PostgreSql
1
+ # Entity Storage Connector PostgreSQL
2
2
 
3
- Entity Storage connector implementation using PostgreSql storage.
3
+ This package provides a PostgreSQL backend for relational persistence, transactions and advanced SQL features. It is designed to work with the wider storage ecosystem so applications can keep behaviour consistent across connectors and environments.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,18 +8,13 @@ Entity Storage connector implementation using PostgreSql storage.
8
8
  npm install @twin.org/entity-storage-connector-postgresql
9
9
  ```
10
10
 
11
- ## Testing
11
+ ## Docker
12
12
 
13
- The tests developed are functional tests and need an instance of PostgreSql up and running. To run PostgreSql locally:
13
+ To perform testing of this component it may be necessary to launch a local instance to communicate with.
14
14
 
15
- ```sh
16
- docker run -p 5444:5432 --name twin-entity-storage-postgresql --hostname postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password -d postgres
17
- ```
18
-
19
- Afterwards you can run the tests as follows:
20
-
21
- ```sh
22
- npm run test
15
+ ```shell
16
+ docker pull postgres:latest
17
+ docker run -d --name twin-entity-storage-postgresql -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password -p 5444:5432 postgres:latest
23
18
  ```
24
19
 
25
20
  ## Examples
@@ -153,6 +153,16 @@ export class PostgreSqlEntityStorageConnector {
153
153
  className() {
154
154
  return PostgreSqlEntityStorageConnector.CLASS_NAME;
155
155
  }
156
+ /**
157
+ * The component needs to be stopped when the node is closed.
158
+ * @returns Nothing.
159
+ */
160
+ async stop() {
161
+ if (this._connection) {
162
+ await this._connection.end();
163
+ this._connection = undefined;
164
+ }
165
+ }
156
166
  /**
157
167
  * Get the schema for the entities.
158
168
  * @returns The schema for the entities.
@@ -583,58 +593,99 @@ export class PostgreSqlEntityStorageConnector {
583
593
  const placeholders = inValues.map((_, index) => `$${valueIndex + index}`).join(", ");
584
594
  return `"${prop}" IN (${placeholders})`;
585
595
  }
596
+ // null/undefined must use IS NULL / IS NOT NULL — never a parameterised placeholder.
597
+ // Passing undefined through propertyToDbValue() coerces it to NaN for number fields
598
+ // (Number(undefined) === NaN), and null coerces to 0 (Number(null) === 0), both of
599
+ // which produce semantically wrong or invalid SQL.
600
+ if (comparator.value === null || comparator.value === undefined) {
601
+ if (comparator.comparison === ComparisonOperator.Equals ||
602
+ comparator.comparison === ComparisonOperator.NotEquals) {
603
+ const nullCheck = comparator.comparison === ComparisonOperator.Equals ? "IS NULL" : "IS NOT NULL";
604
+ if (comparator.property.split(".").length > 1) {
605
+ const rootProp = comparator.property.split(".")[0];
606
+ const nestedParts = comparator.property.split(".").slice(1);
607
+ const jsonPath = nestedParts
608
+ .map((p, i, arr) => (i === arr.length - 1 ? `->> '${p}'` : `-> '${p}'`))
609
+ .join("");
610
+ const jsonTextExpr = `("${rootProp}"::jsonb ${jsonPath})`;
611
+ return `${jsonTextExpr} ${nullCheck}`;
612
+ }
613
+ return `"${prop}" ${nullCheck}`;
614
+ }
615
+ }
586
616
  const dbValue = this.propertyToDbValue(comparator.value, type);
587
617
  values.push(dbValue);
588
618
  if (comparator.property.split(".").length > 1) {
589
- const jsonPath = comparator.property
590
- .split(".")
591
- .slice(1)
619
+ const rootProp = comparator.property.split(".")[0];
620
+ const nestedParts = comparator.property.split(".").slice(1);
621
+ const rootSchema = this._entitySchema.properties?.find(p => p.property === rootProp);
622
+ const isArray = rootSchema?.type === EntitySchemaPropertyType.Array;
623
+ const jsonPath = nestedParts
592
624
  .map((p, i, arr) => (i === arr.length - 1 ? `->> '${p}'` : `-> '${p}'`))
593
625
  .join("");
594
- return `("${comparator.property.split(".")[0]}"::jsonb ${jsonPath}) = $${valueIndex}`;
595
- }
596
- else if (comparator.comparison === ComparisonOperator.Equals) {
597
- if (Is.object(comparator.value) || Is.array(comparator.value)) {
598
- return `"${prop}" = $${valueIndex}::jsonb`;
599
- }
600
- return `"${prop}" = $${valueIndex}`;
601
- }
602
- else if (comparator.comparison === ComparisonOperator.NotEquals) {
603
- if (Is.object(comparator.value) || Is.array(comparator.value)) {
604
- return `"${prop}" != $${valueIndex}::jsonb`;
626
+ const jsonTextExpr = `("${rootProp}"::jsonb ${jsonPath})`;
627
+ switch (comparator.comparison) {
628
+ case ComparisonOperator.Includes: {
629
+ values.pop();
630
+ values.push(`%${String(comparator.value).toLowerCase()}%`);
631
+ if (isArray) {
632
+ const elemPath = nestedParts
633
+ .map((p, i, arr) => (i === arr.length - 1 ? `->>'${p}'` : `->'${p}'`))
634
+ .join("");
635
+ return `EXISTS (SELECT 1 FROM jsonb_array_elements("${rootProp}") elem WHERE LOWER(elem${elemPath}) ILIKE $${valueIndex})`;
636
+ }
637
+ return `LOWER(${jsonTextExpr}) ILIKE $${valueIndex}`;
638
+ }
639
+ case ComparisonOperator.NotEquals:
640
+ return `${jsonTextExpr} <> $${valueIndex}`;
641
+ case ComparisonOperator.GreaterThan:
642
+ return `${jsonTextExpr} > $${valueIndex}`;
643
+ case ComparisonOperator.LessThan:
644
+ return `${jsonTextExpr} < $${valueIndex}`;
645
+ case ComparisonOperator.GreaterThanOrEqual:
646
+ return `${jsonTextExpr} >= $${valueIndex}`;
647
+ case ComparisonOperator.LessThanOrEqual:
648
+ return `${jsonTextExpr} <= $${valueIndex}`;
649
+ default:
650
+ return `${jsonTextExpr} = $${valueIndex}`;
605
651
  }
606
- return `"${prop}" <> $${valueIndex}`;
607
652
  }
608
- else if (comparator.comparison === ComparisonOperator.GreaterThan) {
609
- return `"${prop}" > $${valueIndex}`;
610
- }
611
- else if (comparator.comparison === ComparisonOperator.LessThan) {
612
- return `"${prop}" < $${valueIndex}`;
613
- }
614
- else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {
615
- return `"${prop}" >= $${valueIndex}`;
616
- }
617
- else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {
618
- return `"${prop}" <= $${valueIndex}`;
619
- }
620
- else if (comparator.comparison === ComparisonOperator.Includes) {
621
- // For string fields, use ILIKE for case-insensitive substring matching
622
- if (type === EntitySchemaPropertyType.String) {
623
- return `"${prop}" ILIKE '%' || $${valueIndex} || '%'`;
624
- }
625
- // For array and object fields, use jsonb operators
626
- if (type === EntitySchemaPropertyType.Array || type === EntitySchemaPropertyType.Object) {
627
- return `EXISTS (SELECT 1 FROM jsonb_array_elements("${prop}") elem WHERE elem @> $${valueIndex}::jsonb)`;
653
+ switch (comparator.comparison) {
654
+ case ComparisonOperator.Equals:
655
+ if (Is.object(comparator.value) || Is.array(comparator.value)) {
656
+ return `"${prop}" = $${valueIndex}::jsonb`;
657
+ }
658
+ return `"${prop}" = $${valueIndex}`;
659
+ case ComparisonOperator.NotEquals:
660
+ if (Is.object(comparator.value) || Is.array(comparator.value)) {
661
+ return `"${prop}" != $${valueIndex}::jsonb`;
662
+ }
663
+ return `"${prop}" <> $${valueIndex}`;
664
+ case ComparisonOperator.GreaterThan:
665
+ return `"${prop}" > $${valueIndex}`;
666
+ case ComparisonOperator.LessThan:
667
+ return `"${prop}" < $${valueIndex}`;
668
+ case ComparisonOperator.GreaterThanOrEqual:
669
+ return `"${prop}" >= $${valueIndex}`;
670
+ case ComparisonOperator.LessThanOrEqual:
671
+ return `"${prop}" <= $${valueIndex}`;
672
+ case ComparisonOperator.Includes: {
673
+ if (type === EntitySchemaPropertyType.String) {
674
+ return `"${prop}" ILIKE '%' || $${valueIndex} || '%'`;
675
+ }
676
+ if (type === EntitySchemaPropertyType.Array || type === EntitySchemaPropertyType.Object) {
677
+ return `EXISTS (SELECT 1 FROM jsonb_array_elements("${prop}") elem WHERE elem @> $${valueIndex}::jsonb)`;
678
+ }
679
+ throw new GeneralError(PostgreSqlEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
680
+ comparison: comparator.comparison,
681
+ type
682
+ });
628
683
  }
629
- // Includes operator is not supported for other types (number, boolean, etc.)
630
- throw new GeneralError(PostgreSqlEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
631
- comparison: comparator.comparison,
632
- type
633
- });
684
+ default:
685
+ throw new GeneralError(PostgreSqlEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
686
+ comparison: comparator.comparison
687
+ });
634
688
  }
635
- throw new GeneralError(PostgreSqlEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
636
- comparison: comparator.comparison
637
- });
638
689
  }
639
690
  /**
640
691
  * Format a value to insert into DB.
@@ -1 +1 @@
1
- {"version":3,"file":"postgreSqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/postgreSqlEntityStorageConnector.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EACN,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,YAAY,EACZ,MAAM,EACN,EAAE,EACF,YAAY,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,kBAAkB,EAElB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EAIxB,eAAe,EACf,aAAa,EACb,MAAM,kBAAkB,CAAC;AAI1B,OAAO,QAAkC,MAAM,UAAU,CAAC;AAI1D;;GAEG;AACH,MAAM,OAAO,gCAAgC;IAC5C;;OAEG;IACI,MAAM,CAAU,UAAU,sCAAsD;IAEvF;;;OAGG;IACK,MAAM,CAAU,cAAc,GAAW,EAAE,CAAC;IAEpD;;;OAGG;IACK,MAAM,CAAU,cAAc,GAAW,aAAa,CAAC;IAE/D;;;OAGG;IACK,MAAM,CAAU,oBAAoB,GAAW,MAAM,CAAC;IAE9D;;;OAGG;IACc,aAAa,CAAmB;IAEjD;;;OAGG;IACc,oBAAoB,CAAY;IAEjD;;;OAGG;IACc,mBAAmB,CAA2B;IAE/D;;;OAGG;IACc,OAAO,CAA0C;IAElE;;;OAGG;IACK,WAAW,CAAgB;IAEnC;;;OAGG;IACH,YAAY,OAA4D;QACvE,MAAM,CAAC,MAAM,CAAC,gCAAgC,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QACrF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,0BAE3C,OAAO,CAAC,YAAY,CACpB,CAAC;QACF,MAAM,CAAC,MAAM,CACZ,gCAAgC,CAAC,UAAU,oBAE3C,OAAO,CAAC,MAAM,CACd,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,yBAE3C,OAAO,CAAC,MAAM,CAAC,IAAI,CACnB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,yBAE3C,OAAO,CAAC,MAAM,CAAC,IAAI,CACnB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,6BAE3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CACvB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,6BAE3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CACvB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,gCAAgC,CAAC,UAAU,8BAE3C,OAAO,CAAC,MAAM,CAAC,SAAS,CACxB,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACxD,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEhF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CAAC,wBAAiC;QACvD,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAoB,wBAAwB,CAAC,CAAC;QAE9F,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAEnD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YACnD,IAAI,CAAC,cAAc,EAAE,CAAC;gBACrB,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,gCAAgC,CAAC,UAAU;oBACnD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;oBACd,OAAO,EAAE,kBAAkB;oBAC3B,IAAI,EAAE;wBACL,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;qBACnC;iBACD,CAAC,CAAC;gBACH,MAAM,YAAY,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;gBACzE,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACP,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,gCAAgC,CAAC,UAAU;oBACnD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;oBACd,OAAO,EAAE,gBAAgB;oBACzB,IAAI,EAAE;wBACL,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;qBACnC;iBACD,CAAC,CAAC;YACJ,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAE7C,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClB,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,gCAAgC,CAAC,UAAU;oBACnD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;oBACd,OAAO,EAAE,eAAe;oBACxB,IAAI,EAAE;wBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;qBACjC;iBACD,CAAC,CAAC;gBAEH,MAAM,gBAAgB,GAAG,iBAAiB,IAAI,CAAC,OAAO,CAAC,SAAS,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gBAC1H,MAAM,YAAY,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBAC5C,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACP,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,gCAAgC,CAAC,UAAU;oBACnD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;oBACd,OAAO,EAAE,aAAa;oBACtB,IAAI,EAAE;wBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;qBACjC;iBACD,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,OAAO;gBACd,MAAM,EAAE,gCAAgC,CAAC,UAAU;gBACnD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,sBAAsB;gBAC/B,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC;gBACjC,IAAI,EAAE;oBACL,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;iBACnC;aACD,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,gCAAgC,CAAC,UAAU,CAAC;IACpD,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,IAAI,CAAC,aAA8B,CAAC;IAC5C,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,GAAG,CACf,EAAU,EACV,cAAwB,EACxB,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,gCAAgC,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAEhF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAEnD,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,MAAM,MAAM,GAAc,EAAE,CAAC;YAE7B,YAAY,CAAC,IAAI,CAAC,IAAI,gCAAgC,CAAC,cAAc,QAAQ,CAAC,CAAC;YAC/E,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,gCAAgC,CAAC,oBAAoB,CAAC,CAAC;YAEnF,IAAI,cAAc,EAAE,CAAC;gBACpB,YAAY,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACtD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACP,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAkB,QAAQ,CAAC,CAAC;gBAC3E,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;YAED,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;oBACpC,YAAY,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;oBAC7E,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;YACF,CAAC;YAED,MAAM,KAAK,GAAG,kBAAkB,IAAI,CAAC,OAAO,CAAC,SAAS,WAAW,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;YAEtG,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAA2C,CAAC,CAAC;YAE3F,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;oBACnC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;wBAClD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAA0C,CAAC;wBAC7D,IAAI,UAAU,GAAG,IAAI,CAAC,QAAkB,CAAC;wBACzC,UAAU,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;wBAEtC,IACC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC,MAAM;4BAC7C,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC,KAAK,CAAC;4BAC9C,OAAO,GAAG,CAAC,UAAU,CAAC,KAAK,QAAQ,EAClC,CAAC;4BACF,IAAI,KAAc,CAAC;4BACnB,IAAI,CAAC;gCACJ,KAAK,GAAG,IAAI,CAAC,KAAK,CAAE,IAAI,CAAC,CAAC,CAAgC,CAAC,UAAU,CAAW,CAAC,CAAC;4BACnF,CAAC;4BAAC,MAAM,CAAC;gCACR,gDAAgD;gCAChD,wEAAwE;gCACxE,KAAK,GAAI,IAAI,CAAC,CAAC,CAAgC,CAAC,UAAU,CAAC,CAAC;4BAC7D,CAAC;4BACD,OAAQ,IAAI,CAAC,CAAC,CAAgC,CAAC,UAAU,CAAC,CAAC;4BAC1D,IAAI,CAAC,CAAC,CAAgC,CAAC,IAAI,CAAC,QAAkB,CAAC,GAAG,KAAK,CAAC;wBAC1E,CAAC;wBACD,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;4BAC7B,IAAI,CAAC,CAAC,CAAgC,CAAC,IAAI,CAAC,QAAkB,CAAC,GAAG,SAAS,CAAC;wBAC9E,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,MAAM,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtF,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,gCAAgC,CAAC,cAAc,CAAC,CAAC;gBACrF,OAAO,MAAM,CAAC;YACf,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,WAAW,EACX;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,GAAG,CAAC,MAAS,EAAE,UAAoD;QAC/E,MAAM,CAAC,MAAM,CAAI,gCAAgC,CAAC,UAAU,YAAkB,MAAM,CAAC,CAAC;QAEtF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,kBAAkB,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAE5D,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAsB,CAAC;QAE1E,IAAI,CAAC;YACJ,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAa,CAAC,EAAE,CAAC;oBAChF,OAAO;gBACR,CAAC;YACF,CAAC;YAED,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAE/C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;YACzD,KAAK,CAAC,OAAO,CAAC;gBACb,QAAQ,EAAE,gCAAgC,CAAC,cAAyB;gBACpE,IAAI,EAAE,wBAAwB,CAAC,MAAM;aACrC,CAAC,CAAC;YAEH,YAAY,CAAC,WAAW,CACvB,WAAW,EACX,gCAAgC,CAAC,cAAc,EAC/C,YAAY,IAAI,gCAAgC,CAAC,oBAAoB,CACrE,CAAC;YAEF,YAAY,CAAC,WAAW,CACvB,WAAW,EACX,gCAAgC,CAAC,cAAc,EAC/C,YAAY,IAAI,gCAAgC,CAAC,oBAAoB,CACrE,CAAC;YAEF,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAc,EAAE,CAAC;YAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;oBACzE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAkB,CAAC,CAAC;oBACnC,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;wBAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACP,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACzC,CAAC;gBACF,CAAC;YACF,CAAC;YAED,IAAI,GAAG,GAAG,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC;YACpD,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACtD,GAAG,IAAI,YAAY,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACnE,GAAG,IAAI,kBAAkB,gCAAgC,CAAC,cAAc,OAAO,IAAI,CAAC,mBAAmB,CAAC,QAAkB,IAAI,CAAC;YAC/H,GAAG,IAAI,kBAAkB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,iBAAiB,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAEvF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAkC,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,WAAW,EACX;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,MAAM,CAClB,EAAU,EACV,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,gCAAgC,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAEhF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAEnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACpC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3B,MAAM,MAAM,GAAc,EAAE,CAAC;gBAC7B,MAAM,YAAY,GAAa,EAAE,CAAC;gBAElC,YAAY,CAAC,IAAI,CAChB,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAkB,QAAQ,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAC1E,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAEhB,YAAY,CAAC,IAAI,CAChB,IAAI,gCAAgC,CAAC,cAAc,QAAQ,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAC9E,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,gCAAgC,CAAC,oBAAoB,CAAC,CAAC;gBAEnF,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC/B,YAAY,CAAC,IAAI,CAChB,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;wBAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;wBAC7B,OAAO,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;oBAC9D,CAAC,CAAC,CACF,CAAC;gBACH,CAAC;gBAED,MAAM,KAAK,GAAG,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,WAAW,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5F,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAA2C,CAAC,CAAC;YAC/E,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,cAAc,EACd;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,KAAK,CACjB,UAA+B,EAC/B,cAAsE,EACtE,UAAwB,EACxB,MAAe,EACf,KAAc;QAEd,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,KAAK,IAAI,gCAAgC,CAAC,cAAc,CAAC;YAE5E,IAAI,aAAa,GAAW,EAAE,CAAC;YAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnC,MAAM,YAAY,GAAa,EAAE,CAAC;gBAClC,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;oBAC3C,MAAM,SAAS,GAAG,YAAY,CAAC,aAAa,KAAK,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC1F,YAAY,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC,CAAC;gBACtE,CAAC;gBACD,aAAa,GAAG,YAAY,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,CAAC;YAED,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,MAAM,MAAM,GAAc,EAAE,CAAC;YAE7B,MAAM,eAAe,GAAuB;gBAC3C,UAAU,EAAE,EAAE;gBACd,eAAe,EAAE,eAAe,CAAC,GAAG;aACpC,CAAC;YAEF,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC/B,QAAQ,EAAE,gCAAgC,CAAC,cAAc;gBACzD,UAAU,EAAE,kBAAkB,CAAC,MAAM;gBACrC,KAAK,EAAE,YAAY,IAAI,gCAAgC,CAAC,oBAAoB;aAC5E,CAAC,CAAC;YAEH,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3B,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,CAAC,oBAAoB,CAAC,EAAE,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAExE,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAE9C,GAAG,GAAG,UAAU,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC;YACvH,GAAG,IAAI,UAAU,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,GAAG,IAAI,IAAI,aAAa,UAAU,UAAU,WAAW,UAAU,EAAE,CAAC;YAEpE,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAA2C,CAAC,CAAC;YAEzF,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;gBACnC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;oBACxB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;wBAClD,IAAI,UAAU,GAAG,IAAI,CAAC,QAAkB,CAAC;wBACzC,UAAU,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;wBACtC,IACC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC,MAAM;4BAC7C,IAAI,CAAC,IAAI,KAAK,wBAAwB,CAAC,KAAK,CAAC;4BAC9C,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EACzB,CAAC;4BACF,IAAI,KAAc,CAAC;4BACnB,IAAI,CAAC;gCACJ,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAW,CAAC,CAAC;4BAC/C,CAAC;4BAAC,MAAM,CAAC;gCACR,gDAAgD;gCAChD,wEAAwE;gCACxE,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;4BACzB,CAAC;4BACD,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC;4BACvB,GAAG,CAAC,IAAI,CAAC,QAAkB,CAAC,GAAG,KAAK,CAAC;wBACtC,CAAC;wBACD,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;4BAC9B,GAAG,CAAC,IAAI,CAAC,QAAkB,CAAC,GAAG,SAAS,CAAC;wBAC1C,CAAC;oBACF,CAAC;gBACF,CAAC;YACF,CAAC;YAED,MAAM,QAAQ,GAAG,IAA+B,CAAC;YACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC1C,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gCAAgC,CAAC,cAAc,CAAC,CAAC;gBAC1F,QAAQ,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;YACrF,CAAC;YAED,OAAO;gBACN,QAAQ;gBACR,MAAM,EACL,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;oBAC3C,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;oBACxC,CAAC,CAAC,SAAS;aACb,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,aAAa,EACb,EAAE,GAAG,EAAE,EACP,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACJ,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClB,OAAO;YACR,CAAC;YACD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,YAAY,CAAC,MAAM,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;YAErE,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACR,gBAAgB;QACjB,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,cAAc;QAC3B,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CACpC,+DAA+D,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,CACvF,CAAC;YACF,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,qBAAqB;QAClC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YACnD,IAAI,cAAc,EAAE,CAAC;gBACpB,MAAM;YACP,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,WAAW;QACxB,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACnD,MAAM,gBAAgB,GAAG,uBAAuB,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC;YAC3E,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACtE,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,kBAAkB;QAC/B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,WAAW,EAAE,CAAC;gBACjB,MAAM;YACP,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,qBAAqB;QAClC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClB,MAAM;YACP,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,gBAAgB;QAC7B,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACK,sBAAsB;QAC7B,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI;YAC/B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;SAC/B,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,oBAAoB,CAC3B,UAAkB,EAClB,SAAyC,EACzC,YAAsB,EACtB,MAAiB,EACjB,UAAkB;QAElB,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,OAAO;QACR,CAAC;QAED,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvC,OAAO;YACR,CAAC;YACD,MAAM,cAAc,GAAa,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC7D,MAAM,eAAe,GAAa,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAc,EAAE,CAAC;gBAChC,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;gBACjF,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;gBAC1B,UAAU,IAAI,SAAS,CAAC,MAAM,CAAC;gBAC/B,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC/E,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,eAAe,GAAG,CAAC,CAAC;YAE1F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,YAAY,CAAC,IAAI,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC;YACvC,CAAC;YACD,OAAO;QACR,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/F,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAC5C,UAAU,EACV,SAAS,EACT,UAAU,EAAE,IAAI,EAChB,MAAM,EACN,UAAU,CACV,CAAC;QACF,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;OAUG;IACK,qBAAqB,CAC5B,UAAkB,EAClB,UAAuB,EACvB,IAA0C,EAC1C,MAAiB,EACjB,UAAkB;QAElB,IAAI,IAAI,GAAG,UAAU,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,IAAI,IAAI,GAAG,CAAC;QACb,CAAC;QAED,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC;QAE5B,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,EAAE,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACvE,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrF,OAAO,IAAI,IAAI,SAAS,YAAY,GAAG,CAAC;QACzC,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAErB,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ;iBAClC,KAAK,CAAC,GAAG,CAAC;iBACV,KAAK,CAAC,CAAC,CAAC;iBACR,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;iBACvE,IAAI,CAAC,EAAE,CAAC,CAAC;YACX,OAAO,KAAK,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,QAAQ,QAAQ,UAAU,EAAE,CAAC;QACvF,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,MAAM,EAAE,CAAC;YAChE,IAAI,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/D,OAAO,IAAI,IAAI,QAAQ,UAAU,SAAS,CAAC;YAC5C,CAAC;YACD,OAAO,IAAI,IAAI,QAAQ,UAAU,EAAE,CAAC;QACrC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,SAAS,EAAE,CAAC;YACnE,IAAI,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/D,OAAO,IAAI,IAAI,SAAS,UAAU,SAAS,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,IAAI,SAAS,UAAU,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,WAAW,EAAE,CAAC;YACrE,OAAO,IAAI,IAAI,QAAQ,UAAU,EAAE,CAAC;QACrC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,QAAQ,EAAE,CAAC;YAClE,OAAO,IAAI,IAAI,QAAQ,UAAU,EAAE,CAAC;QACrC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;YAC5E,OAAO,IAAI,IAAI,SAAS,UAAU,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,eAAe,EAAE,CAAC;YACzE,OAAO,IAAI,IAAI,SAAS,UAAU,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,QAAQ,EAAE,CAAC;YAClE,uEAAuE;YACvE,IAAI,IAAI,KAAK,wBAAwB,CAAC,MAAM,EAAE,CAAC;gBAC9C,OAAO,IAAI,IAAI,mBAAmB,UAAU,SAAS,CAAC;YACvD,CAAC;YACD,mDAAmD;YACnD,IAAI,IAAI,KAAK,wBAAwB,CAAC,KAAK,IAAI,IAAI,KAAK,wBAAwB,CAAC,MAAM,EAAE,CAAC;gBACzF,OAAO,+CAA+C,IAAI,0BAA0B,UAAU,UAAU,CAAC;YAC1G,CAAC;YACD,6EAA6E;YAC7E,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,wBAAwB,EACxB;gBACC,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,IAAI;aACJ,CACD,CAAC;QACH,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,gCAAgC,CAAC,UAAU,EAAE,wBAAwB,EAAE;YAC7F,UAAU,EAAE,UAAU,CAAC,UAAU;SACjC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,iBAAiB,CAAC,KAAc,EAAE,IAA+B;QACxE,IAAI,IAAI,KAAK,wBAAwB,CAAC,MAAM,EAAE,CAAC;YAC9C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,KAAK,wBAAwB,CAAC,MAAM,EAAE,CAAC;YACrD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,KAAK,wBAAwB,CAAC,OAAO,EAAE,CAAC;YACtD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;aAAM,IACN,IAAI,KAAK,wBAAwB,CAAC,MAAM;YACxC,IAAI,KAAK,wBAAwB,CAAC,KAAK,EACtC,CAAC;YACF,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACK,sBAAsB,CAAC,QAA0B;QACxD,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,eAAe,CAAC,GAAG,EAAE,CAAC;YAC/D,OAAO,KAAK,CAAC;QACd,CAAC;aAAM,IAAI,QAAQ,KAAK,eAAe,CAAC,EAAE,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,gCAAgC,CAAC,UAAU,EAAE,yBAAyB,EAAE;YAC9F,QAAQ;SACR,CAAC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,gBAAgB,CACvB,UAAmD,EACnD,GAAkC;QAElC,OAAO,UAAU,CAAC,KAAK,CACtB,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,QAAkB,CAAC,KAAK,SAAS,CAAC,KAAK,CAC5F,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,uBAAuB,CAAC,YAA8B;QAC7D,MAAM,UAAU,GAAkD;YACjE,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM;YACzC,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM;YACzC,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,SAAS;YAC7C,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,OAAO;YAC1C,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,OAAO;YACzC,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,SAAS;SAC7C,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;YAC9B,MAAM,IAAI,YAAY,CACrB,gCAAgC,CAAC,UAAU,EAC3C,iCAAiC,CACjC,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,CAAC;QAEjC,MAAM,KAAK,GAA+B,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QAEvE,KAAK,CAAC,OAAO,CAAC;YACb,QAAQ,EAAE,gCAAgC,CAAC,cAAyB;YACpE,IAAI,EAAE,wBAAwB,CAAC,MAAM;YACrC,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,KAAK;aAC7B,GAAG,CAAC,IAAI,CAAC,EAAE;YACX,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;YAChD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;YAEvD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACpB,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YAED,OAAO,IAAI,UAAU,KAAK,OAAO,GAAG,QAAQ,EAAE,CAAC;QAChD,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,MAAM,oBAAoB,GACzB,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,OAAO,iBAAiB,GAAG,oBAAoB,CAAC;IACjD,CAAC","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\tIs,\n\tObjectHelper\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 postgres, { type ParameterOrJSON } from \"postgres\";\nimport type { IPostgreSqlEntityStorageConnectorConfig } from \"./models/IPostgreSqlEntityStorageConnectorConfig.js\";\nimport type { IPostgreSqlEntityStorageConnectorConstructorOptions } from \"./models/IPostgreSqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using ql.\n */\nexport class PostgreSqlEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<PostgreSqlEntityStorageConnector>();\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 primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IPostgreSqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate _connection?: postgres.Sql;\n\n\t/**\n\t * Create a new instance of PostgreSqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IPostgreSqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(PostgreSqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IPostgreSqlEntityStorageConnectorConfig>(\n\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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 * Initialize the PostgreSql 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 dbConnection = await this.createConnection();\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: PostgreSqlEntityStorageConnector.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 dbConnection.unsafe(`CREATE DATABASE \"${this._config.database}\";`);\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: PostgreSqlEntityStorageConnector.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\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: PostgreSqlEntityStorageConnector.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\tconst createTableQuery = `CREATE TABLE \"${this._config.tableName}\" (${this.mapPostgreSqlProperties(this._entitySchema)})`;\n\t\t\t\tawait dbConnection.unsafe(createTableQuery);\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: PostgreSqlEntityStorageConnector.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: PostgreSqlEntityStorageConnector.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 * 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 PostgreSqlEntityStorageConnector.CLASS_NAME;\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 * Get an entity from PostgreSql.\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(PostgreSqlEntityStorageConnector.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 dbConnection = await this.createConnection();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\" = $1`);\n\t\t\tvalues.push(partitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\"${String(secondaryIndex)}\" = $2`);\n\t\t\t\tvalues.push(id);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\"${this._primaryKeyProperty.property as string}\" = $2`);\n\t\t\t\tvalues.push(id);\n\t\t\t}\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)}\" = $${values.length + 1}`);\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.tableName}\" WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\n\t\t\tconst rows = await dbConnection.unsafe(query, values as postgres.ParameterOrJSON<never>[]);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tif (this._entitySchema.properties) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tconst row = rows[0] as unknown as { [key: string]: unknown };\n\t\t\t\t\t\tlet propColumn = prop.property as string;\n\t\t\t\t\t\tpropColumn = propColumn.toLowerCase();\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t(prop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array) &&\n\t\t\t\t\t\t\ttypeof row[propColumn] === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tlet value: unknown;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvalue = JSON.parse((rows[0] as { [key: string]: unknown })[propColumn] as string);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// If JSON.parse fails, keep the value as string\n\t\t\t\t\t\t\t\t// This handles cases where plain text was stored in Object/Array fields\n\t\t\t\t\t\t\t\tvalue = (rows[0] as { [key: string]: unknown })[propColumn];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete (rows[0] as { [key: string]: unknown })[propColumn];\n\t\t\t\t\t\t\t(rows[0] as { [key: string]: unknown })[prop.property as string] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (row[propColumn] === null) {\n\t\t\t\t\t\t\t(rows[0] as { [key: string]: unknown })[prop.property as string] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst entity = ObjectHelper.removeEmptyProperties(rows[0] as T, { removeNull: true });\n\t\t\t\tObjectHelper.propertyDelete(entity, PostgreSqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t\treturn entity;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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>(PostgreSqlEntityStorageConnector.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.getSchema());\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: PostgreSqlEntityStorageConnector._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\tPostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\n\t\t\tObjectHelper.propertySet(\n\t\t\t\tfinalEntity,\n\t\t\t\tPostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values: unknown[] = [];\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 (finalEntity[prop.property] === undefined) {\n\t\t\t\t\t\tvalues.push(null);\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.tableName}\"`;\n\t\t\tsql += ` (${keys.map(key => `\"${key}\"`).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map((_, i) => `$${i + 1}`).join(\", \")})`;\n\t\t\tsql += ` ON CONFLICT (\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\", \"${this._primaryKeyProperty.property as string}\")`;\n\t\t\tsql += ` DO UPDATE SET ${keys.map(key => `\"${key}\" = EXCLUDED.\"${key}\"`).join(\", \")};`;\n\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tawait dbConnection.unsafe(sql, values as ParameterOrJSON<never>[]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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 * 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(PostgreSqlEntityStorageConnector.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 dbConnection = await this.createConnection();\n\n\t\t\tconst itemData = await this.get(id);\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(\n\t\t\t\t\t`\"${this._primaryKeyProperty.property as string}\" = $${values.length + 1}`\n\t\t\t\t);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(\n\t\t\t\t\t`\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\" = $${values.length + 1}`\n\t\t\t\t);\n\t\t\t\tvalues.push(partitionKey ?? PostgreSqlEntityStorageConnector._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)}\" = $${values.length}`;\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.tableName}\" WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait dbConnection.unsafe(query, values as postgres.ParameterOrJSON<never>[]);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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 * 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 ?? PostgreSqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.arrayValue(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: PostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey ?? PostgreSqlEntityStorageConnector._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, 1);\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.tableName}\"`;\n\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\tsql += ` ${orderByClause} LIMIT ${returnSize} OFFSET ${startIndex}`;\n\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tconst rows = await dbConnection.unsafe(sql, values as postgres.ParameterOrJSON<never>[]);\n\n\t\t\tif (this._entitySchema.properties) {\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tlet propColumn = prop.property as string;\n\t\t\t\t\t\tpropColumn = propColumn.toLowerCase();\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t(prop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array) &&\n\t\t\t\t\t\t\tIs.string(row[propColumn])\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tlet value: unknown;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvalue = JSON.parse(row[propColumn] as string);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// If JSON.parse fails, keep the value as string\n\t\t\t\t\t\t\t\t// This handles cases where plain text was stored in Object/Array fields\n\t\t\t\t\t\t\t\tvalue = row[propColumn];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete row[propColumn];\n\t\t\t\t\t\t\trow[prop.property as string] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (row[propColumn] === null) {\n\t\t\t\t\t\t\trow[prop.property as string] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst entities = rows as unknown as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tObjectHelper.propertyDelete(entities[i], PostgreSqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t\tentities[i] = ObjectHelper.removeEmptyProperties(entities[i], { removeNull: true });\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(\n\t\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\t{ sql },\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Drop the table.\n\t * @returns Nothing.\n\t */\n\tpublic async tableDrop(): Promise<void> {\n\t\ttry {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tawait dbConnection.unsafe(`DROP TABLE \"${this._config.tableName}\";`);\n\n\t\t\tawait this.waitForTableNotExists();\n\t\t} catch {\n\t\t\t// Ignore errors\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 * @internal\n\t */\n\tprivate async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tconst res = await dbConnection.unsafe(\n\t\t\t\t`SELECT datname FROM pg_catalog.pg_database WHERE datname = '${this._config.database}'`\n\t\t\t);\n\t\t\treturn res.length > 0;\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 dbConnection = await this.createConnection();\n\t\t\tconst tableExistsQuery = `SELECT to_regclass('${this._config.tableName}')`;\n\t\t\tconst tableExistsResult = await dbConnection.unsafe(tableExistsQuery);\n\t\t\treturn tableExistsResult[0].to_regclass !== null;\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 * Create a new DB connection.\n\t * @returns The PostgreSql connection.\n\t * @internal\n\t */\n\tprivate async createConnection(): Promise<postgres.Sql> {\n\t\tif (Is.empty(this._connection)) {\n\t\t\tthis._connection = postgres(this.createConnectionConfig());\n\t\t}\n\t\treturn this._connection;\n\t}\n\n\t/**\n\t * Create a new DB connection configuration.\n\t * @returns The PostgreSql connection configuration.\n\t * @internal\n\t */\n\tprivate createConnectionConfig(): postgres.Options<{ [key: string]: postgres.PostgresType }> {\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 5432,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password\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 * @param valueIndex The current value index.\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\tvalueIndex: number\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, valueIndex);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\tvalueIndex += subValues.length;\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(\n\t\t\tobjectPath,\n\t\t\tcondition,\n\t\t\tschemaProp?.type,\n\t\t\tvalues,\n\t\t\tvalueIndex\n\t\t);\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 * @param valueIndex The current value index.\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\tvalueIndex: number\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((_, index) => `$${valueIndex + index}`).join(\", \");\n\t\t\treturn `\"${prop}\" IN (${placeholders})`;\n\t\t}\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 jsonPath = comparator.property\n\t\t\t\t.split(\".\")\n\t\t\t\t.slice(1)\n\t\t\t\t.map((p, i, arr) => (i === arr.length - 1 ? `->> '${p}'` : `-> '${p}'`))\n\t\t\t\t.join(\"\");\n\t\t\treturn `(\"${comparator.property.split(\".\")[0]}\"::jsonb ${jsonPath}) = $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\treturn `\"${prop}\" = $${valueIndex}::jsonb`;\n\t\t\t}\n\t\t\treturn `\"${prop}\" = $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\tif (Is.object(comparator.value) || Is.array(comparator.value)) {\n\t\t\t\treturn `\"${prop}\" != $${valueIndex}::jsonb`;\n\t\t\t}\n\t\t\treturn `\"${prop}\" <> $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThan) {\n\t\t\treturn `\"${prop}\" > $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThan) {\n\t\t\treturn `\"${prop}\" < $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {\n\t\t\treturn `\"${prop}\" >= $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {\n\t\t\treturn `\"${prop}\" <= $${valueIndex}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\t// For string fields, use ILIKE for case-insensitive substring matching\n\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\treturn `\"${prop}\" ILIKE '%' || $${valueIndex} || '%'`;\n\t\t\t}\n\t\t\t// For array and object fields, use jsonb operators\n\t\t\tif (type === EntitySchemaPropertyType.Array || type === EntitySchemaPropertyType.Object) {\n\t\t\t\treturn `EXISTS (SELECT 1 FROM jsonb_array_elements(\"${prop}\") elem WHERE elem @> $${valueIndex}::jsonb)`;\n\t\t\t}\n\t\t\t// Includes operator is not supported for other types (number, boolean, etc.)\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"comparisonNotSupported\",\n\t\t\t\t{\n\t\t\t\t\tcomparison: comparator.comparison,\n\t\t\t\t\ttype\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tthrow new GeneralError(PostgreSqlEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\tcomparison: comparator.comparison\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 (type === EntitySchemaPropertyType.String) {\n\t\t\treturn String(value);\n\t\t} else if (type === EntitySchemaPropertyType.Number) {\n\t\t\treturn Number(value);\n\t\t} else if (type === EntitySchemaPropertyType.Boolean) {\n\t\t\treturn Boolean(value);\n\t\t} else if (\n\t\t\ttype === EntitySchemaPropertyType.Object ||\n\t\t\ttype === EntitySchemaPropertyType.Array\n\t\t) {\n\t\t\treturn value;\n\t\t}\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(PostgreSqlEntityStorageConnector.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 entitySchema The schema of the entity.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t */\n\tprivate mapPostgreSqlProperties(entitySchema: IEntitySchema<T>): string {\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"TEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"REAL\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INTEGER\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSONB\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSONB\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"BOOLEAN\"\n\t\t};\n\n\t\tif (!entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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: PostgreSqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\toptional: false,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tconst sqlType = sqlTypeMap[prop.type] || \"TEXT\";\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\tprimaryKeys.push(columnName);\n\t\t\t\t}\n\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":"postgreSqlEntityStorageConnector.js","sourceRoot":"","sources":["../../src/postgreSqlEntityStorageConnector.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\tIs,\n\tObjectHelper\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 postgres, { type ParameterOrJSON } from \"postgres\";\nimport type { IPostgreSqlEntityStorageConnectorConfig } from \"./models/IPostgreSqlEntityStorageConnectorConfig.js\";\nimport type { IPostgreSqlEntityStorageConnectorConstructorOptions } from \"./models/IPostgreSqlEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using ql.\n */\nexport class PostgreSqlEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<PostgreSqlEntityStorageConnector>();\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 primary key property.\n\t * @internal\n\t */\n\tprivate readonly _primaryKeyProperty: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IPostgreSqlEntityStorageConnectorConfig;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate _connection?: postgres.Sql;\n\n\t/**\n\t * Create a new instance of PostgreSqlEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IPostgreSqlEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(PostgreSqlEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IPostgreSqlEntityStorageConnectorConfig>(\n\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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\tPostgreSqlEntityStorageConnector.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 * Initialize the PostgreSql 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 dbConnection = await this.createConnection();\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: PostgreSqlEntityStorageConnector.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 dbConnection.unsafe(`CREATE DATABASE \"${this._config.database}\";`);\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: PostgreSqlEntityStorageConnector.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\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: PostgreSqlEntityStorageConnector.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\tconst createTableQuery = `CREATE TABLE \"${this._config.tableName}\" (${this.mapPostgreSqlProperties(this._entitySchema)})`;\n\t\t\t\tawait dbConnection.unsafe(createTableQuery);\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: PostgreSqlEntityStorageConnector.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: PostgreSqlEntityStorageConnector.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 * 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 PostgreSqlEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._connection) {\n\t\t\tawait this._connection.end();\n\t\t\tthis._connection = undefined;\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 * Get an entity from PostgreSql.\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(PostgreSqlEntityStorageConnector.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 dbConnection = await this.createConnection();\n\n\t\t\tconst whereClauses: string[] = [];\n\t\t\tconst values: unknown[] = [];\n\n\t\t\twhereClauses.push(`\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\" = $1`);\n\t\t\tvalues.push(partitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE);\n\n\t\t\tif (secondaryIndex) {\n\t\t\t\twhereClauses.push(`\"${String(secondaryIndex)}\" = $2`);\n\t\t\t\tvalues.push(id);\n\t\t\t} else {\n\t\t\t\twhereClauses.push(`\"${this._primaryKeyProperty.property as string}\" = $2`);\n\t\t\t\tvalues.push(id);\n\t\t\t}\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)}\" = $${values.length + 1}`);\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.tableName}\" WHERE ${whereClauses.join(\" AND \")} LIMIT 1`;\n\n\t\t\tconst rows = await dbConnection.unsafe(query, values as postgres.ParameterOrJSON<never>[]);\n\n\t\t\tif (Is.array(rows) && rows.length === 1) {\n\t\t\t\tif (this._entitySchema.properties) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tconst row = rows[0] as unknown as { [key: string]: unknown };\n\t\t\t\t\t\tlet propColumn = prop.property as string;\n\t\t\t\t\t\tpropColumn = propColumn.toLowerCase();\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t(prop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array) &&\n\t\t\t\t\t\t\ttypeof row[propColumn] === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tlet value: unknown;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvalue = JSON.parse((rows[0] as { [key: string]: unknown })[propColumn] as string);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// If JSON.parse fails, keep the value as string\n\t\t\t\t\t\t\t\t// This handles cases where plain text was stored in Object/Array fields\n\t\t\t\t\t\t\t\tvalue = (rows[0] as { [key: string]: unknown })[propColumn];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete (rows[0] as { [key: string]: unknown })[propColumn];\n\t\t\t\t\t\t\t(rows[0] as { [key: string]: unknown })[prop.property as string] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (row[propColumn] === null) {\n\t\t\t\t\t\t\t(rows[0] as { [key: string]: unknown })[prop.property as string] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst entity = ObjectHelper.removeEmptyProperties(rows[0] as T, { removeNull: true });\n\t\t\t\tObjectHelper.propertyDelete(entity, PostgreSqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t\treturn entity;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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>(PostgreSqlEntityStorageConnector.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.getSchema());\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: PostgreSqlEntityStorageConnector._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\tPostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\n\t\t\tObjectHelper.propertySet(\n\t\t\t\tfinalEntity,\n\t\t\t\tPostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey ?? PostgreSqlEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\n\t\t\tconst keys: string[] = [];\n\t\t\tconst values: unknown[] = [];\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 (finalEntity[prop.property] === undefined) {\n\t\t\t\t\t\tvalues.push(null);\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.tableName}\"`;\n\t\t\tsql += ` (${keys.map(key => `\"${key}\"`).join(\", \")})`;\n\t\t\tsql += ` VALUES (${values.map((_, i) => `$${i + 1}`).join(\", \")})`;\n\t\t\tsql += ` ON CONFLICT (\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\", \"${this._primaryKeyProperty.property as string}\")`;\n\t\t\tsql += ` DO UPDATE SET ${keys.map(key => `\"${key}\" = EXCLUDED.\"${key}\"`).join(\", \")};`;\n\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tawait dbConnection.unsafe(sql, values as ParameterOrJSON<never>[]);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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 * 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(PostgreSqlEntityStorageConnector.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 dbConnection = await this.createConnection();\n\n\t\t\tconst itemData = await this.get(id);\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(\n\t\t\t\t\t`\"${this._primaryKeyProperty.property as string}\" = $${values.length + 1}`\n\t\t\t\t);\n\t\t\t\tvalues.push(id);\n\n\t\t\t\twhereClauses.push(\n\t\t\t\t\t`\"${PostgreSqlEntityStorageConnector._PARTITION_KEY}\" = $${values.length + 1}`\n\t\t\t\t);\n\t\t\t\tvalues.push(partitionKey ?? PostgreSqlEntityStorageConnector._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)}\" = $${values.length}`;\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.tableName}\" WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\t\tawait dbConnection.unsafe(query, values as postgres.ParameterOrJSON<never>[]);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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 * 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 ?? PostgreSqlEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Is.arrayValue(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: PostgreSqlEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey ?? PostgreSqlEntityStorageConnector._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, 1);\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.tableName}\"`;\n\t\t\tsql += ` WHERE ${whereClauses.join(\" AND \")}`;\n\t\t\tsql += ` ${orderByClause} LIMIT ${returnSize} OFFSET ${startIndex}`;\n\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tconst rows = await dbConnection.unsafe(sql, values as postgres.ParameterOrJSON<never>[]);\n\n\t\t\tif (this._entitySchema.properties) {\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tlet propColumn = prop.property as string;\n\t\t\t\t\t\tpropColumn = propColumn.toLowerCase();\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t(prop.type === EntitySchemaPropertyType.Object ||\n\t\t\t\t\t\t\t\tprop.type === EntitySchemaPropertyType.Array) &&\n\t\t\t\t\t\t\tIs.string(row[propColumn])\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tlet value: unknown;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tvalue = JSON.parse(row[propColumn] as string);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// If JSON.parse fails, keep the value as string\n\t\t\t\t\t\t\t\t// This handles cases where plain text was stored in Object/Array fields\n\t\t\t\t\t\t\t\tvalue = row[propColumn];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdelete row[propColumn];\n\t\t\t\t\t\t\trow[prop.property as string] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (row[propColumn] === null) {\n\t\t\t\t\t\t\trow[prop.property as string] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst entities = rows as unknown as Partial<T>[];\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tObjectHelper.propertyDelete(entities[i], PostgreSqlEntityStorageConnector._PARTITION_KEY);\n\t\t\t\tentities[i] = ObjectHelper.removeEmptyProperties(entities[i], { removeNull: true });\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(\n\t\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\t{ sql },\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Drop the table.\n\t * @returns Nothing.\n\t */\n\tpublic async tableDrop(): Promise<void> {\n\t\ttry {\n\t\t\tconst tableExists = await this.tableExists();\n\t\t\tif (!tableExists) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tawait dbConnection.unsafe(`DROP TABLE \"${this._config.tableName}\";`);\n\n\t\t\tawait this.waitForTableNotExists();\n\t\t} catch {\n\t\t\t// Ignore errors\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 * @internal\n\t */\n\tprivate async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst dbConnection = await this.createConnection();\n\t\t\tconst res = await dbConnection.unsafe(\n\t\t\t\t`SELECT datname FROM pg_catalog.pg_database WHERE datname = '${this._config.database}'`\n\t\t\t);\n\t\t\treturn res.length > 0;\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 dbConnection = await this.createConnection();\n\t\t\tconst tableExistsQuery = `SELECT to_regclass('${this._config.tableName}')`;\n\t\t\tconst tableExistsResult = await dbConnection.unsafe(tableExistsQuery);\n\t\t\treturn tableExistsResult[0].to_regclass !== null;\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 * Create a new DB connection.\n\t * @returns The PostgreSql connection.\n\t * @internal\n\t */\n\tprivate async createConnection(): Promise<postgres.Sql> {\n\t\tif (Is.empty(this._connection)) {\n\t\t\tthis._connection = postgres(this.createConnectionConfig());\n\t\t}\n\t\treturn this._connection;\n\t}\n\n\t/**\n\t * Create a new DB connection configuration.\n\t * @returns The PostgreSql connection configuration.\n\t * @internal\n\t */\n\tprivate createConnectionConfig(): postgres.Options<{ [key: string]: postgres.PostgresType }> {\n\t\treturn {\n\t\t\thost: this._config.host,\n\t\t\tport: this._config.port ?? 5432,\n\t\t\tuser: this._config.user,\n\t\t\tpassword: this._config.password\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 * @param valueIndex The current value index.\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\tvalueIndex: number\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, valueIndex);\n\t\t\t\tvalues.push(...subValues);\n\t\t\t\tvalueIndex += subValues.length;\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(\n\t\t\tobjectPath,\n\t\t\tcondition,\n\t\t\tschemaProp?.type,\n\t\t\tvalues,\n\t\t\tvalueIndex\n\t\t);\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 * @param valueIndex The current value index.\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\tvalueIndex: number\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((_, index) => `$${valueIndex + index}`).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 nestedParts = comparator.property.split(\".\").slice(1);\n\t\t\t\t\tconst jsonPath = nestedParts\n\t\t\t\t\t\t.map((p, i, arr) => (i === arr.length - 1 ? `->> '${p}'` : `-> '${p}'`))\n\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\tconst jsonTextExpr = `(\"${rootProp}\"::jsonb ${jsonPath})`;\n\t\t\t\t\treturn `${jsonTextExpr} ${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 nestedParts = comparator.property.split(\".\").slice(1);\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 = nestedParts\n\t\t\t\t.map((p, i, arr) => (i === arr.length - 1 ? `->> '${p}'` : `-> '${p}'`))\n\t\t\t\t.join(\"\");\n\t\t\tconst jsonTextExpr = `(\"${rootProp}\"::jsonb ${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\tif (isArray) {\n\t\t\t\t\t\tconst elemPath = nestedParts\n\t\t\t\t\t\t\t.map((p, i, arr) => (i === arr.length - 1 ? `->>'${p}'` : `->'${p}'`))\n\t\t\t\t\t\t\t.join(\"\");\n\t\t\t\t\t\treturn `EXISTS (SELECT 1 FROM jsonb_array_elements(\"${rootProp}\") elem WHERE LOWER(elem${elemPath}) ILIKE $${valueIndex})`;\n\t\t\t\t\t}\n\t\t\t\t\treturn `LOWER(${jsonTextExpr}) ILIKE $${valueIndex}`;\n\t\t\t\t}\n\t\t\t\tcase ComparisonOperator.NotEquals:\n\t\t\t\t\treturn `${jsonTextExpr} <> $${valueIndex}`;\n\t\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\t\treturn `${jsonTextExpr} > $${valueIndex}`;\n\t\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\t\treturn `${jsonTextExpr} < $${valueIndex}`;\n\t\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\t\treturn `${jsonTextExpr} >= $${valueIndex}`;\n\t\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\t\treturn `${jsonTextExpr} <= $${valueIndex}`;\n\t\t\t\tdefault:\n\t\t\t\t\treturn `${jsonTextExpr} = $${valueIndex}`;\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 `\"${prop}\" = $${valueIndex}::jsonb`;\n\t\t\t\t}\n\t\t\t\treturn `\"${prop}\" = $${valueIndex}`;\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 `\"${prop}\" != $${valueIndex}::jsonb`;\n\t\t\t\t}\n\t\t\t\treturn `\"${prop}\" <> $${valueIndex}`;\n\t\t\tcase ComparisonOperator.GreaterThan:\n\t\t\t\treturn `\"${prop}\" > $${valueIndex}`;\n\t\t\tcase ComparisonOperator.LessThan:\n\t\t\t\treturn `\"${prop}\" < $${valueIndex}`;\n\t\t\tcase ComparisonOperator.GreaterThanOrEqual:\n\t\t\t\treturn `\"${prop}\" >= $${valueIndex}`;\n\t\t\tcase ComparisonOperator.LessThanOrEqual:\n\t\t\t\treturn `\"${prop}\" <= $${valueIndex}`;\n\t\t\tcase ComparisonOperator.Includes: {\n\t\t\t\tif (type === EntitySchemaPropertyType.String) {\n\t\t\t\t\treturn `\"${prop}\" ILIKE '%' || $${valueIndex} || '%'`;\n\t\t\t\t}\n\t\t\t\tif (type === EntitySchemaPropertyType.Array || type === EntitySchemaPropertyType.Object) {\n\t\t\t\t\treturn `EXISTS (SELECT 1 FROM jsonb_array_elements(\"${prop}\") elem WHERE elem @> $${valueIndex}::jsonb)`;\n\t\t\t\t}\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"comparisonNotSupported\",\n\t\t\t\t\t{\n\t\t\t\t\t\tcomparison: comparator.comparison,\n\t\t\t\t\t\ttype\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tPostgreSqlEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"comparisonNotSupported\",\n\t\t\t\t\t{\n\t\t\t\t\t\tcomparison: comparator.comparison\n\t\t\t\t\t}\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 (type === EntitySchemaPropertyType.String) {\n\t\t\treturn String(value);\n\t\t} else if (type === EntitySchemaPropertyType.Number) {\n\t\t\treturn Number(value);\n\t\t} else if (type === EntitySchemaPropertyType.Boolean) {\n\t\t\treturn Boolean(value);\n\t\t} else if (\n\t\t\ttype === EntitySchemaPropertyType.Object ||\n\t\t\ttype === EntitySchemaPropertyType.Array\n\t\t) {\n\t\t\treturn value;\n\t\t}\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(PostgreSqlEntityStorageConnector.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 entitySchema The schema of the entity.\n\t * @returns The SQL properties as a string.\n\t * @throws GeneralError if the entity properties do not exist.\n\t */\n\tprivate mapPostgreSqlProperties(entitySchema: IEntitySchema<T>): string {\n\t\tconst sqlTypeMap: { [key in EntitySchemaPropertyType]: string } = {\n\t\t\t[EntitySchemaPropertyType.String]: \"TEXT\",\n\t\t\t[EntitySchemaPropertyType.Number]: \"REAL\",\n\t\t\t[EntitySchemaPropertyType.Integer]: \"INTEGER\",\n\t\t\t[EntitySchemaPropertyType.Object]: \"JSONB\",\n\t\t\t[EntitySchemaPropertyType.Array]: \"JSONB\",\n\t\t\t[EntitySchemaPropertyType.Boolean]: \"BOOLEAN\"\n\t\t};\n\n\t\tif (!entitySchema.properties) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tPostgreSqlEntityStorageConnector.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: PostgreSqlEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\ttype: EntitySchemaPropertyType.String,\n\t\t\toptional: false,\n\t\t\tisPrimary: true\n\t\t});\n\n\t\tconst columnDefinitions = props\n\t\t\t.map(prop => {\n\t\t\t\tconst sqlType = sqlTypeMap[prop.type] || \"TEXT\";\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\tprimaryKeys.push(columnName);\n\t\t\t\t}\n\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"]}
@@ -25,6 +25,11 @@ export declare class PostgreSqlEntityStorageConnector<T = unknown> implements IE
25
25
  * @returns The class name of the component.
26
26
  */
27
27
  className(): string;
28
+ /**
29
+ * The component needs to be stopped when the node is closed.
30
+ * @returns Nothing.
31
+ */
32
+ stop(): Promise<void>;
28
33
  /**
29
34
  * Get the schema for the entities.
30
35
  * @returns The schema for the entities.
package/docs/changelog.md CHANGED
@@ -1,4 +1,36 @@
1
- # @twin.org/entity-storage-connector-postgresql - Changelog
1
+ # Changelog
2
+
3
+ ## [0.0.3-next.8](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-postgresql-v0.0.3-next.7...entity-storage-connector-postgresql-v0.0.3-next.8) (2026-03-20)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * tests and fixes for the comparisons for null and undefined ([#79](https://github.com/twinfoundation/entity-storage/issues/79)) ([e7ffd62](https://github.com/twinfoundation/entity-storage/commit/e7ffd62e9ec40ef31498e6e2350bb25d9c84638a))
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.7 to 0.0.3-next.8
16
+ * devDependencies
17
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.7 to 0.0.3-next.8
18
+
19
+ ## [0.0.3-next.7](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-postgresql-v0.0.3-next.6...entity-storage-connector-postgresql-v0.0.3-next.7) (2026-03-13)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * adding tests and fixes for dot notation ([#76](https://github.com/twinfoundation/entity-storage/issues/76)) ([3879337](https://github.com/twinfoundation/entity-storage/commit/387933797e33543e4d8b2d49b8beeb792512a4ff))
25
+
26
+
27
+ ### Dependencies
28
+
29
+ * The following workspace dependencies were updated
30
+ * dependencies
31
+ * @twin.org/entity-storage-models bumped from 0.0.3-next.6 to 0.0.3-next.7
32
+ * devDependencies
33
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.6 to 0.0.3-next.7
2
34
 
3
35
  ## [0.0.3-next.6](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-postgresql-v0.0.3-next.5...entity-storage-connector-postgresql-v0.0.3-next.6) (2026-01-21)
4
36
 
package/docs/examples.md CHANGED
@@ -1 +1,98 @@
1
- # @twin.org/entity-storage-connector-postgresql - Examples
1
+ # Entity Storage Connector PostgreSQL Examples
2
+
3
+ These snippets demonstrate day-to-day usage with PostgreSQL, including setup, CRUD operations, conditional query calls, and table cleanup.
4
+
5
+ ## PostgreSqlEntityStorageConnector
6
+
7
+ ```typescript
8
+ import {
9
+ PostgreSqlEntityStorageConnector,
10
+ type IPostgreSqlEntityStorageConnectorConstructorOptions
11
+ } from '@twin.org/entity-storage-connector-postgresql';
12
+ import {
13
+ ComparisonOperator,
14
+ LogicalOperator,
15
+ SortDirection,
16
+ type EntityCondition
17
+ } from '@twin.org/entity';
18
+
19
+ interface Profile {
20
+ id: string;
21
+ email: string;
22
+ status: 'active' | 'inactive';
23
+ createdAt: string;
24
+ }
25
+
26
+ const options: IPostgreSqlEntityStorageConnectorConstructorOptions = {
27
+ entitySchema: 'Profile',
28
+ config: {
29
+ host: 'localhost',
30
+ port: 5432,
31
+ user: 'postgres',
32
+ password: 'postgres',
33
+ database: 'entity_storage',
34
+ tableName: 'profiles'
35
+ }
36
+ };
37
+
38
+ const connector = new PostgreSqlEntityStorageConnector<Profile>(options);
39
+ await connector.bootstrap();
40
+
41
+ const className = connector.className();
42
+ const schema = connector.getSchema();
43
+
44
+ await connector.set({
45
+ id: 'profile-1',
46
+ email: 'ada@example.com',
47
+ status: 'active',
48
+ createdAt: '2026-03-09T10:30:00.000Z'
49
+ });
50
+
51
+ const byPrimaryKey = await connector.get('profile-1');
52
+ const bySecondaryIndex = await connector.get('ada@example.com', 'email');
53
+
54
+ const activeCondition: EntityCondition<Profile> = {
55
+ logicalOperator: LogicalOperator.And,
56
+ conditions: [
57
+ {
58
+ property: 'status',
59
+ comparison: ComparisonOperator.Equals,
60
+ value: 'active'
61
+ }
62
+ ]
63
+ };
64
+
65
+ const result = await connector.query(
66
+ activeCondition,
67
+ [{ property: 'createdAt', sortDirection: SortDirection.Descending }],
68
+ ['id', 'email', 'status'],
69
+ undefined,
70
+ 25
71
+ );
72
+
73
+ await connector.remove('profile-1');
74
+ ```
75
+
76
+ ```typescript
77
+ import { PostgreSqlEntityStorageConnector } from '@twin.org/entity-storage-connector-postgresql';
78
+
79
+ interface Profile {
80
+ id: string;
81
+ email: string;
82
+ status: 'active' | 'inactive';
83
+ createdAt: string;
84
+ }
85
+
86
+ const connector = new PostgreSqlEntityStorageConnector<Profile>({
87
+ entitySchema: 'Profile',
88
+ config: {
89
+ host: 'localhost',
90
+ user: 'postgres',
91
+ password: 'postgres',
92
+ database: 'entity_storage',
93
+ tableName: 'profiles'
94
+ }
95
+ });
96
+
97
+ await connector.tableDrop();
98
+ ```
@@ -34,7 +34,7 @@ The options for the connector.
34
34
 
35
35
  ## Properties
36
36
 
37
- ### CLASS\_NAME
37
+ ### CLASS\_NAME {#class_name}
38
38
 
39
39
  > `readonly` `static` **CLASS\_NAME**: `string`
40
40
 
@@ -42,7 +42,7 @@ Runtime name for the class.
42
42
 
43
43
  ## Methods
44
44
 
45
- ### bootstrap()
45
+ ### bootstrap() {#bootstrap}
46
46
 
47
47
  > **bootstrap**(`nodeLoggingComponentType?`): `Promise`\<`boolean`\>
48
48
 
@@ -68,7 +68,7 @@ A promise that resolves to a boolean indicating success.
68
68
 
69
69
  ***
70
70
 
71
- ### className()
71
+ ### className() {#classname}
72
72
 
73
73
  > **className**(): `string`
74
74
 
@@ -86,7 +86,25 @@ The class name of the component.
86
86
 
87
87
  ***
88
88
 
89
- ### getSchema()
89
+ ### stop() {#stop}
90
+
91
+ > **stop**(): `Promise`\<`void`\>
92
+
93
+ The component needs to be stopped when the node is closed.
94
+
95
+ #### Returns
96
+
97
+ `Promise`\<`void`\>
98
+
99
+ Nothing.
100
+
101
+ #### Implementation of
102
+
103
+ `IEntityStorageConnector.stop`
104
+
105
+ ***
106
+
107
+ ### getSchema() {#getschema}
90
108
 
91
109
  > **getSchema**(): `IEntitySchema`
92
110
 
@@ -104,7 +122,7 @@ The schema for the entities.
104
122
 
105
123
  ***
106
124
 
107
- ### get()
125
+ ### get() {#get}
108
126
 
109
127
  > **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`T` \| `undefined`\>
110
128
 
@@ -142,7 +160,7 @@ The object if it can be found or undefined.
142
160
 
143
161
  ***
144
162
 
145
- ### set()
163
+ ### set() {#set}
146
164
 
147
165
  > **set**(`entity`, `conditions?`): `Promise`\<`void`\>
148
166
 
@@ -174,7 +192,7 @@ The id of the entity.
174
192
 
175
193
  ***
176
194
 
177
- ### remove()
195
+ ### remove() {#remove}
178
196
 
179
197
  > **remove**(`id`, `conditions?`): `Promise`\<`void`\>
180
198
 
@@ -206,7 +224,7 @@ Nothing.
206
224
 
207
225
  ***
208
226
 
209
- ### query()
227
+ ### query() {#query}
210
228
 
211
229
  > **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `limit?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
212
230
 
@@ -257,7 +275,7 @@ and a cursor which can be used to request more entities.
257
275
 
258
276
  ***
259
277
 
260
- ### tableDrop()
278
+ ### tableDrop() {#tabledrop}
261
279
 
262
280
  > **tableDrop**(): `Promise`\<`void`\>
263
281
 
@@ -4,7 +4,7 @@ Configuration for the PostgreSql Entity Storage Connector.
4
4
 
5
5
  ## Properties
6
6
 
7
- ### host
7
+ ### host {#host}
8
8
 
9
9
  > **host**: `string`
10
10
 
@@ -12,15 +12,15 @@ The host for the PostgreSql instance.
12
12
 
13
13
  ***
14
14
 
15
- ### port?
15
+ ### port? {#port}
16
16
 
17
- > `optional` **port**: `number`
17
+ > `optional` **port?**: `number`
18
18
 
19
19
  The port for the PostgreSql instance.
20
20
 
21
21
  ***
22
22
 
23
- ### user
23
+ ### user {#user}
24
24
 
25
25
  > **user**: `string`
26
26
 
@@ -28,7 +28,7 @@ The user for the PostgreSql instance.
28
28
 
29
29
  ***
30
30
 
31
- ### password
31
+ ### password {#password}
32
32
 
33
33
  > **password**: `string`
34
34
 
@@ -36,7 +36,7 @@ The password for the PostgreSql instance.
36
36
 
37
37
  ***
38
38
 
39
- ### database
39
+ ### database {#database}
40
40
 
41
41
  > **database**: `string`
42
42
 
@@ -44,7 +44,7 @@ The name of the database to be used.
44
44
 
45
45
  ***
46
46
 
47
- ### tableName
47
+ ### tableName {#tablename}
48
48
 
49
49
  > **tableName**: `string`
50
50
 
@@ -4,7 +4,7 @@ The options for the PostgreSql entity storage connector constructor.
4
4
 
5
5
  ## Properties
6
6
 
7
- ### entitySchema
7
+ ### entitySchema {#entityschema}
8
8
 
9
9
  > **entitySchema**: `string`
10
10
 
@@ -12,17 +12,17 @@ The schema for the entity.
12
12
 
13
13
  ***
14
14
 
15
- ### partitionContextIds?
15
+ ### partitionContextIds? {#partitioncontextids}
16
16
 
17
- > `optional` **partitionContextIds**: `string`[]
17
+ > `optional` **partitionContextIds?**: `string`[]
18
18
 
19
19
  The keys to use from the context ids to create partitions.
20
20
 
21
21
  ***
22
22
 
23
- ### loggingComponentType?
23
+ ### loggingComponentType? {#loggingcomponenttype}
24
24
 
25
- > `optional` **loggingComponentType**: `string`
25
+ > `optional` **loggingComponentType?**: `string`
26
26
 
27
27
  The type of logging component to use.
28
28
 
@@ -34,7 +34,7 @@ logging
34
34
 
35
35
  ***
36
36
 
37
- ### config
37
+ ### config {#config}
38
38
 
39
39
  > **config**: [`IPostgreSqlEntityStorageConnectorConfig`](IPostgreSqlEntityStorageConnectorConfig.md)
40
40
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-postgresql",
3
- "version": "0.0.3-next.6",
4
- "description": "Entity Storage connector implementation using PostgreSql storage",
3
+ "version": "0.0.3-next.8",
4
+ "description": "PostgreSQL connector for relational persistence and advanced SQL features.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/twinfoundation/entity-storage.git",
@@ -17,10 +17,10 @@
17
17
  "@twin.org/context": "next",
18
18
  "@twin.org/core": "next",
19
19
  "@twin.org/entity": "next",
20
- "@twin.org/entity-storage-models": "0.0.3-next.6",
20
+ "@twin.org/entity-storage-models": "0.0.3-next.8",
21
21
  "@twin.org/logging-models": "next",
22
22
  "@twin.org/nameof": "next",
23
- "postgres": "3.4.7"
23
+ "postgres": "3.4.8"
24
24
  },
25
25
  "main": "./dist/es/index.js",
26
26
  "types": "./dist/types/index.d.ts",