Kaynağa Gözat

feat: store filter param for more DataStoreSerializer methods

Sv443 3 hafta önce
ebeveyn
işleme
48306da
3 değiştirilmiş dosya ile 52 ekleme ve 26 silme
  1. 5 0
      .changeset/modern-oranges-compete.md
  2. 9 6
      docs.md
  3. 38 20
      lib/DataStoreSerializer.ts

+ 5 - 0
.changeset/modern-oranges-compete.md

@@ -0,0 +1,5 @@
+---
+"@sv443-network/userutils": minor
+---
+
+Added `stores` filter parameter to the `DataStoreSerializer` methods `loadStoresData()`, `resetStoresData()` and `deleteStoresData()`

+ 9 - 6
docs.md

@@ -1559,8 +1559,9 @@ If you want to import all serialized data, refer to the method [`DataStoreSerial
 <br>
 
 #### `DataStoreSerializer.loadStoresData()`
-Signature: `loadStoresData(): PromiseSettledResult<{ id: string, data: object }>[];`  
-Loads the persistent data of the DataStore instances into the in-memory cache of each DataStore instance.  
+Signature: `loadStoresData(stores?: string[] | ((id: string) => boolean)): PromiseSettledResult<{ id: string, data: object }>[];`  
+Loads the persistent data of the DataStore instances with IDs matching the `stores` parameter into the in-memory cache of each DataStore instance.  
+If no stores are specified, all stores will be loaded.  
 Also triggers the migration process if the data format has changed.  
 See the [`DataStore.loadData()`](#datastoreloaddata) method for more information.  
   
@@ -1590,16 +1591,18 @@ See the [`DataStore.loadData()`](#datastoreloaddata) method for more information
 <br>
 
 #### `DataStoreSerializer.resetStoresData()`
-Signature: `resetStoresData(): PromiseSettledResult[];`  
-Resets the persistent data of the DataStore instances to their default values.  
+Signature: `resetStoresData(stores?: string[] | ((id: string) => boolean)): PromiseSettledResult[];`  
+Resets the persistent data of the DataStore instances with IDs matching the `stores` parameter to their default values.  
+If no stores are specified, all stores will be reset.  
 This affects both the in-memory cache and the persistent storage.  
 Any call to `serialize()` will then use the value of `options.defaultData` of the respective DataStore instance.  
 
 <br>
 
 #### `DataStoreSerializer.deleteStoresData()`
-Signature: `deleteStoresData(): PromiseSettledResult[];`  
-Deletes the persistent data of the DataStore instances from the set storage method.  
+Signature: `deleteStoresData(stores?: string[] | ((id: string) => boolean)): PromiseSettledResult[];`  
+Deletes the persistent data of the DataStore instances with IDs matching the `stores` parameter from the set storage method.  
+If no stores are specified, all stores' persistent data will be deleted.  
 Leaves the in-memory cache of the DataStore instances untouched.  
 Any call to `setData()` on the instances will recreate their own persistent storage data.
 

+ 38 - 20
lib/DataStoreSerializer.ts

@@ -9,9 +9,9 @@ import { ChecksumMismatchError } from "./errors.js";
 import type { DataStore } from "./DataStore.js";
 
 export type DataStoreSerializerOptions = {
-  /** Whether to add a checksum to the exported data */
+  /** Whether to add a checksum to the exported data. Defaults to `true` */
   addChecksum?: boolean;
-  /** Whether to ensure the integrity of the data when importing it by throwing an error (doesn't throw when the checksum property doesn't exist) */
+  /** Whether to ensure the integrity of the data when importing it by throwing an error (doesn't throw when the checksum property doesn't exist). Defaults to `true` */
   ensureIntegrity?: boolean;
 };
 
@@ -37,6 +37,9 @@ export type LoadStoresDataResult = {
   data: object;
 }
 
+/** A filter for selecting data stores */
+export type StoreFilter = string[] | ((id: string) => boolean);
+
 /**
  * Allows for easy serialization and deserialization of multiple DataStore instances.  
  *   
@@ -72,28 +75,28 @@ export class DataStoreSerializer {
    * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
    * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
    */
-  public async serializePartial(stores: string[] | ((id: string) => boolean), useEncoding?: boolean, stringified?: true): Promise<string>;
+  public async serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: true): Promise<string>;
   /**
    * Serializes only a subset of the data stores into a string.  
    * @param stores An array of store IDs or functions that take a store ID and return a boolean
    * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
    * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
    */
-  public async serializePartial(stores: string[] | ((id: string) => boolean), useEncoding?: boolean, stringified?: false): Promise<SerializedDataStore[]>;
+  public async serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: false): Promise<SerializedDataStore[]>;
   /**
    * Serializes only a subset of the data stores into a string.  
    * @param stores An array of store IDs or functions that take a store ID and return a boolean
    * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
    * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
    */
-  public async serializePartial(stores: string[] | ((id: string) => boolean), useEncoding?: boolean, stringified?: boolean): Promise<string | SerializedDataStore[]>;
+  public async serializePartial(stores: StoreFilter, useEncoding?: boolean, stringified?: boolean): Promise<string | SerializedDataStore[]>;
   /**
    * Serializes only a subset of the data stores into a string.  
    * @param stores An array of store IDs or functions that take a store ID and return a boolean
    * @param useEncoding Whether to encode the data using each DataStore's `encodeData()` method
    * @param stringified Whether to return the result as a string or as an array of `SerializedDataStore` objects
    */
-  public async serializePartial(stores: string[] | ((id: string) => boolean), useEncoding = true, stringified = true): Promise<string | SerializedDataStore[]> {
+  public async serializePartial(stores: StoreFilter, useEncoding = true, stringified = true): Promise<string | SerializedDataStore[]> {
     const serData: SerializedDataStore[] = [];
 
     for(const storeInst of this.stores.filter(s => typeof stores === "function" ? stores(s.id) : stores.includes(s.id))) {
@@ -140,7 +143,7 @@ export class DataStoreSerializer {
    * Deserializes the data exported via {@linkcode serialize()} and imports only a subset into the DataStore instances.  
    * Also triggers the migration process if the data format has changed.
    */
-  public async deserializePartial(stores: string[] | ((id: string) => boolean), data: string | SerializedDataStore[]): Promise<void> {
+  public async deserializePartial(stores: StoreFilter, data: string | SerializedDataStore[]): Promise<void> {
     const deserStores: SerializedDataStore[] = typeof data === "string" ? JSON.parse(data) : data;
 
     if(!Array.isArray(deserStores) || !deserStores.every(DataStoreSerializer.isSerializedDataStore))
@@ -179,32 +182,47 @@ export class DataStoreSerializer {
   /**
    * Loads the persistent data of the DataStore instances into the in-memory cache.  
    * Also triggers the migration process if the data format has changed.
+   * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be loaded
    * @returns Returns a PromiseSettledResult array with the results of each DataStore instance in the format `{ id: string, data: object }`
    */
-  public async loadStoresData(): Promise<PromiseSettledResult<LoadStoresDataResult>[]> {
-    return Promise.allSettled(this.stores.map(
-      async store => ({
-        id: store.id,
-        data: await store.loadData(),
-      })
-    ));
+  public async loadStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<LoadStoresDataResult>[]> {
+    return Promise.allSettled(
+      this.getStoresFiltered(stores)
+        .map(async (store) => ({
+          id: store.id,
+          data: await store.loadData(),
+        })),
+    );
   }
 
-  /** Resets the persistent data of the DataStore instances to their default values. */
-  public async resetStoresData(): Promise<PromiseSettledResult<void>[]> {
-    return Promise.allSettled(this.stores.map(store => store.saveDefaultData()));
+  /**
+   * Resets the persistent and in-memory data of the DataStore instances to their default values.
+   * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
+   */
+  public async resetStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<void>[]> {
+    return Promise.allSettled(
+      this.getStoresFiltered(stores).map(store => store.saveDefaultData()),
+    );
   }
 
   /**
    * Deletes the persistent data of the DataStore instances.  
-   * Leaves the in-memory data untouched.
+   * Leaves the in-memory data untouched.  
+   * @param stores An array of store IDs or a function that takes the store IDs and returns a boolean - if omitted, all stores will be affected
    */
-  public async deleteStoresData(): Promise<PromiseSettledResult<void>[]> {
-    return Promise.allSettled(this.stores.map(store => store.deleteData()));
+  public async deleteStoresData(stores?: StoreFilter): Promise<PromiseSettledResult<void>[]> {
+    return Promise.allSettled(
+      this.getStoresFiltered(stores).map(store => store.deleteData()),
+    );
   }
 
   /** Checks if a given value is a SerializedDataStore object */
   public static isSerializedDataStore(obj: unknown): obj is SerializedDataStore {
     return typeof obj === "object" && obj !== null && "id" in obj && "data" in obj && "formatVersion" in obj && "encoded" in obj;
   }
+
+  /** Returns the DataStore instances whose IDs match the provided array or function */
+  protected getStoresFiltered(stores?: StoreFilter): DataStore[] {
+    return this.stores.filter(s => typeof stores === "undefined" ? true : Array.isArray(stores) ? stores.includes(s.id) : stores(s.id));
+  }
 }