@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.
Files changed (60) hide show
  1. package/arrayBuffer.d.ts +4 -2
  2. package/assert.d.ts +3 -1
  3. package/average.d.ts +3 -1
  4. package/base64Url.d.ts +4 -2
  5. package/dateTimeStr.d.ts +15 -13
  6. package/duration.d.ts +15 -13
  7. package/isEmpty.d.ts +3 -1
  8. package/iterators.cjs +34 -0
  9. package/iterators.d.mts +4 -0
  10. package/iterators.d.ts +4 -0
  11. package/iterators.min.cjs +2 -0
  12. package/iterators.min.cjs.map +1 -0
  13. package/iterators.min.mjs +2 -0
  14. package/iterators.min.mjs.map +1 -0
  15. package/iterators.mjs +9 -0
  16. package/kvStore.cjs +103 -71
  17. package/kvStore.d.mts +91 -49
  18. package/kvStore.d.ts +95 -50
  19. package/kvStore.min.cjs +1 -1
  20. package/kvStore.min.cjs.map +1 -1
  21. package/kvStore.min.mjs +1 -1
  22. package/kvStore.min.mjs.map +1 -1
  23. package/kvStore.mjs +99 -66
  24. package/localStore.cjs +267 -0
  25. package/localStore.d.mts +119 -0
  26. package/localStore.d.ts +119 -0
  27. package/localStore.min.cjs +2 -0
  28. package/localStore.min.cjs.map +1 -0
  29. package/localStore.min.mjs +2 -0
  30. package/localStore.min.mjs.map +1 -0
  31. package/localStore.mjs +235 -0
  32. package/logging.d.ts +4 -2
  33. package/nonEmpty.d.ts +3 -1
  34. package/nonNil.d.ts +3 -1
  35. package/package.json +48 -15
  36. package/round.d.ts +4 -2
  37. package/safeBtoa.d.ts +3 -1
  38. package/safeParseFloat.d.ts +3 -1
  39. package/safeParseInt.d.ts +3 -1
  40. package/sha256.d.ts +3 -1
  41. package/sleep.d.ts +3 -1
  42. package/storageAdapter.cjs +18 -0
  43. package/storageAdapter.d.mts +33 -0
  44. package/storageAdapter.d.ts +33 -0
  45. package/storageAdapter.min.cjs +2 -0
  46. package/storageAdapter.min.cjs.map +1 -0
  47. package/storageAdapter.min.mjs +1 -0
  48. package/storageAdapter.min.mjs.map +1 -0
  49. package/storageAdapter.mjs +0 -0
  50. package/sum.d.ts +3 -1
  51. package/timeConstants.d.ts +16 -14
  52. package/timer.d.ts +4 -2
  53. package/localStorageCache.cjs +0 -119
  54. package/localStorageCache.d.mts +0 -57
  55. package/localStorageCache.d.ts +0 -55
  56. package/localStorageCache.min.cjs +0 -2
  57. package/localStorageCache.min.cjs.map +0 -1
  58. package/localStorageCache.min.mjs +0 -2
  59. package/localStorageCache.min.mjs.map +0 -1
  60. 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
- export declare function arrayBufferToHex(buffer: ArrayBuffer): string;
4
+ declare function arrayBufferToHex(buffer: ArrayBuffer): string;
5
5
  /**
6
6
  * Encode an input ArrayBuffer into a base64 string.
7
7
  */
8
- export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
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
- export declare function assert<T>(t: T | null | undefined | "" | 0 | -0 | 0n | false | typeof NaN, errorMessage?: string): asserts t is T;
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
- export declare function average(numbers: (number | null | undefined)[]): number;
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
- export declare function base64ToBase64URL(base64: string): string;
4
+ declare function base64ToBase64URL(base64: string): string;
5
5
  /**
6
6
  * Convert a base64url string to a base64 string.
7
7
  */
