Skip to main content

@idpass/data-collect-core / EntityStoreImpl

Class: EntityStoreImpl

Defined in: components/EntityStore.ts:92

Entity store implementation for managing current entity state with change tracking.

The EntityStoreImpl provides the current state view in the event sourcing architecture. It maintains both the initial state (from last sync/load) and the current modified state for each entity, enabling conflict resolution and change tracking.

Key responsibilities:

  • State Management: Maintains current entity state derived from events.
  • Change Tracking: Tracks changes between initial and current state.
  • Duplicate Detection: Manages potential duplicate entity pairs.
  • Search Operations: Provides flexible entity querying capabilities.
  • Sync Coordination: Marks entities as synced and manages sync states.
  • External ID Mapping: Maps between internal and external system IDs.

Architecture:

  • Uses pluggable storage adapters for different persistence backends.
  • Implements CQRS query side - provides read operations for entities.
  • Maintains entity pairs (initial + modified) for conflict resolution.
  • Supports flexible search criteria with MongoDB-style queries.

Examples​

Basic usage:

const entityStore = new EntityStoreImpl(storageAdapter);
await entityStore.initialize();

// Save entity state
await entityStore.saveEntity(initialEntity, modifiedEntity);

// Retrieve entity
const entityPair = await entityStore.getEntity('entity-123');
if (entityPair) {
console.log('Initial state:', entityPair.initial);
console.log('Current state:', entityPair.modified);
console.log('Has changes:', entityPair.initial.version !== entityPair.modified.version);
}

Search operations:

// Find all adults
const adults = await entityStore.searchEntities([
{ "data.age": { $gte: 18 } },
{ "type": "individual" }
]);

// Find groups by name pattern
const families = await entityStore.searchEntities([
{ "data.name": { $regex: /family/i } },
{ "type": "group" }
]);

Duplicate management:

// Save potential duplicates found during entity creation
await entityStore.savePotentialDuplicates([
{ entityGuid: 'person-123', duplicateGuid: 'person-456' }
]);

// Get all potential duplicates for review
const duplicates = await entityStore.getPotentialDuplicates();

// Resolve duplicates after manual review
await entityStore.resolvePotentialDuplicates(resolvedDuplicates);

Implements​

Constructors​

Constructor​

new EntityStoreImpl(entityStorageAdapter): EntityStoreImpl

Defined in: components/EntityStore.ts:111

Creates a new EntityStoreImpl instance.

Parameters​

entityStorageAdapter​

EntityStorageAdapter

Storage adapter for persistence (IndexedDB, PostgreSQL, etc.).

Returns​

EntityStoreImpl

Example​

// With IndexedDB for browser
const indexedDbAdapter = new IndexedDbEntityStorageAdapter('tenant-123');
const browserEntityStore = new EntityStoreImpl(indexedDbAdapter);

// With PostgreSQL for server
const postgresAdapter = new PostgresEntityStorageAdapter(connectionString, 'tenant-123');
const serverEntityStore = new EntityStoreImpl(postgresAdapter);

Methods​

closeConnection()​

closeConnection(): Promise<void>

Defined in: components/EntityStore.ts:122

Closes database connections and cleans up resources.

Should be called when the EntityStore is no longer needed to prevent memory leaks.

Returns​

Promise<void>

A Promise that resolves when the connection is closed.

Implementation of​

EntityStore.closeConnection


initialize()​

initialize(): Promise<void>

Defined in: components/EntityStore.ts:134

Initializes the entity store and prepares it for operations.

This method must be called before any other operations.

Returns​

Promise<void>

A Promise that resolves when the store is initialized.

Throws​

When storage initialization fails.

Implementation of​

EntityStore.initialize


deleteEntity()​

deleteEntity(id): Promise<void>

Defined in: components/EntityStore.ts:147

Deletes an entity from the store.

⚠️ WARNING: This permanently removes the entity and cannot be undone!

Parameters​

id​

string

Internal database ID of the entity to delete.

Returns​

Promise<void>

A Promise that resolves when the entity is deleted.

Throws​

When deletion fails.

