Skip to main content

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:

TypeEntityTypeTypical uses
GroupEntityType.GroupHouseholds, families, program cohorts
IndividualEntityType.IndividualPersons, beneficiaries
RecordEntityType.RecordActivities, 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 parentEntityGuid pointing 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