Skip to main content

@idpass/data-collect-core / EntityDataManager

Class: EntityDataManager

Defined in: components/EntityDataManager.ts:140

Primary API interface for the ID PASS DataCollect library.

The EntityDataManager orchestrates all data operations including:

  • Form submission and event processing
  • Entity creation, modification, and querying
  • Data synchronization with remote servers and external systems
  • Audit trail management and duplicate detection

This class implements the Command Query Responsibility Segregation (CQRS) pattern, where all changes go through events (FormSubmissions) and queries access the current state through the EntityStore.

Examples

Basic usage:

import { EntityDataManager, EntityType, SyncLevel } from 'idpass-data-collect';

// Initialize the manager (typically done once)
const manager = new EntityDataManager(
eventStore,
entityStore,
eventApplierService,
externalSyncManager,
internalSyncManager
);

// Create a new individual
const individual = await manager.submitForm({
guid: uuidv4(),
entityGuid: uuidv4(),
type: 'create-individual',
data: { name: 'John Doe', age: 30 },
timestamp: new Date().toISOString(),
userId: 'user-123',
syncLevel: SyncLevel.LOCAL
});

// Create a household group
const group = await manager.submitForm({
guid: uuidv4(),
entityGuid: uuidv4(),
type: 'create-group',
data: { name: 'Smith Family' },
timestamp: new Date().toISOString(),
userId: 'user-123',
syncLevel: SyncLevel.LOCAL
});

// Add individual to group
await manager.submitForm({
guid: uuidv4(),
entityGuid: group.guid,
type: 'add-member',
data: { members: [{ guid: individual.guid, name: individual.data.name }] },
timestamp: new Date().toISOString(),
userId: 'user-123',
syncLevel: SyncLevel.LOCAL
});

Offline-first usage:

// Works completely offline
const offlineManager = new EntityDataManager(
eventStore,
entityStore,
eventApplierService
// No sync managers - offline only
);

// All operations work locally
const entity = await offlineManager.submitForm(formData);
const allEntities = await offlineManager.getAllEntities();

With synchronization:

// Sync with remote server
if (manager.hasInternalSyncManager()) {
await manager.sync();
}

// Check sync status
if (manager.isSyncing()) {
console.log('Sync in progress...');
}

Constructors

Constructor

new EntityDataManager(eventStore, entityStore, eventApplierService, externalSyncManager?, internalSyncManager?, authManager?): EntityDataManager

Defined in: components/EntityDataManager.ts:153

Creates a new EntityDataManager instance.

Parameters

eventStore

EventStore

Store for managing events/form submissions.

entityStore

EntityStore

Store for managing current entity state.

eventApplierService

EventApplierService

Service for applying events to entities.

externalSyncManager?

ExternalSyncManager

Optional manager for external system sync.

internalSyncManager?

InternalSyncManager

Optional manager for server sync.

authManager?

AuthManager

Optional manager for authentication.

Returns

EntityDataManager

Methods

isSyncing()

isSyncing(): boolean

Defined in: components/EntityDataManager.ts:167

Checks if a synchronization operation is currently in progress.

Returns

boolean

True if sync is active, false otherwise.


submitForm()

submitForm(formData): Promise<EntityDoc | null>

Defined in: components/EntityDataManager.ts:207

Submits a form to create or modify entities through the event sourcing system.

All modifications go through events (FormSubmissions) which are applied to create the new state.

Parameters

formData

FormSubmission

The form submission containing the event data.

Returns

Promise<EntityDoc | null>

The resulting entity after applying the event, or null if creation failed.

Example

// Create a new individual
const individual = await manager.submitForm({
guid: uuidv4(),
entityGuid: uuidv4(),
type: 'create-individual',
data: { name: 'John Doe', age: 30, email: 'john@example.com' },
timestamp: new Date().toISOString(),
userId: 'user-123',
syncLevel: SyncLevel.LOCAL
});

// Update an existing individual
const updated = await manager.submitForm({
guid: uuidv4(),
entityGuid: individual.guid,
type: 'update-individual',
data: { age: 31 }, // Only changed fields
timestamp: new Date().toISOString(),
userId: 'user-123',
syncLevel: SyncLevel.LOCAL
});

