@twin.org/entity 0.0.3-next.9 → 0.0.4-next.1

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.
Files changed (43) hide show
  1. package/README.md +1 -5
  2. package/dist/es/decorators/entityDecorator.js +2 -1
  3. package/dist/es/decorators/entityDecorator.js.map +1 -1
  4. package/dist/es/decorators/propertyDecorator.js +1 -0
  5. package/dist/es/decorators/propertyDecorator.js.map +1 -1
  6. package/dist/es/index.js +2 -0
  7. package/dist/es/index.js.map +1 -1
  8. package/dist/es/models/IEntitySchemaDiff.js +2 -0
  9. package/dist/es/models/IEntitySchemaDiff.js.map +1 -0
  10. package/dist/es/utils/decoratorHelper.js +1 -0
  11. package/dist/es/utils/decoratorHelper.js.map +1 -1
  12. package/dist/es/utils/entityConditions.js +10 -0
  13. package/dist/es/utils/entityConditions.js.map +1 -1
  14. package/dist/es/utils/entitySchemaDiffHelper.js +139 -0
  15. package/dist/es/utils/entitySchemaDiffHelper.js.map +1 -0
  16. package/dist/types/decorators/entityDecorator.d.ts +1 -0
  17. package/dist/types/decorators/propertyDecorator.d.ts +1 -0
  18. package/dist/types/index.d.ts +2 -0
  19. package/dist/types/models/IEntitySchemaDiff.d.ts +33 -0
  20. package/dist/types/utils/decoratorHelper.d.ts +1 -0
  21. package/dist/types/utils/entitySchemaDiffHelper.d.ts +44 -0
  22. package/docs/changelog.md +885 -98
  23. package/docs/examples.md +70 -1
  24. package/docs/reference/classes/DecoratorHelper.md +2 -2
  25. package/docs/reference/classes/EntityConditions.md +2 -2
  26. package/docs/reference/classes/EntitySchemaDiffHelper.md +147 -0
  27. package/docs/reference/classes/EntitySchemaHelper.md +6 -6
  28. package/docs/reference/classes/EntitySorter.md +4 -4
  29. package/docs/reference/index.md +2 -0
  30. package/docs/reference/interfaces/IComparator.md +3 -3
  31. package/docs/reference/interfaces/IComparatorGroup.md +3 -3
  32. package/docs/reference/interfaces/IEntitySchema.md +5 -5
  33. package/docs/reference/interfaces/IEntitySchemaDiff.md +59 -0
  34. package/docs/reference/interfaces/IEntitySchemaOptions.md +2 -2
  35. package/docs/reference/interfaces/IEntitySchemaProperty.md +20 -20
  36. package/docs/reference/interfaces/IEntitySort.md +3 -3
  37. package/docs/reference/variables/ComparisonOperator.md +9 -9
  38. package/docs/reference/variables/EntitySchemaPropertyFormat.md +17 -17
  39. package/docs/reference/variables/EntitySchemaPropertyType.md +6 -6
  40. package/docs/reference/variables/LogicalOperator.md +2 -2
  41. package/docs/reference/variables/SortDirection.md +2 -2
  42. package/locales/en.json +4 -0
  43. package/package.json +7 -6
package/README.md CHANGED
@@ -1,10 +1,6 @@
1
1
  # TWIN Entity
2
2
 
3
- This package contains helper methods and classes for working with entities.
4
-
5
- - Defining
6
- - Sorting
7
- - Comparing
3
+ This package is part of the framework workspace and provides helpers for defining and working with entities to support consistent development workflows across the ecosystem.
8
4
 
9
5
  ## Installation
10
6
 
@@ -1,7 +1,8 @@
1
- // Copyright 2024 IOTA Stiftung.
1
+ // Copyright 2026 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
4
  import "reflect-metadata";
5
+ import "tslib";
5
6
  import { DecoratorHelper } from "../utils/decoratorHelper.js";
6
7
  /**
7
8
  * Decorator to produce schema data for entity.
@@ -1 +1 @@
1
- {"version":3,"file":"entityDecorator.js","sourceRoot":"","sources":["../../../src/decorators/entityDecorator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,uDAAuD;AACvD,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,OAA8B;IACpD,OAAO,CAAC,MAAW,EAAE,EAAE;QACtB,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvD,YAAY,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QAChC,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC;QAC/B,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport \"reflect-metadata\";\nimport type { IEntitySchemaOptions } from \"../models/IEntitySchemaOptions.js\";\nimport { DecoratorHelper } from \"../utils/decoratorHelper.js\";\n\n/**\n * Decorator to produce schema data for entity.\n * @param options The options for the entity.\n * @returns The class decorator.\n */\nexport function entity(options?: IEntitySchemaOptions): any {\n\treturn (target: any) => {\n\t\tconst entitySchema = DecoratorHelper.getSchema(target);\n\t\tentitySchema.type = target.name;\n\t\tentitySchema.options = options;\n\t\tDecoratorHelper.setSchema(target, entitySchema);\n\t};\n}\n"]}
1
+ {"version":3,"file":"entityDecorator.js","sourceRoot":"","sources":["../../../src/decorators/entityDecorator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,uDAAuD;AACvD,OAAO,kBAAkB,CAAC;AAC1B,OAAO,OAAO,CAAC;AAEf,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,OAA8B;IACpD,OAAO,CAAC,MAAW,EAAE,EAAE;QACtB,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvD,YAAY,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QAChC,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC;QAC/B,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport \"reflect-metadata\";\nimport \"tslib\";\nimport type { IEntitySchemaOptions } from \"../models/IEntitySchemaOptions.js\";\nimport { DecoratorHelper } from \"../utils/decoratorHelper.js\";\n\n/**\n * Decorator to produce schema data for entity.\n * @param options The options for the entity.\n * @returns The class decorator.\n */\nexport function entity(options?: IEntitySchemaOptions): any {\n\treturn (target: any) => {\n\t\tconst entitySchema = DecoratorHelper.getSchema(target);\n\t\tentitySchema.type = target.name;\n\t\tentitySchema.options = options;\n\t\tDecoratorHelper.setSchema(target, entitySchema);\n\t};\n}\n"]}
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
4
  import "reflect-metadata";
5
+ import "tslib";
5
6
  import { DecoratorHelper } from "../utils/decoratorHelper.js";
