@sv443-network/userutils 1.1.0 → 1.1.2
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 +12 -0
- package/README.md +10 -9
- package/dist/index.global.js +443 -0
- package/dist/index.js +426 -28
- package/dist/index.mjs +400 -2
- package/dist/lib/config.d.ts +4 -4
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,401 @@
|
|
|
1
|
-
var
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __publicField = (obj, key, value) => {
|
|
21
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
24
|
+
var __async = (__this, __arguments, generator) => {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
var fulfilled = (value) => {
|
|
27
|
+
try {
|
|
28
|
+
step(generator.next(value));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
reject(e);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var rejected = (value) => {
|
|
34
|
+
try {
|
|
35
|
+
step(generator.throw(value));
|
|
36
|
+
} catch (e) {
|
|
37
|
+
reject(e);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
41
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
2
44
|
|
|
3
|
-
|
|
45
|
+
// lib/math.ts
|
|
46
|
+
function clamp(value, min, max) {
|
|
47
|
+
return Math.max(Math.min(value, max), min);
|
|
48
|
+
}
|
|
49
|
+
function mapRange(value, range_1_min, range_1_max, range_2_min, range_2_max) {
|
|
50
|
+
if (Number(range_1_min) === 0 && Number(range_2_min) === 0)
|
|
51
|
+
return value * (range_2_max / range_1_max);
|
|
52
|
+
return (value - range_1_min) * ((range_2_max - range_2_min) / (range_1_max - range_1_min)) + range_2_min;
|
|
53
|
+
}
|
|
54
|
+
function randRange(...args) {
|
|
55
|
+
let min, max;
|
|
56
|
+
if (typeof args[0] === "number" && typeof args[1] === "number") {
|
|
57
|
+
[min, max] = args;
|
|
58
|
+
} else if (typeof args[0] === "number" && typeof args[1] !== "number") {
|
|
59
|
+
min = 0;
|
|
60
|
+
max = args[0];
|
|
61
|
+
} else
|
|
62
|
+
throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof args[0]}" and "${typeof args[1]}"`);
|
|
63
|
+
min = Number(min);
|
|
64
|
+
max = Number(max);
|
|
65
|
+
if (isNaN(min) || isNaN(max))
|
|
66
|
+
throw new TypeError(`Parameters "min" and "max" can't be NaN`);
|
|
67
|
+
if (min > max)
|
|
68
|
+
throw new TypeError(`Parameter "min" can't be bigger than "max"`);
|
|
69
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// lib/array.ts
|
|
73
|
+
function randomItem(array) {
|
|
74
|
+
return randomItemIndex(array)[0];
|
|
75
|
+
}
|
|
76
|
+
function randomItemIndex(array) {
|
|
77
|
+
if (array.length === 0)
|
|
78
|
+
return [void 0, void 0];
|
|
79
|
+
const idx = randRange(array.length - 1);
|
|
80
|
+
return [array[idx], idx];
|
|
81
|
+
}
|
|
82
|
+
function takeRandomItem(arr) {
|
|
83
|
+
const [itm, idx] = randomItemIndex(arr);
|
|
84
|
+
if (idx === void 0)
|
|
85
|
+
return void 0;
|
|
86
|
+
arr.splice(idx, 1);
|
|
87
|
+
return itm;
|
|
88
|
+
}
|
|
89
|
+
function randomizeArray(array) {
|
|
90
|
+
const retArray = [...array];
|
|
91
|
+
if (array.length === 0)
|
|
92
|
+
return array;
|
|
93
|
+
for (let i = retArray.length - 1; i > 0; i--) {
|
|
94
|
+
const j = Math.floor(randRange(0, 1e4) / 1e4 * (i + 1));
|
|
95
|
+
[retArray[i], retArray[j]] = [retArray[j], retArray[i]];
|
|
96
|
+
}
|
|
97
|
+
return retArray;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// lib/config.ts
|
|
101
|
+
var ConfigManager = class {
|
|
102
|
+
/**
|
|
103
|
+
* Creates an instance of ConfigManager to manage a user configuration that is cached in memory and persistently saved across sessions.
|
|
104
|
+
* 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.
|
|
105
|
+
*
|
|
106
|
+
* ⚠️ Requires the directives `@grant GM.getValue` and `@grant GM.setValue`
|
|
107
|
+
* ⚠️ Make sure to call `loadData()` at least once after creating an instance, or the returned data will be the same as `options.defaultConfig`
|
|
108
|
+
*
|
|
109
|
+
* @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`
|
|
110
|
+
* @param options The options for this ConfigManager instance
|
|
111
|
+
*/
|
|
112
|
+
constructor(options) {
|
|
113
|
+
__publicField(this, "id");
|
|
114
|
+
__publicField(this, "formatVersion");
|
|
115
|
+
__publicField(this, "defaultConfig");
|
|
116
|
+
__publicField(this, "cachedConfig");
|
|
117
|
+
__publicField(this, "migrations");
|
|
118
|
+
this.id = options.id;
|
|
119
|
+
this.formatVersion = options.formatVersion;
|
|
120
|
+
this.defaultConfig = options.defaultConfig;
|
|
121
|
+
this.cachedConfig = options.defaultConfig;
|
|
122
|
+
this.migrations = options.migrations;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Loads the data saved in persistent storage into the in-memory cache and also returns it.
|
|
126
|
+
* Automatically populates persistent storage with default data if it doesn't contain any data yet.
|
|
127
|
+
* Also runs all necessary migration functions if the data format has changed since the last time the data was saved.
|
|
128
|
+
*/
|
|
129
|
+
loadData() {
|
|
130
|
+
return __async(this, null, function* () {
|
|
131
|
+
try {
|
|
132
|
+
const gmData = yield GM.getValue(`_uucfg-${this.id}`, this.defaultConfig);
|
|
133
|
+
let gmFmtVer = Number(yield GM.getValue(`_uucfgver-${this.id}`));
|
|
134
|
+
if (typeof gmData !== "string") {
|
|
135
|
+
yield this.saveDefaultData();
|
|
136
|
+
return this.defaultConfig;
|
|
137
|
+
}
|
|
138
|
+
if (isNaN(gmFmtVer))
|
|
139
|
+
yield GM.setValue(`_uucfgver-${this.id}`, gmFmtVer = this.formatVersion);
|
|
140
|
+
let parsed = JSON.parse(gmData);
|
|
141
|
+
if (gmFmtVer < this.formatVersion && this.migrations)
|
|
142
|
+
parsed = yield this.runMigrations(parsed, gmFmtVer);
|
|
143
|
+
return this.cachedConfig = typeof parsed === "object" ? parsed : void 0;
|
|
144
|
+
} catch (err) {
|
|
145
|
+
yield this.saveDefaultData();
|
|
146
|
+
return this.defaultConfig;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/** Returns a copy of the data from the in-memory cache. Use `loadData()` to get fresh data from persistent storage (usually not necessary since the cache should always exactly reflect persistent storage). */
|
|
151
|
+
getData() {
|
|
152
|
+
return this.deepCopy(this.cachedConfig);
|
|
153
|
+
}
|
|
154
|
+
/** Saves the data synchronously to the in-memory cache and asynchronously to the persistent storage */
|
|
155
|
+
setData(data) {
|
|
156
|
+
this.cachedConfig = data;
|
|
157
|
+
return new Promise((resolve) => __async(this, null, function* () {
|
|
158
|
+
yield Promise.all([
|
|
159
|
+
GM.setValue(`_uucfg-${this.id}`, JSON.stringify(data)),
|
|
160
|
+
GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
|
|
161
|
+
]);
|
|
162
|
+
resolve();
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
/** Saves the default configuration data passed in the constructor synchronously to the in-memory cache and asynchronously to persistent storage */
|
|
166
|
+
saveDefaultData() {
|
|
167
|
+
return __async(this, null, function* () {
|
|
168
|
+
this.cachedConfig = this.defaultConfig;
|
|
169
|
+
return new Promise((resolve) => __async(this, null, function* () {
|
|
170
|
+
yield Promise.all([
|
|
171
|
+
GM.setValue(`_uucfg-${this.id}`, JSON.stringify(this.defaultConfig)),
|
|
172
|
+
GM.setValue(`_uucfgver-${this.id}`, this.formatVersion)
|
|
173
|
+
]);
|
|
174
|
+
resolve();
|
|
175
|
+
}));
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Call this method to clear all persistently stored data associated with this ConfigManager instance.
|
|
180
|
+
* The in-memory cache will be left untouched, so you may still access the data with `getData()`.
|
|
181
|
+
* Calling `loadData()` or `setData()` after this method was called will recreate persistent storage with the cached or default data.
|
|
182
|
+
*
|
|
183
|
+
* ⚠️ This requires the additional directive `@grant GM.deleteValue`
|
|
184
|
+
*/
|
|
185
|
+
deleteConfig() {
|
|
186
|
+
return __async(this, null, function* () {
|
|
187
|
+
yield Promise.all([
|
|
188
|
+
GM.deleteValue(`_uucfg-${this.id}`),
|
|
189
|
+
GM.deleteValue(`_uucfgver-${this.id}`)
|
|
190
|
+
]);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** Runs all necessary migration functions consecutively - may be overwritten in a subclass */
|
|
194
|
+
runMigrations(oldData, oldFmtVer) {
|
|
195
|
+
return __async(this, null, function* () {
|
|
196
|
+
if (!this.migrations)
|
|
197
|
+
return oldData;
|
|
198
|
+
let newData = oldData;
|
|
199
|
+
const sortedMigrations = Object.entries(this.migrations).sort(([a], [b]) => Number(a) - Number(b));
|
|
200
|
+
let lastFmtVer = oldFmtVer;
|
|
201
|
+
for (const [fmtVer, migrationFunc] of sortedMigrations) {
|
|
202
|
+
const ver = Number(fmtVer);
|
|
203
|
+
if (oldFmtVer < this.formatVersion && oldFmtVer < ver) {
|
|
204
|
+
try {
|
|
205
|
+
const migRes = migrationFunc(newData);
|
|
206
|
+
newData = migRes instanceof Promise ? yield migRes : migRes;
|
|
207
|
+
lastFmtVer = oldFmtVer = ver;
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.error(`Error while running migration function for format version ${fmtVer}:`, err);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
yield Promise.all([
|
|
214
|
+
GM.setValue(`_uucfg-${this.id}`, JSON.stringify(newData)),
|
|
215
|
+
GM.setValue(`_uucfgver-${this.id}`, lastFmtVer)
|
|
216
|
+
]);
|
|
217
|
+
return newData;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/** Copies a JSON-compatible object and loses its internal references */
|
|
221
|
+
deepCopy(obj) {
|
|
222
|
+
return JSON.parse(JSON.stringify(obj));
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// lib/dom.ts
|
|
227
|
+
function getUnsafeWindow() {
|
|
228
|
+
try {
|
|
229
|
+
return unsafeWindow;
|
|
230
|
+
} catch (e) {
|
|
231
|
+
return window;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function insertAfter(beforeElement, afterElement) {
|
|
235
|
+
var _a;
|
|
236
|
+
(_a = beforeElement.parentNode) == null ? void 0 : _a.insertBefore(afterElement, beforeElement.nextSibling);
|
|
237
|
+
return afterElement;
|
|
238
|
+
}
|
|
239
|
+
function addParent(element, newParent) {
|
|
240
|
+
const oldParent = element.parentNode;
|
|
241
|
+
if (!oldParent)
|
|
242
|
+
throw new Error("Element doesn't have a parent node");
|
|
243
|
+
oldParent.replaceChild(newParent, element);
|
|
244
|
+
newParent.appendChild(element);
|
|
245
|
+
return newParent;
|
|
246
|
+
}
|
|
247
|
+
function addGlobalStyle(style) {
|
|
248
|
+
const styleElem = document.createElement("style");
|
|
249
|
+
styleElem.innerHTML = style;
|
|
250
|
+
document.head.appendChild(styleElem);
|
|
251
|
+
}
|
|
252
|
+
function preloadImages(srcUrls, rejects = false) {
|
|
253
|
+
const promises = srcUrls.map((src) => new Promise((res, rej) => {
|
|
254
|
+
const image = new Image();
|
|
255
|
+
image.src = src;
|
|
256
|
+
image.addEventListener("load", () => res(image));
|
|
257
|
+
image.addEventListener("error", (evt) => rejects && rej(evt));
|
|
258
|
+
}));
|
|
259
|
+
return Promise.allSettled(promises);
|
|
260
|
+
}
|
|
261
|
+
function openInNewTab(href) {
|
|
262
|
+
const openElem = document.createElement("a");
|
|
263
|
+
Object.assign(openElem, {
|
|
264
|
+
className: "userutils-open-in-new-tab",
|
|
265
|
+
target: "_blank",
|
|
266
|
+
rel: "noopener noreferrer",
|
|
267
|
+
href
|
|
268
|
+
});
|
|
269
|
+
openElem.style.display = "none";
|
|
270
|
+
document.body.appendChild(openElem);
|
|
271
|
+
openElem.click();
|
|
272
|
+
setTimeout(openElem.remove, 50);
|
|
273
|
+
}
|
|
274
|
+
function interceptEvent(eventObject, eventName, predicate) {
|
|
275
|
+
if (typeof Error.stackTraceLimit === "number" && Error.stackTraceLimit < 1e3) {
|
|
276
|
+
Error.stackTraceLimit = 1e3;
|
|
277
|
+
}
|
|
278
|
+
(function(original) {
|
|
279
|
+
eventObject.__proto__.addEventListener = function(...args) {
|
|
280
|
+
var _a, _b;
|
|
281
|
+
const origListener = typeof args[1] === "function" ? args[1] : (_b = (_a = args[1]) == null ? void 0 : _a.handleEvent) != null ? _b : () => void 0;
|
|
282
|
+
args[1] = function(...a) {
|
|
283
|
+
if (args[0] === eventName && predicate(Array.isArray(a) ? a[0] : a))
|
|
284
|
+
return;
|
|
285
|
+
else
|
|
286
|
+
return origListener.apply(this, a);
|
|
287
|
+
};
|
|
288
|
+
original.apply(this, args);
|
|
289
|
+
};
|
|
290
|
+
})(eventObject.__proto__.addEventListener);
|
|
291
|
+
}
|
|
292
|
+
function interceptWindowEvent(eventName, predicate) {
|
|
293
|
+
return interceptEvent(getUnsafeWindow(), eventName, predicate);
|
|
294
|
+
}
|
|
295
|
+
function amplifyMedia(mediaElement, multiplier = 1) {
|
|
296
|
+
const context = new (window.AudioContext || window.webkitAudioContext)();
|
|
297
|
+
const result = {
|
|
298
|
+
mediaElement,
|
|
299
|
+
amplify: (multiplier2) => {
|
|
300
|
+
result.gain.gain.value = multiplier2;
|
|
301
|
+
},
|
|
302
|
+
getAmpLevel: () => result.gain.gain.value,
|
|
303
|
+
context,
|
|
304
|
+
source: context.createMediaElementSource(mediaElement),
|
|
305
|
+
gain: context.createGain()
|
|
306
|
+
};
|
|
307
|
+
result.source.connect(result.gain);
|
|
308
|
+
result.gain.connect(context.destination);
|
|
309
|
+
result.amplify(multiplier);
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
function isScrollable(element) {
|
|
313
|
+
const { overflowX, overflowY } = getComputedStyle(element);
|
|
314
|
+
return {
|
|
315
|
+
vertical: (overflowY === "scroll" || overflowY === "auto") && element.scrollHeight > element.clientHeight,
|
|
316
|
+
horizontal: (overflowX === "scroll" || overflowX === "auto") && element.scrollWidth > element.clientWidth
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// lib/misc.ts
|
|
321
|
+
function autoPlural(word, num) {
|
|
322
|
+
if (Array.isArray(num) || num instanceof NodeList)
|
|
323
|
+
num = num.length;
|
|
324
|
+
return `${word}${num === 1 ? "" : "s"}`;
|
|
325
|
+
}
|
|
326
|
+
function pauseFor(time) {
|
|
327
|
+
return new Promise((res) => {
|
|
328
|
+
setTimeout(() => res(), time);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
function debounce(func, timeout = 300) {
|
|
332
|
+
let timer;
|
|
333
|
+
return function(...args) {
|
|
334
|
+
clearTimeout(timer);
|
|
335
|
+
timer = setTimeout(() => func.apply(this, args), timeout);
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function fetchAdvanced(_0) {
|
|
339
|
+
return __async(this, arguments, function* (url, options = {}) {
|
|
340
|
+
const { timeout = 1e4 } = options;
|
|
341
|
+
const controller = new AbortController();
|
|
342
|
+
const id = setTimeout(() => controller.abort(), timeout);
|
|
343
|
+
const res = yield fetch(url, __spreadProps(__spreadValues({}, options), {
|
|
344
|
+
signal: controller.signal
|
|
345
|
+
}));
|
|
346
|
+
clearTimeout(id);
|
|
347
|
+
return res;
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// lib/onSelector.ts
|
|
352
|
+
var selectorMap = /* @__PURE__ */ new Map();
|
|
353
|
+
function onSelector(selector, options) {
|
|
354
|
+
let selectorMapItems = [];
|
|
355
|
+
if (selectorMap.has(selector))
|
|
356
|
+
selectorMapItems = selectorMap.get(selector);
|
|
357
|
+
selectorMapItems.push(options);
|
|
358
|
+
selectorMap.set(selector, selectorMapItems);
|
|
359
|
+
checkSelectorExists(selector, selectorMapItems);
|
|
360
|
+
}
|
|
361
|
+
function removeOnSelector(selector) {
|
|
362
|
+
return selectorMap.delete(selector);
|
|
363
|
+
}
|
|
364
|
+
function checkSelectorExists(selector, options) {
|
|
365
|
+
const deleteIndices = [];
|
|
366
|
+
options.forEach((option, i) => {
|
|
367
|
+
try {
|
|
368
|
+
const elements = option.all ? document.querySelectorAll(selector) : document.querySelector(selector);
|
|
369
|
+
if (elements !== null && elements instanceof NodeList && elements.length > 0 || elements !== null) {
|
|
370
|
+
option.listener(elements);
|
|
371
|
+
if (!option.continuous)
|
|
372
|
+
deleteIndices.push(i);
|
|
373
|
+
}
|
|
374
|
+
} catch (err) {
|
|
375
|
+
console.error(`Couldn't call listener for selector '${selector}'`, err);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
if (deleteIndices.length > 0) {
|
|
379
|
+
const newOptsArray = options.filter((_, i) => !deleteIndices.includes(i));
|
|
380
|
+
if (newOptsArray.length === 0)
|
|
381
|
+
selectorMap.delete(selector);
|
|
382
|
+
else {
|
|
383
|
+
selectorMap.set(selector, newOptsArray);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function initOnSelector(options = {}) {
|
|
388
|
+
const observer = new MutationObserver(() => {
|
|
389
|
+
for (const [selector, options2] of selectorMap.entries())
|
|
390
|
+
checkSelectorExists(selector, options2);
|
|
391
|
+
});
|
|
392
|
+
observer.observe(document.body, __spreadValues({
|
|
393
|
+
subtree: true,
|
|
394
|
+
childList: true
|
|
395
|
+
}, options));
|
|
396
|
+
}
|
|
397
|
+
function getSelectorMap() {
|
|
398
|
+
return selectorMap;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export { ConfigManager, addGlobalStyle, addParent, amplifyMedia, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, isScrollable, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, randomItem, randomItemIndex, randomizeArray, removeOnSelector, takeRandomItem };
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Function that takes the data in the old format and returns the data in the new format. Also supports an asynchronous migration. */
|
|
2
|
-
type MigrationFunc =
|
|
2
|
+
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
|
-
type
|
|
4
|
+
export type ConfigMigrationsDict = Record<number, MigrationFunc>;
|
|
5
5
|
/** Options for the ConfigManager instance */
|
|
6
6
|
export interface ConfigManagerOptions<TData> {
|
|
7
7
|
/** A unique internal ID for this configuration - choose wisely as changing it is not supported yet. */
|
|
@@ -15,7 +15,7 @@ export interface ConfigManagerOptions<TData> {
|
|
|
15
15
|
defaultConfig: TData;
|
|
16
16
|
/**
|
|
17
17
|
* An incremental, whole integer version number of the current format of config data.
|
|
18
|
-
* If the format of the data is changed, this number should be incremented, in which case all necessary functions of the migrations dictionary will be run consecutively.
|
|
18
|
+
* 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.
|
|
19
19
|
*
|
|
20
20
|
* ⚠️ Never decrement this number and optimally don't skip any numbers either!
|
|
21
21
|
*/
|
|
@@ -27,7 +27,7 @@ export interface ConfigManagerOptions<TData> {
|
|
|
27
27
|
* The functions will be run in order from the oldest to the newest version.
|
|
28
28
|
* If the current format version is not in the dictionary, no migrations will be run.
|
|
29
29
|
*/
|
|
30
|
-
migrations?:
|
|
30
|
+
migrations?: ConfigMigrationsDict;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Manages a user configuration that is cached in memory and persistently saved across sessions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
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",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"build-types": "tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
11
11
|
"build-common": "tsup lib/index.ts --format cjs,esm --clean --treeshake",
|
|
12
12
|
"build-global": "tsup lib/index.ts --format cjs,esm,iife --treeshake --onSuccess \"npm run post-build-global\"",
|
|
13
|
-
"build": "npm run build-common --
|
|
13
|
+
"build": "npm run build-common -- && npm run build-types",
|
|
14
14
|
"post-build-global": "npm run node-ts -- ./tools/post-build-global.mts",
|
|
15
15
|
"dev": "npm run build-common -- --sourcemap --watch --onSuccess \"npm run build-types\"",
|
|
16
|
-
"publish-package": "
|
|
16
|
+
"publish-package": "changeset publish",
|
|
17
17
|
"node-ts": "node --no-warnings=ExperimentalWarning --enable-source-maps --loader ts-node/esm"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|