getAllEvents()

getAllEvents(options): Promise<FormSubmission[]>

Defined in: components/EntityDataManager.ts:233

Retrieves all events (form submissions) from the event store.

Provides access to the complete audit trail of all changes made to entities. Events are returned in chronological order.

Parameters

options

ReadAuditOptions = {}

Returns

Promise<FormSubmission[]>

Array of all form submissions/events.

Example

const events = await manager.getAllEvents();

// Filter events by type
const createEvents = events.filter(e => e.type.startsWith('create-'));

// Filter events by user
const userEvents = events.filter(e => e.userId === 'user-123');

// Filter events by entity
const entityEvents = events.filter(e => e.entityGuid === 'entity-456');

getAllEntities()

getAllEntities(options): Promise<object[]>

Defined in: components/EntityDataManager.ts:267

Retrieves all entities from the entity store.

Returns EntityPairs containing both the initial state (when first loaded/synced) and the current modified state. This enables change tracking and conflict resolution.

Parameters

options

ReadAuditOptions = {}

Returns

Promise<object[]>

Array of entity pairs with initial and current state.

Example

const entities = await manager.getAllEntities();

// Find entities that have been modified locally
const modifiedEntities = entities.filter(pair =>
pair.initial.version !== pair.modified.version
);

// Get only individuals
const individuals = entities.filter(pair =>
pair.modified.type === EntityType.Individual
);

// Get only groups
const groups = entities.filter(pair =>
pair.modified.type === EntityType.Group
);

getEntity()

getEntity(id, options): Promise<{ initial: EntityDoc; modified: EntityDoc; }>

Defined in: components/EntityDataManager.ts:304

Retrieves a specific entity by its internal database ID.

Parameters

id

string

Internal database ID of the entity.

options

ReadAuditOptions = {}

Returns

Promise<{ initial: EntityDoc; modified: EntityDoc; }>

Entity pair with initial and current state.

Throws

When entity is not found.

Example

try {
const entityPair = await manager.getEntity('entity-123');

console.log('Original state:', entityPair.initial);
console.log('Current state:', entityPair.modified);

// Check if entity has been modified
const hasChanges = entityPair.initial.version !== entityPair.modified.version;

if (entityPair.modified.type === EntityType.Group) {
const group = entityPair.modified as GroupDoc;
console.log('Group members:', group.memberIds);
}
} catch (error) {
if (error instanceof AppError && error.code === 'ENTITY_NOT_FOUND') {
console.log('Entity does not exist');
}
}

getMembers()

getMembers(groupId): Promise<object[]>

Defined in: components/EntityDataManager.ts:434

Retrieves all members of a specific group.

Parameters

groupId

string

Internal database ID of the group.

Returns

Promise<object[]>

Array of entity pairs for all group members.

Throws

When group is not found or entity is not a group.

Example

try {
const members = await manager.getMembers('group-123');
console.log(`Group has ${members.length} members`);

members.forEach(member => {
console.log(`Member: ${member.modified.data.name}`);
});
} catch (error) {
if (error instanceof AppError && error.code === 'INVALID_GROUP') {
console.log('Group not found or invalid');
}
}

hasUnsyncedEvents()

hasUnsyncedEvents(): Promise<boolean>

Defined in: components/EntityDataManager.ts:459

Checks if there are any unsynced events waiting to be synchronized.

Only available when an InternalSyncManager is configured.

Returns

Promise<boolean>

True if there are unsynced events, false otherwise.

Example

if (await manager.hasUnsyncedEvents()) {
console.log('There are changes waiting to sync');
await manager.syncWithSyncServer();
}

getUnsyncedEventsCount()

getUnsyncedEventsCount(): Promise<number>

Defined in: components/EntityDataManager.ts:483

Gets the count of unsynced events waiting to be synchronized.

Only available when an InternalSyncManager is configured.

Returns

Promise<number>

Number of unsynced events.

Example

const count = await manager.getUnsyncedEventsCount();
console.log(`${count} events waiting to sync`);

if (count > 100) {
console.log('Large number of changes - consider syncing soon');
}

syncWithSyncServer()

syncWithSyncServer(): Promise<void>

