DataCollect Package
The DataCollect package is the core client library for ID PASS DataCollect, providing offline-first data management capabilities for household and individual beneficiary data.
DataCollect implements event sourcing and CQRS patterns to create a robust, auditable system for managing complex data structures while supporting offline operation.
Key Features
- Offline-First: Full functionality without internet connectivity using IndexedDB
- Event Sourcing: Complete audit trail with ability to replay state changes
- Synchronization: Bi-directional sync with central server
- Encryption: Client-side data encryption support
- Cross-Platform: Works in browsers, React Native, and Electron apps
Core Components
EntityDataManager
Central orchestrator for all data operations, providing a clean API for:
- Form submission processing
- Entity state management
- Synchronization coordination
EventStore & EntityStore
- EventStore: Immutable event log with hash chain integrity
- EntityStore: Current state of all entities (Groups, Individuals, and Records)
Sync Managers
- InternalSyncManager: Client ↔ Server synchronization
- ExternalSyncManager: Server ↔ External system integration
Entity Types
DataCollect supports three entity types that map to common beneficiary program concepts:
| Type | EntityType | Typical uses |
|---|---|---|
| Group | EntityType.Group | Households, families, program cohorts |
| Individual | EntityType.Individual | Persons, beneficiaries |
| Record | EntityType.Record | Activities, services, visits, events linked to a group or individual |
Record Entities (v2.0.0)
A Record is an activity or service log attached to an existing group or individual. Unlike groups and individuals — which represent who is in the program — records capture what happened: a home visit, a training session, a grievance filing, an assistance disbursement, or any other time-bound interaction.
TypeScript interface
interface RecordDoc extends EntityDoc {
type: EntityType.Record;
/** GUID of the parent entity this record belongs to (optional) */
parentEntityGuid?: string;
}
Records extend EntityDoc and therefore carry the same guid, data, syncLevel, and version fields as all other entities. The parentEntityGuid field optionally links a record to the group or individual it belongs to.
Configuring record forms
Set entityType: "record" on a form definition in your app configuration to tell DataCollect that submissions should produce create-record / update-record events rather than entity-creation events:
{
"entityForms": [
{
"name": "home-visit",
"title": "Home Visit",
"entityType": "record",
"formio": { }
},
{
"name": "training",
"title": "Training Attendance",
"entityType": "record",
"formio": { }
}
]
}
Forms that have a dependsOn relationship with a parent entity form are automatically classified as record forms by the FormClassifier service, even without an explicit entityType field.
Creating records programmatically
await manager.submitForm({
guid: crypto.randomUUID(),
type: 'create-record',
entityGuid: crypto.randomUUID(), // new record's own GUID
data: {
visitDate: '2025-03-01',
notes: 'Household visited, 4 members present',
parentId: householdGuid // links to the parent entity
},
timestamp: new Date().toISOString(),
userId: currentUserId,
syncLevel: SyncLevel.LOCAL
});
The EventApplierService handles create-record and update-record form types and stores the resulting entity with type: EntityType.Record. The data.parentId field is automatically promoted to parentEntityGuid on the stored document.
Querying records
Records are stored in the same EntityStore as groups and individuals. Filter by type to retrieve them:
const records = await entityStore.searchEntities([
{ type: EntityType.Record }
]);
// Records belonging to a specific parent
const visitsForHousehold = await entityStore.searchEntities([
{ type: EntityType.Record },
{ parentEntityGuid: householdGuid }
]);
How records differ from groups and individuals
- Groups contain member references (
memberIds). Records do not. - Individuals represent people. Records represent events or services.
- Records are always associated with an activity in time. They have a
parentEntityGuidpointing to the group or individual they describe. - All three types sync with the server in the same way — via the standard internal sync pipeline — and are subject to the same audit trail and conflict resolution mechanisms.
Quick Start
Installation
cd ./packages/datacollect
pnpm install
pnpm build
Basic Usage
import {
EntityDataManager,
IndexedDbEntityStorageAdapter,
IndexedDbEventStorageAdapter,
IndexedDbAuthStorageAdapter,
EventStoreImpl,
EntityStoreImpl,
EventApplierService,
InternalSyncManager,
ExternalSyncManager,
AuthManager
} from '@idpass/data-collect-core';
// Initialize storage adapters
const eventStorageAdapter = new IndexedDbEventStorageAdapter('my-events');
const entityStorageAdapter = new IndexedDbEntityStorageAdapter('my-entities');
const authStorageAdapter = new IndexedDbAuthStorageAdapter('my-auth');
// Initialize stores
const eventStore = new EventStoreImpl(eventStorageAdapter);
const entityStore = new EntityStoreImpl(entityStorageAdapter);
await eventStore.initialize();
await entityStore.initialize();
await authStorageAdapter.initialize();
// Set up services
const eventApplierService = new EventApplierService(eventStore, entityStore);
// Create sync managers
const internalSyncManager = new InternalSyncManager(
eventStore,
entityStore,
eventApplierService,
'http://your-sync-server.com',
authStorageAdapter
);
const externalSyncManager = new ExternalSyncManager(
eventStore,
eventApplierService,
{
type: 'mock',
url: 'http://localhost:4000',
auth: '',
extraFields: {}
}
);
// Create authentication manager
const authManager = new AuthManager(
[
{
type: 'auth0',
fields: {
domain: 'your-domain.auth0.com',
clientId: 'your-client-id',
audience: 'your-api-audience',
scope: 'openid profile email'
}
}
],
'http://your-sync-server.com',
authStorageAdapter
);
// Create the main manager
const manager = new EntityDataManager(
eventStore,
entityStore,
eventApplierService,
externalSyncManager,
internalSyncManager,
authManager
);
Documentation Sections
API Reference
Complete TypeScript API documentation with examples
Tutorials
Step-by-step guides for common use cases:
- Creating your first DataCollection app
- Implementing custom event types
- Setting up offline-online synchronization
Configuration
Configuration options and environment setup
Examples
Working code examples for different scenarios
Architecture Integration
DataCollect works as part of the larger ID PASS ecosystem:
Performance Characteristics
- Storage: Efficient IndexedDB usage with pagination
- Memory: Event streaming with configurable batch sizes
- Sync: Incremental synchronization with conflict resolution
- Scalability: Tested with 10,000+ entities per client
Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
Next Steps
- Tutorials - Learn by building
- Backend Package - Add server synchronization
- Admin Package - Complete management solution