@twin.org/entity-storage-connector-synchronised 0.0.3-next.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # TWIN Entity Storage Connector Synchronised
1
+ # Entity Storage Connector Synchronised
2
2
 
3
- Entity Storage connector implementation using synchronised storage.
3
+ This package integrates synchronised storage with an entity storage connector so local writes can be published as sync events and remote updates can be applied to local persistence.
4
4
 
5
5
  ## Installation
6
6
 
@@ -61,6 +61,7 @@ export class SynchronisedEntityStorageConnector {
61
61
  /**
62
62
  * Create a new instance of SynchronisedEntityStorageConnector.
63
63
  * @param options The options for the connector.
64
+ * @throws GeneralError if the entity schema is missing required synchronisation properties.
64
65
  */
65
66
  constructor(options) {
66
67
  Guards.object(SynchronisedEntityStorageConnector.CLASS_NAME, "options", options);
@@ -107,7 +108,7 @@ export class SynchronisedEntityStorageConnector {
107
108
  /**
108
109
  * The component needs to be started when the node is initialized.
109
110
  * @param nodeLoggingComponentType The node logging component type.
110
- * @returns Nothing.
111
+ * @returns A promise that resolves when the connector is started and event bus subscriptions are active.
111
112
  */
112
113
  async start(nodeLoggingComponentType) {
113
114
  const contextIds = await ContextIdStore.getContextIds();
@@ -134,7 +135,7 @@ export class SynchronisedEntityStorageConnector {
134
135
  * Set an entity.
135
136
  * @param entity The entity to set.
136
137
  * @param conditions The optional conditions to match for the entities.
137
- * @returns The id of the entity.
138
+ * @returns A promise that resolves when the entity is stored and the change event is published.
138
139
  */
139
140
  async set(entity, conditions) {
140
141
  Guards.object(SynchronisedEntityStorageConnector.CLASS_NAME, "entity", entity);
@@ -152,11 +153,35 @@ export class SynchronisedEntityStorageConnector {
152
153
  });
153
154
  }
154
155
  }
156
+ /**
157
+ * Set multiple entities in a batch.
158
+ * @param entities The entities to set.
159
+ * @returns A promise that resolves when all entities are stored and change events are published.
160
+ */
161
+ async setBatch(entities) {
162
+ Guards.arrayValue(SynchronisedEntityStorageConnector.CLASS_NAME, "entities", entities);
163
+ if (Is.stringValue(this._nodeId)) {
164
+ const now = new Date(Date.now()).toISOString();
165
+ for (const entity of entities) {
166
+ entity.dateModified = now;
167
+ entity.nodeIdentity = this._nodeId;
168
+ }
169
+ await this._entityStorageConnector.setBatch(entities);
170
+ for (const entity of entities) {
171
+ await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
172
+ storageKey: this._storageKey,
173
+ operation: SyncChangeOperation.Set,
174
+ nodeId: this._nodeId,
175
+ id: entity[this._primaryKey.property]
176
+ });
177
+ }
178
+ }
179
+ }
155
180
  /**
156
181
  * Remove the entity.
157
182
  * @param id The id of the entity to remove.
158
183
  * @param conditions The optional conditions to match for the entities.
159
- * @returns Nothing.
184
+ * @returns A promise that resolves when the entity is removed and the delete event is published.
160
185
  */
161
186
  async remove(id, conditions) {
162
187
  Guards.stringValue(SynchronisedEntityStorageConnector.CLASS_NAME, "id", id);
@@ -171,6 +196,59 @@ export class SynchronisedEntityStorageConnector {
171
196
  });
172
197
  }
173
198
  }
199
+ /**
200
+ * Remove multiple entities by id.
201
+ * @param ids The ids of the entities to remove.
202
+ * @returns A promise that resolves when all entities are removed and delete events are published.
203
+ */
204
+ async removeBatch(ids) {
205
+ Guards.arrayValue(SynchronisedEntityStorageConnector.CLASS_NAME, "ids", ids);
206
+ if (Is.stringValue(this._nodeId)) {
207
+ await this._entityStorageConnector.removeBatch(ids);
208
+ for (const id of ids) {
209
+ await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
210
+ storageKey: this._storageKey,
211
+ operation: SyncChangeOperation.Delete,
212
+ nodeId: this._nodeId,
213
+ id
214
+ });
215
+ }
216
+ }
217
+ }
218
+ /**
219
+ * Remove all entities from the storage.
220
+ * @returns A promise that resolves when all entities are removed and delete events are published.
221
+ */
222
+ async empty() {
223
+ if (Is.stringValue(this._nodeId)) {
224
+ let cursor;
225
+ const ids = [];
226
+ do {
227
+ const result = await this._entityStorageConnector.query(undefined, undefined, [this._primaryKey.property], cursor);
228
+ cursor = result.cursor;
229
+ ids.push(...result.entities.map(e => e[this._primaryKey.property]));
230
+ } while (Is.stringValue(cursor));
231
+ await this._entityStorageConnector.empty();
232
+ for (const id of ids) {
233
+ await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
234
+ storageKey: this._storageKey,
235
+ operation: SyncChangeOperation.Delete,
236
+ nodeId: this._nodeId,
237
+ id
238
+ });
239
+ }
240
+ }
241
+ else {
242
+ await this._entityStorageConnector.empty();
243
+ }
244
+ }
245
+ /**
246
+ * Count all the entities which match the conditions.
247
+ * @returns The total count of entities in the storage.
248
+ */
249
+ async count() {
250
+ return this._entityStorageConnector.count();
251
+ }
174
252
  /**
175
253
  * Find all the entities which match the conditions.
176
254
  * @param conditions The conditions to match for the entities.
@@ -187,6 +265,7 @@ export class SynchronisedEntityStorageConnector {
187
265
  }
188
266
  /**
189
267
  * Handle the event bus messages.
268
+ * @returns A promise that resolves when all subscriptions are registered.
190
269
  * @internal
191
270
  */