6
7
  /**
7
8
  * Decorator to produce schema property data for entities.
@@ -1 +1 @@
1
- {"version":3,"file":"propertyDecorator.js","sourceRoot":"","sources":["../../../src/decorators/propertyDecorator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,uDAAuD;AACvD,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgD;IACxE,OAAO,CAAC,MAAW,EAAE,WAAmB,EAAE,EAAE;QAC3C,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAM,MAAM,CAAC,CAAC;QAC5D,YAAY,CAAC,UAAU,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC;QAC/E,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YAChB,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG;gBAC9B,GAAG,OAAO;gBACV,QAAQ,EAAE,WAAW;aACrB,CAAC;QACH,CAAC;aAAM,CAAC;YACP,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC5B,GAAG,OAAO;gBACV,QAAQ,EAAE,WAAW;aACrB,CAAC,CAAC;QACJ,CAAC;QACD,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport \"reflect-metadata\";\nimport type { IEntitySchemaProperty } from \"../models/IEntitySchemaProperty.js\";\nimport { DecoratorHelper } from \"../utils/decoratorHelper.js\";\n\n/**\n * Decorator to produce schema property data for entities.\n * @param options The options for the property.\n * @returns The property decorator.\n */\nexport function property(options: Omit<IEntitySchemaProperty, \"property\">): any {\n\treturn (target: any, propertyKey: string) => {\n\t\tconst entitySchema = DecoratorHelper.getSchema<any>(target);\n\t\tentitySchema.properties ??= [];\n\t\tconst idx = entitySchema.properties.findIndex(p => p.property === propertyKey);\n\t\tif (idx !== -1) {\n\t\t\tentitySchema.properties[idx] = {\n\t\t\t\t...options,\n\t\t\t\tproperty: propertyKey\n\t\t\t};\n\t\t} else {\n\t\t\tentitySchema.properties.push({\n\t\t\t\t...options,\n\t\t\t\tproperty: propertyKey\n\t\t\t});\n\t\t}\n\t\tDecoratorHelper.setSchema(target, entitySchema);\n\t};\n}\n"]}
1
+ {"version":3,"file":"propertyDecorator.js","sourceRoot":"","sources":["../../../src/decorators/propertyDecorator.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,uDAAuD;AACvD,OAAO,kBAAkB,CAAC;AAC1B,OAAO,OAAO,CAAC;AAEf,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgD;IACxE,OAAO,CAAC,MAAW,EAAE,WAAmB,EAAE,EAAE;QAC3C,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAM,MAAM,CAAC,CAAC;QAC5D,YAAY,CAAC,UAAU,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC;QAC/E,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YAChB,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG;gBAC9B,GAAG,OAAO;gBACV,QAAQ,EAAE,WAAW;aACrB,CAAC;QACH,CAAC;aAAM,CAAC;YACP,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC5B,GAAG,OAAO;gBACV,QAAQ,EAAE,WAAW;aACrB,CAAC,CAAC;QACJ,CAAC;QACD,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport \"reflect-metadata\";\nimport \"tslib\";\nimport type { IEntitySchemaProperty } from \"../models/IEntitySchemaProperty.js\";\nimport { DecoratorHelper } from \"../utils/decoratorHelper.js\";\n\n/**\n * Decorator to produce schema property data for entities.\n * @param options The options for the property.\n * @returns The property decorator.\n */\nexport function property(options: Omit<IEntitySchemaProperty, \"property\">): any {\n\treturn (target: any, propertyKey: string) => {\n\t\tconst entitySchema = DecoratorHelper.getSchema<any>(target);\n\t\tentitySchema.properties ??= [];\n\t\tconst idx = entitySchema.properties.findIndex(p => p.property === propertyKey);\n\t\tif (idx !== -1) {\n\t\t\tentitySchema.properties[idx] = {\n\t\t\t\t...options,\n\t\t\t\tproperty: propertyKey\n\t\t\t};\n\t\t} else {\n\t\t\tentitySchema.properties.push({\n\t\t\t\t...options,\n\t\t\t\tproperty: propertyKey\n\t\t\t});\n\t\t}\n\t\tDecoratorHelper.setSchema(target, entitySchema);\n\t};\n}\n"]}
package/dist/es/index.js CHANGED
@@ -18,5 +18,7 @@ export * from "./models/sortDirection.js";
18
18
  export * from "./utils/decoratorHelper.js";
19
19
  export * from "./utils/entityConditions.js";
20
20
  export * from "./utils/entitySchemaHelper.js";
21
+ export * from "./utils/entitySchemaDiffHelper.js";
21
22
  export * from "./utils/entitySorter.js";
