Ionic Storage

repository·main·Indexed 19 days ago

https://github.com/ionic-team/ionic-storage

A simple key-value storage module for Ionic applications that automatically selects the best available storage engine (IndexedDB, LocalStorage, or SQLite) based on the platform. It provides core packages for React, Vue, and Vanilla JavaScript, as well as @ionic/storage-angular for Angular-specific integration. Supports custom drivers, including localForage-CordovaSQLiteDriver and enterprise-grade Ionic Secure Storage with 256-bit AES encryption.

Tokens
5K
Snippets
19
Records
21
Agent score
65%

What's inside Ionic Storage

  1. Use Ionic Secure Storage (Enterprise)

    main

    Ionic Secure Storage is an enterprise-grade SQLite engine with 256-bit AES encryption.

    Setup:

    1. Follow the official installation guide for @ionic-enterprise/secure-storage.
    2. Configure: Set Drivers.SecureStorage as the first entry in driverOrder.
    3. Register: Call await storage.defineDriver(IonicSecureStorageDriver) during initialization.
    4. Encryption: Use storage.setEncryptionKey('mykey') to enable encryption.
    import { Drivers } from '@ionic/storage';
    import IonicSecureStorageDriver from '@ionic-enterprise/secure-storage/driver';
    
    // React/Vue/Vanilla JS
    const store = new Storage({
      driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
    });
    await store.defineDriver(IonicSecureStorageDriver);
    
    // Angular
    @NgModule({
      imports: [
        IonicStorageModule.forRoot({
          driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
        })
      ]
    })
    export class AppModule { }
    
    // In component
    async ngOnInit() {
      await this.storage.defineDriver(IonicSecureStorageDriver);
      await this.storage.create();
    }
    
    // Enable encryption
    storage.setEncryptionKey('mykey');
  2. Migrate an existing SQLite database to an encrypted database

    main

    If you are moving from an unencrypted SQLite database to an encrypted one powered by Ionic Secure Storage, you must perform a one-time manual migration.

    1. Update Dependencies: Ensure you are on Ionic Storage v3+, have localForage-CordovaSQLiteDriver installed, and have integrated Ionic Secure Storage.
    2. Reset Configuration: Remove any specific name or driverOrder configurations from your IonicStorageModule.forRoot() call in your Angular module (e.g., app.module.ts).
    3. Execute Migration Logic: Create a migration function that:
      • Initializes a temporary Storage instance pointing to the old database name and drivers.
      • Initializes a new Storage instance with a new database name and Drivers.SecureStorage in the driverOrder.
      • Sets the encryption key on the new instance.
      • Iterates through the old store using .forEach(), copying each key-value pair to the new store using .set().
      • Clears the old store using .clear() once the copy is complete.
      • Replaces the active storage instance with the new encrypted one.
    async migrateDatabase() {
      // 1. Setup the original unencrypted store
      const origStore = new Storage({
        name: 'originalDB', // the original database name
        driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
      });
      await origStore.defineDriver(CordovaSQLiteDriver);
    
      // 2. Setup the new encrypted store
      const newStore = new Storage({
        name: 'encryptedDB', // pick a new db name for the encrypted db
        driverOrder: [Drivers.SecureStorage, Drivers.IndexedDB, Drivers.LocalStorage]
      });
      await newStore.defineDriver(IonicSecureStorageDriver);
      newStore.setEncryptionKey('mykey');
    
      // 3. Perform the data migration
      if (await origStore.length() > 0) {
        // copy existing data into new, encrypted format
        await origStore.forEach((key, value, index) => {
          newStore.set(key, value);
        });
    
        // 4. Clean up old data
        await origStore.clear();
      }
    
      // 5. Use the new store for the rest of the app lifecycle
      this._storage = newStore;
    }
  3. Install and use localForage-CordovaSQLiteDriver

    main

    To use SQLite in non-enterprise apps via Cordova or Capacitor, follow these steps:

    1. Install the SQLite plugin:
      • Cordova: ionic cordova plugin add cordova-sqlite-storage
      • Capacitor: npm install cordova-sqlite-storage
    2. Install the driver: npm install localforage-cordovasqlitedriver
    3. Configure the driver: Add CordovaSQLiteDriver._driver to your driverOrder.
    4. Register the driver: Call await storage.defineDriver(CordovaSQLiteDriver) before any data operations.
    import CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
    import { Storage, Drivers } from '@ionic/storage';
    
    // Configuration
    const store = new Storage({
      driverOrder: [CordovaSQLiteDriver._driver, Drivers.IndexedDB, Drivers.LocalStorage]
    });
    
    // Registration
    await store.defineDriver(CordovaSQLiteDriver);
  4. Install @ionic/storage-angular

    main

    If you are building an Angular application, install the @ionic/storage-angular package instead of the core package to benefit from Angular-specific integration like Dependency Injection and Modules.

    npm install @ionic/storage-angular
  5. Use Ionic Storage with Angular

    main

    In Angular, you must import IonicStorageModule in your NgModule and then inject the Storage class into your components or services.

    Note: create() should be called only once in the application lifecycle. For complex apps, it is recommended to wrap storage logic in an Angular Service.

    // 1. Import IonicStorageModule in your AppModule
    import { IonicStorageModule } from '@ionic/storage-angular';
    
    @NgModule({
      imports: [
        IonicStorageModule.forRoot()
      ]
    })
    export class AppModule { }
    
    // 2. Inject Storage into a component
    import { Component } from '@angular/core';
    import { Storage } from '@ionic/storage-angular';
    
    @Component({
      selector: 'app-root',
      templateUrl: 'app.component.html'
    })
    export class AppComponent {
      constructor(private storage: Storage) {}
    
      async ngOnInit() {
        await this.storage.create();
      }
    }
  6. Configure Storage engine priorities

    main

    You can configure the storage engine by specifying a name for the database and a driverOrder to define the priority of storage engines (e.

    React/Vue/Vanilla JS: Pass options to the Storage constructor. Angular: Pass options to IonicStorageModule.forRoot() in your NgModule.

    // React/Vue/Vanilla JS
    const storage = new Storage({
      name: '__mydb',
      driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
    });
    
    // Angular
    @NgModule({
      imports: [
       IonicStorageModule.forRoot({
         name: '__mydb',
         driverOrder: [Drivers.IndexedDB, Drivers.LocalStorage]
       })
      ]
    })
    export class AppModule { }
  7. Use Ionic Storage with React, Vue, or Vanilla JavaScript

    main

    In non-Angular projects, instantiate the Storage class and call create() to initialize the storage engine before performing operations.

    import { Storage } from '@ionic/storage';
    
    const store = new Storage();
    await store.create();
  8. Create an Angular Storage Service

    main

    For sophisticated usage in Angular, create a dedicated service to manage database initialization and operations. This ensures create() is called in a single location and provides a clean API for the rest of your app.

    import { Injectable } from '@angular/core';
    import { Storage } from '@ionic/storage-angular';
    
    @Injectable({
      providedIn: 'root'
    })
    export class StorageService {
      private _storage: Storage | null = null;
    
      constructor(private storage: Storage) {
        this.init();
      }
    
      async init() {
        const storage = await this.storage.create();
        this._storage = storage;
      }
    
      public set(key: string, value: any) {
        this._storage?.set(key, value);
      }
    }
  9. Enable encryption with setEncryptionKey()

    main

    Ionic Storage v3+ supports encryption when used in conjunction with Ionic Secure Storage. You can enable this by calling the setEncryptionKey(key) method on your Storage instance. This allows you to use the standard key-value API while ensuring data is encrypted at rest. For advanced key management and biometric authentication, this can be paired with Ionic Identity Vault.

    // Assuming storage is initialized and IonicSecureStorageDriver is defined
    await storage.setEncryptionKey('your-secret-key');
  10. Storage API Reference

    main

    The Storage instance provides the following methods for key-value operations:

    • set(key, value): Stores a value associated with a key. Returns a Promise.
    • get(key): Retrieves the value associated with a key. Returns a Promise.
    • remove(key): Removes the item associated with the key. Returns a Promise.
    • clear(): Removes all items from the storage. Returns a Promise.
    • keys(): Returns an array of all stored keys. Returns a Promise.
    • length(): Returns the number of key/value pairs stored. Returns a Promise.
    • forEach((key, value, index) => { ... }): Enumerates the stored key/value pairs.
    await storage.set('name', 'Mr. Ionitron');
    const name = await storage.get('name');
    await storage.remove('name');
    await storage.clear();
    await storage.keys();
    await storage.length();
    storage.forEach((key, value, index) => {
      // logic here
    });
  11. Use Storage methods for data operations

    main

    The Storage class provides the following asynchronous methods for managing data:

    • get(key: string): Returns the value associated with the given key.
    • set(key: string, value: any): Sets the value for the given key.
    • remove(key: string): Removes the value associated with the key.
    • clear(): Clears the entire key-value store.
    • length(): Returns the number of keys in the store.
    • keys(): Returns an array of all keys in the store.
    • forEach(iteratorCallback): Iterates through each key-value pair using a callback with the signature (value, key, iterationNumber).
    // Example of forEach
    await storage.forEach((value, key, iterationNumber) => {
      console.log(`Key: ${key}, Value: ${value}, Index: ${iterationNumber}`);
    });