Defined in: components/EntityDataManager.ts:511

Synchronizes local data with the remote sync server.

Performs a full bidirectional sync: pushes local changes to server and pulls remote changes to local storage.

Only available when an InternalSyncManager is configured.

Returns

Promise<void>

Throws

When sync fails or authentication is required.

Example

try {
console.log('Starting sync...');
await manager.syncWithSyncServer();
console.log('Sync completed successfully');
} catch (error) {
console.error('Sync failed:', error.message);
}

searchEntities()

searchEntities(criteria, options): Promise<object[]>

Defined in: components/EntityDataManager.ts:540

Searches entities using specified criteria.

Parameters

criteria

SearchCriteria

Search criteria array with query conditions.

options

ReadAuditOptions = {}

Returns

Promise<object[]>

Array of entity pairs matching the criteria.

Example

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

// Search for groups with specific name
const smithFamilies = await manager.searchEntities([
{ "data.name": { $regex: /smith/i } },
{ "type": "group" }
]);

// TODO: Document the exact query syntax supported

getAuditTrailByEntityGuid()

getAuditTrailByEntityGuid(entityGuid, options): Promise<AuditLogEntry[]>

Defined in: components/EntityDataManager.ts:572

Retrieves the complete audit trail for a specific entity.

Parameters

entityGuid

string

Global unique identifier of the entity.

options

ReadAuditOptions = {}

Returns

Promise<AuditLogEntry[]>

Array of audit log entries in chronological order.

Throws

When audit trail retrieval fails.

Example

try {
const auditTrail = await manager.getAuditTrailByEntityGuid('entity-123');

console.log(`Found ${auditTrail.length} audit entries`);
auditTrail.forEach(entry => {
console.log(`${entry.timestamp}: ${entry.action} by ${entry.userId}`);
});
} catch (error) {
if (error instanceof AppError && error.code === 'AUDIT_TRAIL_ERROR') {
console.error('Failed to retrieve audit trail');
}
}

getEventsSince()

getEventsSince(timestamp): Promise<FormSubmission[]>

Defined in: components/EntityDataManager.ts:629

Retrieves events created since a specific timestamp.

Useful for incremental sync operations and change tracking.

Parameters

timestamp

string

ISO timestamp to filter events from.

Returns

Promise<FormSubmission[]>

Array of events created after the specified timestamp.

Example

const lastSync = '2024-01-01T00:00:00Z';
const recentEvents = await manager.getEventsSince(lastSync);

console.log(`${recentEvents.length} events since last sync`);
recentEvents.forEach(event => {
console.log(`${event.timestamp}: ${event.type} on ${event.entityGuid}`);
});

getEventsSincePagination()

getEventsSincePagination(timestamp, limit): Promise<{ events: FormSubmission[]; nextCursor: string | Date | null; }>

Defined in: components/EntityDataManager.ts:654

Retrieves events since a timestamp with pagination support.

Parameters

timestamp

string

ISO timestamp to filter events from.

limit

number

Maximum number of events to return (default: 10).

Returns

Promise<{ events: FormSubmission[]; nextCursor: string | Date | null; }>

Object with events array and cursor for next page.

Example

let cursor = '2024-01-01T00:00:00Z';
let allEvents: FormSubmission[] = [];

do {
const result = await manager.getEventsSincePagination(cursor, 50);
allEvents.push(...result.events);
cursor = result.nextCursor;
} while (cursor);

console.log(`Retrieved ${allEvents.length} events total`);

closeConnection()

closeConnection(): Promise<void>

Defined in: components/EntityDataManager.ts:674

Closes all database connections and cleans up resources.

Should be called when the EntityDataManager is no longer needed to properly release database connections and prevent memory leaks.

Returns

Promise<void>

Example

// At application shutdown
await manager.closeConnection();
console.log('Database connections closed');

clearStore()

clearStore(): Promise<void>

Defined in: components/EntityDataManager.ts:694

Clears all data from both entity and event stores.

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

Returns

Promise<void>

Example

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

saveAuditLogs()

saveAuditLogs(auditLogs): Promise<void>

Defined in: components/EntityDataManager.ts:722

Saves multiple audit log entries to the event store.

Parameters

auditLogs