23
+ export * from "./models/IEntitySchemaDiff.js";
22
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./decorators/entityDecorator.js\";\nexport * from \"./decorators/propertyDecorator.js\";\nexport * from \"./factories/entitySchemaFactory.js\";\nexport * from \"./models/comparisonOperator.js\";\nexport * from \"./models/entityCondition.js\";\nexport * from \"./models/entitySchemaPropertyFormat.js\";\nexport * from \"./models/entitySchemaPropertyType.js\";\nexport * from \"./models/IComparator.js\";\nexport * from \"./models/IComparatorGroup.js\";\nexport * from \"./models/IEntitySchema.js\";\nexport * from \"./models/IEntitySchemaOptions.js\";\nexport * from \"./models/IEntitySchemaProperty.js\";\nexport * from \"./models/IEntitySort.js\";\nexport * from \"./models/logicalOperator.js\";\nexport * from \"./models/sortDirection.js\";\nexport * from \"./utils/decoratorHelper.js\";\nexport * from \"./utils/entityConditions.js\";\nexport * from \"./utils/entitySchemaHelper.js\";\nexport * from \"./utils/entitySorter.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./decorators/entityDecorator.js\";\nexport * from \"./decorators/propertyDecorator.js\";\nexport * from \"./factories/entitySchemaFactory.js\";\nexport * from \"./models/comparisonOperator.js\";\nexport * from \"./models/entityCondition.js\";\nexport * from \"./models/entitySchemaPropertyFormat.js\";\nexport * from \"./models/entitySchemaPropertyType.js\";\nexport * from \"./models/IComparator.js\";\nexport * from \"./models/IComparatorGroup.js\";\nexport * from \"./models/IEntitySchema.js\";\nexport * from \"./models/IEntitySchemaOptions.js\";\nexport * from \"./models/IEntitySchemaProperty.js\";\nexport * from \"./models/IEntitySort.js\";\nexport * from \"./models/logicalOperator.js\";\nexport * from \"./models/sortDirection.js\";\nexport * from \"./utils/decoratorHelper.js\";\nexport * from \"./utils/entityConditions.js\";\nexport * from \"./utils/entitySchemaHelper.js\";\nexport * from \"./utils/entitySchemaDiffHelper.js\";\nexport * from \"./utils/entitySorter.js\";\nexport * from \"./models/IEntitySchemaDiff.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IEntitySchemaDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IEntitySchemaDiff.js","sourceRoot":"","sources":["../../../src/models/IEntitySchemaDiff.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IEntitySchemaProperty } from \"./IEntitySchemaProperty.js\";\n\n/**\n * The result of comparing two sets of entity schema properties.\n */\nexport interface IEntitySchemaDiff<T = unknown, U = unknown> {\n\t/**\n\t * Properties that are structurally identical between the old and new schemas.\n\t */\n\tunchanged: IEntitySchemaProperty<T | U>[];\n\n\t/**\n\t * Properties present in the new schema but absent from the old one.\n\t */\n\tadded: IEntitySchemaProperty<U>[];\n\n\t/**\n\t * Properties present in the old schema but absent from the new one.\n\t */\n\tremoved: IEntitySchemaProperty<T>[];\n\n\t/**\n\t * Properties that exist in both schemas but differ in at least one structural\n\t * field (property, type, format, isPrimary, isSecondary, sortDirection, optional, itemType, itemTypeRef).\n\t * `from` is the old descriptor; `to` is the new one.\n\t */\n\tmodified: {\n\t\t/**\n\t\t * The old property descriptor.\n\t\t */\n\t\tfrom: IEntitySchemaProperty<T>;\n\t\t/**\n\t\t * The new property descriptor.\n\t\t */\n\t\tto: IEntitySchemaProperty<U>;\n\t}[];\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  // Copyright 2024 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  import "reflect-metadata";
4
+ import "tslib";
4
5
  const META_DATA_KEY = "EntitySchemaMetadata";
5
6
  /**
6
7
  * Class to help with decorators.
@@ -1 +1 @@
1
- {"version":3,"file":"decoratorHelper.js","sourceRoot":"","sources":["../../../src/utils/decoratorHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,kBAAkB,CAAC;AAG1B,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAE7C;;GAEG;AACH,MAAM,OAAO,eAAe;IAC3B;;;;OAIG;IACH,8DAA8D;IACvD,MAAM,CAAC,SAAS,CAAc,MAAW;QAC/C,OAAO,CACN,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;YAC1F,EAAE,CACF,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,8DAA8D;IACvD,MAAM,CAAC,SAAS,CAAc,MAAW,EAAE,YAA8B;QAC/E,OAAO,CAAC,cAAc,CACrB,aAAa,EACb,YAAY,EACZ,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CACtD,CAAC;IACH,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport \"reflect-metadata\";\nimport type { IEntitySchema } from \"../models/IEntitySchema.js\";\n\nconst META_DATA_KEY = \"EntitySchemaMetadata\";\n\n/**\n * Class to help with decorators.\n */\nexport class DecoratorHelper {\n\t/**\n\t * Get the schema from the reflection metadata.\n\t * @param target The object to get the schema data from.\n\t * @returns The schema from the metadata if it can be found.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static getSchema<T = unknown>(target: any): IEntitySchema<T> {\n\t\treturn (\n\t\t\tReflect.getMetadata(META_DATA_KEY, typeof target === \"object\" ? target : target.prototype) ??\n\t\t\t{}\n\t\t);\n\t}\n\n\t/**\n\t * Set the schema from the reflection metadata.\n\t * @param target The object to get the schema data from.\n\t * @param entitySchema The schema to set.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static setSchema<T = unknown>(target: any, entitySchema: IEntitySchema<T>): void {\n\t\tReflect.defineMetadata(\n\t\t\tMETA_DATA_KEY,\n\t\t\tentitySchema,\n\t\t\ttypeof target === \"object\" ? target : target.prototype\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"decoratorHelper.js","sourceRoot":"","sources":["../../../src/utils/decoratorHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,kBAAkB,CAAC;AAC1B,OAAO,OAAO,CAAC;AAGf,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAE7C;;GAEG;AACH,MAAM,OAAO,eAAe;IAC3B;;;;OAIG;IACH,8DAA8D;IACvD,MAAM,CAAC,SAAS,CAAc,MAAW;QAC/C,OAAO,CACN,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;YAC1F,EAAE,CACF,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,8DAA8D;IACvD,MAAM,CAAC,SAAS,CAAc,MAAW,EAAE,YAA8B;QAC/E,OAAO,CAAC,cAAc,CACrB,aAAa,EACb,YAAY,EACZ,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CACtD,CAAC;IACH,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport \"reflect-metadata\";\nimport \"tslib\";\nimport type { IEntitySchema } from \"../models/IEntitySchema.js\";\n\nconst META_DATA_KEY = \"EntitySchemaMetadata\";\n\n/**\n * Class to help with decorators.\n */\nexport class DecoratorHelper {\n\t/**\n\t * Get the schema from the reflection metadata.\n\t * @param target The object to get the schema data from.\n\t * @returns The schema from the metadata if it can be found.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static getSchema<T = unknown>(target: any): IEntitySchema<T> {\n\t\treturn (\n\t\t\tReflect.getMetadata(META_DATA_KEY, typeof target === \"object\" ? target : target.prototype) ??\n\t\t\t{}\n\t\t);\n\t}\n\n\t/**\n\t * Set the schema from the reflection metadata.\n\t * @param target The object to get the schema data from.\n\t * @param entitySchema The schema to set.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic static setSchema<T = unknown>(target: any, entitySchema: IEntitySchema<T>): void {\n\t\tReflect.defineMetadata(\n\t\t\tMETA_DATA_KEY,\n\t\t\tentitySchema,\n\t\t\ttypeof target === \"object\" ? target : target.prototype\n\t\t);\n\t}\n}\n"]}
@@ -67,6 +67,16 @@ export class EntityConditions {
67
67
  }
68
68
  return false;
69
69
  }
70
+ else if (conditionValue === null) {
71
+ const valNull = val === null;
72
+ if (valNull && comparator.comparison === ComparisonOperator.Equals) {
73
+ return true;
74
+ }
75
+ else if (!valNull && comparator.comparison === ComparisonOperator.NotEquals) {
76
+ return true;
77
+ }
78
+ return false;
79
+ }
70
80
  else if (Is.string(val)) {
71
81
  if (Is.string(conditionValue)) {
72
82
  if (!((comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||
@@ -1 +1 @@
1
- {"version":3,"file":"entityConditions.js","sourceRoot":"","sources":["../../../src/utils/entityConditions.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ArrayHelper, Is, ObjectHelper } from \"@twin.org/core\";\nimport { ComparisonOperator } from \"../models/comparisonOperator.js\";\nimport type { EntityCondition } from \"../models/entityCondition.js\";\nimport type { IComparator } from \"../models/IComparator.js\";\nimport { LogicalOperator } from \"../models/logicalOperator.js\";\n\n/**\n * Class to perform condition checks.\n */\nexport class EntityConditions {\n\t/**\n\t * See if the entity matches the conditions.\n\t * @param entity The entity to test.\n\t * @param condition The conditions to test.\n\t * @returns True if the entity matches.\n\t */\n\tpublic static check<T>(entity: T, condition?: EntityCondition<T>): boolean {\n\t\t// If no conditions are defined then it's a match\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\t// It's a group of comparisons, so check the individual items and combine with the logical operator\n\t\t\tconst results: boolean[] = condition.conditions.map(c => EntityConditions.check(entity, c));\n\t\t\tif ((condition.logicalOperator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\t\treturn results.every(Boolean);\n\t\t\t}\n\t\t\treturn results.some(Boolean);\n\t\t}\n\n\t\tif (condition.property.includes(\".\")) {\n\t\t\t// It's a child property comparison, so evaluate the child property\n\t\t\t// and then compare it to the conditions\n\t\t\tconst path = condition.property.split(\".\");\n\n\t\t\tconst child = ObjectHelper.propertyGet(entity, path[0]);\n\n\t\t\t// If the child is an array then check each item\n\t\t\tif (Is.array(child)) {\n\t\t\t\tfor (const c of child) {\n\t\t\t\t\tconst check = EntityConditions.check(c, {\n\t\t\t\t\t\t...condition,\n\t\t\t\t\t\tproperty: path.slice(1).join(\".\")\n\t\t\t\t\t});\n\t\t\t\t\tif (check) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// It's a single value so just check the condition\n\t\treturn EntityConditions.compare(entity, condition);\n\t}\n\n\t/**\n\t * See if the entity matches the conditions.\n\t * @param entity The entity to test.\n\t * @param comparator The condition to test.\n\t * @returns True if the entity matches.\n\t */\n\tpublic static compare<T>(entity: T, comparator: IComparator): boolean {\n\t\tconst val = ObjectHelper.propertyGet(entity, comparator.property);\n\t\tconst conditionValue = comparator.value;\n\n\t\tif (Is.undefined(conditionValue)) {\n\t\t\tconst valUndefined = Is.undefined(val);\n\t\t\tif (valUndefined && comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn true;\n\t\t\t} else if (!valUndefined && comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.string(val)) {\n\t\t\tif (Is.string(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&\n\t\t\t\t\t\t\tval >= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThanOrEqual &&\n\t\t\t\t\t\t\tval <= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Includes &&\n\t\t\t\t\t\t\tval.includes(conditionValue)) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotIncludes &&\n\t\t\t\t\t\t\t!val.includes(conditionValue))\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else if (Is.array(conditionValue)) {\n\t\t\t\tif (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.number(val)) {\n\t\t\tif (Is.number(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&\n\t\t\t\t\t\t\tval >= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThanOrEqual && val <= conditionValue)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else if (Is.array(conditionValue)) {\n\t\t\t\tif (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.boolean(val)) {\n\t\t\tif (Is.boolean(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.array(val)) {\n\t\t\tif (Is.array(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t\t) {\n\t\t\t\t\tconst matches = ArrayHelper.matches(val, conditionValue);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && matches) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && !matches)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else if (Is.number(conditionValue) || Is.string(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Includes ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.NotIncludes ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.In\n\t\t\t\t) {\n\t\t\t\t\tconst includes = val.includes(conditionValue);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Includes && includes) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotIncludes && !includes) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.In && includes)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else if (Is.object(conditionValue)) {\n\t\t\t\tif (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\t\t\tfor (const v of val) {\n\t\t\t\t\t\tif (ObjectHelper.equal(v, conditionValue)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\t\t\tfor (const v of val) {\n\t\t\t\t\t\tif (!ObjectHelper.equal(v, conditionValue)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.object(val)) {\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn ObjectHelper.equal(val, conditionValue);\n\t\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn !ObjectHelper.equal(val, conditionValue);\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"]}
1
+ {"version":3,"file":"entityConditions.js","sourceRoot":"","sources":["../../../src/utils/entityConditions.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ArrayHelper, Is, ObjectHelper } from \"@twin.org/core\";\nimport { ComparisonOperator } from \"../models/comparisonOperator.js\";\nimport type { EntityCondition } from \"../models/entityCondition.js\";\nimport type { IComparator } from \"../models/IComparator.js\";\nimport { LogicalOperator } from \"../models/logicalOperator.js\";\n\n/**\n * Class to perform condition checks.\n */\nexport class EntityConditions {\n\t/**\n\t * See if the entity matches the conditions.\n\t * @param entity The entity to test.\n\t * @param condition The conditions to test.\n\t * @returns True if the entity matches.\n\t */\n\tpublic static check<T>(entity: T, condition?: EntityCondition<T>): boolean {\n\t\t// If no conditions are defined then it's a match\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\t// It's a group of comparisons, so check the individual items and combine with the logical operator\n\t\t\tconst results: boolean[] = condition.conditions.map(c => EntityConditions.check(entity, c));\n\t\t\tif ((condition.logicalOperator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\t\treturn results.every(Boolean);\n\t\t\t}\n\t\t\treturn results.some(Boolean);\n\t\t}\n\n\t\tif (condition.property.includes(\".\")) {\n\t\t\t// It's a child property comparison, so evaluate the child property\n\t\t\t// and then compare it to the conditions\n\t\t\tconst path = condition.property.split(\".\");\n\n\t\t\tconst child = ObjectHelper.propertyGet(entity, path[0]);\n\n\t\t\t// If the child is an array then check each item\n\t\t\tif (Is.array(child)) {\n\t\t\t\tfor (const c of child) {\n\t\t\t\t\tconst check = EntityConditions.check(c, {\n\t\t\t\t\t\t...condition,\n\t\t\t\t\t\tproperty: path.slice(1).join(\".\")\n\t\t\t\t\t});\n\t\t\t\t\tif (check) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// It's a single value so just check the condition\n\t\treturn EntityConditions.compare(entity, condition);\n\t}\n\n\t/**\n\t * See if the entity matches the conditions.\n\t * @param entity The entity to test.\n\t * @param comparator The condition to test.\n\t * @returns True if the entity matches.\n\t */\n\tpublic static compare<T>(entity: T, comparator: IComparator): boolean {\n\t\tconst val = ObjectHelper.propertyGet(entity, comparator.property);\n\t\tconst conditionValue = comparator.value;\n\n\t\tif (Is.undefined(conditionValue)) {\n\t\t\tconst valUndefined = Is.undefined(val);\n\t\t\tif (valUndefined && comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn true;\n\t\t\t} else if (!valUndefined && comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (conditionValue === null) {\n\t\t\tconst valNull = val === null;\n\t\t\tif (valNull && comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn true;\n\t\t\t} else if (!valNull && comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.string(val)) {\n\t\t\tif (Is.string(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&\n\t\t\t\t\t\t\tval >= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThanOrEqual &&\n\t\t\t\t\t\t\tval <= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Includes &&\n\t\t\t\t\t\t\tval.includes(conditionValue)) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotIncludes &&\n\t\t\t\t\t\t\t!val.includes(conditionValue))\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else if (Is.array(conditionValue)) {\n\t\t\t\tif (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.number(val)) {\n\t\t\tif (Is.number(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&\n\t\t\t\t\t\t\tval >= conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.LessThanOrEqual && val <= conditionValue)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} else if (Is.array(conditionValue)) {\n\t\t\t\tif (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.boolean(val)) {\n\t\t\tif (Is.boolean(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\t!(\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||\n\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.array(val)) {\n\t\t\tif (Is.array(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals\n\t\t\t\t) {\n\t\t\t\t\tconst matches = ArrayHelper.matches(val, conditionValue);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Equals && matches) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotEquals && !matches)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else if (Is.number(conditionValue) || Is.string(conditionValue)) {\n\t\t\t\tif (\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.Includes ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.NotIncludes ||\n\t\t\t\t\tcomparator.comparison === ComparisonOperator.In\n\t\t\t\t) {\n\t\t\t\t\tconst includes = val.includes(conditionValue);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.Includes && includes) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.NotIncludes && !includes) ||\n\t\t\t\t\t\t\t(comparator.comparison === ComparisonOperator.In && includes)\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else if (Is.object(conditionValue)) {\n\t\t\t\tif (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\t\t\tfor (const v of val) {\n\t\t\t\t\t\tif (ObjectHelper.equal(v, conditionValue)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\t\t\tfor (const v of val) {\n\t\t\t\t\t\tif (!ObjectHelper.equal(v, conditionValue)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Is.object(val)) {\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn ObjectHelper.equal(val, conditionValue);\n\t\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn !ObjectHelper.equal(val, conditionValue);\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"]}
@@ -0,0 +1,139 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { GeneralError, Guards } from "@twin.org/core";
4
+ /**
5
+ * Helper class for comparing entity schemas and generating diffs.
6
+ */
7
+ export class EntitySchemaDiffHelper {
8
+ /**
9
+ * Runtime name for the class.
10
+ */
11
+ static CLASS_NAME = "EntitySchemaDiffHelper";
12
+ /**
13
+ * Compare two arrays of entity schema properties and return a structured diff.
14
+ *
15
+ * Properties are matched by their `property` key name. A property is considered modified when any structural field differs: `type`, `format`, `isPrimary`, `isSecondary`, `sortDirection`, `optional`, `itemType`, or `itemTypeRef`.
16
+ * Documentation-only fields (`description`, `examples`) are intentionally excluded from the comparison to avoid spurious diffs.
17
+ *
18
+ * Because a pure name change cannot be detected automatically, callers may supply a `renames` list mapping old names to new names. Renamed properties appear in `modified` (never in `added` or `removed`) even when no other fields changed. Rename lookups take priority over direct same-name matches, which allows swap renames to work correctly and prevents a renamed source from silently disappearing when the target name already existed in the old schema. Self-renames (`from === to`) are ignored and the property is classified normally.
19
+ *
20
+ * When `renames` contains duplicate entries: if two entries share the same target, the last definition wins and the first source is treated as removed; if two entries share the same source, the first target wins and the second target is treated as added. Both cases are deterministic but callers should avoid them.
21
+ * @param oldProperties The property descriptors from the current (live) schema.
22
+ * @param newProperties The property descriptors from the target (new) schema.
23
+ * @param renames Optional list of property renames `{ from, to }` where `from` is the old name and `to` is the new name.
24
+ * @returns A diff object with `added`, `removed`, `modified`, and `unchanged` arrays, each containing full `IEntitySchemaProperty` descriptors.
25
+ * @throws `GeneralError` if either input array contains duplicate property keys.
26
+ */
27
+ static diff(oldProperties, newProperties, renames) {
28
+ Guards.array(EntitySchemaDiffHelper.CLASS_NAME, "oldProperties", oldProperties);
29
+ Guards.array(EntitySchemaDiffHelper.CLASS_NAME, "newProperties", newProperties);
30
+ const added = [];
31
+ const removed = [];
32
+ const modified = [];
33
+ const unchanged = [];
34
+ const oldMap = new Map();
35
+ for (const prop of oldProperties) {
36
+ const propKey = prop.property;
37
+ if (oldMap.has(propKey)) {
38
+ throw new GeneralError(EntitySchemaDiffHelper.CLASS_NAME, "duplicateOldProperty", {
39
+ property: propKey
40
+ });
41
+ }
42
+ oldMap.set(propKey, prop);
43
+ }
44
+ const newMap = new Map();
45
+ for (const prop of newProperties) {
46
+ const propKey = prop.property;
47
+ if (newMap.has(propKey)) {
48
+ throw new GeneralError(EntitySchemaDiffHelper.CLASS_NAME, "duplicateNewProperty", {
49
+ property: propKey
50
+ });
51
+ }
52
+ newMap.set(propKey, prop);
53
+ }
54
+ // new-name → old-name, used when iterating newProperties
55
+ const renameToFrom = new Map();
56
+ if (renames) {
57
+ for (const rename of renames) {
58
+ renameToFrom.set(rename.to, rename.from);
59
+ }
60
+ }
61
+ // Old names that were consumed by a rename (prevents double-use of the same source).
62
+ const consumedByRename = new Set();
63
+ // New names matched via rename path (their same-named old prop is not their direct match).
64
+ const newKeyMatchedViaRename = new Set();
65
+ for (const newProp of newProperties) {
66
+ const key = newProp.property;
67
+ // Rename lookup takes priority over a direct same-name match so that:
68
+ // - swap renames work (both names exist in old and new)
69
+ // - a renamed source does not vanish when the target name already existed in old
70
+ // Self-renames (fromKey === key) are skipped so the property is classified normally.
71
+ const fromKey = renameToFrom.get(key);
72
+ const renamedSource = fromKey !== undefined ? oldMap.get(fromKey) : undefined;
73
+ if (fromKey !== undefined &&
74
+ fromKey !== key &&
75
+ renamedSource !== undefined &&
76
+ !consumedByRename.has(fromKey)) {
77
+ modified.push({ from: renamedSource, to: newProp });
78
+ consumedByRename.add(fromKey);
79
+ newKeyMatchedViaRename.add(key);
80
+ }
81
+ else {
82
+ const oldProp = oldMap.get(key);
83
+ if (oldProp !== undefined) {
84
+ if (!EntitySchemaDiffHelper.schemaPropertiesEqual(oldProp, newProp)) {
85
+ modified.push({ from: oldProp, to: newProp });
86
+ }
87
+ else {
88
+ unchanged.push(newProp);
89
+ }
90
+ }
91
+ else {
92
+ added.push(newProp);
93
+ }
94
+ }
95
+ }
96
+ for (const oldProp of oldProperties) {
97
+ const key = oldProp.property;
98
+ // Removed when absent from new, or when its same-named new prop was claimed by a rename
99
+ // (meaning this old prop was not the match for that new prop).
100
+ // Exception: skip if this old prop was itself consumed as a rename source.
101
+ if ((!newMap.has(key) || newKeyMatchedViaRename.has(key)) && !consumedByRename.has(key)) {
102
+ removed.push(oldProp);
103
+ }
104
+ }
105
+ return { added, removed, modified, unchanged };
106
+ }
107
+ /**
108
+ * Returns true when the diff contains at least one added, removed, or modified property.
109
+ * @param diff The diff to check.
110
+ * @returns True if the diff has any structural changes.
111
+ */
112
+ static hasChanges(diff) {
113
+ Guards.object(EntitySchemaDiffHelper.CLASS_NAME, "diff", diff);
114
+ Guards.array(EntitySchemaDiffHelper.CLASS_NAME, "diff.added", diff.added);
115
+ Guards.array(EntitySchemaDiffHelper.CLASS_NAME, "diff.removed", diff.removed);
116
+ Guards.array(EntitySchemaDiffHelper.CLASS_NAME, "diff.modified", diff.modified);
117
+ return diff.added.length > 0 || diff.removed.length > 0 || diff.modified.length > 0;
118
+ }
119
+ /**
120
+ * Compare two property descriptors for structural equality.
121
+ * The `property` name field and documentation fields (`description`, `examples`) are intentionally excluded — callers match by name before invoking this method.
122
+ * @param schema1 The first property descriptor.
123
+ * @param schema2 The second property descriptor.
124
+ * @returns True if all structural fields are equal.
125
+ */
126
+ static schemaPropertiesEqual(schema1, schema2) {
127
+ Guards.object(EntitySchemaDiffHelper.CLASS_NAME, "schema1", schema1);
128
+ Guards.object(EntitySchemaDiffHelper.CLASS_NAME, "schema2", schema2);
129
+ return (schema1.type === schema2.type &&
130
+ schema1.format === schema2.format &&
131
+ schema1.isPrimary === schema2.isPrimary &&
132
+ schema1.isSecondary === schema2.isSecondary &&
133
+ schema1.sortDirection === schema2.sortDirection &&
134
+ schema1.optional === schema2.optional &&
135
+ schema1.itemType === schema2.itemType &&
136
+ schema1.itemTypeRef === schema2.itemTypeRef);
137
+ }
138
+ }
139
+ //# sourceMappingURL=entitySchemaDiffHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitySchemaDiffHelper.js","sourceRoot":"","sources":["../../../src/utils/entitySchemaDiffHelper.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { GeneralError, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IEntitySchemaDiff } from \"../models/IEntitySchemaDiff.js\";\nimport type { IEntitySchemaProperty } from \"../models/IEntitySchemaProperty.js\";\n\n/**\n * Helper class for comparing entity schemas and generating diffs.\n */\nexport class EntitySchemaDiffHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EntitySchemaDiffHelper>();\n\n\t/**\n\t * Compare two arrays of entity schema properties and return a structured diff.\n\t *\n\t * Properties are matched by their `property` key name. A property is considered modified when any structural field differs: `type`, `format`, `isPrimary`, `isSecondary`, `sortDirection`, `optional`, `itemType`, or `itemTypeRef`.\n\t * Documentation-only fields (`description`, `examples`) are intentionally excluded from the comparison to avoid spurious diffs.\n\t *\n\t * Because a pure name change cannot be detected automatically, callers may supply a `renames` list mapping old names to new names. Renamed properties appear in `modified` (never in `added` or `removed`) even when no other fields changed. Rename lookups take priority over direct same-name matches, which allows swap renames to work correctly and prevents a renamed source from silently disappearing when the target name already existed in the old schema. Self-renames (`from === to`) are ignored and the property is classified normally.\n\t *\n\t * When `renames` contains duplicate entries: if two entries share the same target, the last definition wins and the first source is treated as removed; if two entries share the same source, the first target wins and the second target is treated as added. Both cases are deterministic but callers should avoid them.\n\t * @param oldProperties The property descriptors from the current (live) schema.\n\t * @param newProperties The property descriptors from the target (new) schema.\n\t * @param renames Optional list of property renames `{ from, to }` where `from` is the old name and `to` is the new name.\n\t * @returns A diff object with `added`, `removed`, `modified`, and `unchanged` arrays, each containing full `IEntitySchemaProperty` descriptors.\n\t * @throws `GeneralError` if either input array contains duplicate property keys.\n\t */\n\tpublic static diff<T, U = T>(\n\t\toldProperties: IEntitySchemaProperty<T>[],\n\t\tnewProperties: IEntitySchemaProperty<U>[],\n\t\trenames?: { from: string; to: string }[]\n\t): IEntitySchemaDiff<T, U> {\n\t\tGuards.array(EntitySchemaDiffHelper.CLASS_NAME, nameof(oldProperties), oldProperties);\n\t\tGuards.array(EntitySchemaDiffHelper.CLASS_NAME, nameof(newProperties), newProperties);\n\n\t\tconst added: IEntitySchemaProperty<U>[] = [];\n\t\tconst removed: IEntitySchemaProperty<T>[] = [];\n\t\tconst modified: IEntitySchemaDiff<T, U>[\"modified\"] = [];\n\t\tconst unchanged: IEntitySchemaProperty<T | U>[] = [];\n\n\t\tconst oldMap = new Map<string, IEntitySchemaProperty<T>>();\n\t\tfor (const prop of oldProperties) {\n\t\t\tconst propKey = prop.property as string;\n\t\t\tif (oldMap.has(propKey)) {\n\t\t\t\tthrow new GeneralError(EntitySchemaDiffHelper.CLASS_NAME, \"duplicateOldProperty\", {\n\t\t\t\t\tproperty: propKey\n\t\t\t\t});\n\t\t\t}\n\t\t\toldMap.set(propKey, prop);\n\t\t}\n\n\t\tconst newMap = new Map<string, IEntitySchemaProperty<U>>();\n\t\tfor (const prop of newProperties) {\n\t\t\tconst propKey = prop.property as string;\n\t\t\tif (newMap.has(propKey)) {\n\t\t\t\tthrow new GeneralError(EntitySchemaDiffHelper.CLASS_NAME, \"duplicateNewProperty\", {\n\t\t\t\t\tproperty: propKey\n\t\t\t\t});\n\t\t\t}\n\t\t\tnewMap.set(propKey, prop);\n\t\t}\n\n\t\t// new-name → old-name, used when iterating newProperties\n\t\tconst renameToFrom = new Map<string, string>();\n\t\tif (renames) {\n\t\t\tfor (const rename of renames) {\n\t\t\t\trenameToFrom.set(rename.to, rename.from);\n\t\t\t}\n\t\t}\n\n\t\t// Old names that were consumed by a rename (prevents double-use of the same source).\n\t\tconst consumedByRename = new Set<string>();\n\t\t// New names matched via rename path (their same-named old prop is not their direct match).\n\t\tconst newKeyMatchedViaRename = new Set<string>();\n\n\t\tfor (const newProp of newProperties) {\n\t\t\tconst key = newProp.property as string;\n\n\t\t\t// Rename lookup takes priority over a direct same-name match so that:\n\t\t\t// - swap renames work (both names exist in old and new)\n\t\t\t// - a renamed source does not vanish when the target name already existed in old\n\t\t\t// Self-renames (fromKey === key) are skipped so the property is classified normally.\n\t\t\tconst fromKey = renameToFrom.get(key);\n\t\t\tconst renamedSource = fromKey !== undefined ? oldMap.get(fromKey) : undefined;\n\n\t\t\tif (\n\t\t\t\tfromKey !== undefined &&\n\t\t\t\tfromKey !== key &&\n\t\t\t\trenamedSource !== undefined &&\n\t\t\t\t!consumedByRename.has(fromKey)\n\t\t\t) {\n\t\t\t\tmodified.push({ from: renamedSource, to: newProp });\n\t\t\t\tconsumedByRename.add(fromKey);\n\t\t\t\tnewKeyMatchedViaRename.add(key);\n\t\t\t} else {\n\t\t\t\tconst oldProp = oldMap.get(key);\n\t\t\t\tif (oldProp !== undefined) {\n\t\t\t\t\tif (!EntitySchemaDiffHelper.schemaPropertiesEqual(oldProp, newProp)) {\n\t\t\t\t\t\tmodified.push({ from: oldProp, to: newProp });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tunchanged.push(newProp as IEntitySchemaProperty<T | U>);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tadded.push(newProp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const oldProp of oldProperties) {\n\t\t\tconst key = oldProp.property as string;\n\t\t\t// Removed when absent from new, or when its same-named new prop was claimed by a rename\n\t\t\t// (meaning this old prop was not the match for that new prop).\n\t\t\t// Exception: skip if this old prop was itself consumed as a rename source.\n\t\t\tif ((!newMap.has(key) || newKeyMatchedViaRename.has(key)) && !consumedByRename.has(key)) {\n\t\t\t\tremoved.push(oldProp);\n\t\t\t}\n\t\t}\n\n\t\treturn { added, removed, modified, unchanged };\n\t}\n\n\t/**\n\t * Returns true when the diff contains at least one added, removed, or modified property.\n\t * @param diff The diff to check.\n\t * @returns True if the diff has any structural changes.\n\t */\n\tpublic static hasChanges<T, U>(diff: IEntitySchemaDiff<T, U>): boolean {\n\t\tGuards.object(EntitySchemaDiffHelper.CLASS_NAME, nameof(diff), diff);\n\t\tGuards.array(EntitySchemaDiffHelper.CLASS_NAME, nameof(diff.added), diff.added);\n\t\tGuards.array(EntitySchemaDiffHelper.CLASS_NAME, nameof(diff.removed), diff.removed);\n\t\tGuards.array(EntitySchemaDiffHelper.CLASS_NAME, nameof(diff.modified), diff.modified);\n\t\treturn diff.added.length > 0 || diff.removed.length > 0 || diff.modified.length > 0;\n\t}\n\n\t/**\n\t * Compare two property descriptors for structural equality.\n\t * The `property` name field and documentation fields (`description`, `examples`) are intentionally excluded — callers match by name before invoking this method.\n\t * @param schema1 The first property descriptor.\n\t * @param schema2 The second property descriptor.\n\t * @returns True if all structural fields are equal.\n\t */\n\tpublic static schemaPropertiesEqual<T, U>(\n\t\tschema1: IEntitySchemaProperty<T>,\n\t\tschema2: IEntitySchemaProperty<U>\n\t): boolean {\n\t\tGuards.object(EntitySchemaDiffHelper.CLASS_NAME, nameof(schema1), schema1);\n\t\tGuards.object(EntitySchemaDiffHelper.CLASS_NAME, nameof(schema2), schema2);\n\t\treturn (\n\t\t\tschema1.type === schema2.type &&\n\t\t\tschema1.format === schema2.format &&\n\t\t\tschema1.isPrimary === schema2.isPrimary &&\n\t\t\tschema1.isSecondary === schema2.isSecondary &&\n\t\t\tschema1.sortDirection === schema2.sortDirection &&\n\t\t\tschema1.optional === schema2.optional &&\n\t\t\tschema1.itemType === schema2.itemType &&\n\t\t\tschema1.itemTypeRef === schema2.itemTypeRef\n\t\t);\n\t}\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import "reflect-metadata";
2
+ import "tslib";
2
3
  import type { IEntitySchemaOptions } from "../models/IEntitySchemaOptions.js";
3
4
  /**
4
5
  * Decorator to produce schema data for entity.
@@ -1,4 +1,5 @@
1
1
  import "reflect-metadata";
2
+ import "tslib";
2
3
  import type { IEntitySchemaProperty } from "../models/IEntitySchemaProperty.js";
3
4
  /**
4
5
  * Decorator to produce schema property data for entities.
@@ -16,4 +16,6 @@ export * from "./models/sortDirection.js";
16
16
  export * from "./utils/decoratorHelper.js";
17
17
  export * from "./utils/entityConditions.js";
18
18
  export * from "./utils/entitySchemaHelper.js";
19
+ export * from "./utils/entitySchemaDiffHelper.js";
19
20
  export * from "./utils/entitySorter.js";
21
+ export * from "./models/IEntitySchemaDiff.js";
@@ -0,0 +1,33 @@
1
+ import type { IEntitySchemaProperty } from "./IEntitySchemaProperty.js";
2
+ /**
3
+ * The result of comparing two sets of entity schema properties.
4
+ */
5
+ export interface IEntitySchemaDiff<T = unknown, U = unknown> {
6
+ /**
7
+ * Properties that are structurally identical between the old and new schemas.
8
+ */
9
+ unchanged: IEntitySchemaProperty<T | U>[];
10
+ /**
11
+ * Properties present in the new schema but absent from the old one.
12
+ */
13
+ added: IEntitySchemaProperty<U>[];
14
+ /**
15
+ * Properties present in the old schema but absent from the new one.
16
+ */
17
+ removed: IEntitySchemaProperty<T>[];
18
+ /**
19
+ * Properties that exist in both schemas but differ in at least one structural
20
+ * field (property, type, format, isPrimary, isSecondary, sortDirection, optional, itemType, itemTypeRef).
21
+ * `from` is the old descriptor; `to` is the new one.
22
+ */
23
+ modified: {
24
+ /**
25
+ * The old property descriptor.
26
+ */
27
+ from: IEntitySchemaProperty<T>;
28
+ /**
29
+ * The new property descriptor.
30
+ */
31
+ to: IEntitySchemaProperty<U>;
32
+ }[];
33
+ }
@@ -1,4 +1,5 @@
1
1
  import "reflect-metadata";
2
+ import "tslib";
2
3
  import type { IEntitySchema } from "../models/IEntitySchema.js";
3
4
  /**
4
5
  * Class to help with decorators.
@@ -0,0 +1,44 @@
1
+ import type { IEntitySchemaDiff } from "../models/IEntitySchemaDiff.js";
2
+ import type { IEntitySchemaProperty } from "../models/IEntitySchemaProperty.js";
3
+ /**
4
+ * Helper class for comparing entity schemas and generating diffs.
5
+ */
6
+ export declare class EntitySchemaDiffHelper {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static readonly CLASS_NAME: string;
11
+ /**
12
+ * Compare two arrays of entity schema properties and return a structured diff.
13
+ *
14
+ * Properties are matched by their `property` key name. A property is considered modified when any structural field differs: `type`, `format`, `isPrimary`, `isSecondary`, `sortDirection`, `optional`, `itemType`, or `itemTypeRef`.
15
+ * Documentation-only fields (`description`, `examples`) are intentionally excluded from the comparison to avoid spurious diffs.
16
+ *
17
+ * Because a pure name change cannot be detected automatically, callers may supply a `renames` list mapping old names to new names. Renamed properties appear in `modified` (never in `added` or `removed`) even when no other fields changed. Rename lookups take priority over direct same-name matches, which allows swap renames to work correctly and prevents a renamed source from silently disappearing when the target name already existed in the old schema. Self-renames (`from === to`) are ignored and the property is classified normally.
18
+ *
19
+ * When `renames` contains duplicate entries: if two entries share the same target, the last definition wins and the first source is treated as removed; if two entries share the same source, the first target wins and the second target is treated as added. Both cases are deterministic but callers should avoid them.
20
+ * @param oldProperties The property descriptors from the current (live) schema.
21
+ * @param newProperties The property descriptors from the target (new) schema.
22
+ * @param renames Optional list of property renames `{ from, to }` where `from` is the old name and `to` is the new name.
23
+ * @returns A diff object with `added`, `removed`, `modified`, and `unchanged` arrays, each containing full `IEntitySchemaProperty` descriptors.
24
+ * @throws `GeneralError` if either input array contains duplicate property keys.
25
+ */
26
+ static diff<T, U = T>(oldProperties: IEntitySchemaProperty<T>[], newProperties: IEntitySchemaProperty<U>[], renames?: {
27
+ from: string;
28
+ to: string;
29
+ }[]): IEntitySchemaDiff<T, U>;
30
+ /**
31
+ * Returns true when the diff contains at least one added, removed, or modified property.
32
+ * @param diff The diff to check.
33
+ * @returns True if the diff has any structural changes.
34
+ */
35
+ static hasChanges<T, U>(diff: IEntitySchemaDiff<T, U>): boolean;
36
+ /**
37
+ * Compare two property descriptors for structural equality.
38
+ * The `property` name field and documentation fields (`description`, `examples`) are intentionally excluded — callers match by name before invoking this method.
39
+ * @param schema1 The first property descriptor.
40
+ * @param schema2 The second property descriptor.
41
+ * @returns True if all structural fields are equal.
42
+ */
43
+ static schemaPropertiesEqual<T, U>(schema1: IEntitySchemaProperty<T>, schema2: IEntitySchemaProperty<U>): boolean;
44
+ }