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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@
3
3
  import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
4
4
  import { Coerce, ComponentFactory, Guards, HealthStatus, Is, ObjectHelper } from "@twin.org/core";
5
5
  import { ComparisonOperator, EntityConditions, EntitySchemaFactory, EntitySchemaHelper, EntitySorter, LogicalOperator } from "@twin.org/entity";
6
+ import { EntityHelper } from "@twin.org/entity-storage-models";
6
7
  /**
7
8
  * Class for performing entity storage operations in-memory.
8
9
  */
@@ -53,29 +54,6 @@ export class MemoryEntityStorageConnector {
53
54
  this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
54
55
  this._store = [];
55
56
  }
56
- /**
57
- * Deep-clone condition tree and map `null` to `undefined` on Equals/NotEquals leaves
58
- * so in-memory evaluation matches SQL-style "IS NULL" / "IS NOT NULL" semantics.
59
- * @param condition The user-supplied condition (not mutated).
60
- * @returns A clone safe to pass to {@link EntityConditions.check}.
61
- * @internal
62
- */
63
- static normalizeNullToUndefined(condition) {
64
- if ("conditions" in condition) {
65
- return {
66
- ...condition,
67
- conditions: condition.conditions.map(c => MemoryEntityStorageConnector.normalizeNullToUndefined(c))
68
- };
69
- }
70
- // In the non-group branch, `condition` is the leaf comparator.
71
- const leaf = condition;
72
- if ((leaf.comparison === ComparisonOperator.Equals ||
73
- leaf.comparison === ComparisonOperator.NotEquals) &&
74
- leaf.value === null) {
75
- return { ...leaf, value: undefined };
76
- }
77
- return { ...leaf };
78
- }
79
57
  /**
80
58
  * Returns the class name of the component.
81
59
  * @returns The class name of the component.
@@ -123,11 +101,11 @@ export class MemoryEntityStorageConnector {
123
101
  });
124
102
  }
125
103
  const index = this.findItem(id, secondaryIndex, finalConditions);
126
- const item = index >= 0 ? ObjectHelper.clone(this._store[index]) : undefined;
104
+ const item = index >= 0 ? this._store[index] : undefined;
127
105
  if (Is.objectValue(item)) {
128
- ObjectHelper.propertyDelete(item, MemoryEntityStorageConnector._PARTITION_KEY);
106
+ return EntityHelper.unPrepareEntity(item, [MemoryEntityStorageConnector._PARTITION_KEY]);
129
107
  }
130
- return item;
108
+ return undefined;
131
109
  }
132
110
  /**
133
111
  * Set an entity.
@@ -139,22 +117,22 @@ export class MemoryEntityStorageConnector {
139
117
  Guards.object(MemoryEntityStorageConnector.CLASS_NAME, "entity", entity);
140
118
  const contextIds = await ContextIdStore.getContextIds();
141
119
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
142
- EntitySchemaHelper.validateEntity(entity, this.getSchema());
143
120
  const finalConditions = conditions ?? [];
144
- const finalEntity = ObjectHelper.clone(entity);
121
+ const prepared = EntityHelper.prepareEntity(entity, this._entitySchema, Is.stringValue(partitionKey)
122
+ ? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]
123
+ : undefined);
145
124
  if (Is.stringValue(partitionKey)) {
146
125
  finalConditions.push({
147
126
  property: MemoryEntityStorageConnector._PARTITION_KEY,
148
127
  value: partitionKey
149
128
  });
150
- ObjectHelper.propertySet(finalEntity, MemoryEntityStorageConnector._PARTITION_KEY, partitionKey);
151
129
  }
152
- const existingIndex = this.findItem(finalEntity[this._primaryKey.property], undefined, finalConditions);
130
+ const existingIndex = this.findItem(prepared[this._primaryKey.property], undefined, finalConditions);
153
131
  if (existingIndex >= 0) {
154
- this._store[existingIndex] = finalEntity;
132
+ this._store[existingIndex] = prepared;
155
133
  }
156
134
  else {
157
- this._store.push(finalEntity);
135
+ this._store.push(prepared);
158
136
  }
159
137
  }
160
138
  /**
@@ -166,9 +144,6 @@ export class MemoryEntityStorageConnector {
166
144
  Guards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, "entities", entities);
167
145
  const contextIds = await ContextIdStore.getContextIds();
168
146
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
169
- for (const entity of entities) {
170
- EntitySchemaHelper.validateEntity(entity, this.getSchema());
171
- }
172
147
  const indexMap = new Map();
173
148
  for (let i = 0; i < this._store.length; i++) {
174
149
  const stored = this._store[i];
@@ -178,17 +153,16 @@ export class MemoryEntityStorageConnector {
178
153
  }
179
154
  }
180
155
  for (const entity of entities) {
181
- const finalEntity = ObjectHelper.clone(entity);
182
- if (Is.stringValue(partitionKey)) {
183
- ObjectHelper.propertySet(finalEntity, MemoryEntityStorageConnector._PARTITION_KEY, partitionKey);
184
- }
185
- const id = finalEntity[this._primaryKey.property];
156
+ const prepared = EntityHelper.prepareEntity(entity, this._entitySchema, Is.stringValue(partitionKey)
157
+ ? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]
158
+ : undefined);
159
+ const id = prepared[this._primaryKey.property];
186
160
  const existingIndex = indexMap.get(id);
187
161
  if (existingIndex !== undefined) {
188
- this._store[existingIndex] = finalEntity;
162
+ this._store[existingIndex] = prepared;
189
163
  }
190
164
  else {
191
- const newIndex = this._store.push(finalEntity) - 1;
165
+ const newIndex = this._store.push(prepared) - 1;
192
166
  indexMap.set(id, newIndex);
193
167
  }
194
168
  }
@@ -241,7 +215,7 @@ export class MemoryEntityStorageConnector {
241
215
  });
242
216
  }
243
217
  if (!Is.empty(conditions)) {
244
- finalConditions.conditions.push(MemoryEntityStorageConnector.normalizeNullToUndefined(conditions));
218
+ finalConditions.conditions.push(EntityHelper.normalizeConditionValues(conditions));
245
219
  }
246
220
  const entities = [];
247
221
  const finalLimit = limit ?? MemoryEntityStorageConnector._DEFAULT_LIMIT;
@@ -253,11 +227,10 @@ export class MemoryEntityStorageConnector {
253
227
  for (let i = startIndex; i < allEntities.length; i++) {
254
228
  if (EntityConditions.check(allEntities[i], finalConditions) &&
255
229
  entities.length < finalLimit) {
256
- const entity = ObjectHelper.clone(Is.arrayValue(properties)
230
+ const entity = Is.arrayValue(properties)
257
231
  ? ObjectHelper.pick(allEntities[i], properties)
258
- : allEntities[i]);
259
- ObjectHelper.propertyDelete(entity, MemoryEntityStorageConnector._PARTITION_KEY);
260
- entities.push(entity);
232
+ : allEntities[i];
233
+ entities.push(EntityHelper.unPrepareEntity(entity, [MemoryEntityStorageConnector._PARTITION_KEY]));
261
234
  if (entities.length >= finalLimit) {
262
235
  if (i < allEntities.length - 1) {
263
236
  nextCursor = (i + 1).toString();
@@ -338,23 +311,86 @@ export class MemoryEntityStorageConnector {
338
311
  }
339
312
  /**
340
313
  * Count all the entities which match the conditions.
314
+ * @param conditions The optional conditions to match for the entities.
341
315
  * @returns The total count of entities in the storage.
342
316
  */
