@sv443-network/userutils 4.2.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - c980ff3: `compress()` now uses the same value "string" (unlike previously "base64") for the outputType parameter like `decompress()`
8
+
9
+ ### Minor Changes
10
+
11
+ - ca1b596: Added `encodeData()` and `decodeData()` to the ConfigManager options to allow for easy data compression
12
+
3
13
  ## 4.2.1
4
14
 
5
15
  ### Patch Changes
package/README.md CHANGED
@@ -873,6 +873,8 @@ The options object has the following properties:
873
873
  | `defaultConfig` | The default config data to use if no data is saved in persistent storage yet. Until the data is loaded from persistent storage, this will be the data returned by `getData()`. For TypeScript, the type of the data passed here is what will be used for all other methods of the instance. |
874
874
  | `formatVersion` | An incremental version of the data format. 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 or skip numbers. |
875
875
  | `migrations?` | (Optional) A dictionary of functions that can be used to migrate data from older versions of the configuration 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. If the current format version is not in the dictionary, no migrations will be run. |
876
+ | `encodeData?` | (Optional, but required when decodeData is set) Function that encodes the data before saving - you can use [compress()](#compress) here to save space at the cost of a little bit of performance |
877
+ | `decodeData?` | (Optional, but required when encodeData is set) Function that decodes the data when loading - you can use [decompress()](#decompress) here to decode data that was previously compressed with [compress()](#compress) |
876
878
 
877
879
  <br>
878
880
 
@@ -903,7 +905,7 @@ If `loadData()` or `setData()` are called after this, the persistent storage wil
903
905
  <details><summary><b>Example - click to view</b></summary>
904
906
 
905
907
  ```ts
906
- import { ConfigManager } from "@sv443-network/userutils";
908
+ import { ConfigManager, compress, decompress } from "@sv443-network/userutils";
907
909
 
908
910
  interface MyConfig {
909
911
  foo: string;
@@ -953,6 +955,15 @@ const manager = new ConfigManager({
953
955
  formatVersion,
954
956
  /** Data format migration functions */
955
957
  migrations,
958
+
959
+ // Compression example:
960
+ // Adding this will save space at the cost of a little bit of performance while initially loading and saving the data
961
+ // Only both of these properties or none of them should be set
962
+ // Everything else will be handled by the ConfigManager instance
963
+ /** Encode data using the "deflate-raw" algorithm and digests it as a base64 string */
964
+ encodeData: (data) => compress(data, "deflate-raw", "base64"),
965
+ /** Decode the "deflate-raw" encoded data as a base64 string */
966
+ decodeData: (data) => decompress(data, "deflate-raw", "base64"),
956
967
  });
957
968
 
958
969
  /** Entrypoint of the userscript */
@@ -9,7 +9,7 @@
9
9
  // ==UserLibrary==
10
10
  // @name UserUtils
11
11
  // @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more
12
- // @version 4.2.1
12
+ // @version 5.0.0
13
13
  // @license MIT
14
14
  // @copyright Sv443 (https://github.com/Sv443)
15
15
 
@@ -155,11 +155,15 @@ var UserUtils = (function (exports) {
155
155
  __publicField(this, "defaultConfig");
156
156
  __publicField(this, "cachedConfig");
157
157
  __publicField(this, "migrations");
158
+ __publicField(this, "encodeData");
159
+ __publicField(this, "decodeData");
158
160
  this.id = options.id;
159
161
  this.formatVersion = options.formatVersion;
160
162
  this.defaultConfig = options.defaultConfig;
161
163
  this.cachedConfig = options.defaultConfig;
162
164
  this.migrations = options.migrations;
165
+ this.encodeData = options.encodeData;
166
+ this.decodeData = options.decodeData;
163
167
  }
164
168
  /**
165
169
  * Loads the data saved in persistent storage into the in-memory cache and also returns it.
@@ -175,13 +179,15 @@ var UserUtils = (function (exports) {
175
179
  yield this.saveDefaultData();
176
180
  return this.defaultConfig;
177
181
  }
182
+ const isEncoded = yield GM.getValue(`_uucfgenc-${this.id}`, false);
178
183
  if (isNaN(gmFmtVer))
179
184
  yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
180
- let parsed = JSON.parse(gmData);
185
+ let parsed = yield this.deserializeData(gmData, isEncoded);
181
186
  if (gmFmtVer < this.formatVersion && this.migrations)
182
187
  parsed = yield this.runMigrations(parsed, gmFmtVer);
183
- return this.cachedConfig = typeof parsed === "object" ? parsed : void 0;
188
+ return this.cachedConfig = parsed;
184
189
  } catch (err) {
190
+ console.warn("Error while loading config data, resetting it to the default value.", err);
185
191
  yield this.saveDefaultData();
186
192
  return this.defaultConfig;
187
193
  }
@@ -197,10 +203,12 @@ var UserUtils = (function (exports) {
197
203
  /** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
198
204
  setData(data) {
199
205
  this.cachedConfig = data;
206
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
200
207
  return new Promise((resolve) => __async(this, null, function* () {
201
208
  yield Promise.all([
202
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(data)),
203
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
209
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
210
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
211
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
204
212
  ]);
205
213
  resolve();
206
214
  }));
@@ -209,10 +217,12 @@ var UserUtils = (function (exports) {
209
217
  saveDefaultData() {
210
218
  return __async(this, null, function* () {
211
219
  this.cachedConfig = this.defaultConfig;
220
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
212
221
  return new Promise((resolve) => __async(this, null, function* () {
213
222
  yield Promise.all([
214
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultConfig)),
215
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
223
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultConfig, useEncoding)),
224
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
225
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
216
226
  ]);
217
227
  resolve();
218
228
  }));
@@ -229,7 +239,8 @@ var UserUtils = (function (exports) {
229
239
  return __async(this, null, function* () {
230
240
  yield Promise.all([
231
241
  GM.deleteValue(`_uucfg-${this.id}`),
232
- GM.deleteValue(`_uucfgver-${this.id}`)
242
+ GM.deleteValue(`_uucfgver-${this.id}`),
243
+ GM.deleteValue(`_uucfgenc-${this.id}`)
233
244
  ]);
234
245
  });
235
246
  }
@@ -249,17 +260,41 @@ var UserUtils = (function (exports) {
249
260
  newData = migRes instanceof Promise ? yield migRes : migRes;
250
261
  lastFmtVer = oldFmtVer = ver;
251
262
  } catch (err) {
252
- console.error(`Error while running migration function for format version ${fmtVer}:`, err);
263
+ console.error(`Error while running migration function for format version '${fmtVer}' - resetting to the default value.`, err);
264
+ yield this.saveDefaultData();
265
+ return this.getData();
253
266
  }
254
267
  }
255
268
  }
256
269
  yield Promise.all([
257
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(newData)),
258
- GM.setValue(`_uucfgver-${this.id}`, lastFmtVer)
270
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
271
+ GM.setValue(`_uucfgver-${this.id}`, lastFmtVer),
272
+ GM.setValue(`_uucfgenc-${this.id}`, Boolean(this.encodeData && this.decodeData))
259
273
  ]);
260
274
  return newData;
261
275
  });
262
276
  }
277
+ /** Serializes the data using the optional this.encodeData() and returns it as a string */
278
+ serializeData(data, useEncoding = true) {
279
+ return __async(this, null, function* () {
280
+ const stringData = JSON.stringify(data);
281
+ if (!this.encodeData || !this.decodeData || !useEncoding)
282
+ return stringData;
283
+ const encRes = this.encodeData(stringData);
284
+ if (encRes instanceof Promise)
285
+ return yield encRes;
286
+ return encRes;
287
+ });
288
+ }
289
+ /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
290
+ deserializeData(data, useEncoding = true) {
291
+ return __async(this, null, function* () {
292
+ let decRes = this.decodeData && this.encodeData && useEncoding ? this.decodeData(data) : void 0;
293
+ if (decRes instanceof Promise)
294
+ decRes = yield decRes;
295
+ return JSON.parse(decRes != null ? decRes : data);
296
+ });
297
+ }
263
298
  /** Copies a JSON-compatible object and loses its internal references */
264
299
  deepCopy(obj) {
265
300
  return JSON.parse(JSON.stringify(obj));
@@ -405,7 +440,7 @@ var UserUtils = (function (exports) {
405
440
  return (_b = (_a = values[argIndex]) != null ? _a : match) == null ? void 0 : _b.toString();
406
441
  });
407
442
  }
408
- function compress(input, compressionFormat, outputType = "base64") {
443
+ function compress(input, compressionFormat, outputType = "string") {
409
444
  return __async(this, null, function* () {
410
445
  const byteArray = typeof input === "string" ? new TextEncoder().encode(input) : input;
411
446
  const comp = new CompressionStream(compressionFormat);
package/dist/index.js CHANGED
@@ -134,11 +134,15 @@ var ConfigManager = class {
134
134
  __publicField(this, "defaultConfig");
135
135
  __publicField(this, "cachedConfig");
136
136
  __publicField(this, "migrations");
137
+ __publicField(this, "encodeData");
138
+ __publicField(this, "decodeData");
137
139
  this.id = options.id;
138
140
  this.formatVersion = options.formatVersion;
139
141
  this.defaultConfig = options.defaultConfig;
140
142
  this.cachedConfig = options.defaultConfig;
141
143
  this.migrations = options.migrations;
144
+ this.encodeData = options.encodeData;
145
+ this.decodeData = options.decodeData;
142
146
  }
143
147
  /**
144
148
  * Loads the data saved in persistent storage into the in-memory cache and also returns it.
@@ -154,13 +158,15 @@ var ConfigManager = class {
154
158
  yield this.saveDefaultData();
155
159
  return this.defaultConfig;
156
160
  }
161
+ const isEncoded = yield GM.getValue(`_uucfgenc-${this.id}`, false);
157
162
  if (isNaN(gmFmtVer))
158
163
  yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
159
- let parsed = JSON.parse(gmData);
164
+ let parsed = yield this.deserializeData(gmData, isEncoded);
160
165
  if (gmFmtVer < this.formatVersion && this.migrations)
161
166
  parsed = yield this.runMigrations(parsed, gmFmtVer);
162
- return this.cachedConfig = typeof parsed === "object" ? parsed : void 0;
167
+ return this.cachedConfig = parsed;
163
168
  } catch (err) {
169
+ console.warn("Error while loading config data, resetting it to the default value.", err);
164
170
  yield this.saveDefaultData();
165
171
  return this.defaultConfig;
166
172
  }
@@ -176,10 +182,12 @@ var ConfigManager = class {
176
182
  /** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
177
183
  setData(data) {
178
184
  this.cachedConfig = data;
185
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
179
186
  return new Promise((resolve) => __async(this, null, function* () {
180
187
  yield Promise.all([
181
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(data)),
182
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
188
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
189
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
190
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
183
191
  ]);
184
192
  resolve();
185
193
  }));
@@ -188,10 +196,12 @@ var ConfigManager = class {
188
196
  saveDefaultData() {
189
197
  return __async(this, null, function* () {
190
198
  this.cachedConfig = this.defaultConfig;
199
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
191
200
  return new Promise((resolve) => __async(this, null, function* () {
192
201
  yield Promise.all([
193
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultConfig)),
194
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
202
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultConfig, useEncoding)),
203
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
204
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
195
205
  ]);
196
206
  resolve();
197
207
  }));
@@ -208,7 +218,8 @@ var ConfigManager = class {
208
218
  return __async(this, null, function* () {
209
219
  yield Promise.all([
210
220
  GM.deleteValue(`_uucfg-${this.id}`),
211
- GM.deleteValue(`_uucfgver-${this.id}`)
221
+ GM.deleteValue(`_uucfgver-${this.id}`),
222
+ GM.deleteValue(`_uucfgenc-${this.id}`)
212
223
  ]);
213
224
  });
214
225
  }
@@ -228,17 +239,41 @@ var ConfigManager = class {
228
239
  newData = migRes instanceof Promise ? yield migRes : migRes;
229
240
  lastFmtVer = oldFmtVer = ver;
230
241
  } catch (err) {
231
- console.error(`Error while running migration function for format version ${fmtVer}:`, err);
242
+ console.error(`Error while running migration function for format version '${fmtVer}' - resetting to the default value.`, err);
243
+ yield this.saveDefaultData();
244
+ return this.getData();
232
245
  }
233
246
  }
234
247
  }
235
248
  yield Promise.all([
236
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(newData)),
237
- GM.setValue(`_uucfgver-${this.id}`, lastFmtVer)
249
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
250
+ GM.setValue(`_uucfgver-${this.id}`, lastFmtVer),
251
+ GM.setValue(`_uucfgenc-${this.id}`, Boolean(this.encodeData && this.decodeData))
238
252
  ]);
239
253
  return newData;
240
254
  });
241
255
  }
256
+ /** Serializes the data using the optional this.encodeData() and returns it as a string */
257
+ serializeData(data, useEncoding = true) {
258
+ return __async(this, null, function* () {
259
+ const stringData = JSON.stringify(data);
260
+ if (!this.encodeData || !this.decodeData || !useEncoding)
261
+ return stringData;
262
+ const encRes = this.encodeData(stringData);
263
+ if (encRes instanceof Promise)
264
+ return yield encRes;
265
+ return encRes;
266
+ });
267
+ }
268
+ /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
269
+ deserializeData(data, useEncoding = true) {
270
+ return __async(this, null, function* () {
271
+ let decRes = this.decodeData && this.encodeData && useEncoding ? this.decodeData(data) : void 0;
272
+ if (decRes instanceof Promise)
273
+ decRes = yield decRes;
274
+ return JSON.parse(decRes != null ? decRes : data);
275
+ });
276
+ }
242
277
  /** Copies a JSON-compatible object and loses its internal references */
243
278
  deepCopy(obj) {
244
279
  return JSON.parse(JSON.stringify(obj));
@@ -384,7 +419,7 @@ function insertValues(input, ...values) {
384
419
  return (_b = (_a = values[argIndex]) != null ? _a : match) == null ? void 0 : _b.toString();
385
420
  });
386
421
  }
387
- function compress(input, compressionFormat, outputType = "base64") {
422
+ function compress(input, compressionFormat, outputType = "string") {
388
423
  return __async(this, null, function* () {
389
424
  const byteArray = typeof input === "string" ? new TextEncoder().encode(input) : input;
390
425
  const comp = new CompressionStream(compressionFormat);
package/dist/index.mjs CHANGED
@@ -132,11 +132,15 @@ var ConfigManager = class {
132
132
  __publicField(this, "defaultConfig");
133
133
  __publicField(this, "cachedConfig");
134
134
  __publicField(this, "migrations");
135
+ __publicField(this, "encodeData");
136
+ __publicField(this, "decodeData");
135
137
  this.id = options.id;
136
138
  this.formatVersion = options.formatVersion;
137
139
  this.defaultConfig = options.defaultConfig;
138
140
  this.cachedConfig = options.defaultConfig;
139
141
  this.migrations = options.migrations;
142
+ this.encodeData = options.encodeData;
143
+ this.decodeData = options.decodeData;
140
144
  }
141
145
  /**
142
146
  * Loads the data saved in persistent storage into the in-memory cache and also returns it.
@@ -152,13 +156,15 @@ var ConfigManager = class {
152
156
  yield this.saveDefaultData();
153
157
  return this.defaultConfig;
154
158
  }
159
+ const isEncoded = yield GM.getValue(`_uucfgenc-${this.id}`, false);
155
160
  if (isNaN(gmFmtVer))
156
161
  yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
157
- let parsed = JSON.parse(gmData);
162
+ let parsed = yield this.deserializeData(gmData, isEncoded);
158
163
  if (gmFmtVer < this.formatVersion && this.migrations)
159
164
  parsed = yield this.runMigrations(parsed, gmFmtVer);
160
- return this.cachedConfig = typeof parsed === "object" ? parsed : void 0;
165
+ return this.cachedConfig = parsed;
161
166
  } catch (err) {
167
+ console.warn("Error while loading config data, resetting it to the default value.", err);
162
168
  yield this.saveDefaultData();
163
169
  return this.defaultConfig;
164
170
  }
@@ -174,10 +180,12 @@ var ConfigManager = class {
174
180
  /** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
175
181
  setData(data) {
176
182
  this.cachedConfig = data;
183
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
177
184
  return new Promise((resolve) => __async(this, null, function* () {
178
185
  yield Promise.all([
179
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(data)),
180
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
186
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(data, useEncoding)),
187
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
188
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
181
189
  ]);
182
190
  resolve();
183
191
  }));
@@ -186,10 +194,12 @@ var ConfigManager = class {
186
194
  saveDefaultData() {
187
195
  return __async(this, null, function* () {
188
196
  this.cachedConfig = this.defaultConfig;
197
+ const useEncoding = Boolean(this.encodeData && this.decodeData);
189
198
  return new Promise((resolve) => __async(this, null, function* () {
190
199
  yield Promise.all([
191
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultConfig)),
192
- GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
200
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(this.defaultConfig, useEncoding)),
201
+ GM.setValue(`_uucfgver-${this.id}`, this.formatVersion),
202
+ GM.setValue(`_uucfgenc-${this.id}`, useEncoding)
193
203
  ]);
194
204
  resolve();
195
205
  }));
@@ -206,7 +216,8 @@ var ConfigManager = class {
206
216
  return __async(this, null, function* () {
207
217
  yield Promise.all([
208
218
  GM.deleteValue(`_uucfg-${this.id}`),
209
- GM.deleteValue(`_uucfgver-${this.id}`)
219
+ GM.deleteValue(`_uucfgver-${this.id}`),
220
+ GM.deleteValue(`_uucfgenc-${this.id}`)
210
221
  ]);
211
222
  });
212
223
  }
@@ -226,17 +237,41 @@ var ConfigManager = class {
226
237
  newData = migRes instanceof Promise ? yield migRes : migRes;
227
238
  lastFmtVer = oldFmtVer = ver;
228
239
  } catch (err) {
229
- console.error(`Error while running migration function for format version ${fmtVer}:`, err);
240
+ console.error(`Error while running migration function for format version '${fmtVer}' - resetting to the default value.`, err);
241
+ yield this.saveDefaultData();
242
+ return this.getData();
230
243
  }
231
244
  }
232
245
  }
233
246
  yield Promise.all([
234
- GM.setValue(`_uucfg-${this.id}`, JSON.stringify(newData)),
235
- GM.setValue(`_uucfgver-${this.id}`, lastFmtVer)
247
+ GM.setValue(`_uucfg-${this.id}`, yield this.serializeData(newData)),
248
+ GM.setValue(`_uucfgver-${this.id}`, lastFmtVer),
249
+ GM.setValue(`_uucfgenc-${this.id}`, Boolean(this.encodeData && this.decodeData))
236
250
  ]);
237
251
  return newData;
238
252
  });
239
253
  }
254
+ /** Serializes the data using the optional this.encodeData() and returns it as a string */
255
+ serializeData(data, useEncoding = true) {
256
+ return __async(this, null, function* () {
257
+ const stringData = JSON.stringify(data);
258
+ if (!this.encodeData || !this.decodeData || !useEncoding)
259
+ return stringData;
260
+ const encRes = this.encodeData(stringData);
261
+ if (encRes instanceof Promise)
262
+ return yield encRes;
263
+ return encRes;
264
+ });
265
+ }
266
+ /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
267
+ deserializeData(data, useEncoding = true) {
268
+ return __async(this, null, function* () {
269
+ let decRes = this.decodeData && this.encodeData && useEncoding ? this.decodeData(data) : void 0;
270
+ if (decRes instanceof Promise)
271
+ decRes = yield decRes;
272
+ return JSON.parse(decRes != null ? decRes : data);
273
+ });
274
+ }
240
275
  /** Copies a JSON-compatible object and loses its internal references */
241
276
  deepCopy(obj) {
242
277
  return JSON.parse(JSON.stringify(obj));
@@ -382,7 +417,7 @@ function insertValues(input, ...values) {
382
417
  return (_b = (_a = values[argIndex]) != null ? _a : match) == null ? void 0 : _b.toString();
383
418
  });
384
419
  }
385
- function compress(input, compressionFormat, outputType = "base64") {
420
+ function compress(input, compressionFormat, outputType = "string") {
386
421
  return __async(this, null, function* () {
387
422
  const byteArray = typeof input === "string" ? new TextEncoder().encode(input) : input;
388
423
  const comp = new CompressionStream(compressionFormat);
@@ -3,7 +3,7 @@ type MigrationFunc = (oldData: any) => any | Promise<any>;
3
3
  /** Dictionary of format version numbers and the function that migrates to them from the previous whole integer */
4
4
  export type ConfigMigrationsDict = Record<number, MigrationFunc>;
5
5
  /** Options for the ConfigManager instance */
6
- export interface ConfigManagerOptions<TData> {
6
+ export type ConfigManagerOptions<TData> = {
7
7
  /** A unique internal ID for this configuration - choose wisely as changing it is not supported yet. */
8
8
  id: string;
9
9
  /**
@@ -28,7 +28,27 @@ export interface ConfigManagerOptions<TData> {
28
28
  * If the current format version is not in the dictionary, no migrations will be run.
29
29
  */
30
30
  migrations?: ConfigMigrationsDict;
31
- }
31
+ } & ({
32
+ /**
33
+ * Function to use to encode the data prior to saving it in persistent storage.
34
+ * If this is specified, make sure to declare {@linkcode decodeData()} as well.
35
+ *
36
+ * You can make use of UserUtils' [`compress()`](https://github.com/Sv443-Network/UserUtils?tab=readme-ov-file#compress) function here to make the data use up less space at the cost of a little bit of performance.
37
+ * @param data The input data as a serialized object (JSON string)
38
+ */
39
+ encodeData: (data: string) => string | Promise<string>;
40
+ /**
41
+ * Function to use to decode the data after reading it from persistent storage.
42
+ * If this is specified, make sure to declare {@linkcode encodeData()} as well.
43
+ *
44
+ * You can make use of UserUtils' [`decompress()`](https://github.com/Sv443-Network/UserUtils?tab=readme-ov-file#decompress) function here to make the data use up less space at the cost of a little bit of performance.
45
+ * @returns The resulting data as a valid serialized object (JSON string)
46
+ */
47
+ decodeData: (data: string) => string | Promise<string>;
48
+ } | {
49
+ encodeData?: never;
50
+ decodeData?: never;
51
+ });
32
52
  /**
33
53
  * Manages a user configuration that is cached in memory and persistently saved across sessions.
34
54
  * 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.
@@ -44,6 +64,8 @@ export declare class ConfigManager<TData = any> {
44
64
  readonly defaultConfig: TData;
45
65
  private cachedConfig;
46
66
  private migrations?;
67
+ private encodeData;
68
+ private decodeData;
47
69
  /**
48
70
  * Creates an instance of ConfigManager to manage a user configuration that is cached in memory and persistently saved across sessions.
49
71
  * 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.
@@ -80,6 +102,10 @@ export declare class ConfigManager<TData = any> {
80
102
  deleteConfig(): Promise<void>;
81
103
  /** Runs all necessary migration functions consecutively - may be overwritten in a subclass */
82
104
  protected runMigrations(oldData: any, oldFmtVer: number): Promise<TData>;
105
+ /** Serializes the data using the optional this.encodeData() and returns it as a string */
106
+ private serializeData;
107
+ /** Deserializes the data using the optional this.decodeData() and returns it as a JSON object */
108
+ private deserializeData;
83
109
  /** Copies a JSON-compatible object and loses its internal references */
84
110
  private deepCopy;
85
111
  }
@@ -1,4 +1,4 @@
1
- /** Represents any value that is either a string itself or can be converted to one (implicitly or explicitly) because it has a toString() method */
1
+ /** Represents any value that is either a string itself or can be converted to one (implicitly and explicitly) because it has a toString() method */
2
2
  export type Stringifiable = string | {
3
3
  toString(): string;
4
4
  };
@@ -43,7 +43,7 @@ export declare function fetchAdvanced(input: RequestInfo | URL, options?: FetchA
43
43
  */
44
44
  export declare function insertValues(input: string, ...values: Stringifiable[]): string;
45
45
  /** Compresses a string or an ArrayBuffer using the provided {@linkcode compressionFormat} and returns it as a base64 string */
46
- export declare function compress(input: string | ArrayBuffer, compressionFormat: CompressionFormat, outputType?: "base64"): Promise<string>;
46
+ export declare function compress(input: string | ArrayBuffer, compressionFormat: CompressionFormat, outputType?: "string"): Promise<string>;
47
47
  /** Compresses a string or an ArrayBuffer using the provided {@linkcode compressionFormat} and returns it as an ArrayBuffer */
48
48
  export declare function compress(input: string | ArrayBuffer, compressionFormat: CompressionFormat, outputType: "arrayBuffer"): Promise<ArrayBuffer>;
49
49
  /** Decompresses a previously compressed base64 string or ArrayBuffer, with the format passed by {@linkcode compressionFormat}, converted to a string */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
- "version": "4.2.1",
3
+ "version": "5.0.0",
4
4
  "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",