@choksheak/ts-utils 0.3.0 → 0.3.1
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/arrayBuffer.d.ts +4 -2
- package/assert.d.ts +3 -1
- package/average.d.ts +3 -1
- package/base64Url.d.ts +4 -2
- package/dateTimeStr.d.ts +15 -13
- package/duration.d.ts +15 -13
- package/isEmpty.d.ts +3 -1
- package/iterators.cjs +34 -0
- package/iterators.d.mts +4 -0
- package/iterators.d.ts +4 -0
- package/iterators.min.cjs +2 -0
- package/iterators.min.cjs.map +1 -0
- package/iterators.min.mjs +2 -0
- package/iterators.min.mjs.map +1 -0
- package/iterators.mjs +9 -0
- package/kvStore.cjs +103 -71
- package/kvStore.d.mts +91 -49
- package/kvStore.d.ts +95 -50
- package/kvStore.min.cjs +1 -1
- package/kvStore.min.cjs.map +1 -1
- package/kvStore.min.mjs +1 -1
- package/kvStore.min.mjs.map +1 -1
- package/kvStore.mjs +99 -66
- package/localStore.cjs +267 -0
- package/localStore.d.mts +119 -0
- package/localStore.d.ts +119 -0
- package/localStore.min.cjs +2 -0
- package/localStore.min.cjs.map +1 -0
- package/localStore.min.mjs +2 -0
- package/localStore.min.mjs.map +1 -0
- package/localStore.mjs +235 -0
- package/logging.d.ts +4 -2
- package/nonEmpty.d.ts +3 -1
- package/nonNil.d.ts +3 -1
- package/package.json +48 -15
- package/round.d.ts +4 -2
- package/safeBtoa.d.ts +3 -1
- package/safeParseFloat.d.ts +3 -1
- package/safeParseInt.d.ts +3 -1
- package/sha256.d.ts +3 -1
- package/sleep.d.ts +3 -1
- package/storageAdapter.cjs +18 -0
- package/storageAdapter.d.mts +33 -0
- package/storageAdapter.d.ts +33 -0
- package/storageAdapter.min.cjs +2 -0
- package/storageAdapter.min.cjs.map +1 -0
- package/storageAdapter.min.mjs +1 -0
- package/storageAdapter.min.mjs.map +1 -0
- package/storageAdapter.mjs +0 -0
- package/sum.d.ts +3 -1
- package/timeConstants.d.ts +16 -14
- package/timer.d.ts +4 -2
- package/localStorageCache.cjs +0 -119
- package/localStorageCache.d.mts +0 -57
- package/localStorageCache.d.ts +0 -55
- package/localStorageCache.min.cjs +0 -2
- package/localStorageCache.min.cjs.map +0 -1
- package/localStorageCache.min.mjs +0 -2
- package/localStorageCache.min.mjs.map +0 -1
- package/localStorageCache.mjs +0 -92
package/arrayBuffer.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Encode an input ArrayBuffer into a hex string.
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
declare function arrayBufferToHex(buffer: ArrayBuffer): string;
|
|
5
5
|
/**
|
|
6
6
|
* Encode an input ArrayBuffer into a base64 string.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
9
|
+
|
|
10
|
+
export { arrayBufferToBase64, arrayBufferToHex };
|
package/assert.d.ts
CHANGED
|
@@ -2,4 +2,6 @@
|
|
|
2
2
|
* Type asserts that `t` is truthy. Throws an error with `errorMessage` if
|
|
3
3
|
* `t` is falsy.
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
declare function assert<T>(t: T | null | undefined | "" | 0 | -0 | 0n | false | typeof NaN, errorMessage?: string): asserts t is T;
|
|
6
|
+
|
|
7
|
+
export { assert };
|
package/average.d.ts
CHANGED
|
@@ -2,4 +2,6 @@
|
|
|
2
2
|
* Average all the numbers together in the given array. Treats null, undefined
|
|
3
3
|
* and NaN as zero.
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
declare function average(numbers: (number | null | undefined)[]): number;
|
|
6
|
+
|
|
7
|
+
export { average };
|
package/base64Url.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Convert a base64 string to a base64url string.
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
declare function base64ToBase64URL(base64: string): string;
|
|
5
5
|
/**
|
|
6
6
|
* Convert a base64url string to a base64 string.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
declare function base64UrlToBase64(base64Url: string): string;
|
|
9
|
+
|
|
10
|
+
export { base64ToBase64URL, base64UrlToBase64 };
|
package/dateTimeStr.d.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
type AnyDateTime = number | Date | string;
|
|
2
2
|
/**
|
|
3
3
|
* Convert a number (epoch seconds or milliseconds), string (parseable
|
|
4
4
|
* date/time or epoch seconds or milliseconds), or Date object (no conversion)
|
|
5
5
|
* into a Date object.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
declare function toDate(ts: AnyDateTime): Date;
|
|
8
8
|
/**
|
|
9
9
|
* Returns a date in yyyy-MM format. E.g. '2000-01'.
|
|
10
10
|
*
|
|
11
11
|
* @param dt Specify a date object or default to the current date.
|
|
12
12
|
* @param separator Defaults to '-'.
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
declare function yyyyMm(dt?: Date, separator?: string): string;
|
|
15
15
|
/**
|
|
16
16
|
* Returns a date in yyyy-MM-dd format. E.g. '2000-01-02'.
|
|
17
17
|
*
|
|
18
18
|
* @param dt Specify a date object or default to the current date.
|
|
19
19
|
* @param separator Defaults to '-'.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
declare function yyyyMmDd(dt?: Date, separator?: string): string;
|
|
22
22
|
/**
|
|
23
23
|
* Returns a date in hh:mm format. E.g. '01:02'.
|
|
24
24
|
*
|
|
25
25
|
* @param dt Specify a date object or default to the current date/time.
|
|
26
26
|
* @param separator Defaults to ':'.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
declare function hhMm(dt?: Date, separator?: string): string;
|
|
29
29
|
/**
|
|
30
30
|
* Returns a date in hh:mm:ss format. E.g. '01:02:03'.
|
|
31
31
|
*
|
|
32
32
|
* @param dt Specify a date object or default to the current date/time.
|
|
33
33
|
* @param separator Defaults to ':'.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
declare function hhMmSs(dt?: Date, separator?: string): string;
|
|
36
36
|
/**
|
|
37
37
|
* Returns a date in hh:mm:ss.SSS format. E.g. '01:02:03.004'.
|
|
38
38
|
*
|
|
@@ -40,44 +40,46 @@ export declare function hhMmSs(dt?: Date, separator?: string): string;
|
|
|
40
40
|
* @param timeSeparator Separator for hh/mm/ss. Defaults to ':'.
|
|
41
41
|
* @param msSeparator Separator before SSS. Defaults to '.'.
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
declare function hhMmSsMs(dt?: Date, timeSeparator?: string, msSeparator?: string): string;
|
|
44
44
|
/**
|
|
45
45
|
* Returns the timezone string for the given date. E.g. '+8', '-3.5'.
|
|
46
46
|
* Returns 'Z' for UTC.
|
|
47
47
|
*
|
|
48
48
|
* @param dt Specify a date object or default to the current date/time.
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
declare function tzShort(dt?: Date): string;
|
|
51
51
|
/**
|
|
52
52
|
* Returns the long month name, zero-indexed. E.g. 0 for 'January'.
|
|
53
53
|
*
|
|
54
54
|
* @param month Zero-indexed month.
|
|
55
55
|
* @param locales Specify the locale, e.g. 'en-US', new Intl.Locale("en-US").
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
declare function getLongMonthNameZeroIndexed(month: number, locales?: Intl.LocalesArgument): string;
|
|
58
58
|
/**
|
|
59
59
|
* Returns the long month name, one-indexed. E.g. 1 for 'January'.
|
|
60
60
|
*
|
|
61
61
|
* @param month One-indexed month.
|
|
62
62
|
* @param locales Specify the locale, e.g. 'en-US', new Intl.Locale("en-US").
|
|
63
63
|
*/
|
|
64
|
-
|
|
64
|
+
declare function getLongMonthNameOneIndexed(month: number, locales?: Intl.LocalesArgument): string;
|
|
65
65
|
/**
|
|
66
66
|
* Returns the short month name, zero-indexed. E.g. 0 for 'Jan'.
|
|
67
67
|
*
|
|
68
68
|
* @param month Zero-indexed month.
|
|
69
69
|
* @param locales Specify the locale, e.g. 'en-US', new Intl.Locale("en-US").
|
|
70
70
|
*/
|
|
71
|
-
|
|
71
|
+
declare function getShortMonthNameZeroIndexed(month: number, locales?: Intl.LocalesArgument): string;
|
|
72
72
|
/**
|
|
73
73
|
* Returns the short month name, one-indexed. E.g. 1 for 'Jan'.
|
|
74
74
|
*
|
|
75
75
|
* @param month One-indexed month.
|
|
76
76
|
* @param locales Specify the locale, e.g. 'en-US', new Intl.Locale("en-US").
|
|
77
77
|
*/
|
|
78
|
-
|
|
78
|
+
declare function getShortMonthNameOneIndexed(month: number, locales?: Intl.LocalesArgument): string;
|
|
79
79
|
/**
|
|
80
80
|
* Returns a human-readable string date/time like '2025-01-01 22:31:16Z'.
|
|
81
81
|
* Excludes the milliseconds assuming it is not necessary for display.
|
|
82
82
|
*/
|
|
83
|
-
|
|
83
|
+
declare function getDisplayDateTime(ts: AnyDateTime): string;
|
|
84
|
+
|
|
85
|
+
export { type AnyDateTime, getDisplayDateTime, getLongMonthNameOneIndexed, getLongMonthNameZeroIndexed, getShortMonthNameOneIndexed, getShortMonthNameZeroIndexed, hhMm, hhMmSs, hhMmSsMs, toDate, tzShort, yyyyMm, yyyyMmDd };
|
package/duration.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* from this file. Weeks have fixed durations, but are excluded because we
|
|
7
7
|
* use days as the max duration supported.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
type Duration = {
|
|
10
10
|
days?: number;
|
|
11
11
|
hours?: number;
|
|
12
12
|
minutes?: number;
|
|
@@ -16,11 +16,11 @@ export type Duration = {
|
|
|
16
16
|
/**
|
|
17
17
|
* One of: days, hours, minutes, seconds, milliseconds
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
type DurationType = keyof Duration;
|
|
20
20
|
/**
|
|
21
21
|
* Order in which the duration type appears in the duration string.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
declare const DURATION_TYPE_SEQUENCE: DurationType[];
|
|
24
24
|
/**
|
|
25
25
|
* Follows the same format as Intl.DurationFormat.prototype.format().
|
|
26
26
|
*
|
|
@@ -29,16 +29,16 @@ export declare const DURATION_TYPE_SEQUENCE: DurationType[];
|
|
|
29
29
|
* 7 milliseconds, 8 microseconds, 9 nanoseconds
|
|
30
30
|
* Narrow: 1y 2mo 3w 3d 4h 5m 6s 7ms 8μs 9ns
|
|
31
31
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
type DurationStyle = "short" | "long" | "narrow";
|
|
33
|
+
type DurationSuffixMap = {
|
|
34
34
|
short: string;
|
|
35
35
|
shorts: string;
|
|
36
36
|
long: string;
|
|
37
37
|
longs: string;
|
|
38
38
|
narrow: string;
|
|
39
39
|
};
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
type DurationSuffixType = keyof DurationSuffixMap;
|
|
41
|
+
declare const DURATION_STYLE_SUFFIX_MAP: Record<DurationType, DurationSuffixMap>;
|
|
42
42
|
/**
|
|
43
43
|
* Convert a milliseconds duration into a Duration object. If the given ms is
|
|
44
44
|
* zero, then return an object with a single field of zero with duration type
|
|
@@ -46,31 +46,33 @@ export declare const DURATION_STYLE_SUFFIX_MAP: Record<DurationType, DurationSuf
|
|
|
46
46
|
*
|
|
47
47
|
* @param durationTypeForZero Defaults to 'milliseconds'
|
|
48
48
|
*/
|
|
49
|
-
|
|
49
|
+
declare function msToDuration(ms: number, durationTypeForZero?: DurationType): Duration;
|
|
50
50
|
/**
|
|
51
51
|
* Returns the number of milliseconds for the given duration.
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
declare function durationToMs(duration: Duration): number;
|
|
54
54
|
/**
|
|
55
55
|
* Convenience function to return a duration given an ms or Duration.
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
declare function durationOrMsToMs(duration: number | Duration): number;
|
|
58
58
|
/**
|
|
59
59
|
* Format a given Duration object into a string. If the object has no fields,
|
|
60
60
|
* then returns an empty string.
|
|
61
61
|
*
|
|
62
62
|
* @param style Defaults to 'short'
|
|
63
63
|
*/
|
|
64
|
-
|
|
64
|
+
declare function formatDuration(duration: Duration, style?: DurationStyle): string;
|
|
65
65
|
/**
|
|
66
66
|
* Convert a millisecond duration into a human-readable duration string.
|
|
67
67
|
*
|
|
68
68
|
* @param options.durationTypeForZero - Defaults to 'milliseconds'
|
|
69
69
|
* @param options.style - Defaults to 'short'
|
|
70
70
|
*/
|
|
71
|
-
|
|
71
|
+
declare function readableDuration(ms: number, options?: {
|
|
72
72
|
durationTypeForZero?: DurationType;
|
|
73
73
|
style?: DurationStyle;
|
|
74
74
|
}): string;
|
|
75
75
|
/** A shortened duration string useful for logging timings. */
|
|
76
|
-
|
|
76
|
+
declare function elapsed(ms: number): string;
|
|
77
|
+
|
|
78
|
+
export { DURATION_STYLE_SUFFIX_MAP, DURATION_TYPE_SEQUENCE, type Duration, type DurationStyle, type DurationSuffixMap, type DurationSuffixType, type DurationType, durationOrMsToMs, durationToMs, elapsed, formatDuration, msToDuration, readableDuration };
|
package/isEmpty.d.ts
CHANGED
package/iterators.cjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/iterators.ts
|
|
21
|
+
var iterators_exports = {};
|
|
22
|
+
__export(iterators_exports, {
|
|
23
|
+
concatIterators: () => concatIterators
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(iterators_exports);
|
|
26
|
+
function* concatIterators(...iterators) {
|
|
27
|
+
for (const iterator of iterators) {
|
|
28
|
+
yield* iterator;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
concatIterators
|
|
34
|
+
});
|
package/iterators.d.mts
ADDED
package/iterators.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var n=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var s=(t,o)=>{for(var e in o)n(t,e,{get:o[e],enumerable:!0})},T=(t,o,e,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of f(o))!i.call(t,r)&&r!==e&&n(t,r,{get:()=>o[r],enumerable:!(a=c(o,r))||a.enumerable});return t};var d=t=>T(n({},"__esModule",{value:!0}),t);var p={};s(p,{concatIterators:()=>l});module.exports=d(p);function*l(...t){for(let o of t)yield*o}0&&(module.exports={concatIterators});
|
|
2
|
+
//# sourceMappingURL=iterators.min.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/iterators.ts"],"sourcesContent":["/** Memory-efficient way to concat two or more iterators. */\nexport function* concatIterators<T>(...iterators: Generator<T>[]) {\n for (const iterator of iterators) {\n yield* iterator;\n }\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,IAAA,eAAAC,EAAAH,GACO,SAAUE,KAAsBE,EAA2B,CAChE,QAAWC,KAAYD,EACrB,MAAOC,CAEX","names":["iterators_exports","__export","concatIterators","__toCommonJS","iterators","iterator"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/iterators.ts"],"sourcesContent":["/** Memory-efficient way to concat two or more iterators. */\nexport function* concatIterators<T>(...iterators: Generator<T>[]) {\n for (const iterator of iterators) {\n yield* iterator;\n }\n}\n"],"mappings":"AACO,SAAUA,KAAsBC,EAA2B,CAChE,QAAWC,KAAYD,EACrB,MAAOC,CAEX","names":["concatIterators","iterators","iterator"]}
|
package/iterators.mjs
ADDED
package/kvStore.cjs
CHANGED
|
@@ -20,11 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/kvStore.ts
|
|
21
21
|
var kvStore_exports = {};
|
|
22
22
|
__export(kvStore_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
MILLIS_PER_DAY: () => MILLIS_PER_DAY,
|
|
23
|
+
KvStore: () => KvStore,
|
|
24
|
+
KvStoreConfig: () => KvStoreConfig,
|
|
25
|
+
KvStoreItem: () => KvStoreItem,
|
|
26
|
+
configureKvStore: () => configureKvStore,
|
|
28
27
|
kvStore: () => kvStore,
|
|
29
28
|
kvStoreItem: () => kvStoreItem
|
|
30
29
|
});
|
|
@@ -50,14 +49,32 @@ function durationOrMsToMs(duration) {
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
// src/kvStore.ts
|
|
53
|
-
var
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
var KvStoreConfig = {
|
|
53
|
+
/**
|
|
54
|
+
* Name of the DB in the indexed DB.
|
|
55
|
+
* Updating the DB name will cause all old entries to be gone.
|
|
56
|
+
*/
|
|
57
|
+
dbName: "KVStore",
|
|
58
|
+
/**
|
|
59
|
+
* Version of the DB schema. Most likely you will never want to change this.
|
|
60
|
+
* Updating the version will cause all old entries to be gone.
|
|
61
|
+
*/
|
|
62
|
+
dbVersion: 1,
|
|
63
|
+
/**
|
|
64
|
+
* Name of the store within the indexed DB. Each DB can have multiple stores.
|
|
65
|
+
* In practice, it doesn't matter what you name this to be.
|
|
66
|
+
*/
|
|
67
|
+
storeName: "kvStore",
|
|
68
|
+
/** 30 days in ms. */
|
|
69
|
+
expiryMs: MS_PER_DAY * 30,
|
|
70
|
+
/** Do GC once per day. */
|
|
71
|
+
gcIntervalMs: MS_PER_DAY
|
|
72
|
+
};
|
|
73
|
+
function configureKvStore(config) {
|
|
74
|
+
Object.assign(KvStoreConfig, config);
|
|
75
|
+
}
|
|
59
76
|
function validateStoredObject(obj) {
|
|
60
|
-
if (!obj || typeof obj !== "object" ||
|
|
77
|
+
if (!obj || typeof obj !== "object" || typeof obj.key !== "string" || obj.value === void 0 || typeof obj.storedMs !== "number" || typeof obj.expiryMs !== "number" || Date.now() >= obj.expiryMs) {
|
|
61
78
|
return void 0;
|
|
62
79
|
}
|
|
63
80
|
return obj;
|
|
@@ -68,32 +85,23 @@ function withOnError(request, reject) {
|
|
|
68
85
|
};
|
|
69
86
|
return request;
|
|
70
87
|
}
|
|
71
|
-
var
|
|
72
|
-
constructor(
|
|
73
|
-
this.store = store;
|
|
74
|
-
this.key = key;
|
|
75
|
-
}
|
|
76
|
-
get() {
|
|
77
|
-
return this.store.get(this.key);
|
|
78
|
-
}
|
|
79
|
-
set(t) {
|
|
80
|
-
return this.store.set(this.key, t);
|
|
81
|
-
}
|
|
82
|
-
delete() {
|
|
83
|
-
return this.store.delete(this.key);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
var KVStore = class {
|
|
87
|
-
constructor(dbName, dbVersion, defaultExpiryDeltaMs) {
|
|
88
|
+
var KvStore = class {
|
|
89
|
+
constructor(dbName, options) {
|
|
88
90
|
this.dbName = dbName;
|
|
89
|
-
this.dbVersion = dbVersion;
|
|
90
|
-
this.
|
|
91
|
-
this.
|
|
91
|
+
this.dbVersion = options?.dbVersion ?? KvStoreConfig.dbVersion;
|
|
92
|
+
this.storeName = options?.storeName ?? KvStoreConfig.storeName;
|
|
93
|
+
this.defaultExpiryMs = options?.defaultExpiryMs ? durationOrMsToMs(options.defaultExpiryMs) : KvStoreConfig.expiryMs;
|
|
94
|
+
this.gcIntervalMs = options?.gcIntervalMs ? durationOrMsToMs(options.gcIntervalMs) : KvStoreConfig.gcIntervalMs;
|
|
95
|
+
this.gcMsStorageKey = `__kvStore:lastGcMs:${dbName}:v${this.dbVersion}:${this.storeName}`;
|
|
92
96
|
}
|
|
93
|
-
|
|
97
|
+
/** We'll init the DB only on first use. */
|
|
94
98
|
db;
|
|
95
|
-
|
|
99
|
+
/** Local storage key name for the last GC completed timestamp. */
|
|
96
100
|
gcMsStorageKey;
|
|
101
|
+
dbVersion;
|
|
102
|
+
storeName;
|
|
103
|
+
defaultExpiryMs;
|
|
104
|
+
gcIntervalMs;
|
|
97
105
|
async getOrCreateDb() {
|
|
98
106
|
if (!this.db) {
|
|
99
107
|
this.db = await new Promise((resolve, reject) => {
|
|
@@ -103,7 +111,7 @@ var KVStore = class {
|
|
|
103
111
|
);
|
|
104
112
|
request.onupgradeneeded = (event) => {
|
|
105
113
|
const db = event.target.result;
|
|
106
|
-
const objectStore = db.createObjectStore(
|
|
114
|
+
const objectStore = db.createObjectStore(this.storeName, {
|
|
107
115
|
keyPath: "key"
|
|
108
116
|
});
|
|
109
117
|
objectStore.createIndex("key", "key", {
|
|
@@ -121,15 +129,19 @@ var KVStore = class {
|
|
|
121
129
|
async transact(mode, callback) {
|
|
122
130
|
const db = await this.getOrCreateDb();
|
|
123
131
|
return await new Promise((resolve, reject) => {
|
|
124
|
-
const transaction = withOnError(
|
|
132
|
+
const transaction = withOnError(
|
|
133
|
+
db.transaction(this.storeName, mode),
|
|
134
|
+
reject
|
|
135
|
+
);
|
|
125
136
|
transaction.onabort = (event) => {
|
|
126
137
|
reject(event);
|
|
127
138
|
};
|
|
128
|
-
const objectStore = transaction.objectStore(
|
|
139
|
+
const objectStore = transaction.objectStore(this.storeName);
|
|
129
140
|
callback(objectStore, resolve, reject);
|
|
130
141
|
});
|
|
131
142
|
}
|
|
132
|
-
|
|
143
|
+
/** Set a value in the store. */
|
|
144
|
+
async set(key, value, expiryDeltaMs = this.defaultExpiryMs) {
|
|
133
145
|
const nowMs = Date.now();
|
|
134
146
|
const obj = {
|
|
135
147
|
key,
|
|
@@ -166,6 +178,7 @@ var KVStore = class {
|
|
|
166
178
|
}
|
|
167
179
|
);
|
|
168
180
|
}
|
|
181
|
+
/** Mainly used to get the expiration timestamp of an object. */
|
|
169
182
|
async getStoredObject(key) {
|
|
170
183
|
const stored = await this.transact(
|
|
171
184
|
"readonly",
|
|
@@ -194,10 +207,12 @@ var KVStore = class {
|
|
|
194
207
|
return void 0;
|
|
195
208
|
}
|
|
196
209
|
}
|
|
210
|
+
/** Get a value by key, or undefined if it does not exist. */
|
|
197
211
|
async get(key) {
|
|
198
212
|
const obj = await this.getStoredObject(key);
|
|
199
213
|
return obj?.value;
|
|
200
214
|
}
|
|
215
|
+
/** Generic way to iterate through all entries. */
|
|
201
216
|
async forEach(callback) {
|
|
202
217
|
await this.transact("readonly", (objectStore, resolve, reject) => {
|
|
203
218
|
const request = withOnError(objectStore.openCursor(), reject);
|
|
@@ -206,10 +221,13 @@ var KVStore = class {
|
|
|
206
221
|
if (cursor) {
|
|
207
222
|
if (cursor.key) {
|
|
208
223
|
const obj = validateStoredObject(cursor.value);
|
|
209
|
-
if (obj) {
|
|
210
|
-
await callback(
|
|
211
|
-
|
|
212
|
-
|
|
224
|
+
if (obj !== void 0) {
|
|
225
|
+
await callback(
|
|
226
|
+
String(cursor.key),
|
|
227
|
+
obj.value,
|
|
228
|
+
obj.expiryMs,
|
|
229
|
+
obj.storedMs
|
|
230
|
+
);
|
|
213
231
|
}
|
|
214
232
|
}
|
|
215
233
|
cursor.continue();
|
|
@@ -219,7 +237,11 @@ var KVStore = class {
|
|
|
219
237
|
};
|
|
220
238
|
});
|
|
221
239
|
}
|
|
222
|
-
/**
|
|
240
|
+
/**
|
|
241
|
+
* Returns the number of items in the store. Note that getting the size
|
|
242
|
+
* requires iterating through the entire store because the items could expire
|
|
243
|
+
* at any time, and hence the size is a dynamic number.
|
|
244
|
+
*/
|
|
223
245
|
async size() {
|
|
224
246
|
let count = 0;
|
|
225
247
|
await this.forEach(() => {
|
|
@@ -227,6 +249,7 @@ var KVStore = class {
|
|
|
227
249
|
});
|
|
228
250
|
return count;
|
|
229
251
|
}
|
|
252
|
+
/** Remove all items from the store. */
|
|
230
253
|
async clear() {
|
|
231
254
|
const keys = [];
|
|
232
255
|
await this.forEach((key) => {
|
|
@@ -234,36 +257,45 @@ var KVStore = class {
|
|
|
234
257
|
});
|
|
235
258
|
await this.delete(keys);
|
|
236
259
|
}
|
|
237
|
-
/**
|
|
260
|
+
/**
|
|
261
|
+
* Returns all items as map of key to value, mainly used for debugging dumps.
|
|
262
|
+
* The type T is applied to all values, even though they might not be of type
|
|
263
|
+
* T (in the case when you store different data types in the same store).
|
|
264
|
+
*/
|
|
238
265
|
async asMap() {
|
|
239
266
|
const map = /* @__PURE__ */ new Map();
|
|
240
|
-
await this.forEach((key, value, expiryMs) => {
|
|
241
|
-
map.set(key, { value, expiryMs });
|
|
267
|
+
await this.forEach((key, value, expiryMs, storedMs) => {
|
|
268
|
+
map.set(key, { value, expiryMs, storedMs });
|
|
242
269
|
});
|
|
243
270
|
return map;
|
|
244
271
|
}
|
|
272
|
+
/** Returns the ms timestamp for the last GC (garbage collection). */
|
|
245
273
|
get lastGcMs() {
|
|
246
274
|
const lastGcMsStr = globalThis.localStorage.getItem(this.gcMsStorageKey);
|
|
247
275
|
if (!lastGcMsStr) return 0;
|
|
248
276
|
const ms = Number(lastGcMsStr);
|
|
249
277
|
return isNaN(ms) ? 0 : ms;
|
|
250
278
|
}
|
|
279
|
+
/** Set the ms timestamp for the last GC (garbage collection). */
|
|
251
280
|
set lastGcMs(ms) {
|
|
252
281
|
globalThis.localStorage.setItem(this.gcMsStorageKey, String(ms));
|
|
253
282
|
}
|
|
254
|
-
/** Perform garbage-collection if due. */
|
|
283
|
+
/** Perform garbage-collection if due, else do nothing. */
|
|
255
284
|
async gc() {
|
|
256
285
|
const lastGcMs = this.lastGcMs;
|
|
257
286
|
if (!lastGcMs) {
|
|
258
287
|
this.lastGcMs = Date.now();
|
|
259
288
|
return;
|
|
260
289
|
}
|
|
261
|
-
if (Date.now() < lastGcMs +
|
|
290
|
+
if (Date.now() < lastGcMs + this.gcIntervalMs) {
|
|
262
291
|
return;
|
|
263
292
|
}
|
|
264
293
|
await this.gcNow();
|
|
265
294
|
}
|
|
266
|
-
/**
|
|
295
|
+
/**
|
|
296
|
+
* Perform garbage collection immediately without checking whether we are
|
|
297
|
+
* due for the next GC or not.
|
|
298
|
+
*/
|
|
267
299
|
async gcNow() {
|
|
268
300
|
console.log(`Starting kvStore GC on ${this.dbName} v${this.dbVersion}...`);
|
|
269
301
|
this.lastGcMs = Date.now();
|
|
@@ -283,51 +315,51 @@ var KVStore = class {
|
|
|
283
315
|
);
|
|
284
316
|
this.lastGcMs = Date.now();
|
|
285
317
|
}
|
|
286
|
-
/**
|
|
287
|
-
|
|
288
|
-
return
|
|
318
|
+
/** Returns `this` casted into a StorageAdapter<T>. */
|
|
319
|
+
asStorageAdapter() {
|
|
320
|
+
return this;
|
|
289
321
|
}
|
|
290
322
|
};
|
|
291
|
-
var kvStore = new
|
|
292
|
-
DEFAULT_DB_NAME,
|
|
293
|
-
DEFAULT_DB_VERSION,
|
|
294
|
-
DEFAULT_EXPIRY_DELTA_MS
|
|
295
|
-
);
|
|
323
|
+
var kvStore = new KvStore(KvStoreConfig.dbName);
|
|
296
324
|
var KvStoreItem = class {
|
|
297
|
-
constructor(key,
|
|
325
|
+
constructor(key, defaultExpiryMs = KvStoreConfig.expiryMs, store = kvStore) {
|
|
298
326
|
this.key = key;
|
|
299
|
-
this.defaultExpiryDeltaMs = defaultExpiryDeltaMs;
|
|
300
327
|
this.store = store;
|
|
328
|
+
this.defaultExpiryMs = defaultExpiryMs && durationOrMsToMs(defaultExpiryMs);
|
|
329
|
+
}
|
|
330
|
+
defaultExpiryMs;
|
|
331
|
+
/** Set a value in the store. */
|
|
332
|
+
async set(value, expiryDeltaMs = this.defaultExpiryMs) {
|
|
333
|
+
await this.store.set(this.key, value, expiryDeltaMs);
|
|
301
334
|
}
|
|
302
335
|
/**
|
|
303
336
|
* Example usage:
|
|
304
337
|
*
|
|
305
|
-
* const { value, storedMs, expiryMs } =
|
|
338
|
+
* const { value, storedMs, expiryMs, storedMs } =
|
|
339
|
+
* await myKvItem.getStoredObject();
|
|
306
340
|
*/
|
|
307
341
|
async getStoredObject() {
|
|
308
342
|
return await this.store.getStoredObject(this.key);
|
|
309
343
|
}
|
|
344
|
+
/** Get a value by key, or undefined if it does not exist. */
|
|
310
345
|
async get() {
|
|
311
346
|
return await this.store.get(this.key);
|
|
312
347
|
}
|
|
313
|
-
|
|
314
|
-
await this.store.set(this.key, value, expiryDeltaMs);
|
|
315
|
-
}
|
|
348
|
+
/** Delete this key from the store. */
|
|
316
349
|
async delete() {
|
|
317
350
|
await this.store.delete(this.key);
|
|
318
351
|
}
|
|
319
352
|
};
|
|
320
|
-
function kvStoreItem(key,
|
|
321
|
-
|
|
322
|
-
return new KvStoreItem(key,
|
|
353
|
+
function kvStoreItem(key, expiryMs, store = kvStore) {
|
|
354
|
+
expiryMs = expiryMs && durationOrMsToMs(expiryMs);
|
|
355
|
+
return new KvStoreItem(key, expiryMs, store);
|
|
323
356
|
}
|
|
324
357
|
// Annotate the CommonJS export names for ESM import in node:
|
|
325
358
|
0 && (module.exports = {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
MILLIS_PER_DAY,
|
|
359
|
+
KvStore,
|
|
360
|
+
KvStoreConfig,
|
|
361
|
+
KvStoreItem,
|
|
362
|
+
configureKvStore,
|
|
331
363
|
kvStore,
|
|
332
364
|
kvStoreItem
|
|
333
365
|
});
|