343
- async count() {
317
+ async count(conditions) {
344
318
  const contextIds = await ContextIdStore.getContextIds();
345
319
  const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
346
- if (!Is.stringValue(partitionKey)) {
320
+ const finalConditions = {
321
+ conditions: [],
322
+ logicalOperator: LogicalOperator.And
323
+ };
324
+ if (Is.stringValue(partitionKey)) {
325
+ finalConditions.conditions.push({
326
+ property: MemoryEntityStorageConnector._PARTITION_KEY,
327
+ comparison: ComparisonOperator.Equals,
328
+ value: partitionKey
329
+ });
330
+ }
331
+ if (!Is.empty(conditions)) {
332
+ finalConditions.conditions.push(EntityHelper.normalizeConditionValues(conditions));
333
+ }
334
+ if (finalConditions.conditions.length === 0) {
347
335
  return this._store.length;
348
336
  }
349
- return this._store.filter(item => ObjectHelper.propertyGet(item, MemoryEntityStorageConnector._PARTITION_KEY) ===
350
- partitionKey).length;
337
+ return this._store.filter(item => EntityConditions.check(item, finalConditions)).length;
351
338
  }
352
339
  /**
353
340
  * Get the memory store.
354
341
  * @returns The store.
355
342
  */
356
343
  getStore() {
357
- return this._store;
344
+ return this._store.map(item => EntityHelper.unPrepareEntity(item, [MemoryEntityStorageConnector._PARTITION_KEY]));
345
+ }
346
+ /**
347
+ * Get a unique list of all the context ids from the storage.
348
+ * @returns The list of unique context ids.
349
+ */
350
+ async getPartitionContextIds() {
351
+ const contextIds = {};
352
+ for (const entity of this._store) {
353
+ const partitionId = ObjectHelper.propertyGet(entity, MemoryEntityStorageConnector._PARTITION_KEY);
354
+ if (Is.stringValue(partitionId)) {
355
+ contextIds[partitionId] = ContextIdHelper.shortSplit(this._partitionContextIds ?? [], partitionId);
356
+ }
357
+ }
358
+ return Object.values(contextIds);
359
+ }
360
+ /**
361
+ * Create the target connector for performing the migration it will use a temporary storage location.
362
+ * @param newEntitySchema The name of the new entity schema to create the connector for.
363
+ * @returns Connector for performing the migration.
364
+ */
365
+ async createTargetConnector(newEntitySchema) {
366
+ // No resources to manipulate for in-memory, just return a new connector with the new store and the new schema.
367
+ return new MemoryEntityStorageConnector({
368
+ entitySchema: newEntitySchema,
369
+ partitionContextIds: this._partitionContextIds
370
+ });
371
+ }
372
+ /**
373
+ * Finalize the migration by tearing down the old connector and replacing it with the target connector.
374
+ * @param targetConnector The target connector to finalize the migration with.
375
+ * @param options The options to control how the migration is finalized.
376
+ * @param loggingComponentType The optional component type to use for logging the migration progress.
377
+ * @returns A promise that resolves when the migration is finalized.
378
+ */
379
+ async finalizeMigration(targetConnector, options, loggingComponentType) {
380
+ // Nothing to do for in-memory as the new connector is already using the correct store and schema.
381
+ // And there is nothing to teardown for the old connector as it is in-memory and will be garbage
382
+ // collected when there are no references to it.
383
+ return targetConnector;
384
+ }
385
+ /**
386
+ * Cleanup the migration if a migration fails or needs to be aborted.
387
+ * @param targetConnector The target connector to cleanup the migration with.
388
+ * @param options The options to control how the migration is cleaned up.
389
+ * @param loggingComponentType The optional component type to use for logging the migration progress.
390
+ * @returns A promise that resolves when the migration is cleaned up.
391
+ */
392
+ async cleanupMigration(targetConnector, options, loggingComponentType) {
393
+ // Nothing to do for in-memory as there are no resources to cleanup.
358
394
  }
359
395
  /**
360
396
  * Find the item in the store.
@@ -1 +1 @@
1
- {"version":3,"file":"memoryEntityStorageConnector.js","sourceRoot":"","sources":["../../src/memoryEntityStorageConnector.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\tCoerce,\n\tComponentFactory,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\tEntityConditions,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySorter,\n\tLogicalOperator,\n\ttype EntityCondition,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\ttype SortDirection\n} from \"@twin.org/entity\";\nimport type { IEntityStorageConnector } from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IMemoryEntityStorageConnectorConstructorOptions } from \"./models/IMemoryEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in-memory.\n */\nexport class MemoryEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MemoryEntityStorageConnector>();\n\n\t/**\n\t * Default limit for the number of items to return.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition key for the operation.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\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.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The storage for the in-memory items.\n\t * @internal\n\t */\n\tprivate readonly _store: T[];\n\n\t/**\n\t * Create a new instance of MemoryEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMemoryEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MemoryEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\t\tthis._store = [];\n\t}\n\n\t/**\n\t * Deep-clone condition tree and map `null` to `undefined` on Equals/NotEquals leaves\n\t * so in-memory evaluation matches SQL-style \"IS NULL\" / \"IS NOT NULL\" semantics.\n\t * @param condition The user-supplied condition (not mutated).\n\t * @returns A clone safe to pass to {@link EntityConditions.check}.\n\t * @internal\n\t */\n\tprivate static normalizeNullToUndefined<T>(condition: EntityCondition<T>): EntityCondition<T> {\n\t\tif (\"conditions\" in condition) {\n\t\t\treturn {\n\t\t\t\t...condition,\n\t\t\t\tconditions: condition.conditions.map(c =>\n\t\t\t\t\tMemoryEntityStorageConnector.normalizeNullToUndefined(c)\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\t// In the non-group branch, `condition` is the leaf comparator.\n\t\tconst leaf = condition;\n\t\tif (\n\t\t\t(leaf.comparison === ComparisonOperator.Equals ||\n\t\t\t\tleaf.comparison === ComparisonOperator.NotEquals) &&\n\t\t\tleaf.value === null\n\t\t) {\n\t\t\treturn { ...leaf, value: undefined };\n\t\t}\n\t\treturn { ...leaf };\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 MemoryEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tdata: { entityType: this._entitySchema.type }\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Get an entity.\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(MemoryEntityStorageConnector.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\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tconst index = this.findItem(id, secondaryIndex, finalConditions);\n\t\tconst item = index >= 0 ? ObjectHelper.clone(this._store[index]) : undefined;\n\n\t\tif (Is.objectValue(item)) {\n\t\t\tObjectHelper.propertyDelete(item, MemoryEntityStorageConnector._PARTITION_KEY);\n\t\t}\n\n\t\treturn item;\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>(MemoryEntityStorageConnector.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 finalConditions = conditions ?? [];\n\t\tconst finalEntity = ObjectHelper.clone(entity);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t\tObjectHelper.propertySet(\n\t\t\t\tfinalEntity,\n\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tpartitionKey\n\t\t\t);\n\t\t}\n\n\t\tconst existingIndex = this.findItem(\n\t\t\tfinalEntity[this._primaryKey.property] as string,\n\t\t\tundefined,\n\t\t\tfinalConditions\n\t\t);\n\t\tif (existingIndex >= 0) {\n\t\t\tthis._store[existingIndex] = finalEntity;\n\t\t} else {\n\t\t\tthis._store.push(finalEntity);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tfor (const entity of entities) {\n\t\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\t\t}\n\n\t\tconst indexMap = new Map<string, number>();\n\t\tfor (let i = 0; i < this._store.length; i++) {\n\t\t\tconst stored = this._store[i];\n\t\t\tconst storedPartition = ObjectHelper.propertyGet(\n\t\t\t\tstored,\n\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t);\n\t\t\tif (!Is.stringValue(partitionKey) || storedPartition === partitionKey) {\n\t\t\t\tindexMap.set(stored[this._primaryKey.property] as string, i);\n\t\t\t}\n\t\t}\n\n\t\tfor (const entity of entities) {\n\t\t\tconst finalEntity = ObjectHelper.clone(entity);\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tObjectHelper.propertySet(\n\t\t\t\t\tfinalEntity,\n\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tpartitionKey\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst id = finalEntity[this._primaryKey.property] as string;\n\t\t\tconst existingIndex = indexMap.get(id);\n\t\t\tif (existingIndex !== undefined) {\n\t\t\t\tthis._store[existingIndex] = finalEntity;\n\t\t\t} else {\n\t\t\t\tconst newIndex = this._store.push(finalEntity) - 1;\n\t\t\t\tindexMap.set(id, newIndex);\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(MemoryEntityStorageConnector.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\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tconst index = this.findItem(id, undefined, finalConditions);\n\n\t\tif (index >= 0) {\n\t\t\tthis._store.splice(index, 1);\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?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tlet allEntities = this._store.slice();\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(\n\t\t\t\tMemoryEntityStorageConnector.normalizeNullToUndefined(conditions)\n\t\t\t);\n\t\t}\n\n\t\tconst entities = [];\n\t\tconst finalLimit = limit ?? MemoryEntityStorageConnector._DEFAULT_LIMIT;\n\t\tlet nextCursor: string | undefined;\n\n\t\tif (allEntities.length > 0) {\n\t\t\tconst finalSortKeys = EntitySchemaHelper.buildSortProperties<T>(\n\t\t\t\tthis._entitySchema,\n\t\t\t\tsortProperties\n\t\t\t);\n\t\t\tallEntities = EntitySorter.sort(allEntities, finalSortKeys);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tfor (let i = startIndex; i < allEntities.length; i++) {\n\t\t\t\tif (\n\t\t\t\t\tEntityConditions.check(allEntities[i], finalConditions) &&\n\t\t\t\t\tentities.length < finalLimit\n\t\t\t\t) {\n\t\t\t\t\tconst entity = ObjectHelper.clone(\n\t\t\t\t\t\tIs.arrayValue(properties)\n\t\t\t\t\t\t\t? ObjectHelper.pick(allEntities[i], properties)\n\t\t\t\t\t\t\t: allEntities[i]\n\t\t\t\t\t);\n\t\t\t\t\tObjectHelper.propertyDelete(entity, MemoryEntityStorageConnector._PARTITION_KEY);\n\t\t\t\t\tentities.push(entity);\n\t\t\t\t\tif (entities.length >= finalLimit) {\n\t\t\t\t\t\tif (i < allEntities.length - 1) {\n\t\t\t\t\t\t\tnextCursor = (i + 1).toString();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tentities,\n\t\t\tcursor: nextCursor\n\t\t};\n\t}\n\n\t/**\n\t * Remove all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfor (let i = this._store.length - 1; i >= 0; i--) {\n\t\t\t\tif (\n\t\t\t\t\tObjectHelper.propertyGet(this._store[i], MemoryEntityStorageConnector._PARTITION_KEY) ===\n\t\t\t\t\tpartitionKey\n\t\t\t\t) {\n\t\t\t\t\tthis._store.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis._store.splice(0, this._store.length);\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: { property: keyof T; value: unknown }[] = [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tfor (const id of ids) {\n\t\t\tconst index = this.findItem(id, undefined, finalConditions);\n\t\t\tif (index >= 0) {\n\t\t\t\tthis._store.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the storage by clearing the underlying store.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\tthis._store.splice(0, this._store.length);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTornDown\"\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(): Promise<number> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (!Is.stringValue(partitionKey)) {\n\t\t\treturn this._store.length;\n\t\t}\n\n\t\treturn this._store.filter(\n\t\t\titem =>\n\t\t\t\tObjectHelper.propertyGet(item as object, MemoryEntityStorageConnector._PARTITION_KEY) ===\n\t\t\t\tpartitionKey\n\t\t).length;\n\t}\n\n\t/**\n\t * Get the memory store.\n\t * @returns The store.\n\t */\n\tpublic getStore(): T[] {\n\t\treturn this._store;\n\t}\n\n\t/**\n\t * Find the item in the store.\n\t * @param id The id to search for.\n\t * @param secondaryIndex The secondary index to search for.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The index of the item if found or -1.\n\t * @internal\n\t */\n\tprivate findItem(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): number {\n\t\tconst finalConditions: EntityCondition<T>[] = [];\n\n\t\tif (!Is.empty(secondaryIndex)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: secondaryIndex as string,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: id\n\t\t\t});\n\t\t}\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\t// If we haven't added a secondary index condition we need to add the primary key condition.\n\t\t\tif (finalConditions.length === 0) {\n\t\t\t\tfinalConditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tfinalConditions.push(\n\t\t\t\t...conditions.map(c => ({\n\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: c.value\n\t\t\t\t}))\n\t\t\t);\n\t\t}\n\n\t\tif (finalConditions.length > 0) {\n\t\t\tfor (let i = 0; i < this._store.length; i++) {\n\t\t\t\tif (EntityConditions.check(this._store[i], { conditions: finalConditions })) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._store.findIndex(e => e[this._primaryKey.property] === id);\n\t\t}\n\n\t\treturn -1;\n\t}\n}\n"]}
1
+ {"version":3,"file":"memoryEntityStorageConnector.js","sourceRoot":"","sources":["../../src/memoryEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tCoerce,\n\tComponentFactory,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntityConditions,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySorter,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\ttype SortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IMemoryEntityStorageConnectorConstructorOptions } from \"./models/IMemoryEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in-memory.\n */\nexport class MemoryEntityStorageConnector<T = unknown>\n\timplements IEntityStorageConnector<T>, IEntityStorageMigrationConnector\n{\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MemoryEntityStorageConnector>();\n\n\t/**\n\t * Default limit for the number of items to return.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition key for the operation.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\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.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The storage for the in-memory items.\n\t * @internal\n\t */\n\tprivate _store: T[];\n\n\t/**\n\t * Create a new instance of MemoryEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMemoryEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(MemoryEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\t\tthis._store = [];\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 MemoryEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tdata: { entityType: this._entitySchema.type }\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Get an entity.\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(MemoryEntityStorageConnector.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\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tconst index = this.findItem(id, secondaryIndex, finalConditions);\n\t\tconst item = index >= 0 ? this._store[index] : undefined;\n\n\t\tif (Is.objectValue(item)) {\n\t\t\treturn EntityHelper.unPrepareEntity<T>(item, [MemoryEntityStorageConnector._PARTITION_KEY]);\n\t\t}\n\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>(MemoryEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\n\t\tconst prepared = EntityHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t: undefined\n\t\t);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tconst existingIndex = this.findItem(\n\t\t\tprepared[this._primaryKey.property] as string,\n\t\t\tundefined,\n\t\t\tfinalConditions\n\t\t);\n\t\tif (existingIndex >= 0) {\n\t\t\tthis._store[existingIndex] = prepared;\n\t\t} else {\n\t\t\tthis._store.push(prepared);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst indexMap = new Map<string, number>();\n\t\tfor (let i = 0; i < this._store.length; i++) {\n\t\t\tconst stored = this._store[i];\n\t\t\tconst storedPartition = ObjectHelper.propertyGet(\n\t\t\t\tstored,\n\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t);\n\t\t\tif (!Is.stringValue(partitionKey) || storedPartition === partitionKey) {\n\t\t\t\tindexMap.set(stored[this._primaryKey.property] as string, i);\n\t\t\t}\n\t\t}\n\n\t\tfor (const entity of entities) {\n\t\t\tconst prepared = EntityHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t\t: undefined\n\t\t\t);\n\t\t\tconst id = prepared[this._primaryKey.property] as string;\n\t\t\tconst existingIndex = indexMap.get(id);\n\t\t\tif (existingIndex !== undefined) {\n\t\t\t\tthis._store[existingIndex] = prepared;\n\t\t\t} else {\n\t\t\t\tconst newIndex = this._store.push(prepared) - 1;\n\t\t\t\tindexMap.set(id, newIndex);\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(MemoryEntityStorageConnector.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\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tconst index = this.findItem(id, undefined, finalConditions);\n\n\t\tif (index >= 0) {\n\t\t\tthis._store.splice(index, 1);\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?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tlet allEntities = this._store.slice();\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(EntityHelper.normalizeConditionValues(conditions));\n\t\t}\n\n\t\tconst entities = [];\n\t\tconst finalLimit = limit ?? MemoryEntityStorageConnector._DEFAULT_LIMIT;\n\t\tlet nextCursor: string | undefined;\n\n\t\tif (allEntities.length > 0) {\n\t\t\tconst finalSortKeys = EntitySchemaHelper.buildSortProperties<T>(\n\t\t\t\tthis._entitySchema,\n\t\t\t\tsortProperties\n\t\t\t);\n\t\t\tallEntities = EntitySorter.sort(allEntities, finalSortKeys);\n\n\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\tfor (let i = startIndex; i < allEntities.length; i++) {\n\t\t\t\tif (\n\t\t\t\t\tEntityConditions.check(allEntities[i], finalConditions) &&\n\t\t\t\t\tentities.length < finalLimit\n\t\t\t\t) {\n\t\t\t\t\tconst entity = Is.arrayValue(properties)\n\t\t\t\t\t\t? ObjectHelper.pick(allEntities[i], properties)\n\t\t\t\t\t\t: allEntities[i];\n\t\t\t\t\tentities.push(\n\t\t\t\t\t\tEntityHelper.unPrepareEntity<T>(entity, [MemoryEntityStorageConnector._PARTITION_KEY])\n\t\t\t\t\t);\n\t\t\t\t\tif (entities.length >= finalLimit) {\n\t\t\t\t\t\tif (i < allEntities.length - 1) {\n\t\t\t\t\t\t\tnextCursor = (i + 1).toString();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tentities,\n\t\t\tcursor: nextCursor\n\t\t};\n\t}\n\n\t/**\n\t * Remove all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfor (let i = this._store.length - 1; i >= 0; i--) {\n\t\t\t\tif (\n\t\t\t\t\tObjectHelper.propertyGet(this._store[i], MemoryEntityStorageConnector._PARTITION_KEY) ===\n\t\t\t\t\tpartitionKey\n\t\t\t\t) {\n\t\t\t\t\tthis._store.splice(i, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis._store.splice(0, this._store.length);\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: { property: keyof T; value: unknown }[] = [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tfor (const id of ids) {\n\t\t\tconst index = this.findItem(id, undefined, finalConditions);\n\t\t\tif (index >= 0) {\n\t\t\t\tthis._store.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the storage by clearing the underlying store.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\tthis._store.splice(0, this._store.length);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTornDown\"\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(EntityHelper.normalizeConditionValues(conditions));\n\t\t}\n\n\t\tif (finalConditions.conditions.length === 0) {\n\t\t\treturn this._store.length;\n\t\t}\n\n\t\treturn this._store.filter(item => EntityConditions.check(item, finalConditions)).length;\n\t}\n\n\t/**\n\t * Get the memory store.\n\t * @returns The store.\n\t */\n\tpublic getStore(): T[] {\n\t\treturn this._store.map(item =>\n\t\t\tEntityHelper.unPrepareEntity<T>(item, [MemoryEntityStorageConnector._PARTITION_KEY])\n\t\t);\n\t}\n\n\t/**\n\t * Get a unique list of all the context ids from the storage.\n\t * @returns The list of unique context ids.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\tconst contextIds: { [id: string]: IContextIds } = {};\n\n\t\tfor (const entity of this._store) {\n\t\t\tconst partitionId = ObjectHelper.propertyGet(\n\t\t\t\tentity,\n\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t);\n\t\t\tif (Is.stringValue(partitionId)) {\n\t\t\t\tcontextIds[partitionId] = ContextIdHelper.shortSplit(\n\t\t\t\t\tthis._partitionContextIds ?? [],\n\t\t\t\t\tpartitionId\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn Object.values(contextIds);\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration it will use a temporary storage location.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\t// No resources to manipulate for in-memory, just return a new connector with the new store and the new schema.\n\t\treturn new MemoryEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old connector and replacing it with the target connector.\n\t * @param targetConnector The target connector to finalize the migration with.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is finalized.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\t// Nothing to do for in-memory as the new connector is already using the correct store and schema.\n\t\t// And there is nothing to teardown for the old connector as it is in-memory and will be garbage\n\t\t// collected when there are no references to it.\n\t\treturn targetConnector;\n\t}\n\n\t/**\n\t * Cleanup the migration if a migration fails or needs to be aborted.\n\t * @param targetConnector The target connector to cleanup the migration with.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is cleaned up.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// Nothing to do for in-memory as there are no resources to cleanup.\n\t}\n\n\t/**\n\t * Find the item in the store.\n\t * @param id The id to search for.\n\t * @param secondaryIndex The secondary index to search for.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The index of the item if found or -1.\n\t * @internal\n\t */\n\tprivate findItem(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): number {\n\t\tconst finalConditions: EntityCondition<T>[] = [];\n\n\t\tif (!Is.empty(secondaryIndex)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: secondaryIndex as string,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: id\n\t\t\t});\n\t\t}\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\t// If we haven't added a secondary index condition we need to add the primary key condition.\n\t\t\tif (finalConditions.length === 0) {\n\t\t\t\tfinalConditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tfinalConditions.push(\n\t\t\t\t...conditions.map(c => ({\n\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: c.value\n\t\t\t\t}))\n\t\t\t);\n\t\t}\n\n\t\tif (finalConditions.length > 0) {\n\t\t\tfor (let i = 0; i < this._store.length; i++) {\n\t\t\t\tif (EntityConditions.check(this._store[i], { conditions: finalConditions })) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._store.findIndex(e => e[this._primaryKey.property] === id);\n\t\t}\n\n\t\treturn -1;\n\t}\n}\n"]}
@@ -1,11 +1,12 @@
1
+ import { type IContextIds } from "@twin.org/context";
1
2
  import { type IHealth } from "@twin.org/core";
2
3
  import { type EntityCondition, type IEntitySchema, type SortDirection } from "@twin.org/entity";
3
- import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
4
+ import { type IEntityStorageConnector, type IEntityStorageMigrationConnector, type IMigrationOptions } from "@twin.org/entity-storage-models";
4
5
  import type { IMemoryEntityStorageConnectorConstructorOptions } from "./models/IMemoryEntityStorageConnectorConstructorOptions.js";
5
6
  /**
6
7
  * Class for performing entity storage operations in-memory.
7
8
  */
8
- export declare class MemoryEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {
9
+ export declare class MemoryEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T>, IEntityStorageMigrationConnector {
9
10
  /**
10
11
  * Runtime name for the class.
11
12
  */
@@ -109,12 +110,40 @@ export declare class MemoryEntityStorageConnector<T = unknown> implements IEntit
109
110
  teardown(nodeLoggingComponentType?: string): Promise<boolean>;
110
111
  /**
111
112
  * Count all the entities which match the conditions.
113
+ * @param conditions The optional conditions to match for the entities.
112
114
  * @returns The total count of entities in the storage.
113
115
  */
114
- count(): Promise<number>;
116
+ count(conditions?: EntityCondition<T>): Promise<number>;
115
117
  /**
116
118
  * Get the memory store.
117
119
  * @returns The store.
118
120
  */
119
121
  getStore(): T[];
122
+ /**
123
+ * Get a unique list of all the context ids from the storage.
124
+ * @returns The list of unique context ids.
125
+ */
126
+ getPartitionContextIds(): Promise<IContextIds[]>;
127
+ /**
128
+ * Create the target connector for performing the migration it will use a temporary storage location.
129
+ * @param newEntitySchema The name of the new entity schema to create the connector for.
130
+ * @returns Connector for performing the migration.
131
+ */
132
+ createTargetConnector<U>(newEntitySchema: string): Promise<IEntityStorageConnector<U>>;
133
+ /**
134
+ * Finalize the migration by tearing down the old connector and replacing it with the target connector.
135
+ * @param targetConnector The target connector to finalize the migration with.
136
+ * @param options The options to control how the migration is finalized.
137
+ * @param loggingComponentType The optional component type to use for logging the migration progress.
138
+ * @returns A promise that resolves when the migration is finalized.
139
+ */
140
+ finalizeMigration<U>(targetConnector: IEntityStorageConnector<U>, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<IEntityStorageConnector<U>>;
141
+ /**
142
+ * Cleanup the migration if a migration fails or needs to be aborted.
143
+ * @param targetConnector The target connector to cleanup the migration with.
144
+ * @param options The options to control how the migration is cleaned up.
145
+ * @param loggingComponentType The optional component type to use for logging the migration progress.
146
+ * @returns A promise that resolves when the migration is cleaned up.
147
+ */
148
+ cleanupMigration<U>(targetConnector: IEntityStorageConnector<U> | undefined, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<void>;
120
149
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.14](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-memory-v0.0.3-next.13...entity-storage-connector-memory-v0.0.3-next.14) (2026-05-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * adding schema migration functionality to all the connectors ([#85](https://github.com/iotaledger/twin-entity-storage/issues/85)) ([fd1555a](https://github.com/iotaledger/twin-entity-storage/commit/fd1555a34380158214a577586dafae821e72a578))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/entity-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
16
+
3
17
  ## [0.0.3-next.13](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-memory-v0.0.3-next.12...entity-storage-connector-memory-v0.0.3-next.13) (2026-05-13)
4
18
 
5
19
 
@@ -11,6 +11,7 @@ Class for performing entity storage operations in-memory.
11
11
  ## Implements
12
12
 
13
13
  - `IEntityStorageConnector`\<`T`\>
14
+ - `IEntityStorageMigrationConnector`
14
15
 
15
16
  ## Constructors
16
17
 
@@ -347,10 +348,18 @@ True if the teardown process was successful.
347
348
 
348
349
  ### count() {#count}
349
350
 
350
- > **count**(): `Promise`\<`number`\>
351
+ > **count**(`conditions?`): `Promise`\<`number`\>
351
352
 
352
353
  Count all the entities which match the conditions.
353
354
 
355
+ #### Parameters
356
+
357
+ ##### conditions?
358
+
359
+ `EntityCondition`\<`T`\>
360
+
361
+ The optional conditions to match for the entities.
362
+
354
363
  #### Returns
355
364
 
356
365
  `Promise`\<`number`\>
@@ -374,3 +383,141 @@ Get the memory store.
374
383
  `T`[]
375
384
 
376
385
  The store.
386
+
387
+ ***
388
+
389
+ ### getPartitionContextIds() {#getpartitioncontextids}
390
+
391
+ > **getPartitionContextIds**(): `Promise`\<`IContextIds`[]\>
392
+
393
+ Get a unique list of all the context ids from the storage.
394
+
395
+ #### Returns
396
+
397
+ `Promise`\<`IContextIds`[]\>
398
+
399
+ The list of unique context ids.
400
+
401
+ #### Implementation of
402
+
403
+ `IEntityStorageMigrationConnector.getPartitionContextIds`
404
+
405
+ ***
406
+
407
+ ### createTargetConnector() {#createtargetconnector}
408
+
409
+ > **createTargetConnector**\<`U`\>(`newEntitySchema`): `Promise`\<`IEntityStorageConnector`\<`U`\>\>
410
+
411
+ Create the target connector for performing the migration it will use a temporary storage location.
412
+
413
+ #### Type Parameters
414
+
415
+ ##### U
416
+
417
+ `U`
418
+
419
+ #### Parameters
420
+
421
+ ##### newEntitySchema
422
+
423
+ `string`
424
+
425
+ The name of the new entity schema to create the connector for.
426
+
427
+ #### Returns
428
+
429
+ `Promise`\<`IEntityStorageConnector`\<`U`\>\>
430
+
431
+ Connector for performing the migration.
432
+
433
+ #### Implementation of
434
+
435
+ `IEntityStorageMigrationConnector.createTargetConnector`
436
+
437
+ ***
438
+
439
+ ### finalizeMigration() {#finalizemigration}
440
+
441
+ > **finalizeMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`IEntityStorageConnector`\<`U`\>\>
442
+
443
+ Finalize the migration by tearing down the old connector and replacing it with the target connector.
444
+
445
+ #### Type Parameters
446
+
447
+ ##### U
448
+
449
+ `U`
450
+
451
+ #### Parameters
452
+
453
+ ##### targetConnector
454
+
455
+ `IEntityStorageConnector`\<`U`\>
456
+
457
+ The target connector to finalize the migration with.
458
+
459
+ ##### options?
460
+
461
+ `IMigrationOptions`\<`T`, `U`\>
462
+
463
+ The options to control how the migration is finalized.
464
+
465
+ ##### loggingComponentType?
466
+
467
+ `string`
468
+
469
+ The optional component type to use for logging the migration progress.
470
+
471
+ #### Returns
472
+
473
+ `Promise`\<`IEntityStorageConnector`\<`U`\>\>
474
+
475
+ A promise that resolves when the migration is finalized.
476
+
477
+ #### Implementation of
478
+
479
+ `IEntityStorageMigrationConnector.finalizeMigration`
480
+
481
+ ***
482
+
483
+ ### cleanupMigration() {#cleanupmigration}
484
+
485
+ > **cleanupMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`void`\>
486
+
487
+ Cleanup the migration if a migration fails or needs to be aborted.
488
+
489
+ #### Type Parameters
490
+
491
+ ##### U
492
+
493
+ `U`
494
+
495
+ #### Parameters
496
+
497
+ ##### targetConnector
498
+
499
+ `IEntityStorageConnector`\<`U`\> \| `undefined`
500
+
501
+ The target connector to cleanup the migration with.
502
+
503
+ ##### options?
504
+
505
+ `IMigrationOptions`\<`T`, `U`\>
506
+
507
+ The options to control how the migration is cleaned up.
508
+
509
+ ##### loggingComponentType?
510
+
511
+ `string`
512
+
513
+ The optional component type to use for logging the migration progress.
514
+
515
+ #### Returns
516
+
517
+ `Promise`\<`void`\>
518
+
519
+ A promise that resolves when the migration is cleaned up.
520
+
521
+ #### Implementation of
522
+
523
+ `IEntityStorageMigrationConnector.cleanupMigration`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-memory",
3
- "version": "0.0.3-next.13",
3
+ "version": "0.0.3-next.14",
4
4
  "description": "In-memory connector for local development, testing and short-lived workloads.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
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.13",
20
+ "@twin.org/entity-storage-models": "0.0.3-next.14",
21
21
  "@twin.org/logging-models": "next",
22
22
  "@twin.org/nameof": "next"
23
23
  },