Implementation of​

EntityStore.deleteEntity


searchEntities()​

searchEntities(criteria): Promise<EntityPair[]>

Defined in: components/EntityStore.ts:174

Searches entities using flexible criteria.

Supports MongoDB-style query syntax for complex searches.

Parameters​

criteria​

SearchCriteria

Search criteria array with query conditions.

Returns​

Promise<EntityPair[]>

Array of entity pairs matching the criteria.

Example​

// Search for adults
const adults = await entityStore.searchEntities([
{ "data.age": { $gte: 18 } },
{ "type": "individual" }
]);

// Search for groups containing "family"
const families = await entityStore.searchEntities([
{ "data.name": { $regex: /family/i } },
{ "type": "group" }
]);

Implementation of​

EntityStore.searchEntities


getEntity()​

getEntity(id): Promise<EntityPair | null>

Defined in: components/EntityStore.ts:200

Retrieves a specific entity by its internal database ID.

Parameters​

id​

string

Internal database ID of the entity.

Returns​

Promise<EntityPair | null>

Entity pair with initial and current state, or null if not found.

Example​

const entityPair = await entityStore.getEntity('entity-123');
if (entityPair) {
console.log('Found entity:', entityPair.modified.data.name);

// Check if entity has local changes
const hasChanges = entityPair.initial.version !== entityPair.modified.version;
if (hasChanges) {
console.log('Entity has unsaved changes');
}
} else {
console.log('Entity not found');
}

Implementation of​

EntityStore.getEntity


saveEntity()​

saveEntity(initial, modified): Promise<void>

Defined in: components/EntityStore.ts:231

Saves an entity with both initial and current state for change tracking.

Parameters​

initial​

EntityDoc | null

Initial state of the entity (from last sync).

modified​

EntityDoc

Current modified state of the entity.

Returns​

Promise<void>

Example​

// Save a new entity
const newEntity = {
id: 'person-123',
guid: 'person-123',
type: 'individual',
data: { name: 'John Doe', age: 30 },
version: 1,
lastUpdated: new Date().toISOString(),
syncLevel: SyncLevel.LOCAL
};

// Initially, both states are the same
await entityStore.saveEntity(newEntity, newEntity);

// Later, after modifications
const modifiedEntity = { ...newEntity, data: { ...newEntity.data, age: 31 }, version: 2 };
await entityStore.saveEntity(newEntity, modifiedEntity); // Keep original initial state

Implementation of​

EntityStore.saveEntity


getAllEntities()​

getAllEntities(): Promise<EntityPair[]>

Defined in: components/EntityStore.ts:252

Retrieves all entities from the store.

Returns​

Promise<EntityPair[]>

Array of all entity pairs with initial and current state.

Example​

const allEntities = await entityStore.getAllEntities();

// Find entities with local changes
const modifiedEntities = allEntities.filter(pair =>
pair.initial.version !== pair.modified.version
);

console.log(`${modifiedEntities.length} entities have local changes`);

Implementation of​

EntityStore.getAllEntities


getModifiedEntitiesSince()​

getModifiedEntitiesSince(timestamp): Promise<EntityPair[]>

Defined in: components/EntityStore.ts:275

Retrieves entities modified since a specific timestamp.

Useful for incremental sync operations to identify entities that need synchronization.

Parameters​

timestamp​

string

ISO timestamp to filter entities from.

Returns​

Promise<EntityPair[]>

Array of entity pairs modified after the specified timestamp.

Example​

const lastSync = '2024-01-01T00:00:00Z';
const modifiedEntities = await entityStore.getModifiedEntitiesSince(lastSync);

console.log(`${modifiedEntities.length} entities modified since last sync`);
modifiedEntities.forEach(pair => {
console.log(`${pair.modified.data.name} was updated at ${pair.modified.lastUpdated}`);
});

Implementation of​

EntityStore.getModifiedEntitiesSince


markEntityAsSynced()​

markEntityAsSynced(id): Promise<void>

Defined in: components/EntityStore.ts:299

Marks an entity as synced by updating its initial state to match current state.

