Переглянути джерело

ref!: renamed ConfigManager to DataStore

Sv443 1 рік тому
батько
коміт
e921593
3 змінених файлів з 39 додано та 31 видалено
  1. 8 0
      .changeset/breezy-pumpkins-march.md
  2. 30 30
      lib/DataStore.ts
  3. 1 1
      lib/index.ts

+ 8 - 0
.changeset/breezy-pumpkins-march.md

@@ -0,0 +1,8 @@
+---
+"@sv443-network/userutils": major
+---
+
+Renamed `ConfigManager` to `DataStore` to make its implied purpose as a generic JSON database more clear.
+- the constructor property `defaultConfig` is now called `defaultData`
+- `deleteConfig()` is now called `deleteData()`
+- the internal GM storage keys will still have the prefix `_uucfg` for backwards compatibility

+ 30 - 30
lib/ConfigManager.ts → lib/DataStore.ts

@@ -5,26 +5,26 @@ type MigrationFunc = (oldData: any) => any | Promise<any>;
 /** Dictionary of format version numbers and the function that migrates to them from the previous whole integer */
 export type ConfigMigrationsDict = Record<number, MigrationFunc>;
 
-/** Options for the ConfigManager instance */
-export type ConfigManagerOptions<TData> = {
-  /** A unique internal ID for this configuration - choose wisely as changing it is not supported yet. */
+/** Options for the DataStore instance */
+export type DataStoreOptions<TData> = {
+  /** A unique internal ID for this data store - choose wisely as changing it is not supported yet. */
   id: string;
   /**
-   * The default config data object to use if no data is saved in persistent storage yet.  
+   * The default data object to use if no data is saved in persistent storage yet.  
    * Until the data is loaded from persistent storage with `loadData()`, this will be the data returned by `getData()`  
    *   
    * ⚠️ This has to be an object that can be serialized to JSON, so no functions or circular references are allowed, they will cause unexpected behavior.  
    */
-  defaultConfig: TData;
+  defaultData: TData;
   /**
-   * An incremental, whole integer version number of the current format of config data.  
+   * An incremental, whole integer version number of the current format of data.  
    * If the format of the data is changed in any way, this number should be incremented, in which case all necessary functions of the migrations dictionary will be run consecutively.  
    *   
    * ⚠️ Never decrement this number and optimally don't skip any numbers either!
    */
   formatVersion: number;
   /**
-   * A dictionary of functions that can be used to migrate data from older versions of the configuration to newer ones.  
+   * A dictionary of functions that can be used to migrate data from older versions to newer ones.  
    * The keys of the dictionary should be the format version that the functions can migrate to, from the previous whole integer value.  
    * The values should be functions that take the data in the old format and return the data in the new format.  
    * The functions will be run in order from the oldest to the newest version.  
@@ -55,38 +55,38 @@ export type ConfigManagerOptions<TData> = {
 });
 
 /**
- * Manages a user configuration that is cached in memory and persistently saved across sessions.  
+ * Manages a sync & async persistent JSON database that is cached in memory and persistently saved across sessions.  
  * Supports migrating data from older versions of the configuration to newer ones and populating the cache with default data if no persistent data is found.  
  *   
  * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue`  
- * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultConfig`
+ * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
  * 
- * @template TData The type of the data that is saved in persistent storage (will be automatically inferred from `config.defaultConfig`) - this should also be the type of the data format associated with the current `options.formatVersion`
+ * @template TData The type of the data that is saved in persistent storage (will be automatically inferred from `defaultData`) - this should also be the type of the data format associated with the current `formatVersion`
  */
-export class ConfigManager<TData = any> {
+export class DataStore<TData = any> {
   public readonly id: string;
   public readonly formatVersion: number;
-  public readonly defaultConfig: TData;
+  public readonly defaultData: TData;
   private cachedData: TData;
   private migrations?: ConfigMigrationsDict;
-  private encodeData: ConfigManagerOptions<TData>["encodeData"];
-  private decodeData: ConfigManagerOptions<TData>["decodeData"];
+  private encodeData: DataStoreOptions<TData>["encodeData"];
+  private decodeData: DataStoreOptions<TData>["decodeData"];
 
   /**
-   * Creates an instance of ConfigManager to manage a user configuration that is cached in memory and persistently saved across sessions.  
-   * Supports migrating data from older versions of the configuration to newer ones and populating the cache with default data if no persistent data is found.  
+   * Creates an instance of DataStore to manage a sync & async database that is cached in memory and persistently saved across sessions.  
+   * Supports migrating data from older versions to newer ones and populating the cache with default data if no persistent data is found.  
    *   
    * ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue`  
-   * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultConfig`
+   * ⚠️ Make sure to call {@linkcode loadData()} at least once after creating an instance, or the returned data will be the same as `options.defaultData`
    * 
-   * @template TData The type of the data that is saved in persistent storage (will be automatically inferred from `config.defaultConfig`) - this should also be the type of the data format associated with the current `options.formatVersion`
-   * @param options The options for this ConfigManager instance
+   * @template TData The type of the data that is saved in persistent storage (will be automatically inferred from `config.defaultData`) - this should also be the type of the data format associated with the current `options.formatVersion`
+   * @param options The options for this DataStore instance
   */
-  constructor(options: ConfigManagerOptions<TData>) {
+  constructor(options: DataStoreOptions<TData>) {
     this.id = options.id;
     this.formatVersion = options.formatVersion;
-    this.defaultConfig = options.defaultConfig;
-    this.cachedData = options.defaultConfig;
+    this.defaultData = options.defaultData;
+    this.cachedData = options.defaultData;
     this.migrations = options.migrations;
     this.encodeData = options.encodeData;
     this.decodeData = options.decodeData;
@@ -99,12 +99,12 @@ export class ConfigManager<TData = any> {
    */
   public async loadData(): Promise<TData> {
     try {
-      const gmData = await GM.getValue(`_uucfg-${this.id}`, this.defaultConfig);
+      const gmData = await GM.getValue(`_uucfg-${this.id}`, this.defaultData);
       let gmFmtVer = Number(await GM.getValue(`_uucfgver-${this.id}`));
 
       if(typeof gmData !== "string") {
         await this.saveDefaultData();
-        return { ...this.defaultConfig };
+        return { ...this.defaultData };
       }
 
       const isEncoded = await GM.getValue(`_uucfgenc-${this.id}`, false);
@@ -120,9 +120,9 @@ export class ConfigManager<TData = any> {
       return { ...(this.cachedData = parsed) };
     }
     catch(err) {
-      console.warn("Error while loading config data, resetting it to the default value.", err);
+      console.warn("Error while parsing JSON data, resetting it to the default value.", err);
       await this.saveDefaultData();
-      return this.defaultConfig;
+      return this.defaultData;
     }
   }
 
@@ -150,11 +150,11 @@ export class ConfigManager<TData = any> {
 
   /** Saves the default configuration data passed in the constructor synchronously to the in-memory cache and asynchronously to persistent storage */
   public async saveDefaultData() {
-    this.cachedData = this.defaultConfig;
+    this.cachedData = this.defaultData;
     const useEncoding = Boolean(this.encodeData && this.decodeData);
     return new Promise<void>(async (resolve) => {
       await Promise.all([
-        GM.setValue(`_uucfg-${this.id}`, await this.serializeData(this.defaultConfig, useEncoding)),
+        GM.setValue(`_uucfg-${this.id}`, await this.serializeData(this.defaultData, useEncoding)),
         GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
         GM.setValue(`_uucfgenc-${this.id}`, useEncoding),
       ]);
@@ -163,13 +163,13 @@ export class ConfigManager<TData = any> {
   }
 
   /**
-   * Call this method to clear all persistently stored data associated with this ConfigManager instance.  
+   * Call this method to clear all persistently stored data associated with this DataStore instance.  
    * The in-memory cache will be left untouched, so you may still access the data with {@linkcode getData()}  
    * Calling {@linkcode loadData()} or {@linkcode setData()} after this method was called will recreate persistent storage with the cached or default data.  
    *   
    * ⚠️ This requires the additional directive `@grant GM.deleteValue`
    */
-  public async deleteConfig() {
+  public async deleteData() {
     await Promise.all([
       GM.deleteValue(`_uucfg-${this.id}`),
       GM.deleteValue(`_uucfgver-${this.id}`),

+ 1 - 1
lib/index.ts

@@ -1,5 +1,5 @@
 export * from "./array";
-export * from "./ConfigManager";
+export * from "./DataStore";
 export * from "./dom";
 export * from "./math";
 export * from "./misc";