AuditLogEntry[]

Array of audit log entries to save.

Returns

Promise<void>

Example

const auditLogs: AuditLogEntry[] = [
{
guid: 'audit-1',
timestamp: '2024-01-01T12:00:00Z',
userId: 'user-123',
action: 'create-individual',
eventGuid: 'event-456',
entityGuid: 'person-789',
changes: { name: 'John Doe' },
signature: 'sha256:abc123'
}
];

await manager.saveAuditLogs(auditLogs);

getAuditLogsSince()

getAuditLogsSince(since): Promise<AuditLogEntry[]>

Defined in: components/EntityDataManager.ts:740

Retrieves audit logs created since a specific timestamp.

Parameters

since

string

ISO timestamp to filter audit logs from.

Returns

Promise<AuditLogEntry[]>

Array of audit log entries created after the specified timestamp.

Example

const lastAuditSync = '2024-01-01T00:00:00Z';
const recentAudits = await manager.getAuditLogsSince(lastAuditSync);

console.log(`${recentAudits.length} audit entries since last sync`);

getPotentialDuplicates()

getPotentialDuplicates(): Promise<object[]>

Defined in: components/EntityDataManager.ts:769

Retrieves all potential duplicate entity pairs detected by the system.

Returns

Promise<object[]>

Array of entity GUID pairs that are potential duplicates.

Example

const duplicates = await manager.getPotentialDuplicates();

if (duplicates.length > 0) {
console.log(`Found ${duplicates.length} potential duplicate pairs`);

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

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

// TODO: Implement duplicate resolution workflow
}
}

syncWithExternalSystem()

syncWithExternalSystem(credentials?): Promise<void>

Defined in: components/EntityDataManager.ts:796

Synchronizes data with external systems (e.g., OpenSPP, custom APIs).

Parameters

credentials?

ExternalSyncCredentials

Optional credentials for external system authentication.

Returns

Promise<void>

Throws

When external sync fails or credentials are invalid.

Example

// Sync with OpenSPP system
try {
await manager.syncWithExternalSystem({
username: 'sync_user',
password: 'sync_password'
});
console.log('External sync completed');
} catch (error) {
console.error('External sync failed:', error.message);
}

// Sync without credentials (if configured in adapter)
await manager.syncWithExternalSystem();

login()

login(credentials, type?): Promise<void>

Defined in: components/EntityDataManager.ts:850

Logs in the user via the configured AuthManager.

Parameters

credentials

The credentials for login.

PasswordCredentials | TokenCredentials | null

type?

string

Optional. The type of authentication provider to use.

Returns

Promise<void>

A Promise that resolves when the login operation is complete.

Throws

If AuthManager is not configured or login fails.


initializeAuthManager()

initializeAuthManager(): Promise<void>

Defined in: components/EntityDataManager.ts:862

Initializes the AuthManager.

Returns

Promise<void>

A Promise that resolves when the AuthManager is initialized.

Throws

If AuthManager is not configured.


logout()

logout(): Promise<void>

Defined in: components/EntityDataManager.ts:874

Logs out the user via the configured AuthManager.

Returns

Promise<void>

A Promise that resolves when the logout operation is complete.

Throws

If AuthManager is not configured or logout fails.


validateToken()

validateToken(type, token): Promise<boolean>

Defined in: components/EntityDataManager.ts:888

Validates an authentication token via the configured AuthManager.

Parameters

type

string

The type of authentication provider.

token

string

The token string to validate.

Returns

Promise<boolean>

A Promise that resolves to true if the token is valid, false otherwise.

Throws

If AuthManager is not configured.


isAuthenticated()

isAuthenticated(): Promise<boolean>

Defined in: components/EntityDataManager.ts:901

Checks if the user is authenticated via the configured AuthManager.

Returns

Promise<boolean>

A Promise that resolves to true if authenticated, false otherwise.

Throws

If AuthManager is not configured.


handleCallback()

handleCallback(type): Promise<void>

Defined in: components/EntityDataManager.ts:915

Handles the authentication callback via the configured AuthManager.

Parameters

type

string

The type of authentication provider.

Returns

Promise<void>

A Promise that resolves when the callback is handled.

Throws

If AuthManager is not configured.