This method is typically called after successfully syncing an entity with the server, to indicate that the current state is now the baseline for future change detection.

Parameters​

id​

string

Internal database ID of the entity to mark as synced.

Returns​

Promise<void>

A Promise that resolves when the entity is marked as synced.

Example​

// After successfully syncing entity to server
await syncEntityToServer(entityId);
await entityStore.markEntityAsSynced(entityId);

// Now the entity is considered "clean" with no local changes
const entityPair = await entityStore.getEntity(entityId);
console.log('Has changes:', entityPair.initial.version !== entityPair.modified.version); // false

Implementation of​

EntityStore.markEntityAsSynced


getEntityByExternalId()​

getEntityByExternalId(externalId): Promise<EntityPair | null>

Defined in: components/EntityStore.ts:326

Retrieves an entity by its external system ID.

Used for mapping between internal entities and external system records during synchronization operations.

Parameters​

externalId​

string

External system identifier for the entity.

Returns​

Promise<EntityPair | null>

Entity pair if found, null otherwise.

Example​

// Find entity by OpenSPP ID
const entityPair = await entityStore.getEntityByExternalId('openspp-123');
if (entityPair) {
console.log('Found entity for external ID:', entityPair.modified.data.name);
// Update with new external data...
}

Implementation of​

EntityStore.getEntityByExternalId


savePotentialDuplicates()​

savePotentialDuplicates(duplicates): Promise<void>

Defined in: components/EntityStore.ts:348

Saves potential duplicate entity pairs for manual review.

Parameters​

duplicates​

object[]

Array of entity GUID pairs that are potential duplicates.

Returns​

Promise<void>

A Promise that resolves when duplicates are saved.

Example​

// System detected potential duplicates during entity creation
const duplicates = [
{ entityGuid: 'person-123', duplicateGuid: 'person-456' },
{ entityGuid: 'person-789', duplicateGuid: 'person-101' }
];

await entityStore.savePotentialDuplicates(duplicates);
console.log('Potential duplicates saved for review');

Implementation of​

EntityStore.savePotentialDuplicates


getPotentialDuplicates()​

getPotentialDuplicates(): Promise<object[]>

Defined in: components/EntityStore.ts:373

Retrieves all potential duplicate entity pairs awaiting review.

Returns​

Promise<object[]>

Array of entity GUID pairs that are potential duplicates.

Example​

const duplicates = await entityStore.getPotentialDuplicates();

for (const pair of duplicates) {
const entity1 = await entityStore.getEntity(pair.entityGuid);
const entity2 = await entityStore.getEntity(pair.duplicateGuid);

console.log('Potential duplicate pair:');
console.log('Entity 1:', entity1?.modified.data);
console.log('Entity 2:', entity2?.modified.data);

// Present to user for manual review...
}

Implementation of​

EntityStore.getPotentialDuplicates


resolvePotentialDuplicates()​

resolvePotentialDuplicates(duplicates): Promise<void>

Defined in: components/EntityStore.ts:394

Resolves potential duplicate pairs after manual review.

Parameters​

duplicates​

object[]

Array of duplicate pairs that have been resolved.

Returns​

Promise<void>

A Promise that resolves when duplicates are resolved.

Example​

// After user manually reviews and resolves duplicates
const resolvedDuplicates = [
{ entityGuid: 'person-123', duplicateGuid: 'person-456' } // User confirmed these are different people
];

await entityStore.resolvePotentialDuplicates(resolvedDuplicates);
console.log('Duplicate pairs resolved and removed from pending list');

Implementation of​

EntityStore.resolvePotentialDuplicates


clearStore()​

clearStore(): Promise<void>

Defined in: components/EntityStore.ts:413

Clears all entities from the store.

⚠️ WARNING: This permanently deletes all entity data and cannot be undone! Only use for testing or when intentionally resetting the system.

Returns​

Promise<void>

Example​

// For testing only
if (process.env.NODE_ENV === 'test') {
await entityStore.clearStore();
console.log('Test entity data cleared');
}

Implementation of​

EntityStore.clearStore