8
- export declare function base64UrlToBase64(base64Url: string): string;
8
+ declare function base64UrlToBase64(base64Url: string): string;
9
+
10
+ export { base64ToBase64URL, base64UrlToBase64 };
package/dateTimeStr.d.ts CHANGED
@@ -1,38 +1,38 @@
1
- export type AnyDateTime = number | Date | string;
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
- export declare function toDate(ts: AnyDateTime): Date;
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
- export declare function yyyyMm(dt?: Date, separator?: string): string;
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
- export declare function yyyyMmDd(dt?: Date, separator?: string): string;
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
- export declare function hhMm(dt?: Date, separator?: string): string;
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
- export declare function hhMmSs(dt?: Date, separator?: string): string;
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
- export declare function hhMmSsMs(dt?: Date, timeSeparator?: string, msSeparator?: string): string;
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
- export declare function tzShort(dt?: Date): string;
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
- export declare function getLongMonthNameZeroIndexed(month: number, locales?: Intl.LocalesArgument): string;
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
- export declare function getLongMonthNameOneIndexed(month: number, locales?: Intl.LocalesArgument): string;
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
- export declare function getShortMonthNameZeroIndexed(month: number, locales?: Intl.LocalesArgument): string;
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
- export declare function getShortMonthNameOneIndexed(month: number, locales?: Intl.LocalesArgument): string;
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
- export declare function getDisplayDateTime(ts: AnyDateTime): string;
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
- export type Duration = {
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
- export type DurationType = keyof Duration;
19
+ type DurationType = keyof Duration;
20
20
  /**
21
21
  * Order in which the duration type appears in the duration string.
22
22
  */
23
- export declare const DURATION_TYPE_SEQUENCE: DurationType[];
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
- export type DurationStyle = "short" | "long" | "narrow";
33
- export type DurationSuffixMap = {
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
- export type DurationSuffixType = keyof DurationSuffixMap;
41
- export declare const DURATION_STYLE_SUFFIX_MAP: Record<DurationType, DurationSuffixMap>;
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
- export declare function msToDuration(ms: number, durationTypeForZero?: DurationType): Duration;
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
- export declare function durationToMs(duration: Duration): number;
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
- export declare function durationOrMsToMs(duration: number | Duration): number;
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
- export declare function formatDuration(duration: Duration, style?: DurationStyle): string;
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
- export declare function readableDuration(ms: number, options?: {
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
- export declare function elapsed(ms: number): string;
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
@@ -1,4 +1,6 @@
1
1
  /**
2
2
  * Returns true if `t` is empty.
3
3
  */
4
- export declare function isEmpty(t: unknown): boolean;
4
+ declare function isEmpty(t: unknown): boolean;
5
+
6
+ export { isEmpty };
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
+ });
@@ -0,0 +1,4 @@
1
+ /** Memory-efficient way to concat two or more iterators. */
2
+ declare function concatIterators<T>(...iterators: Generator<T>[]): Generator<T, void, any>;
3
+
4
+ export { concatIterators };
package/iterators.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /** Memory-efficient way to concat two or more iterators. */
2
+ declare function concatIterators<T>(...iterators: Generator<T>[]): Generator<T, void, any>;
3
+
4
+ export { concatIterators };
@@ -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,2 @@
1
+ function*r(...o){for(let t of o)yield*t}export{r as concatIterators};
2
+ //# sourceMappingURL=iterators.min.mjs.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":"AACO,SAAUA,KAAsBC,EAA2B,CAChE,QAAWC,KAAYD,EACrB,MAAOC,CAEX","names":["concatIterators","iterators","iterator"]}
package/iterators.mjs ADDED
@@ -0,0 +1,9 @@
1
+ // src/iterators.ts
2
+ function* concatIterators(...iterators) {
3
+ for (const iterator of iterators) {
4
+ yield* iterator;
5
+ }
6
+ }
7
+ export {
8
+ concatIterators
9
+ };
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
- DEFAULT_EXPIRY_DELTA_MS: () => DEFAULT_EXPIRY_DELTA_MS,
24
- GC_INTERVAL_MS: () => GC_INTERVAL_MS,
25
- KVStore: () => KVStore,
26
- KVStoreField: () => KVStoreField,
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 DEFAULT_DB_NAME = "KVStore";
54
- var DEFAULT_DB_VERSION = 1;
55
- var STORE_NAME = "kvStore";
56
- var MILLIS_PER_DAY = 864e5;
57
- var DEFAULT_EXPIRY_DELTA_MS = MILLIS_PER_DAY * 30;
58
- var GC_INTERVAL_MS = MILLIS_PER_DAY;
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" || !("key" in obj) || typeof obj.key !== "string" || !("value" in obj) || !("storedMs" in obj) || typeof obj.storedMs !== "number" || obj.value === void 0 || !("expiryMs" in obj) || typeof obj.expiryMs !== "number" || Date.now() >= obj.expiryMs) {
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 KVStoreField = class {
72
- constructor(store, key) {
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.defaultExpiryDeltaMs = defaultExpiryDeltaMs;
91
- this.gcMsStorageKey = `__kvStore:lastGcMs:${dbName}:v${dbVersion}:${STORE_NAME}`;
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
- // We'll init the DB only on first use.
97
+ /** We'll init the DB only on first use. */
94
98
  db;
95
- // Local storage key name for the last GC completed timestamp.
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(STORE_NAME, {
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(db.transaction(STORE_NAME, mode), reject);
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(STORE_NAME);
139
+ const objectStore = transaction.objectStore(this.storeName);
129
140
  callback(objectStore, resolve, reject);
130
141
  });
131
142
  }
132
- async set(key, value, expiryDeltaMs = this.defaultExpiryDeltaMs) {
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(String(cursor.key), obj.value, obj.expiryMs);
211
- } else {
212
- await callback(String(cursor.key), void 0, 0);
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
- /** Cannot be a getter because this needs to be async. */
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
- /** Mainly for debugging dumps. */
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 + GC_INTERVAL_MS) {
290
+ if (Date.now() < lastGcMs + this.gcIntervalMs) {
262
291
  return;
263
292
  }
264
293
  await this.gcNow();
265
294
  }
266
- /** Perform garbage-collection immediately without checking. */
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
- /** Get an independent store item with a locked key and value type. */
287
- field(key) {
288
- return new KVStoreField(this, key);
318
+ /** Returns `this` casted into a StorageAdapter<T>. */
319
+ asStorageAdapter() {
320
+ return this;
289
321
  }
290
322
  };
291
- var kvStore = new KVStore(
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, defaultExpiryDeltaMs, store = kvStore) {
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 } = await myKvItem.getStoredObject();
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
- async set(value, expiryDeltaMs = this.defaultExpiryDeltaMs) {
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, defaultExpiration) {
321
- const defaultExpiryDeltaMs = durationOrMsToMs(defaultExpiration);
322
- return new KvStoreItem(key, defaultExpiryDeltaMs);
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
- DEFAULT_EXPIRY_DELTA_MS,
327
- GC_INTERVAL_MS,
328
- KVStore,
329
- KVStoreField,
330
- MILLIS_PER_DAY,
359
+ KvStore,
360
+ KvStoreConfig,
361
+ KvStoreItem,
362
+ configureKvStore,
331
363
  kvStore,
332
364
  kvStoreItem
333
365
  });