Skip to content

Docs: Keyval

ng-druid edited this page Aug 8, 2025 · 1 revision

Documentation for Keyval Angular Library


Table of Contents

  1. Introduction
  2. Installation
  3. Overview
  4. Key Concepts
    • IndexedDB Integration
    • CRUD Operations with Keyval
    • JSON Rules Engine for Filtering and Querying
  5. Core Components
    • KeyvalModule
  6. Key Factories
    • idbEntityCrudAdaptorPluginFactory
    • initializeIdbDataFactory
  7. Usage
    • Registering the Plugin
    • Performing CRUD Operations
    • Querying Data with Rules
  8. API Reference
  9. Examples
  10. Testing

1. Introduction

The Keyval library provides an Angular module and factory for integrating CRUD operations with IndexedDB in the browser. It serves as an adaptor plugin for @rollthecloudinc/crud and enables persistent data storage, offline capabilities, and complex filtering using rules-based engines (json-rules-engine).

The library is designed to handle scenarios where lightweight, client-side data storage is essential while supporting extensive querying and CRUD workflows.


2. Installation

Install the library along with required dependencies:

npm install keyval idb-keyval @rollthecloudinc/crud @rollthecloudinc/dparam

Ensure @angular/common is already installed as it assists in platform detection.


3. Overview

Keyval serves as an Angular module and IndexedDB integration tool for local data storage. It supports dynamic CRUD operations and advanced filtering.

Features:

  • CRUD Operations: create, read, update, delete, and query operations powered by idb-keyval.
  • Advanced Querying: Allows queries using rules defined by json-rules-engine.
  • Offline Mode: Utilizes IndexedDB for local persistence on the browser platform.
  • Param Evaluation: Dynamically evaluates parameters and configurations via @rollthecloudinc/dparam.

4. Key Concepts

4.1 IndexedDB Integration

The library uses the lightweight idb-keyval library to interact with the browser's IndexedDB storage mechanism. This provides fast and scalable storage for client-side applications.

4.2 CRUD Operations with Keyval

The library defines four basic actions: create, read, update, and delete, each implemented with idb-keyval methods (set, getMany, etc.).

4.3 JSON Rules Engine for Filtering and Querying

json-rules-engine allows complex condition-based filtering of stored data. Custom operators, facts, and rules define how entities are queried based on dynamic conditions.


5. Core Components

KeyvalModule

The KeyvalModule is the primary module of the library, responsible for:

  • Registering the IndexedDB plugin (idb_keyval) with the CrudAdaptorPluginManager.
  • Injecting services such as ParamEvaluatorService for dynamic parameter evaluation.
  • Handling CRUD actions and queries using factories.

6. Key Factories

idbEntityCrudAdaptorPluginFactory

This factory creates a new CrudAdaptorPlugin for interacting with IndexedDB. It defines CRUD operations and custom query handling.

Features:

  • create(): Persists an object into IndexedDB using a unique key and optional prefix.
  • update(): Updates an existing object in IndexedDB.
  • delete(): Deletes an object from IndexedDB (currently stubbed for development).
  • query(): Retrieves entities that match query parameters and optional filtering rules.

initializeIdbDataFactory

This factory initializes IndexedDB with predefined data during application load. It loads key-value pairs into the browser's IndexedDB storage, ensuring data is available offline.


7. Usage

7.1 Registering the Plugin

To enable the idbEntityCrudAdaptorPlugin, simply import and initialize the KeyvalModule in your Angular application.

Example:

import { KeyvalModule } from 'keyval';