192
271
  async handleEventBusMessages() {
@@ -213,7 +292,8 @@ export class SynchronisedEntityStorageConnector {
213
292
  }
214
293
  /**
215
294
  * Handle a local item request.
216
- * @param event The request parameters
295
+ * @param event The request parameters.
296
+ * @returns A promise that resolves when the item response is published.
217
297
  * @internal
218
298
  */
219
299
  async handleLocalItemRequest(event) {
@@ -234,7 +314,8 @@ export class SynchronisedEntityStorageConnector {
234
314
  }
235
315
  /**
236
316
  * Handle a remote item set event.
237
- * @param event The event parameters
317
+ * @param event The event parameters.
318
+ * @returns A promise that resolves when the entity is stored locally if it matches this connector's storage key.
238
319
  * @internal
239
320
  */
240
321
  async handleRemoteItemSet(event) {
@@ -248,7 +329,8 @@ export class SynchronisedEntityStorageConnector {
248
329
  }
249
330
  /**
250
331
  * Handle a remote item remove event.
251
- * @param params The event parameters
332
+ * @param params The event parameters.
333
+ * @returns A promise that resolves when the entity is removed locally if it matches this connector's storage key.
252
334
  * @internal
253
335
  */
254
336
  async handleRemoteItemRemove(params) {
@@ -261,7 +343,8 @@ export class SynchronisedEntityStorageConnector {
261
343
  }
262
344
  /**
263
345
  * Handle a batch request.
264
- * @param event The request parameters
346
+ * @param event The request parameters.
347
+ * @returns A promise that resolves when all batch response pages are published.
265
348
  * @internal
266
349
  */
267
350
  async handleBatchRequest(event) {
@@ -300,7 +383,8 @@ export class SynchronisedEntityStorageConnector {
300
383
  }
301
384
  /**
302
385
  * Handle a reset event.
303
- * @param event The event parameters
386
+ * @param event The event parameters.
387
+ * @returns A promise that resolves when matching entities are removed from local storage.
304
388
  * @internal
305
389
  */
306
390
  async handleReset(event) {
@@ -1 +1 @@
1
- {"version":3,"file":"synchronisedEntityStorageConnector.js","sourceRoot":"","sources":["../../src/synchronisedEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, GeneralError, Guards, Is, StringHelper } from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport type { IEvent, IEventBusComponent } from \"@twin.org/event-bus-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype ISyncBatchRequest,\n\ttype ISyncBatchResponse,\n\ttype ISynchronisedEntity,\n\ttype ISyncItemChange,\n\ttype ISyncItemRemove,\n\ttype ISyncItemRequest,\n\ttype ISyncItemResponse,\n\ttype ISyncItemSet,\n\ttype ISyncRegisterStorageKey,\n\ttype ISyncReset,\n\tSyncChangeOperation,\n\tSynchronisedStorageTopics,\n\tSyncNodeIdMode\n} from \"@twin.org/synchronised-storage-models\";\nimport type { ISynchronisedEntityStorageConnectorConstructorOptions } from \"./models/ISynchronisedEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in synchronised storage.\n */\nexport class SynchronisedEntityStorageConnector<\n\tT extends ISynchronisedEntity = ISynchronisedEntity\n> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<SynchronisedEntityStorageConnector>();\n\n\t/**\n\t * Fixed name for node id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_NODE_IDENTITY = \"nodeIdentity\";\n\n\t/**\n\t * Fixed name for date modified properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_DATE_MODIFIED = \"dateModified\";\n\n\t/**\n\t * Fixed name for id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_ID = \"id\";\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 primary key for the entity schema.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The storage key for the entity.\n\t * @internal\n\t */\n\tprivate readonly _storageKey: string;\n\n\t/**\n\t * The entity storage connector to use for actual data.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnector: IEntityStorageConnector<T>;\n\n\t/**\n\t * The event bus component.\n\t * @internal\n\t */\n\tprivate readonly _eventBusComponent: IEventBusComponent;\n\n\t/**\n\t * The node identity.\n\t * @internal\n\t */\n\tprivate _nodeId?: string;\n\n\t/**\n\t * Create a new instance of SynchronisedEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: ISynchronisedEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object<ISynchronisedEntityStorageConnectorConstructorOptions>(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options),\n\t\t\toptions\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entityStorageConnectorType),\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._storageKey = options?.config?.storageKey ?? StringHelper.kebabCase(options.entitySchema);\n\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tconst requiredProperties: (keyof ISynchronisedEntity)[] = [\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_ID,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_NODE_IDENTITY,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED\n\t\t];\n\n\t\tfor (const requiredProperty of requiredProperties) {\n\t\t\tconst foundProperty = this._entitySchema.properties?.find(\n\t\t\t\tprop => prop.property === requiredProperty\n\t\t\t);\n\t\t\tif (Is.empty(foundProperty)) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredProperty\",\n\t\t\t\t\t{ requiredProperty }\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tIs.empty(foundProperty.isPrimary) &&\n\t\t\t\tIs.empty(foundProperty.isSecondary) &&\n\t\t\t\tIs.empty(foundProperty.sortDirection)\n\t\t\t) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredPropertySort\",\n\t\t\t\t\t{\n\t\t\t\t\t\trequiredProperty\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._eventBusComponent = ComponentFactory.get(options.eventBusComponentType ?? \"event-bus\");\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 SynchronisedEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * The component needs to be started when the node is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Node);\n\t\tthis._nodeId = contextIds[ContextIdKeys.Node];\n\n\t\t// Tell the synchronised storage about this storage key\n\t\tawait this._eventBusComponent.publish<ISyncRegisterStorageKey>(\n\t\t\tSynchronisedStorageTopics.RegisterStorageKey,\n\t\t\t{\n\t\t\t\tstorageKey: this._storageKey\n\t\t\t}\n\t\t);\n\n\t\tawait this.handleEventBusMessages();\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\treturn this._entityStorageConnector.get(id, secondaryIndex, conditions);\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>(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\t// Make sure the entity has the required properties populated\n\t\t\tentity.dateModified = new Date(Date.now()).toISOString();\n\t\t\tentity.nodeIdentity = this._nodeId;\n\n\t\t\tawait this._entityStorageConnector.set(entity, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity changes\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Set,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid: entity[this._primaryKey.property] as string\n\t\t\t\t}\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tawait this._entityStorageConnector.remove(id, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity removal\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Delete,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: {\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\t// We deliberately skip the partition key as we want to query all partitions in synchronised storage\n\t\treturn this._entityStorageConnector.query(\n\t\t\tconditions,\n\t\t\tsortProperties,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\t}\n\n\t/**\n\t * Handle the event bus messages.\n\t * @internal\n\t */\n\tprivate async handleEventBusMessages(): Promise<void> {\n\t\t// When the synchronised storage requests an item, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRequest>(\n\t\t\tSynchronisedStorageTopics.LocalItemRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleLocalItemRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// When the synchronised storage requests a batch, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncBatchRequest>(\n\t\t\tSynchronisedStorageTopics.BatchRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleBatchRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item set events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemSet>(\n\t\t\tSynchronisedStorageTopics.RemoteItemSet,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemSet(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item remove events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRemove>(\n\t\t\tSynchronisedStorageTopics.RemoteItemRemove,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemRemove(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to resets from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncReset>(\n\t\t\tSynchronisedStorageTopics.Reset,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleReset(params);\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Handle a local item request.\n\t * @param event The request parameters\n\t * @internal\n\t */\n\tprivate async handleLocalItemRequest(event: IEvent<ISyncItemRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet entity: T | undefined;\n\t\t\ttry {\n\t\t\t\tentity = await this._entityStorageConnector.get(event.data.id);\n\t\t\t} catch {}\n\n\t\t\t// Publish the item response with the entity\n\t\t\tawait this._eventBusComponent.publish<ISyncItemResponse>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemResponse,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\tid: event.data.id,\n\t\t\t\t\tentity\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item set event.\n\t * @param event The event parameters\n\t * @internal\n\t */\n\tprivate async handleRemoteItemSet(event: IEvent<ISyncItemSet>): Promise<void> {\n\t\t// Only set the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (\n\t\t\tevent.data.storageKey === this._storageKey &&\n\t\t\tevent.data.entity.nodeIdentity !== this._nodeId\n\t\t) {\n\t\t\tawait this._entityStorageConnector.set(event.data.entity as T);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item remove event.\n\t * @param params The event parameters\n\t * @internal\n\t */\n\tprivate async handleRemoteItemRemove(params: IEvent<ISyncItemRemove>): Promise<void> {\n\t\t// Only remove the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (params.data.storageKey === this._storageKey && params.data.nodeId !== this._nodeId) {\n\t\t\tawait this._entityStorageConnector.remove(params.data.id);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a batch request.\n\t * @param event The request parameters\n\t * @internal\n\t */\n\tprivate async handleBatchRequest(event: IEvent<ISyncBatchRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\t\t\t\tif (\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_NODE_IDENTITY,\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED,\n\t\t\t\t\t\t\tsortDirection: SortDirection.Ascending\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor,\n\t\t\t\t\tevent.data.batchSize\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\n\t\t\t\t// Publish the batch response with the entities\n\t\t\t\tawait this._eventBusComponent.publish<ISyncBatchResponse>(\n\t\t\t\t\tSynchronisedStorageTopics.BatchResponse,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\tentities: result.entities as T[],\n\t\t\t\t\t\tlastEntry: !Is.stringValue(cursor)\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} while (Is.stringValue(cursor));\n\t\t}\n\t}\n\n\t/**\n\t * Handle a reset event.\n\t * @param event The event parameters\n\t * @internal\n\t */\n\tprivate async handleReset(event: IEvent<ISyncReset>): Promise<void> {\n\t\t// Only reset the storage if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tlet toRemove: string[] = [];\n\n\t\t\t// Build a list of the ids to remove\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\n\t\t\t\t// Depending on the reset mode we can filter the entities to remove\n\t\t\t\tif (\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: \"nodeIdentity\",\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\t\t\t\ttoRemove = toRemove.concat(result.entities.map(entity => (entity as T).id));\n\t\t\t} while (Is.stringValue(cursor));\n\n\t\t\t// Remove the entities\n\t\t\tfor (let i = 0; i < toRemove.length; i++) {\n\t\t\t\tawait this.remove(toRemove[i]);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"synchronisedEntityStorageConnector.js","sourceRoot":"","sources":["../../src/synchronisedEntityStorageConnector.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EACN,kBAAkB,EAElB,mBAAmB,EACnB,kBAAkB,EAGlB,aAAa,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,6BAA6B,EAE7B,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAWN,mBAAmB,EACnB,yBAAyB,EACzB,cAAc,EACd,MAAM,uCAAuC,CAAC;AAG/C;;GAEG;AACH,MAAM,OAAO,kCAAkC;IAG9C;;OAEG;IACI,MAAM,CAAU,UAAU,wCAAwD;IAEzF;;;OAGG;IACK,MAAM,CAAU,wBAAwB,GAAG,cAAc,CAAC;IAElE;;;OAGG;IACK,MAAM,CAAU,wBAAwB,GAAG,cAAc,CAAC;IAElE;;;OAGG;IACK,MAAM,CAAU,aAAa,GAAG,IAAI,CAAC;IAE7C;;;OAGG;IACc,aAAa,CAAmB;IAEjD;;;OAGG;IACc,WAAW,CAA2B;IAEvD;;;OAGG;IACc,WAAW,CAAS;IAErC;;;OAGG;IACc,uBAAuB,CAA6B;IAErE;;;OAGG;IACc,kBAAkB,CAAqB;IAExD;;;OAGG;IACK,OAAO,CAAU;IAEzB;;;;OAIG;IACH,YAAY,OAA8D;QACzE,MAAM,CAAC,MAAM,CACZ,kCAAkC,CAAC,UAAU,aAE7C,OAAO,CACP,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,kCAAkC,CAAC,UAAU,0BAE7C,OAAO,CAAC,YAAY,CACpB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,kCAAkC,CAAC,UAAU,wCAE7C,OAAO,CAAC,0BAA0B,CAClC,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,IAAI,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAE/F,IAAI,CAAC,WAAW,GAAG,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAExE,MAAM,kBAAkB,GAAkC;YACzD,kCAAkC,CAAC,aAAa;YAChD,kCAAkC,CAAC,wBAAwB;YAC3D,kCAAkC,CAAC,wBAAwB;SAC3D,CAAC;QAEF,KAAK,MAAM,gBAAgB,IAAI,kBAAkB,EAAE,CAAC;YACnD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CACxD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,gBAAgB,CAC1C,CAAC;YACF,IAAI,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,YAAY,CACrB,kCAAkC,CAAC,UAAU,EAC7C,yBAAyB,EACzB,EAAE,gBAAgB,EAAE,CACpB,CAAC;YACH,CAAC;iBAAM,IACN,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC;gBACjC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;gBACnC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,EACpC,CAAC;gBACF,MAAM,IAAI,YAAY,CACrB,kCAAkC,CAAC,UAAU,EAC7C,6BAA6B,EAC7B;oBACC,gBAAgB;iBAChB,CACD,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,CAAC,uBAAuB,GAAG,6BAA6B,CAAC,GAAG,CAC/D,OAAO,CAAC,0BAA0B,CAClC,CAAC;QAEF,IAAI,CAAC,kBAAkB,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,IAAI,WAAW,CAAC,CAAC;IAC9F,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,kCAAkC,CAAC,UAAU,CAAC;IACtD,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,IAAI,CAAC,aAA8B,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,KAAK,CAAC,wBAAiC;QACnD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,eAAe,CAAC,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAE9C,uDAAuD;QACvD,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,kBAAkB,EAC5C;YACC,UAAU,EAAE,IAAI,CAAC,WAAW;SAC5B,CACD,CAAC;QAEF,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,GAAG,CACf,EAAU,EACV,cAAwB,EACxB,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,kCAAkC,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAElF,OAAO,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACzE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,GAAG,CAAC,MAAS,EAAE,UAAoD;QAC/E,MAAM,CAAC,MAAM,CAAI,kCAAkC,CAAC,UAAU,YAAkB,MAAM,CAAC,CAAC;QAExF,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,6DAA6D;YAC7D,MAAM,CAAC,YAAY,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YACzD,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC;YAEnC,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAE3D,yDAAyD;YACzD,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,eAAe,EACzC;gBACC,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,SAAS,EAAE,mBAAmB,CAAC,GAAG;gBAClC,MAAM,EAAE,IAAI,CAAC,OAAO;gBACpB,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAW;aAC/C,CACD,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,QAAQ,CAAC,QAAa;QAClC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,UAAU,cAAoB,QAAQ,CAAC,CAAC;QAE7F,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAC/C,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;gBAC1B,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC;YACpC,CAAC;YAED,MAAM,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEtD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,eAAe,EACzC;oBACC,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,SAAS,EAAE,mBAAmB,CAAC,GAAG;oBAClC,MAAM,EAAE,IAAI,CAAC,OAAO;oBACpB,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAW;iBAC/C,CACD,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,MAAM,CAClB,EAAU,EACV,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,kCAAkC,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAElF,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAE1D,yDAAyD;YACzD,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,eAAe,EACzC;gBACC,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,SAAS,EAAE,mBAAmB,CAAC,MAAM;gBACrC,MAAM,EAAE,IAAI,CAAC,OAAO;gBACpB,EAAE;aACF,CACD,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,WAAW,CAAC,GAAa;QACrC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QAEnF,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAEpD,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACtB,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,eAAe,EACzC;oBACC,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,SAAS,EAAE,mBAAmB,CAAC,MAAM;oBACrC,MAAM,EAAE,IAAI,CAAC,OAAO;oBACpB,EAAE;iBACF,CACD,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,KAAK;QACjB,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,IAAI,MAA0B,CAAC;YAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;YAEzB,GAAG,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAC3B,MAAM,CACN,CAAC;gBACF,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBACvB,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,CAAO,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAW,CAAC,CAAC,CAAC;YACtF,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;YAEjC,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;YAE3C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACtB,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,eAAe,EACzC;oBACC,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,SAAS,EAAE,mBAAmB,CAAC,MAAM;oBACrC,MAAM,EAAE,IAAI,CAAC,OAAO;oBACpB,EAAE;iBACF,CACD,CAAC;YACH,CAAC;QACF,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QAC5C,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,KAAK;QACjB,OAAO,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,KAAK,CACjB,UAA+B,EAC/B,cAGG,EACH,UAAwB,EACxB,MAAe,EACf,KAAc;QAWd,oGAAoG;QACpG,OAAO,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACxC,UAAU,EACV,cAAc,EACd,UAAU,EACV,MAAM,EACN,KAAK,CACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,sBAAsB;QACnC,wEAAwE;QACxE,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CACtC,yBAAyB,CAAC,gBAAgB,EAC1C,KAAK,EAAC,MAAM,EAAC,EAAE;YACd,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC,CACD,CAAC;QAEF,wEAAwE;QACxE,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CACtC,yBAAyB,CAAC,YAAY,EACtC,KAAK,EAAC,MAAM,EAAC,EAAE;YACd,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CACD,CAAC;QAEF,iGAAiG;QACjG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CACtC,yBAAyB,CAAC,aAAa,EACvC,KAAK,EAAC,MAAM,EAAC,EAAE;YACd,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC,CACD,CAAC;QAEF,oGAAoG;QACpG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CACtC,yBAAyB,CAAC,gBAAgB,EAC1C,KAAK,EAAC,MAAM,EAAC,EAAE;YACd,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC,CACD,CAAC;QAEF,iFAAiF;QACjF,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CACtC,yBAAyB,CAAC,KAAK,EAC/B,KAAK,EAAC,MAAM,EAAC,EAAE;YACd,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC,CACD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,sBAAsB,CAAC,KAA+B;QACnE,wDAAwD;QACxD,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAChD,IAAI,MAAqB,CAAC;YAC1B,IAAI,CAAC;gBACJ,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChE,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAEV,4CAA4C;YAC5C,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,iBAAiB,EAC3C;gBACC,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE;gBACjB,MAAM;aACN,CACD,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,mBAAmB,CAAC,KAA2B;QAC5D,kDAAkD;QAClD,gFAAgF;QAChF,2DAA2D;QAC3D,IACC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW;YAC1C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC,OAAO,EAC9C,CAAC;YACF,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAW,CAAC,CAAC;QAChE,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,sBAAsB,CAAC,MAA+B;QACnE,qDAAqD;QACrD,gFAAgF;QAChF,2DAA2D;QAC3D,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACxF,MAAM,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,kBAAkB,CAAC,KAAgC;QAChE,wDAAwD;QACxD,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC;YACX,GAAG,CAAC;gBACH,MAAM,SAAS,GAAuB;oBACrC,UAAU,EAAE,EAAE;iBACd,CAAC;gBACF,IACC,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,KAAK;oBAC/C,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,MAAM,EAC/C,CAAC;oBACF,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC;wBACzB,QAAQ,EAAE,kCAAkC,CAAC,wBAAwB;wBACrE,KAAK,EAAE,IAAI,CAAC,OAAO;wBACnB,UAAU,EACT,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,cAAc,CAAC,KAAK;4BAC9C,CAAC,CAAC,kBAAkB,CAAC,MAAM;4BAC3B,CAAC,CAAC,kBAAkB,CAAC,SAAS;qBAChC,CAAC,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT;oBACC;wBACC,QAAQ,EAAE,kCAAkC,CAAC,wBAAwB;wBACrE,aAAa,EAAE,aAAa,CAAC,SAAS;qBACtC;iBACD,EACD,SAAS,EACT,MAAM,EACN,KAAK,CAAC,IAAI,CAAC,SAAS,CACpB,CAAC;gBAEF,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBAEvB,+CAA+C;gBAC/C,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CACpC,yBAAyB,CAAC,aAAa,EACvC;oBACC,UAAU,EAAE,IAAI,CAAC,WAAW;oBAC5B,QAAQ,EAAE,MAAM,CAAC,QAAe;oBAChC,SAAS,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;iBAClC,CACD,CAAC;YACH,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;QAClC,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,WAAW,CAAC,KAAyB;QAClD,uDAAuD;QACvD,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAChD,IAAI,MAAM,CAAC;YACX,IAAI,QAAQ,GAAa,EAAE,CAAC;YAE5B,oCAAoC;YACpC,GAAG,CAAC;gBACH,MAAM,SAAS,GAAuB;oBACrC,UAAU,EAAE,EAAE;iBACd,CAAC;gBAEF,mEAAmE;gBACnE,IACC,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,cAAc,CAAC,KAAK;oBAC7C,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,cAAc,CAAC,MAAM,EAC7C,CAAC;oBACF,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC;wBACzB,QAAQ,EAAE,cAAc;wBACxB,KAAK,EAAE,IAAI,CAAC,OAAO;wBACnB,UAAU,EACT,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,cAAc,CAAC,KAAK;4BAC5C,CAAC,CAAC,kBAAkB,CAAC,MAAM;4BAC3B,CAAC,CAAC,kBAAkB,CAAC,SAAS;qBAChC,CAAC,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,CACN,CAAC;gBAEF,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBACvB,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAE,MAAY,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7E,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;YAEjC,sBAAsB;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC1C,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, GeneralError, Guards, Is, StringHelper } from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport type { IEvent, IEventBusComponent } from \"@twin.org/event-bus-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype ISyncBatchRequest,\n\ttype ISyncBatchResponse,\n\ttype ISynchronisedEntity,\n\ttype ISyncItemChange,\n\ttype ISyncItemRemove,\n\ttype ISyncItemRequest,\n\ttype ISyncItemResponse,\n\ttype ISyncItemSet,\n\ttype ISyncRegisterStorageKey,\n\ttype ISyncReset,\n\tSyncChangeOperation,\n\tSynchronisedStorageTopics,\n\tSyncNodeIdMode\n} from \"@twin.org/synchronised-storage-models\";\nimport type { ISynchronisedEntityStorageConnectorConstructorOptions } from \"./models/ISynchronisedEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in synchronised storage.\n */\nexport class SynchronisedEntityStorageConnector<\n\tT extends ISynchronisedEntity = ISynchronisedEntity\n> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<SynchronisedEntityStorageConnector>();\n\n\t/**\n\t * Fixed name for node id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_NODE_IDENTITY = \"nodeIdentity\";\n\n\t/**\n\t * Fixed name for date modified properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_DATE_MODIFIED = \"dateModified\";\n\n\t/**\n\t * Fixed name for id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_ID = \"id\";\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 primary key for the entity schema.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The storage key for the entity.\n\t * @internal\n\t */\n\tprivate readonly _storageKey: string;\n\n\t/**\n\t * The entity storage connector to use for actual data.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnector: IEntityStorageConnector<T>;\n\n\t/**\n\t * The event bus component.\n\t * @internal\n\t */\n\tprivate readonly _eventBusComponent: IEventBusComponent;\n\n\t/**\n\t * The node identity.\n\t * @internal\n\t */\n\tprivate _nodeId?: string;\n\n\t/**\n\t * Create a new instance of SynchronisedEntityStorageConnector.\n\t * @param options The options for the connector.\n\t * @throws GeneralError if the entity schema is missing required synchronisation properties.\n\t */\n\tconstructor(options: ISynchronisedEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object<ISynchronisedEntityStorageConnectorConstructorOptions>(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options),\n\t\t\toptions\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entityStorageConnectorType),\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._storageKey = options?.config?.storageKey ?? StringHelper.kebabCase(options.entitySchema);\n\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tconst requiredProperties: (keyof ISynchronisedEntity)[] = [\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_ID,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_NODE_IDENTITY,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED\n\t\t];\n\n\t\tfor (const requiredProperty of requiredProperties) {\n\t\t\tconst foundProperty = this._entitySchema.properties?.find(\n\t\t\t\tprop => prop.property === requiredProperty\n\t\t\t);\n\t\t\tif (Is.empty(foundProperty)) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredProperty\",\n\t\t\t\t\t{ requiredProperty }\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tIs.empty(foundProperty.isPrimary) &&\n\t\t\t\tIs.empty(foundProperty.isSecondary) &&\n\t\t\t\tIs.empty(foundProperty.sortDirection)\n\t\t\t) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredPropertySort\",\n\t\t\t\t\t{\n\t\t\t\t\t\trequiredProperty\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._eventBusComponent = ComponentFactory.get(options.eventBusComponentType ?? \"event-bus\");\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 SynchronisedEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * The component needs to be started when the node is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when the connector is started and event bus subscriptions are active.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Node);\n\t\tthis._nodeId = contextIds[ContextIdKeys.Node];\n\n\t\t// Tell the synchronised storage about this storage key\n\t\tawait this._eventBusComponent.publish<ISyncRegisterStorageKey>(\n\t\t\tSynchronisedStorageTopics.RegisterStorageKey,\n\t\t\t{\n\t\t\t\tstorageKey: this._storageKey\n\t\t\t}\n\t\t);\n\n\t\tawait this.handleEventBusMessages();\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\treturn this._entityStorageConnector.get(id, secondaryIndex, conditions);\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 A promise that resolves when the entity is stored and the change event is published.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\t// Make sure the entity has the required properties populated\n\t\t\tentity.dateModified = new Date(Date.now()).toISOString();\n\t\t\tentity.nodeIdentity = this._nodeId;\n\n\t\t\tawait this._entityStorageConnector.set(entity, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity changes\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Set,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid: entity[this._primaryKey.property] as string\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns A promise that resolves when all entities are stored and change events are published.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tconst now = new Date(Date.now()).toISOString();\n\t\t\tfor (const entity of entities) {\n\t\t\t\tentity.dateModified = now;\n\t\t\t\tentity.nodeIdentity = this._nodeId;\n\t\t\t}\n\n\t\t\tawait this._entityStorageConnector.setBatch(entities);\n\n\t\t\tfor (const entity of entities) {\n\t\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\toperation: SyncChangeOperation.Set,\n\t\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\t\tid: entity[this._primaryKey.property] as string\n\t\t\t\t\t}\n\t\t\t\t);\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 A promise that resolves when the entity is removed and the delete event is published.\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tawait this._entityStorageConnector.remove(id, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity removal\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Delete,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t);\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 A promise that resolves when all entities are removed and delete events are published.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tawait this._entityStorageConnector.removeBatch(ids);\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\toperation: SyncChangeOperation.Delete,\n\t\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all entities from the storage.\n\t * @returns A promise that resolves when all entities are removed and delete events are published.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tlet cursor: string | undefined;\n\t\t\tconst ids: string[] = [];\n\n\t\t\tdo {\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\t[this._primaryKey.property],\n\t\t\t\t\tcursor\n\t\t\t\t);\n\t\t\t\tcursor = result.cursor;\n\t\t\t\tids.push(...result.entities.map(e => (e as T)[this._primaryKey.property] as string));\n\t\t\t} while (Is.stringValue(cursor));\n\n\t\t\tawait this._entityStorageConnector.empty();\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\toperation: SyncChangeOperation.Delete,\n\t\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tawait this._entityStorageConnector.empty();\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(): Promise<number> {\n\t\treturn this._entityStorageConnector.count();\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\t// We deliberately skip the partition key as we want to query all partitions in synchronised storage\n\t\treturn this._entityStorageConnector.query(\n\t\t\tconditions,\n\t\t\tsortProperties,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\t}\n\n\t/**\n\t * Handle the event bus messages.\n\t * @returns A promise that resolves when all subscriptions are registered.\n\t * @internal\n\t */\n\tprivate async handleEventBusMessages(): Promise<void> {\n\t\t// When the synchronised storage requests an item, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRequest>(\n\t\t\tSynchronisedStorageTopics.LocalItemRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleLocalItemRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// When the synchronised storage requests a batch, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncBatchRequest>(\n\t\t\tSynchronisedStorageTopics.BatchRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleBatchRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item set events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemSet>(\n\t\t\tSynchronisedStorageTopics.RemoteItemSet,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemSet(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item remove events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRemove>(\n\t\t\tSynchronisedStorageTopics.RemoteItemRemove,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemRemove(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to resets from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncReset>(\n\t\t\tSynchronisedStorageTopics.Reset,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleReset(params);\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Handle a local item request.\n\t * @param event The request parameters.\n\t * @returns A promise that resolves when the item response is published.\n\t * @internal\n\t */\n\tprivate async handleLocalItemRequest(event: IEvent<ISyncItemRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet entity: T | undefined;\n\t\t\ttry {\n\t\t\t\tentity = await this._entityStorageConnector.get(event.data.id);\n\t\t\t} catch {}\n\n\t\t\t// Publish the item response with the entity\n\t\t\tawait this._eventBusComponent.publish<ISyncItemResponse>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemResponse,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\tid: event.data.id,\n\t\t\t\t\tentity\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item set event.\n\t * @param event The event parameters.\n\t * @returns A promise that resolves when the entity is stored locally if it matches this connector's storage key.\n\t * @internal\n\t */\n\tprivate async handleRemoteItemSet(event: IEvent<ISyncItemSet>): Promise<void> {\n\t\t// Only set the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (\n\t\t\tevent.data.storageKey === this._storageKey &&\n\t\t\tevent.data.entity.nodeIdentity !== this._nodeId\n\t\t) {\n\t\t\tawait this._entityStorageConnector.set(event.data.entity as T);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item remove event.\n\t * @param params The event parameters.\n\t * @returns A promise that resolves when the entity is removed locally if it matches this connector's storage key.\n\t * @internal\n\t */\n\tprivate async handleRemoteItemRemove(params: IEvent<ISyncItemRemove>): Promise<void> {\n\t\t// Only remove the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (params.data.storageKey === this._storageKey && params.data.nodeId !== this._nodeId) {\n\t\t\tawait this._entityStorageConnector.remove(params.data.id);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a batch request.\n\t * @param event The request parameters.\n\t * @returns A promise that resolves when all batch response pages are published.\n\t * @internal\n\t */\n\tprivate async handleBatchRequest(event: IEvent<ISyncBatchRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\t\t\t\tif (\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_NODE_IDENTITY,\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED,\n\t\t\t\t\t\t\tsortDirection: SortDirection.Ascending\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor,\n\t\t\t\t\tevent.data.batchSize\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\n\t\t\t\t// Publish the batch response with the entities\n\t\t\t\tawait this._eventBusComponent.publish<ISyncBatchResponse>(\n\t\t\t\t\tSynchronisedStorageTopics.BatchResponse,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\tentities: result.entities as T[],\n\t\t\t\t\t\tlastEntry: !Is.stringValue(cursor)\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} while (Is.stringValue(cursor));\n\t\t}\n\t}\n\n\t/**\n\t * Handle a reset event.\n\t * @param event The event parameters.\n\t * @returns A promise that resolves when matching entities are removed from local storage.\n\t * @internal\n\t */\n\tprivate async handleReset(event: IEvent<ISyncReset>): Promise<void> {\n\t\t// Only reset the storage if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tlet toRemove: string[] = [];\n\n\t\t\t// Build a list of the ids to remove\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\n\t\t\t\t// Depending on the reset mode we can filter the entities to remove\n\t\t\t\tif (\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: \"nodeIdentity\",\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\t\t\t\ttoRemove = toRemove.concat(result.entities.map(entity => (entity as T).id));\n\t\t\t} while (Is.stringValue(cursor));\n\n\t\t\t// Remove the entities\n\t\t\tfor (let i = 0; i < toRemove.length; i++) {\n\t\t\t\tawait this.remove(toRemove[i]);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -13,6 +13,7 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
13
13
  /**
14
14
  * Create a new instance of SynchronisedEntityStorageConnector.
15
15
  * @param options The options for the connector.
16
+ * @throws GeneralError if the entity schema is missing required synchronisation properties.
16
17
  */
17
18
  constructor(options: ISynchronisedEntityStorageConnectorConstructorOptions);
18
19
  /**
@@ -28,7 +29,7 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
28
29
  /**
29
30
  * The component needs to be started when the node is initialized.
30
31
  * @param nodeLoggingComponentType The node logging component type.
31
- * @returns Nothing.
32
+ * @returns A promise that resolves when the connector is started and event bus subscriptions are active.
32
33
  */
33
34
  start(nodeLoggingComponentType?: string): Promise<void>;
34
35
  /**
@@ -46,22 +47,44 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
46
47
  * Set an entity.
47
48
  * @param entity The entity to set.
48
49
  * @param conditions The optional conditions to match for the entities.
49
- * @returns The id of the entity.
50
+ * @returns A promise that resolves when the entity is stored and the change event is published.
50
51
  */
51
52
  set(entity: T, conditions?: {
52
53
  property: keyof T;
53
54
  value: unknown;
54
55
  }[]): Promise<void>;
56
+ /**
57
+ * Set multiple entities in a batch.
58
+ * @param entities The entities to set.
59
+ * @returns A promise that resolves when all entities are stored and change events are published.
60
+ */
61
+ setBatch(entities: T[]): Promise<void>;
55
62
  /**
56
63
  * Remove the entity.
57
64
  * @param id The id of the entity to remove.
58
65
  * @param conditions The optional conditions to match for the entities.
59
- * @returns Nothing.
66
+ * @returns A promise that resolves when the entity is removed and the delete event is published.
60
67
  */
61
68
  remove(id: string, conditions?: {
62
69
  property: keyof T;
63
70
  value: unknown;
64
71
  }[]): Promise<void>;
72
+ /**
73
+ * Remove multiple entities by id.
74
+ * @param ids The ids of the entities to remove.
75
+ * @returns A promise that resolves when all entities are removed and delete events are published.
76
+ */
77
+ removeBatch(ids: string[]): Promise<void>;
78
+ /**
79
+ * Remove all entities from the storage.
80
+ * @returns A promise that resolves when all entities are removed and delete events are published.
81
+ */
82
+ empty(): Promise<void>;
83
+ /**
84
+ * Count all the entities which match the conditions.
85
+ * @returns The total count of entities in the storage.
86
+ */
87
+ count(): Promise<number>;
65
88
  /**
66
89
  * Find all the entities which match the conditions.
67
90
  * @param conditions The conditions to match for the entities.
package/docs/changelog.md CHANGED
@@ -1,6 +1,121 @@
1
1
  # Changelog
2
2
 
3
- ## [0.0.3-next.9](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.8...entity-storage-connector-synchronised-v0.0.3-next.9) (2026-03-04)
3
+ ## [0.9.0](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.9.0...entity-storage-connector-synchronised-v0.9.0) (2026-06-25)
4
+
5
+
6
+ ### Features
7
+
8
+ * release to production ([#55](https://github.com/iotaledger/twin-synchronised-storage/issues/55)) ([8e5df2f](https://github.com/iotaledger/twin-synchronised-storage/commit/8e5df2fd3ef9c7a39d7bd9f366fe54b266eb0d5b))
9
+
10
+ ## [0.9.0-next.1](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.9.0-next.0...entity-storage-connector-synchronised-v0.9.0-next.1) (2026-06-24)
11
+
12
+
13
+ ### Features
14
+
15
+ * add context id features ([#24](https://github.com/iotaledger/twin-synchronised-storage/issues/24)) ([5266b18](https://github.com/iotaledger/twin-synchronised-storage/commit/5266b18088317c7dc274a209a79102a6fc88a8e4))
16
+ * json ld contexts ([#36](https://github.com/iotaledger/twin-synchronised-storage/issues/36)) ([3a87a9f](https://github.com/iotaledger/twin-synchronised-storage/commit/3a87a9fb16d21baf672e44b4e8914cf1937b1d6a))
17
+ * typescript 6 update ([b0e6d52](https://github.com/iotaledger/twin-synchronised-storage/commit/b0e6d52f622dc1ff2273f5e09e8370382742ae50))
18
+ * update dependencies ([2bce2e2](https://github.com/iotaledger/twin-synchronised-storage/commit/2bce2e205f9e1acdef41681720e192b77aa50468))
19
+ * update to latest entity storage model ([14fc53f](https://github.com/iotaledger/twin-synchronised-storage/commit/14fc53fd93140fb9aff6bf937a7646d0a654fd9d))
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * package.json ([9d3c7d6](https://github.com/iotaledger/twin-synchronised-storage/commit/9d3c7d65d01b4100f7831b5f057b96fba8211815))
25
+ * use async getStore in tests ([b883778](https://github.com/iotaledger/twin-synchronised-storage/commit/b8837787b9876d836e69e3f81ac6508fd97a5465))
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @twin.org/synchronised-storage-models bumped from 0.9.0-next.0 to 0.9.0-next.1
33
+
34
+ ## [0.0.3-next.15](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.14...entity-storage-connector-synchronised-v0.0.3-next.15) (2026-06-11)
35
+
36
+
37
+ ### Miscellaneous Chores
38
+
39
+ * **entity-storage-connector-synchronised:** Synchronize repo versions
40
+
41
+
42
+ ### Dependencies
43
+
44
+ * The following workspace dependencies were updated
45
+ * dependencies
46
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.14 to 0.0.3-next.15
47
+
48
+ ## [0.0.3-next.14](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.13...entity-storage-connector-synchronised-v0.0.3-next.14) (2026-05-20)
49
+
50
+
51
+ ### Features
52
+
53
+ * update dependencies ([2bce2e2](https://github.com/iotaledger/twin-synchronised-storage/commit/2bce2e205f9e1acdef41681720e192b77aa50468))
54
+
55
+
56
+ ### Dependencies
57
+
58
+ * The following workspace dependencies were updated
59
+ * dependencies
60
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
61
+
62
+ ## [0.0.3-next.13](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.12...entity-storage-connector-synchronised-v0.0.3-next.13) (2026-05-12)
63
+
64
+
65
+ ### Features
66
+
67
+ * typescript 6 update ([b0e6d52](https://github.com/iotaledger/twin-synchronised-storage/commit/b0e6d52f622dc1ff2273f5e09e8370382742ae50))
68
+
69
+
70
+ ### Dependencies
71
+
72
+ * The following workspace dependencies were updated
73
+ * dependencies
74
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.12 to 0.0.3-next.13
75
+
76
+ ## [0.0.3-next.12](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.11...entity-storage-connector-synchronised-v0.0.3-next.12) (2026-05-07)
77
+
78
+
79
+ ### Features
80
+
81
+ * update to latest entity storage model ([14fc53f](https://github.com/iotaledger/twin-synchronised-storage/commit/14fc53fd93140fb9aff6bf937a7646d0a654fd9d))
82
+
83
+
84
+ ### Dependencies
85
+
86
+ * The following workspace dependencies were updated
87
+ * dependencies
88
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.11 to 0.0.3-next.12
89
+
90
+ ## [0.0.3-next.11](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.10...entity-storage-connector-synchronised-v0.0.3-next.11) (2026-04-10)
91
+
92
+
93
+ ### Miscellaneous Chores
94
+
95
+ * **entity-storage-connector-synchronised:** Synchronize repo versions
96
+
97
+
98
+ ### Dependencies
99
+
100
+ * The following workspace dependencies were updated
101
+ * dependencies
102
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.10 to 0.0.3-next.11
103
+
104
+ ## [0.0.3-next.10](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.9...entity-storage-connector-synchronised-v0.0.3-next.10) (2026-03-20)
105
+
106
+
107
+ ### Miscellaneous Chores
108
+
109
+ * **entity-storage-connector-synchronised:** Synchronize repo versions
110
+
111
+
112
+ ### Dependencies
113
+
114
+ * The following workspace dependencies were updated
115
+ * dependencies
116
+ * @twin.org/synchronised-storage-models bumped from 0.0.3-next.9 to 0.0.3-next.10
117
+
118
+ ## [0.0.3-next.9](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.8...entity-storage-connector-synchronised-v0.0.3-next.9) (2026-03-04)
4
119
 
5
120
 
6
121
  ### Miscellaneous Chores
@@ -14,7 +129,7 @@
14
129
  * dependencies
15
130
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.8 to 0.0.3-next.9
16
131
 
17
- ## [0.0.3-next.8](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.7...entity-storage-connector-synchronised-v0.0.3-next.8) (2026-02-25)
132
+ ## [0.0.3-next.8](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.7...entity-storage-connector-synchronised-v0.0.3-next.8) (2026-02-25)
18
133
 
19
134
 
20
135
  ### Miscellaneous Chores
@@ -28,12 +143,12 @@
28
143
  * dependencies
29
144
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.7 to 0.0.3-next.8
30
145
 
31
- ## [0.0.3-next.7](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.6...entity-storage-connector-synchronised-v0.0.3-next.7) (2026-01-28)
146
+ ## [0.0.3-next.7](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.6...entity-storage-connector-synchronised-v0.0.3-next.7) (2026-01-28)
32
147
 
33
148
 
34
149
  ### Features
35
150
 
36
- * json ld contexts ([#36](https://github.com/twinfoundation/synchronised-storage/issues/36)) ([3a87a9f](https://github.com/twinfoundation/synchronised-storage/commit/3a87a9fb16d21baf672e44b4e8914cf1937b1d6a))
151
+ * json ld contexts ([#36](https://github.com/iotaledger/twin-synchronised-storage/issues/36)) ([3a87a9f](https://github.com/iotaledger/twin-synchronised-storage/commit/3a87a9fb16d21baf672e44b4e8914cf1937b1d6a))
37
152
 
38
153
 
39
154
  ### Dependencies
@@ -42,7 +157,7 @@
42
157
  * dependencies
43
158
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.6 to 0.0.3-next.7
44
159
 
45
- ## [0.0.3-next.6](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.5...entity-storage-connector-synchronised-v0.0.3-next.6) (2026-01-22)
160
+ ## [0.0.3-next.6](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.5...entity-storage-connector-synchronised-v0.0.3-next.6) (2026-01-22)
46
161
 
47
162
 
48
163
  ### Miscellaneous Chores
@@ -56,7 +171,7 @@
56
171
  * dependencies
57
172
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.5 to 0.0.3-next.6
58
173
 
59
- ## [0.0.3-next.5](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.4...entity-storage-connector-synchronised-v0.0.3-next.5) (2026-01-19)
174
+ ## [0.0.3-next.5](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.4...entity-storage-connector-synchronised-v0.0.3-next.5) (2026-01-19)
60
175
 
61
176
 
62
177
  ### Miscellaneous Chores
@@ -70,7 +185,7 @@
70
185
  * dependencies
71
186
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.4 to 0.0.3-next.5
72
187
 
73
- ## [0.0.3-next.4](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.3...entity-storage-connector-synchronised-v0.0.3-next.4) (2026-01-15)
188
+ ## [0.0.3-next.4](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.3...entity-storage-connector-synchronised-v0.0.3-next.4) (2026-01-15)
74
189
 
75
190
 
76
191
  ### Miscellaneous Chores
@@ -84,7 +199,7 @@
84
199
  * dependencies
85
200
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.3 to 0.0.3-next.4
86
201
 
87
- ## [0.0.3-next.3](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.2...entity-storage-connector-synchronised-v0.0.3-next.3) (2026-01-12)
202
+ ## [0.0.3-next.3](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.2...entity-storage-connector-synchronised-v0.0.3-next.3) (2026-01-12)
88
203
 
89
204
 
90
205
  ### Miscellaneous Chores
@@ -98,12 +213,12 @@
98
213
  * dependencies
99
214
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.2 to 0.0.3-next.3
100
215
 
101
- ## [0.0.3-next.2](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.1...entity-storage-connector-synchronised-v0.0.3-next.2) (2025-12-04)
216
+ ## [0.0.3-next.2](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.1...entity-storage-connector-synchronised-v0.0.3-next.2) (2025-12-04)
102
217
 
103
218
 
104
219
  ### Bug Fixes
105
220
 
106
- * package.json ([9d3c7d6](https://github.com/twinfoundation/synchronised-storage/commit/9d3c7d65d01b4100f7831b5f057b96fba8211815))
221
+ * package.json ([9d3c7d6](https://github.com/iotaledger/twin-synchronised-storage/commit/9d3c7d65d01b4100f7831b5f057b96fba8211815))
107
222
 
108
223
 
109
224
  ### Dependencies
@@ -112,12 +227,12 @@
112
227
  * dependencies
113
228
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.1 to 0.0.3-next.2
114
229
 
115
- ## [0.0.3-next.1](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.0...entity-storage-connector-synchronised-v0.0.3-next.1) (2025-11-12)
230
+ ## [0.0.3-next.1](https://github.com/iotaledger/twin-synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.0...entity-storage-connector-synchronised-v0.0.3-next.1) (2025-11-12)
116
231
 
117
232
 
118
233
  ### Features
119
234
 
120
- * add context id features ([#24](https://github.com/twinfoundation/synchronised-storage/issues/24)) ([5266b18](https://github.com/twinfoundation/synchronised-storage/commit/5266b18088317c7dc274a209a79102a6fc88a8e4))
235
+ * add context id features ([#24](https://github.com/iotaledger/twin-synchronised-storage/issues/24)) ([5266b18](https://github.com/iotaledger/twin-synchronised-storage/commit/5266b18088317c7dc274a209a79102a6fc88a8e4))
121
236
 
122
237
 
123
238
  ### Dependencies
@@ -126,12 +241,12 @@
126
241
  * dependencies
127
242
  * @twin.org/synchronised-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
128
243
 
129
- ## [0.0.2-next.10](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.9...entity-storage-connector-synchronised-v0.0.2-next.10) (2025-10-09)
244
+ ## [0.0.2-next.10](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.9...entity-storage-connector-synchronised-v0.0.2-next.10) (2025-10-09)
130
245
 
131
246
 
132
247
  ### Features
133
248
 
134
- * add validate-locales ([e66ef0d](https://github.com/twinfoundation/entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
249
+ * add validate-locales ([e66ef0d](https://github.com/iotaledger/twin-entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
135
250
 
136
251
 
137
252
  ### Dependencies
@@ -142,7 +257,7 @@
142
257
  * devDependencies
143
258
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.9 to 0.0.2-next.10
144
259
 
145
- ## [0.0.2-next.9](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.8...entity-storage-connector-synchronised-v0.0.2-next.9) (2025-10-02)
260
+ ## [0.0.2-next.9](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.8...entity-storage-connector-synchronised-v0.0.2-next.9) (2025-10-02)
146
261
 
147
262
 
148
263
  ### Miscellaneous Chores
@@ -158,13 +273,13 @@
158
273
  * devDependencies
159
274
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.8 to 0.0.2-next.9
160
275
 
161
- ## [0.0.2-next.8](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.7...entity-storage-connector-synchronised-v0.0.2-next.8) (2025-08-29)
276
+ ## [0.0.2-next.8](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.7...entity-storage-connector-synchronised-v0.0.2-next.8) (2025-08-29)
162
277
 
163
278
 
164
279
  ### Features
165
280
 
166
- * eslint migration to flat config ([f033b64](https://github.com/twinfoundation/entity-storage/commit/f033b64984c0e6a8129d929c9dd816dcc1b8dab0))
167
- * remove unused property ([459e859](https://github.com/twinfoundation/entity-storage/commit/459e859ebfdb8e74d0f063601e6075300e37d7f8))
281
+ * eslint migration to flat config ([f033b64](https://github.com/iotaledger/twin-entity-storage/commit/f033b64984c0e6a8129d929c9dd816dcc1b8dab0))
282
+ * remove unused property ([459e859](https://github.com/iotaledger/twin-entity-storage/commit/459e859ebfdb8e74d0f063601e6075300e37d7f8))
168
283
 
169
284
 
170
285
  ### Dependencies
@@ -175,7 +290,7 @@
175
290
  * devDependencies
176
291
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.7 to 0.0.2-next.8
177
292
 
178
- ## [0.0.2-next.7](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.6...entity-storage-connector-synchronised-v0.0.2-next.7) (2025-08-20)
293
+ ## [0.0.2-next.7](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.6...entity-storage-connector-synchronised-v0.0.2-next.7) (2025-08-20)
179
294
 
180
295
 
181
296
  ### Miscellaneous Chores
@@ -191,12 +306,12 @@
191
306
  * devDependencies
192
307
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.6 to 0.0.2-next.7
193
308
 
194
- ## [0.0.2-next.6](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.5...entity-storage-connector-synchronised-v0.0.2-next.6) (2025-08-19)
309
+ ## [0.0.2-next.6](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.5...entity-storage-connector-synchronised-v0.0.2-next.6) (2025-08-19)
195
310
 
196
311
 
197
312
  ### Features
198
313
 
199
- * update framework core ([b59a380](https://github.com/twinfoundation/entity-storage/commit/b59a380bb7fba2b43610f69074dcdee24a4737da))
314
+ * update framework core ([b59a380](https://github.com/iotaledger/twin-entity-storage/commit/b59a380bb7fba2b43610f69074dcdee24a4737da))
200
315
 
201
316
 
202
317
  ### Dependencies
@@ -207,12 +322,12 @@
207
322
  * devDependencies
208
323
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.5 to 0.0.2-next.6
209
324
 
210
- ## [0.0.2-next.5](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.4...entity-storage-connector-synchronised-v0.0.2-next.5) (2025-08-11)
325
+ ## [0.0.2-next.5](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.4...entity-storage-connector-synchronised-v0.0.2-next.5) (2025-08-11)
211
326
 
212
327
 
213
328
  ### Features
214
329
 
215
- * support new synchronised storage features ([0d9ebab](https://github.com/twinfoundation/entity-storage/commit/0d9ebab237040892cab8e7db751aa2e40c0c76e0))
330
+ * support new synchronised storage features ([0d9ebab](https://github.com/iotaledger/twin-entity-storage/commit/0d9ebab237040892cab8e7db751aa2e40c0c76e0))
216
331
 
217
332
 
218
333
  ### Dependencies
@@ -223,12 +338,12 @@
223
338
  * devDependencies
224
339
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.4 to 0.0.2-next.5
225
340
 
226
- ## [0.0.2-next.4](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.3...entity-storage-connector-synchronised-v0.0.2-next.4) (2025-08-08)
341
+ ## [0.0.2-next.4](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.3...entity-storage-connector-synchronised-v0.0.2-next.4) (2025-08-08)
227
342
 
228
343
 
229
344
  ### Features
230
345
 
231
- * support new synchronised storage features ([a43ee88](https://github.com/twinfoundation/entity-storage/commit/a43ee88431ee3eb8e59e4aeb176009d63ea09d05))
346
+ * support new synchronised storage features ([a43ee88](https://github.com/iotaledger/twin-entity-storage/commit/a43ee88431ee3eb8e59e4aeb176009d63ea09d05))
232
347
 
233
348
 
234
349
  ### Dependencies
@@ -239,21 +354,21 @@
239
354
  * devDependencies
240
355
  * @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.3 to 0.0.2-next.4
241
356
 
242
- ## [0.0.2-next.3](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.2...entity-storage-connector-synchronised-v0.0.2-next.3) (2025-07-25)
357
+ ## [0.0.2-next.3](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.2...entity-storage-connector-synchronised-v0.0.2-next.3) (2025-07-25)
243
358
 
244
359
 
245
360
  ### Features
246
361
 
247
- * add synchronised to release configs ([e1e749c](https://github.com/twinfoundation/entity-storage/commit/e1e749cf261b58c8c36729686861e29c7d5e068e))
248
- * add tests for synchronised storage connector ([1e10623](https://github.com/twinfoundation/entity-storage/commit/1e106231747c8351f3cf5ecb9a33145e3ea56475))
249
- * synchronised storage ([#44](https://github.com/twinfoundation/entity-storage/issues/44)) ([94e10e2](https://github.com/twinfoundation/entity-storage/commit/94e10e26d1feec801449dc04af7a9757ac7495ff))
250
- * test with custom key ([264f372](https://github.com/twinfoundation/entity-storage/commit/264f372a38c0ab66b16300542ae2530bd808b6cb))
251
- * update schema type to storage key for synchronised storage ([a21b206](https://github.com/twinfoundation/entity-storage/commit/a21b2060d0a6d7ec43b189f5fa58b4ada1fde8cb))
362
+ * add synchronised to release configs ([e1e749c](https://github.com/iotaledger/twin-entity-storage/commit/e1e749cf261b58c8c36729686861e29c7d5e068e))
363
+ * add tests for synchronised storage connector ([1e10623](https://github.com/iotaledger/twin-entity-storage/commit/1e106231747c8351f3cf5ecb9a33145e3ea56475))
364
+ * synchronised storage ([#44](https://github.com/iotaledger/twin-entity-storage/issues/44)) ([94e10e2](https://github.com/iotaledger/twin-entity-storage/commit/94e10e26d1feec801449dc04af7a9757ac7495ff))
365
+ * test with custom key ([264f372](https://github.com/iotaledger/twin-entity-storage/commit/264f372a38c0ab66b16300542ae2530bd808b6cb))
366
+ * update schema type to storage key for synchronised storage ([a21b206](https://github.com/iotaledger/twin-entity-storage/commit/a21b2060d0a6d7ec43b189f5fa58b4ada1fde8cb))
252
367
 
253
368
 
254
369
  ### Bug Fixes
255
370
 
256
- * linting ([ba1c21b](https://github.com/twinfoundation/entity-storage/commit/ba1c21b6261de437d68f53f243b297f6d41a49b7))
371
+ * linting ([ba1c21b](https://github.com/iotaledger/twin-entity-storage/commit/ba1c21b6261de437d68f53f243b297f6d41a49b7))
257
372
 
258
373
 
259
374
  ### Dependencies
@@ -264,4 +379,4 @@
264
379
  * devDependencies
265
380
  * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.29 to 0.0.2-next.3
266
381
 
267
- ## @twin.org/entity-storage-connector-synchronised - Changelog
382
+ ## Changelog
package/docs/examples.md CHANGED
@@ -1 +1,98 @@
1
- # @twin.org/entity-storage-connector-synchronised - Examples
1
+ # Entity Storage Connector Synchronised Examples
2
+
3
+ Use these scenarios to wire synchronised entity persistence into a node, query records, and react to remote updates through the event bus.
4
+
5
+ ## SynchronisedEntityStorageConnector
6
+
7
+ ```typescript
8
+ import type { IEntitySchema } from '@twin.org/entity';
9
+ import { SynchronisedEntityStorageConnector } from '@twin.org/entity-storage-connector-synchronised';
10
+ import type { ISynchronisedEntity } from '@twin.org/synchronised-storage-models';
11
+
12
+ interface IProfileEntity extends ISynchronisedEntity {
13
+ displayName: string;
14
+ status: 'active' | 'paused';
15
+ }
16
+
17
+ const connector = new SynchronisedEntityStorageConnector<IProfileEntity>({
18
+ entitySchema: 'Profile',
19
+ entityStorageConnectorType: 'entity-storage-memory',
20
+ eventBusComponentType: 'event-bus',
21
+ config: {
22
+ storageKey: 'profile'
23
+ }
24
+ });
25
+
26
+ const className = connector.className();
27
+ const schema = connector.getSchema() as IEntitySchema<IProfileEntity>;
28
+
29
+ console.log(className); // SynchronisedEntityStorageConnector
30
+ console.log(schema.id); // Profile
31
+ ```
32
+
33
+ ```typescript
34
+ import { SynchronisedEntityStorageConnector } from '@twin.org/entity-storage-connector-synchronised';
35
+ import { ComparisonOperator, SortDirection, type EntityCondition } from '@twin.org/entity';
36
+ import type { ISynchronisedEntity } from '@twin.org/synchronised-storage-models';
37
+
38
+ interface IProfileEntity extends ISynchronisedEntity {
39
+ displayName: string;
40
+ status: 'active' | 'paused';
41
+ }
42
+
43
+ const connector = new SynchronisedEntityStorageConnector<IProfileEntity>({
44
+ entitySchema: 'Profile',
45
+ entityStorageConnectorType: 'entity-storage-memory'
46
+ });
47
+
48
+ await connector.start('logging');
49
+
50
+ await connector.set({
51
+ id: 'profile-1',
52
+ nodeIdentity: 'did:iota:node-1',
53
+ dateModified: '2026-03-10T09:00:00.000Z',
54
+ displayName: 'Alex',
55
+ status: 'active'
56
+ });
57
+
58
+ const condition: EntityCondition<IProfileEntity> = {
59
+ property: 'status',
60
+ comparison: ComparisonOperator.Equals,
61
+ value: 'active'
62
+ };
63
+
64
+ const result = await connector.query(
65
+ condition,
66
+ [{ property: 'dateModified', sortDirection: SortDirection.Descending }],
67
+ ['id', 'displayName', 'status'],
68
+ '',
69
+ 20
70
+ );
71
+
72
+ console.log(result.entities.length); // 1
73
+ ```
74
+
75
+ ```typescript
76
+ import { SynchronisedEntityStorageConnector } from '@twin.org/entity-storage-connector-synchronised';
77
+ import type { ISynchronisedEntity } from '@twin.org/synchronised-storage-models';
78
+
79
+ interface IProfileEntity extends ISynchronisedEntity {
80
+ displayName: string;
81
+ status: 'active' | 'paused';
82
+ }
83
+
84
+ const connector = new SynchronisedEntityStorageConnector<IProfileEntity>({
85
+ entitySchema: 'Profile',
86
+ entityStorageConnectorType: 'entity-storage-memory'
87
+ });
88
+
89
+ const profile = await connector.get('profile-1', 'id', [{ property: 'status', value: 'active' }]);
90
+
91
+ console.log(profile?.displayName); // Alex
92
+
93
+ await connector.remove('profile-1', [{ property: 'status', value: 'active' }]);
94
+
95
+ const deletedProfile = await connector.get('profile-1');
96
+
97
+ console.log(deletedProfile); // undefined
98
+ ```
@@ -32,9 +32,13 @@ The options for the connector.
32
32
 
33
33
  `SynchronisedEntityStorageConnector`\<`T`\>
34
34
 
35
+ #### Throws
36
+
37
+ GeneralError if the entity schema is missing required synchronisation properties.
38
+
35
39
  ## Properties
36
40
 
37
- ### CLASS\_NAME
41
+ ### CLASS\_NAME {#class_name}
38
42
 
39
43
  > `readonly` `static` **CLASS\_NAME**: `string`
40
44
 
@@ -42,7 +46,7 @@ Runtime name for the class.
42
46
 
43
47
  ## Methods
44
48
 
45
- ### className()
49
+ ### className() {#classname}
46
50
 
47
51
  > **className**(): `string`
48
52
 
@@ -60,7 +64,7 @@ The class name of the component.
60
64
 
61
65
  ***
62
66
 
63
- ### getSchema()
67
+ ### getSchema() {#getschema}
64
68
 
65
69
  > **getSchema**(): `IEntitySchema`
66
70
 
@@ -78,7 +82,7 @@ The schema for the entities.
78
82
 
79
83
  ***
80
84
 
81
- ### start()
85
+ ### start() {#start}
82
86
 
83
87
  > **start**(`nodeLoggingComponentType?`): `Promise`\<`void`\>
84
88
 
@@ -96,7 +100,7 @@ The node logging component type.
96
100
 
97
101
  `Promise`\<`void`\>
98
102
 
99
- Nothing.
103
+ A promise that resolves when the connector is started and event bus subscriptions are active.
100
104
 
101
105
  #### Implementation of
102
106
 
@@ -104,7 +108,7 @@ Nothing.
104
108
 
105
109
  ***
106
110
 
107
- ### get()
111
+ ### get() {#get}
108
112
 
109
113
  > **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`T` \| `undefined`\>
110
114
 
@@ -142,7 +146,7 @@ The object if it can be found or undefined.
142
146
 
143
147
  ***
144
148
 
145
- ### set()
149
+ ### set() {#set}
146
150
 
147
151
  > **set**(`entity`, `conditions?`): `Promise`\<`void`\>
148
152
 
@@ -166,7 +170,7 @@ The optional conditions to match for the entities.
166
170
 
167
171
  `Promise`\<`void`\>
168
172
 
169
- The id of the entity.
173
+ A promise that resolves when the entity is stored and the change event is published.
170
174
 
171
175
  #### Implementation of
172
176
 
@@ -174,7 +178,33 @@ The id of the entity.
174
178
 
175
179
  ***
176
180
 
177
- ### remove()
181
+ ### setBatch() {#setbatch}
182
+
183
+ > **setBatch**(`entities`): `Promise`\<`void`\>
184
+
185
+ Set multiple entities in a batch.
186
+
187
+ #### Parameters
188
+
189
+ ##### entities
190
+
191
+ `T`[]
192
+
193
+ The entities to set.
194
+
195
+ #### Returns
196
+
197
+ `Promise`\<`void`\>
198
+
199
+ A promise that resolves when all entities are stored and change events are published.
200
+
201
+ #### Implementation of
202
+
203
+ `IEntityStorageConnector.setBatch`
204
+
205
+ ***
206
+
207
+ ### remove() {#remove}
178
208
 
179
209
  > **remove**(`id`, `conditions?`): `Promise`\<`void`\>
180
210
 
@@ -198,7 +228,7 @@ The optional conditions to match for the entities.
198
228
 
199
229
  `Promise`\<`void`\>
200
230
 
201
- Nothing.
231
+ A promise that resolves when the entity is removed and the delete event is published.
202
232
 
203
233
  #### Implementation of
204
234
 
@@ -206,7 +236,69 @@ Nothing.
206
236
 
207
237
  ***
208
238
 
209
- ### query()
239
+ ### removeBatch() {#removebatch}
240
+
241
+ > **removeBatch**(`ids`): `Promise`\<`void`\>
242
+
243
+ Remove multiple entities by id.
244
+
245
+ #### Parameters
246
+
247
+ ##### ids
248
+
249
+ `string`[]
250
+
251
+ The ids of the entities to remove.
252
+
253
+ #### Returns
254
+
255
+ `Promise`\<`void`\>
256
+
257
+ A promise that resolves when all entities are removed and delete events are published.
258
+
259
+ #### Implementation of
260
+
261
+ `IEntityStorageConnector.removeBatch`
262
+
263
+ ***
264
+
265
+ ### empty() {#empty}
266
+
267
+ > **empty**(): `Promise`\<`void`\>
268
+
269
+ Remove all entities from the storage.
270
+
271
+ #### Returns
272
+
273
+ `Promise`\<`void`\>
274
+
275
+ A promise that resolves when all entities are removed and delete events are published.
276
+
277
+ #### Implementation of
278
+
279
+ `IEntityStorageConnector.empty`
280
+
281
+ ***
282
+
283
+ ### count() {#count}
284
+
285
+ > **count**(): `Promise`\<`number`\>
286
+
287
+ Count all the entities which match the conditions.
288
+
289
+ #### Returns
290
+
291
+ `Promise`\<`number`\>
292
+
293
+ The total count of entities in the storage.
294
+
295
+ #### Implementation of
296
+
297
+ `IEntityStorageConnector.count`
298
+
299
+ ***
300
+
301
+ ### query() {#query}
210
302
 
211
303
  > **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `limit?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
212
304
 
@@ -4,9 +4,9 @@ Configuration for the Synchronised Entity Storage Connector.
4
4
 
5
5
  ## Properties
6
6
 
7
- ### storageKey?
7
+ ### storageKey? {#storagekey}
8
8
 
9
- > `optional` **storageKey**: `string`
9
+ > `optional` **storageKey?**: `string`
10
10
 
11
11
  The storage key for the synchronised entity storage connector.
12
12
  Will default to kebab cased entity schema name.
@@ -4,7 +4,7 @@ Options for the Synchronised Entity Storage Connector constructor.
4
4
 
5
5
  ## Properties
6
6
 
7
- ### entitySchema
7
+ ### entitySchema {#entityschema}
8
8
 
9
9
  > **entitySchema**: `string`
10
10
 
@@ -12,7 +12,7 @@ The name of the entity schema.
12
12
 
13
13
  ***
14
14
 
15
- ### entityStorageConnectorType
15
+ ### entityStorageConnectorType {#entitystorageconnectortype}
16
16
 
17
17
  > **entityStorageConnectorType**: `string`
18
18
 
@@ -20,9 +20,9 @@ The entity storage connector type to use for actual data.
20
20
 
21
21
  ***
22
22
 
23
- ### eventBusComponentType?
23
+ ### eventBusComponentType? {#eventbuscomponenttype}
24
24
 
25
- > `optional` **eventBusComponentType**: `string`
25
+ > `optional` **eventBusComponentType?**: `string`
26
26
 
27
27
  The event bus component type.
28
28
 
@@ -34,8 +34,8 @@ event-bus
34
34
 
35
35
  ***
36
36
 
37
- ### config?
37
+ ### config? {#config}
38
38
 
39
- > `optional` **config**: [`ISynchronisedEntityStorageConnectorConfig`](ISynchronisedEntityStorageConnectorConfig.md)
39
+ > `optional` **config?**: [`ISynchronisedEntityStorageConnectorConfig`](ISynchronisedEntityStorageConnectorConfig.md)
40
40
 
41
41
  The configuration for the connector.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-synchronised",
3
- "version": "0.0.3-next.9",
4
- "description": "Entity Storage connector implementation using synchronised storage",
3
+ "version": "0.9.0",
4
+ "description": "Entity storage connector that publishes local changes and applies remote updates.",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "git+https://github.com/twinfoundation/synchronised-storage.git",
7
+ "url": "git+https://github.com/iotaledger/twin-synchronised-storage.git",
8
8
  "directory": "packages/entity-storage-connector-synchronised"
9
9
  },
10
10
  "author": "martyn.janes@iota.org",
@@ -14,14 +14,14 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/context": "next",
18
- "@twin.org/core": "next",
19
- "@twin.org/entity": "next",
20
- "@twin.org/entity-storage-models": "next",
21
- "@twin.org/event-bus-models": "next",
22
- "@twin.org/logging-models": "next",
23
- "@twin.org/nameof": "next",
24
- "@twin.org/synchronised-storage-models": "0.0.3-next.9"
17
+ "@twin.org/context": "^0.9.0",
18
+ "@twin.org/core": "^0.9.0",
19
+ "@twin.org/entity": "^0.9.0",
20
+ "@twin.org/entity-storage-models": "^0.9.0",
21
+ "@twin.org/event-bus-models": "^0.9.0",
22
+ "@twin.org/logging-models": "^0.9.0",
23
+ "@twin.org/nameof": "^0.9.0",
24
+ "@twin.org/synchronised-storage-models": "^0.9.0"
25
25
  },
26
26
  "main": "./dist/es/index.js",
27
27
  "types": "./dist/types/index.d.ts",
@@ -55,7 +55,7 @@
55
55
  "integration"
56
56
  ],
57
57
  "bugs": {
58
- "url": "git+https://github.com/twinfoundation/synchronised-storage/issues"
58
+ "url": "git+https://github.com/iotaledger/twin-synchronised-storage/issues"
59
59
  },
60
60
  "homepage": "https://twindev.org"
61
61
  }