@NgModule({
  declarations: [],
  imports: [
    KeyvalModule // Enables Keyval Module and registers the plugin
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

7.2 Performing CRUD Operations

Create

The create method writes data into IndexedDB using a key and optional prefix.

Example:

const crudInput = {
  object: { id: '123', name: 'TestItem' },
  params: { prefix: 'myApp_' },
  identity: () => of({ identity: 'testKey' })
};

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).create(crudInput).subscribe(response => {
  console.log('Create successful:', response.success);
});
Read

The read method retrieves individual objects based on their keys.

Example (read stubbed for development):

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).read({}).subscribe(response => {
  console.log('Read successful:', response.success);
});
Update

The update method overwrites an object in IndexedDB with a new value.

Example:

const crudInput = {
  object: { id: '123', name: 'UpdatedItem' },
  params: { prefix: 'myApp_' },
  identity: () => of({ identity: 'testKey' })
};

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).update(crudInput).subscribe(response => {
  console.log('Update successful:', response.success);
});
Delete

The delete method removes an object from IndexedDB.

Example (delete stubbed for development):

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).delete({}).subscribe(response => {
  console.log('Delete successful:', response.success);
});

7.3 Querying Data with Rules

The query method retrieves all entities matching a given prefix and filters the results using rules from json-rules-engine.

Example:

const queryInput = {
  params: { prefix: 'myApp_' },
  rule: {
    conditions: {
      all: [
        { fact: 'identity', operator: 'startsWith', value: 'test' }
      ]
    },
    event: { type: 'visible' }
  },
  identity: () => of({ identity: 'identityValue' })
};

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).query(queryInput).subscribe(response => {
  console.log('Query successful, entities:', response.entities);
});

8. API Reference

Factories

  1. idbEntityCrudAdaptorPluginFactory

    • create(input: CrudOperationInput): Observable<CrudOperationResponse>
    • read(input: CrudOperationInput): Observable<CrudOperationResponse>
    • update(input: CrudOperationInput): Observable<CrudOperationResponse>
    • delete(input: CrudOperationInput): Observable<CrudOperationResponse>
    • query(input: CrudCollectionOperationInput): Observable<CrudCollectionOperationResponse>
  2. initializeIdbDataFactory(config)

    • Initializes IndexedDB with given data and keys.
    • platformId: Object: Identifies the environment.
    • data: Array<any>: Contains the key-value data.
    • key: (data: any) => IDBValidKey: Defines how keys are generated for the data.

9. Examples

Example: Registering IndexedDB Plugin

Register the plugin in the root module using KeyvalModule.

import { KeyvalModule } from 'keyval';

@NgModule({
  imports: [KeyvalModule],
  bootstrap: [AppComponent]
})
export class AppModule { }

Example: Querying Data with Rules

Use the query method to fetch data matching the given parameters and rule conditions.

const input = {
  params: { prefix: 'appPrefix_' },
  rule: {
    conditions: { all: [{ fact: 'identity', operator: 'startsWith', value: 'user' }] },
    event: { type: 'visible' }
  }
};

idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).query(input).subscribe(response => {
  console.log('Queried entities:', response.entities);
});

10. Testing

Testing CRUD Operations

Example test for verifying create functionality:

describe('idbEntityCrudAdaptorPluginFactory', () => {
  it('should create an item in IndexedDB', () => {
    const input = {
      object: { id: 'item1', name: 'Test Name' },
      params: { prefix: 'testPrefix_' },
      identity: () => of({ identity: 'itemKey1' })
    };

    idbEntityCrudAdaptorPluginFactory(paramEvaluatorService).create(input).subscribe(response => {
      expect(response.success).toBeTruthy();
    });
  });
});

Testing Data Initialization

Example test for verifying data factory initialization:

describe('initializeIdbDataFactory', () => {
  it('should initialize IndexedDB with predefined data', () => {
    const data = [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }];
    const factory = initializeIdbDataFactory({
      data,
      key: ({ data }) => `item_${data.id}`
    });

    factory(platformBrowserId)().subscribe(() => {
      expect(console.log).toHaveBeenCalledWith('data loaded into idb');
    });
  });
});

Conclusion

The Keyval library bridges the gap between Angular applications and IndexedDB to create a powerful offline-first solution for client-side data management. By combining CRUD operations, advanced querying, and runtime parameter evaluation, developers can build scalable and modular applications with ease.

For issues, contributions, or questions, feel free to contact us!

Clone this wiki locally