@choksheak/ts-utils 0.3.4 → 0.3.6

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 (285) hide show
  1. package/README.md +9 -3
  2. package/arrayBuffer.cjs +10 -39
  3. package/arrayBuffer.min.cjs +1 -1
  4. package/arrayBuffer.min.cjs.map +1 -1
  5. package/arrayBuffer.min.mjs +1 -1
  6. package/arrayBuffer.min.mjs.map +1 -1
  7. package/arrayBuffer.mjs +7 -10
  8. package/asNumber.cjs +6 -38
  9. package/asNumber.d.mts +1 -1
  10. package/asNumber.d.ts +1 -1
  11. package/asNumber.min.cjs +1 -1
  12. package/asNumber.min.cjs.map +1 -1
  13. package/asNumber.min.mjs +1 -1
  14. package/asNumber.min.mjs.map +1 -1
  15. package/asNumber.mjs +4 -11
  16. package/assert.cjs +4 -27
  17. package/assert.min.cjs +1 -1
  18. package/assert.min.cjs.map +1 -1
  19. package/assert.min.mjs +1 -1
  20. package/assert.min.mjs.map +1 -1
  21. package/assert.mjs +2 -0
  22. package/base64Url.cjs +5 -29
  23. package/base64Url.min.cjs +1 -1
  24. package/base64Url.min.cjs.map +1 -1
  25. package/base64Url.min.mjs +1 -1
  26. package/base64Url.min.mjs.map +1 -1
  27. package/base64Url.mjs +2 -0
  28. package/capLength.cjs +7 -71
  29. package/capLength.min.cjs +1 -5
  30. package/capLength.min.cjs.map +1 -1
  31. package/capLength.min.mjs +1 -5
  32. package/capLength.min.mjs.map +1 -1
  33. package/capLength.mjs +4 -41
  34. package/chunk-22JDWCOS.min.cjs +2 -0
  35. package/chunk-22JDWCOS.min.cjs.map +1 -0
  36. package/chunk-244NBT4Q.min.mjs +2 -0
  37. package/chunk-244NBT4Q.min.mjs.map +1 -0
  38. package/chunk-27MBP3ES.min.cjs +2 -0
  39. package/chunk-27MBP3ES.min.cjs.map +1 -0
  40. package/chunk-34ENP2B3.min.mjs +438 -0
  41. package/chunk-34ENP2B3.min.mjs.map +1 -0
  42. package/chunk-3EBQ2GO2.min.cjs +2 -0
  43. package/chunk-3EBQ2GO2.min.cjs.map +1 -0
  44. package/chunk-4GLOLTJ5.cjs +167 -0
  45. package/chunk-6TQBMXTL.min.cjs +2 -0
  46. package/chunk-6TQBMXTL.min.cjs.map +1 -0
  47. package/chunk-AWZBCFMG.min.cjs +2 -0
  48. package/chunk-AWZBCFMG.min.cjs.map +1 -0
  49. package/chunk-AXNETZET.cjs +20 -0
  50. package/chunk-BKZM6NWX.min.cjs +2 -0
  51. package/chunk-BKZM6NWX.min.cjs.map +1 -0
  52. package/chunk-BZKQXX3A.cjs +40 -0
  53. package/chunk-CERFUU5I.cjs +93 -0
  54. package/chunk-CSTKFJ6G.mjs +239 -0
  55. package/chunk-DUN4UY2Q.cjs +239 -0
  56. package/chunk-EDJJUP4K.min.cjs +6 -0
  57. package/chunk-EDJJUP4K.min.cjs.map +1 -0
  58. package/chunk-FFNQBZH5.cjs +14 -0
  59. package/chunk-FZZRSHSH.min.mjs +6 -0
  60. package/chunk-FZZRSHSH.min.mjs.map +1 -0
  61. package/chunk-GAP2HS5M.min.cjs +2 -0
  62. package/chunk-GAP2HS5M.min.cjs.map +1 -0
  63. package/chunk-GLYMAPS4.min.mjs +2 -0
  64. package/chunk-GLYMAPS4.min.mjs.map +1 -0
  65. package/chunk-I65KPVMO.min.cjs +438 -0
  66. package/chunk-I65KPVMO.min.cjs.map +1 -0
  67. package/chunk-ILGTU46T.cjs +39 -0
  68. package/chunk-IOKRXHKE.min.mjs +2 -0
  69. package/chunk-IOKRXHKE.min.mjs.map +1 -0
  70. package/chunk-ISP4SMRC.min.cjs +2 -0
  71. package/chunk-ISP4SMRC.min.cjs.map +1 -0
  72. package/chunk-KETP5HBF.cjs +24 -0
  73. package/chunk-KLHNGJ4Y.min.mjs +2 -0
  74. package/chunk-KLHNGJ4Y.min.mjs.map +1 -0
  75. package/chunk-KMNTU3DJ.mjs +45 -0
  76. package/chunk-LDVEXETI.cjs +45 -0
  77. package/chunk-LZENHV35.min.cjs +2 -0
  78. package/chunk-LZENHV35.min.cjs.map +1 -0
  79. package/chunk-M5PIM2HB.mjs +42 -0
  80. package/chunk-M6PYQYOX.mjs +39 -0
  81. package/chunk-MN5EYNZN.min.mjs +2 -0
  82. package/chunk-MN5EYNZN.min.mjs.map +1 -0
  83. package/chunk-NRIBJ2OJ.mjs +16031 -0
  84. package/chunk-NVLYXWLX.cjs +32 -0
  85. package/chunk-O352F2MT.mjs +24 -0
  86. package/chunk-O6B2TKFK.min.mjs +2 -0
  87. package/chunk-O6B2TKFK.min.mjs.map +1 -0
  88. package/chunk-OGF34H4T.min.cjs +2 -0
  89. package/chunk-OGF34H4T.min.cjs.map +1 -0
  90. package/chunk-OXSWWWOM.min.mjs +2 -0
  91. package/chunk-OXSWWWOM.min.mjs.map +1 -0
  92. package/chunk-PRUGHVRT.mjs +14 -0
  93. package/chunk-Q4WCMSOW.min.mjs +2 -0
  94. package/chunk-Q4WCMSOW.min.mjs.map +1 -0
  95. package/chunk-QH74JZCK.mjs +9 -0
  96. package/chunk-QNNJNLGK.min.cjs +2 -0
  97. package/chunk-QNNJNLGK.min.cjs.map +1 -0
  98. package/chunk-QWCFN7ZM.mjs +15 -0
  99. package/chunk-SDM2OPT6.mjs +32 -0
  100. package/chunk-SHKRZCF2.cjs +16031 -0
  101. package/chunk-SJDJDNDN.min.cjs +2 -0
  102. package/chunk-SJDJDNDN.min.cjs.map +1 -0
  103. package/chunk-SULNMALN.cjs +328 -0
  104. package/chunk-SV35RBZ7.min.mjs +2 -0
  105. package/chunk-SV35RBZ7.min.mjs.map +1 -0
  106. package/chunk-TJFYGFOW.mjs +328 -0
  107. package/chunk-UHRYBUUX.min.mjs +2 -0
  108. package/chunk-UHRYBUUX.min.mjs.map +1 -0
  109. package/chunk-UOU6IP3S.min.mjs +2 -0
  110. package/chunk-UOU6IP3S.min.mjs.map +1 -0
  111. package/chunk-V76XVNZ5.mjs +20 -0
  112. package/chunk-VFYQ7I5V.min.mjs +2 -0
  113. package/chunk-VFYQ7I5V.min.mjs.map +1 -0
  114. package/chunk-VG7VV7J2.mjs +167 -0
  115. package/chunk-VJCV56DO.cjs +15 -0
  116. package/chunk-VREA6AKG.cjs +9 -0
  117. package/chunk-W5I6Y5FK.min.mjs +2 -0
  118. package/chunk-W5I6Y5FK.min.mjs.map +1 -0
  119. package/chunk-Y7MC73BZ.cjs +42 -0
  120. package/chunk-YVWROQKU.mjs +40 -0
  121. package/chunk-ZKIZ5SWK.min.cjs +2 -0
  122. package/chunk-ZKIZ5SWK.min.cjs.map +1 -0
  123. package/chunk-ZZZB7NJX.mjs +93 -0
  124. package/concatIterators.cjs +4 -27
  125. package/concatIterators.min.cjs +1 -1
  126. package/concatIterators.min.cjs.map +1 -1
  127. package/concatIterators.min.mjs +1 -1
  128. package/concatIterators.min.mjs.map +1 -1
  129. package/concatIterators.mjs +2 -0
  130. package/dateTimeStr.cjs +31 -119
  131. package/dateTimeStr.min.cjs +1 -1
  132. package/dateTimeStr.min.cjs.map +1 -1
  133. package/dateTimeStr.min.mjs +1 -1
  134. package/dateTimeStr.min.mjs.map +1 -1
  135. package/dateTimeStr.mjs +17 -69
  136. package/duration.cjs +24 -188
  137. package/duration.min.cjs +1 -1
  138. package/duration.min.cjs.map +1 -1
  139. package/duration.min.mjs +1 -1
  140. package/duration.min.mjs.map +1 -1
  141. package/duration.mjs +14 -144
  142. package/getEnv.cjs +20 -0
  143. package/getEnv.d.mts +11 -0
  144. package/getEnv.d.ts +11 -0
  145. package/getEnv.min.cjs +2 -0
  146. package/getEnv.min.cjs.map +1 -0
  147. package/getEnv.min.mjs +2 -0
  148. package/getEnv.min.mjs.map +1 -0
  149. package/getEnv.mjs +20 -0
  150. package/isEmpty.cjs +8 -46
  151. package/isEmpty.min.cjs +1 -1
  152. package/isEmpty.min.cjs.map +1 -1
  153. package/isEmpty.min.mjs +1 -1
  154. package/isEmpty.min.mjs.map +1 -1
  155. package/isEmpty.mjs +6 -19
  156. package/isPromise.cjs +5 -29
  157. package/isPromise.min.cjs +1 -1
  158. package/isPromise.min.cjs.map +1 -1
  159. package/isPromise.min.mjs +1 -1
  160. package/isPromise.min.mjs.map +1 -1
  161. package/isPromise.mjs +2 -0
  162. package/kvStore.cjs +15 -362
  163. package/kvStore.d.mts +142 -44
  164. package/kvStore.d.ts +142 -44
  165. package/kvStore.min.cjs +1 -1
  166. package/kvStore.min.cjs.map +1 -1
  167. package/kvStore.min.mjs +1 -1
  168. package/kvStore.min.mjs.map +1 -1
  169. package/kvStore.mjs +13 -328
  170. package/localStore.cjs +15 -263
  171. package/localStore.d.mts +135 -34
  172. package/localStore.d.ts +135 -34
  173. package/localStore.min.cjs +1 -1
  174. package/localStore.min.cjs.map +1 -1
  175. package/localStore.min.mjs +1 -1
  176. package/localStore.min.mjs.map +1 -1
  177. package/localStore.mjs +13 -229
  178. package/magic-string.es-4UY437WL.min.mjs +14 -0
  179. package/magic-string.es-4UY437WL.min.mjs.map +1 -0
  180. package/magic-string.es-OAQWZQTY.mjs +1323 -0
  181. package/magic-string.es-UE2UVQEL.cjs +1323 -0
  182. package/magic-string.es-X6DNUB6Y.min.cjs +14 -0
  183. package/magic-string.es-X6DNUB6Y.min.cjs.map +1 -0
  184. package/mean.cjs +8 -48
  185. package/mean.min.cjs +1 -1
  186. package/mean.min.cjs.map +1 -1
  187. package/mean.min.mjs +1 -1
  188. package/mean.min.mjs.map +1 -1
  189. package/mean.mjs +5 -18
  190. package/median.cjs +7 -41
  191. package/median.min.cjs +1 -1
  192. package/median.min.cjs.map +1 -1
  193. package/median.min.mjs +1 -1
  194. package/median.min.mjs.map +1 -1
  195. package/median.mjs +5 -12
  196. package/nonEmpty.cjs +8 -48
  197. package/nonEmpty.min.cjs +1 -1
  198. package/nonEmpty.min.cjs.map +1 -1
  199. package/nonEmpty.min.mjs +1 -1
  200. package/nonEmpty.min.mjs.map +1 -1
  201. package/nonEmpty.mjs +6 -19
  202. package/nonNil.cjs +4 -27
  203. package/nonNil.min.cjs +1 -1
  204. package/nonNil.min.cjs.map +1 -1
  205. package/nonNil.min.mjs +1 -1
  206. package/nonNil.min.mjs.map +1 -1
  207. package/nonNil.mjs +2 -0
  208. package/package.json +274 -34
  209. package/round.cjs +6 -32
  210. package/round.min.cjs +1 -1
  211. package/round.min.cjs.map +1 -1
  212. package/round.min.mjs +1 -1
  213. package/round.min.mjs.map +1 -1
  214. package/round.mjs +4 -5
  215. package/roundToString.cjs +7 -35
  216. package/roundToString.min.cjs +1 -1
  217. package/roundToString.min.cjs.map +1 -1
  218. package/roundToString.min.mjs +1 -1
  219. package/roundToString.min.mjs.map +1 -1
  220. package/roundToString.mjs +4 -5
  221. package/safeBtoa.cjs +4 -27
  222. package/safeBtoa.d.mts +7 -0
  223. package/safeBtoa.d.ts +7 -0
  224. package/safeBtoa.min.cjs +1 -1
  225. package/safeBtoa.min.cjs.map +1 -1
  226. package/safeBtoa.min.mjs +1 -1
  227. package/safeBtoa.min.mjs.map +1 -1
  228. package/safeBtoa.mjs +2 -0
  229. package/sha256.cjs +8 -34
  230. package/sha256.min.cjs +1 -1
  231. package/sha256.min.cjs.map +1 -1
  232. package/sha256.min.mjs +1 -1
  233. package/sha256.min.mjs.map +1 -1
  234. package/sha256.mjs +6 -7
  235. package/sleep.cjs +4 -27
  236. package/sleep.min.cjs +1 -1
  237. package/sleep.min.cjs.map +1 -1
  238. package/sleep.min.mjs +1 -1
  239. package/sleep.min.mjs.map +1 -1
  240. package/sleep.mjs +2 -0
  241. package/storageAdapter.cjs +1 -18
  242. package/storageAdapter.min.cjs +1 -2
  243. package/storageAdapter.min.cjs.map +1 -1
  244. package/sum.cjs +5 -45
  245. package/sum.min.cjs +1 -1
  246. package/sum.min.cjs.map +1 -1
  247. package/sum.min.mjs +1 -1
  248. package/sum.min.mjs.map +1 -1
  249. package/sum.mjs +5 -18
  250. package/timeConstants.cjs +35 -69
  251. package/timeConstants.min.cjs +1 -1
  252. package/timeConstants.min.cjs.map +1 -1
  253. package/timeConstants.min.mjs +1 -1
  254. package/timeConstants.min.mjs.map +1 -1
  255. package/timeConstants.mjs +19 -15
  256. package/timer.cjs +7 -185
  257. package/timer.d.mts +9 -6
  258. package/timer.d.ts +9 -6
  259. package/timer.min.cjs +1 -1
  260. package/timer.min.cjs.map +1 -1
  261. package/timer.min.mjs +1 -1
  262. package/timer.min.mjs.map +1 -1
  263. package/timer.mjs +8 -158
  264. package/toReadableString.cjs +6 -68
  265. package/toReadableString.min.cjs +1 -5
  266. package/toReadableString.min.cjs.map +1 -1
  267. package/toReadableString.min.mjs +1 -5
  268. package/toReadableString.min.mjs.map +1 -1
  269. package/toReadableString.mjs +4 -41
  270. package/safeParseFloat.cjs +0 -33
  271. package/safeParseFloat.d.mts +0 -6
  272. package/safeParseFloat.d.ts +0 -6
  273. package/safeParseFloat.min.cjs +0 -2
  274. package/safeParseFloat.min.cjs.map +0 -1
  275. package/safeParseFloat.min.mjs +0 -2
  276. package/safeParseFloat.min.mjs.map +0 -1
  277. package/safeParseFloat.mjs +0 -8
  278. package/safeParseInt.cjs +0 -33
  279. package/safeParseInt.d.mts +0 -6
  280. package/safeParseInt.d.ts +0 -6
  281. package/safeParseInt.min.cjs +0 -2
  282. package/safeParseInt.min.cjs.map +0 -1
  283. package/safeParseInt.min.mjs +0 -2
  284. package/safeParseInt.min.mjs.map +0 -1
  285. package/safeParseInt.mjs +0 -8
@@ -0,0 +1,328 @@
1
+ import {
2
+ durationOrMsToMs,
3
+ init_duration
4
+ } from "./chunk-VG7VV7J2.mjs";
5
+ import {
6
+ MS_PER_DAY,
7
+ init_timeConstants
8
+ } from "./chunk-M5PIM2HB.mjs";
9
+ import {
10
+ __esm
11
+ } from "./chunk-M6PYQYOX.mjs";
12
+
13
+ // src/kvStore.ts
14
+ function configureKvStore(config) {
15
+ Object.assign(KvStoreConfig, config);
16
+ }
17
+ function validateStoredObject(obj) {
18
+ 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) {
19
+ return void 0;
20
+ }
21
+ return obj;
22
+ }
23
+ function withOnError(request, reject) {
24
+ request.onerror = (event) => {
25
+ reject(event);
26
+ };
27
+ return request;
28
+ }
29
+ function createKvStore(dbName, options) {
30
+ let db;
31
+ const dbVersion = options?.dbVersion ?? KvStoreConfig.dbVersion;
32
+ const storeName = options?.storeName ?? KvStoreConfig.storeName;
33
+ const defaultExpiryMs = options?.defaultExpiryMs ? durationOrMsToMs(options.defaultExpiryMs) : KvStoreConfig.expiryMs;
34
+ const gcIntervalMs = options?.gcIntervalMs ? durationOrMsToMs(options.gcIntervalMs) : KvStoreConfig.gcIntervalMs;
35
+ const gcMsStorageKey = `__kvStore:lastGcMs:${dbName}:v${dbVersion}:${storeName}`;
36
+ async function getOrCreateDb() {
37
+ if (!db) {
38
+ db = await new Promise((resolve, reject) => {
39
+ const request = withOnError(indexedDB.open(dbName, dbVersion), reject);
40
+ request.onupgradeneeded = (event) => {
41
+ const db2 = event.target.result;
42
+ const objectStore = db2.createObjectStore(storeName, {
43
+ keyPath: "key"
44
+ });
45
+ objectStore.createIndex("key", "key", {
46
+ unique: true
47
+ });
48
+ };
49
+ request.onsuccess = (event) => {
50
+ const db2 = event.target.result;
51
+ resolve(db2);
52
+ };
53
+ });
54
+ }
55
+ return db;
56
+ }
57
+ async function transact(mode, callback) {
58
+ const db2 = await getOrCreateDb();
59
+ return await new Promise((resolve, reject) => {
60
+ const transaction = withOnError(db2.transaction(storeName, mode), reject);
61
+ transaction.onabort = (event) => {
62
+ reject(event);
63
+ };
64
+ const objectStore = transaction.objectStore(storeName);
65
+ callback(objectStore, resolve, reject);
66
+ });
67
+ }
68
+ const obj = {
69
+ /** Input name for the DB. */
70
+ dbName,
71
+ /** Input version for the DB. */
72
+ dbVersion,
73
+ /** Input name for the DB store. */
74
+ storeName,
75
+ /** Default expiry to use if not specified in set(). */
76
+ defaultExpiryMs,
77
+ /** Time interval for when GC's occur. */
78
+ gcIntervalMs,
79
+ /** Local storage key name for the last GC completed timestamp. */
80
+ gcMsStorageKey,
81
+ /** Set a value in the store. */
82
+ async set(key, value, expiryDeltaMs) {
83
+ const nowMs = Date.now();
84
+ const stored = {
85
+ key,
86
+ value,
87
+ storedMs: nowMs,
88
+ expiryMs: nowMs + durationOrMsToMs(expiryDeltaMs ?? defaultExpiryMs)
89
+ };
90
+ return await transact("readwrite", (objectStore, resolve, reject) => {
91
+ const request = withOnError(objectStore.put(stored), reject);
92
+ request.onsuccess = () => {
93
+ resolve(value);
94
+ obj.gc();
95
+ };
96
+ });
97
+ },
98
+ /** Delete one or multiple keys. */
99
+ async delete(key) {
100
+ return await transact(
101
+ "readwrite",
102
+ (objectStore, resolve, reject) => {
103
+ objectStore.transaction.oncomplete = () => {
104
+ resolve();
105
+ };
106
+ if (typeof key === "string") {
107
+ withOnError(objectStore.delete(key), reject);
108
+ } else {
109
+ for (const k of key) {
110
+ withOnError(objectStore.delete(k), reject);
111
+ }
112
+ }
113
+ }
114
+ );
115
+ },
116
+ /** Mainly used to get the expiration timestamp of an object. */
117
+ async getStoredObject(key) {
118
+ const stored = await transact(
119
+ "readonly",
120
+ (objectStore, resolve, reject) => {
121
+ const request = withOnError(objectStore.get(key), reject);
122
+ request.onsuccess = () => {
123
+ resolve(request.result);
124
+ };
125
+ }
126
+ );
127
+ if (!stored) {
128
+ return void 0;
129
+ }
130
+ try {
131
+ const valid = validateStoredObject(stored);
132
+ if (!valid) {
133
+ await obj.delete(key);
134
+ obj.gc();
135
+ return void 0;
136
+ }
137
+ return valid;
138
+ } catch (e) {
139
+ console.error(`Invalid kv value: ${key}=${JSON.stringify(stored)}:`, e);
140
+ await obj.delete(key);
141
+ obj.gc();
142
+ return void 0;
143
+ }
144
+ },
145
+ /** Get a value by key, or undefined if it does not exist. */
146
+ async get(key) {
147
+ const stored = await obj.getStoredObject(key);
148
+ return stored?.value;
149
+ },
150
+ /** Generic way to iterate through all entries. */
151
+ async forEach(callback) {
152
+ await transact("readonly", (objectStore, resolve, reject) => {
153
+ const request = withOnError(objectStore.openCursor(), reject);
154
+ request.onsuccess = async (event) => {
155
+ const cursor = event.target.result;
156
+ if (cursor) {
157
+ if (cursor.key) {
158
+ const valid = validateStoredObject(cursor.value);
159
+ if (valid !== void 0) {
160
+ await callback(
161
+ String(cursor.key),
162
+ valid.value,
163
+ valid.expiryMs,
164
+ valid.storedMs
165
+ );
166
+ }
167
+ }
168
+ cursor.continue();
169
+ } else {
170
+ resolve();
171
+ }
172
+ };
173
+ });
174
+ },
175
+ /**
176
+ * Returns the number of items in the store. Note that getting the size
177
+ * requires iterating through the entire store because the items could expire
178
+ * at any time, and hence the size is a dynamic number.
179
+ */
180
+ async size() {
181
+ let count = 0;
182
+ await obj.forEach(() => {
183
+ count++;
184
+ });
185
+ return count;
186
+ },
187
+ /** Remove all items from the store. */
188
+ async clear() {
189
+ await transact("readwrite", (objectStore, resolve, reject) => {
190
+ const request = withOnError(objectStore.clear(), reject);
191
+ request.onsuccess = () => {
192
+ resolve();
193
+ };
194
+ });
195
+ },
196
+ /**
197
+ * Returns all items as map of key to value, mainly used for debugging dumps.
198
+ * The type T is applied to all values, even though they might not be of type
199
+ * T (in the case when you store different data types in the same store).
200
+ */
201
+ async asMap() {
202
+ const map = /* @__PURE__ */ new Map();
203
+ await obj.forEach((key, value, expiryMs, storedMs) => {
204
+ map.set(key, { value, expiryMs, storedMs });
205
+ });
206
+ return map;
207
+ },
208
+ /** Returns the ms timestamp for the last GC (garbage collection). */
209
+ getLastGcMs() {
210
+ const lastGcMsStr = localStorage.getItem(gcMsStorageKey);
211
+ if (!lastGcMsStr) return 0;
212
+ const ms = Number(lastGcMsStr);
213
+ return isNaN(ms) ? 0 : ms;
214
+ },
215
+ /** Set the ms timestamp for the last GC (garbage collection). */
216
+ setLastGcMs(ms) {
217
+ localStorage.setItem(gcMsStorageKey, String(ms));
218
+ },
219
+ /** Perform garbage-collection if due, else do nothing. */
220
+ async gc() {
221
+ const lastGcMs = obj.getLastGcMs();
222
+ if (!lastGcMs) {
223
+ obj.setLastGcMs(Date.now());
224
+ return;
225
+ }
226
+ if (Date.now() < lastGcMs + gcIntervalMs) {
227
+ return;
228
+ }
229
+ await obj.gcNow();
230
+ },
231
+ /**
232
+ * Perform garbage collection immediately without checking whether we are
233
+ * due for the next GC or not.
234
+ */
235
+ async gcNow() {
236
+ console.log(`Starting kvStore GC on ${dbName} v${dbVersion}...`);
237
+ obj.setLastGcMs(Date.now());
238
+ const keysToDelete = [];
239
+ await obj.forEach(
240
+ async (key, value, expiryMs) => {
241
+ if (value === void 0 || Date.now() >= expiryMs) {
242
+ keysToDelete.push(key);
243
+ }
244
+ }
245
+ );
246
+ if (keysToDelete.length) {
247
+ await obj.delete(keysToDelete);
248
+ }
249
+ console.log(
250
+ `Finished kvStore GC on ${dbName} v${dbVersion} - deleted ${keysToDelete.length} keys`
251
+ );
252
+ obj.setLastGcMs(Date.now());
253
+ },
254
+ /** Returns `this` casted into a StorageAdapter<T>. */
255
+ asStorageAdapter() {
256
+ return obj;
257
+ }
258
+ };
259
+ return obj;
260
+ }
261
+ function kvStoreItem(key, expiryMs, store = kvStore) {
262
+ const defaultExpiryMs = expiryMs && durationOrMsToMs(expiryMs);
263
+ const obj = {
264
+ key,
265
+ defaultExpiryMs,
266
+ store,
267
+ /** Set a value in the store. */
268
+ async set(value, expiryDeltaMs) {
269
+ await store.set(key, value, expiryDeltaMs ?? defaultExpiryMs);
270
+ },
271
+ /**
272
+ * Example usage:
273
+ *
274
+ * const { value, storedMs, expiryMs, storedMs } =
275
+ * await myKvItem.getStoredObject();
276
+ */
277
+ async getStoredObject() {
278
+ return await store.getStoredObject(key);
279
+ },
280
+ /** Get a value by key, or undefined if it does not exist. */
281
+ async get() {
282
+ return await store.get(key);
283
+ },
284
+ /** Delete this key from the store. */
285
+ async delete() {
286
+ await store.delete(key);
287
+ }
288
+ };
289
+ return obj;
290
+ }
291
+ var KvStoreConfig, kvStore;
292
+ var init_kvStore = __esm({
293
+ "src/kvStore.ts"() {
294
+ init_duration();
295
+ init_timeConstants();
296
+ KvStoreConfig = {
297
+ /**
298
+ * Name of the DB in the indexed DB.
299
+ * Updating the DB name will cause all old entries to be gone.
300
+ */
301
+ dbName: "KVStore",
302
+ /**
303
+ * Version of the DB schema. Most likely you will never want to change this.
304
+ * Updating the version will cause all old entries to be gone.
305
+ */
306
+ dbVersion: 1,
307
+ /**
308
+ * Name of the store within the indexed DB. Each DB can have multiple stores.
309
+ * In practice, it doesn't matter what you name this to be.
310
+ */
311
+ storeName: "kvStore",
312
+ /** 30 days in ms. */
313
+ expiryMs: MS_PER_DAY * 30,
314
+ /** Do GC once per day. */
315
+ gcIntervalMs: MS_PER_DAY
316
+ };
317
+ kvStore = createKvStore(KvStoreConfig.dbName);
318
+ }
319
+ });
320
+
321
+ export {
322
+ KvStoreConfig,
323
+ configureKvStore,
324
+ createKvStore,
325
+ kvStore,
326
+ kvStoreItem,
327
+ init_kvStore
328
+ };
@@ -0,0 +1,2 @@
1
+ import{a as n}from"./chunk-KLHNGJ4Y.min.mjs";function o(r){return r.reduce((u,e)=>u+n(e),0)}export{o as a};
2
+ //# sourceMappingURL=chunk-UHRYBUUX.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sum.ts"],"sourcesContent":["import { asNumber } from \"./asNumber\";\n\n/**\n * Add all the numbers together in the given array.\n * Non-numbers will be coerced into numbers if possible.\n */\nexport function sum(numbers: unknown[]): number {\n return numbers.reduce((accumulated: number, current: unknown) => {\n return accumulated + asNumber(current);\n }, 0);\n}\n"],"mappings":"6CAMO,SAASA,EAAIC,EAA4B,CAC9C,OAAOA,EAAQ,OAAO,CAACC,EAAqBC,IACnCD,EAAcE,EAASD,CAAO,EACpC,CAAC,CACN","names":["sum","numbers","accumulated","current","asNumber"]}
@@ -0,0 +1,2 @@
1
+ var g=Object.create;var e=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var m=(b,a)=>()=>(b&&(a=b(b=0)),a);var n=(b,a)=>()=>(a||b((a={exports:{}}).exports,a),a.exports),o=(b,a)=>{for(var c in a)e(b,c,{get:a[c],enumerable:!0})},l=(b,a,c,f)=>{if(a&&typeof a=="object"||typeof a=="function")for(let d of i(a))!k.call(b,d)&&d!==c&&e(b,d,{get:()=>a[d],enumerable:!(f=h(a,d))||f.enumerable});return b};var p=(b,a,c)=>(c=b!=null?g(j(b)):{},l(a||!b||!b.__esModule?e(c,"default",{value:b,enumerable:!0}):c,b));export{m as a,n as b,o as c,p as d};
2
+ //# sourceMappingURL=chunk-UOU6IP3S.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,20 @@
1
+ import {
2
+ __esm
3
+ } from "./chunk-M6PYQYOX.mjs";
4
+
5
+ // src/sha256.ts
6
+ async function sha256(input) {
7
+ const encoder = new TextEncoder();
8
+ const uint8Array = encoder.encode(input);
9
+ const arrayBuffer = await crypto.subtle.digest("SHA-256", uint8Array);
10
+ return arrayBuffer;
11
+ }
12
+ var init_sha256 = __esm({
13
+ "src/sha256.ts"() {
14
+ }
15
+ });
16
+
17
+ export {
18
+ sha256,
19
+ init_sha256
20
+ };
@@ -0,0 +1,2 @@
1
+ function u(r,t=0){let n=Math.pow(10,t);return Math.round(r*n)/n}export{u as a};
2
+ //# sourceMappingURL=chunk-VFYQ7I5V.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/round.ts"],"sourcesContent":["/**\n * Simplifies rounding of floating point numbers. Note that if your number ends\n * with zeros, and you convert the number to string, you will lose the zeroes\n * at the end. To show the exact number of decimal places, you'll need to use\n * roundToString() or toFixed(). E.g. round(1.20, 2).toFixed(2).\n */\nexport function round(n: number, numDecimalPlaces = 0): number {\n const multipler = Math.pow(10, numDecimalPlaces);\n return Math.round(n * multipler) / multipler;\n}\n"],"mappings":"AAMO,SAASA,EAAMC,EAAWC,EAAmB,EAAW,CAC7D,IAAMC,EAAY,KAAK,IAAI,GAAID,CAAgB,EAC/C,OAAO,KAAK,MAAMD,EAAIE,CAAS,EAAIA,CACrC","names":["round","n","numDecimalPlaces","multipler"]}
@@ -0,0 +1,167 @@
1
+ import {
2
+ HOURS_PER_DAY,
3
+ MINUTES_PER_HOUR,
4
+ MS_PER_DAY,
5
+ MS_PER_HOUR,
6
+ MS_PER_MINUTE,
7
+ MS_PER_SECOND,
8
+ SECONDS_PER_MINUTE,
9
+ init_timeConstants
10
+ } from "./chunk-M5PIM2HB.mjs";
11
+ import {
12
+ __esm
13
+ } from "./chunk-M6PYQYOX.mjs";
14
+
15
+ // src/duration.ts
16
+ function getDurationStyleForPlural(style) {
17
+ return style == "short" ? "shorts" : style === "long" ? "longs" : style;
18
+ }
19
+ function getValueAndUnitSeparator(style) {
20
+ return style === "narrow" ? "" : " ";
21
+ }
22
+ function getDurationTypeSeparator(style) {
23
+ return style === "narrow" ? " " : ", ";
24
+ }
25
+ function msToDuration(ms, durationTypeForZero) {
26
+ if (ms === 0) {
27
+ durationTypeForZero = durationTypeForZero ?? "milliseconds";
28
+ return { [durationTypeForZero]: 0 };
29
+ }
30
+ const duration = {};
31
+ for (let i = 0; i < 1; i++) {
32
+ let seconds = Math.floor(ms / MS_PER_SECOND);
33
+ const millis = ms - seconds * MS_PER_SECOND;
34
+ if (millis > 0) {
35
+ duration["milliseconds"] = millis;
36
+ }
37
+ if (seconds === 0) {
38
+ break;
39
+ }
40
+ let minutes = Math.floor(seconds / SECONDS_PER_MINUTE);
41
+ seconds -= minutes * SECONDS_PER_MINUTE;
42
+ if (seconds > 0) {
43
+ duration["seconds"] = seconds;
44
+ }
45
+ if (minutes === 0) {
46
+ break;
47
+ }
48
+ let hours = Math.floor(minutes / MINUTES_PER_HOUR);
49
+ minutes -= hours * MINUTES_PER_HOUR;
50
+ if (minutes > 0) {
51
+ duration["minutes"] = minutes;
52
+ }
53
+ if (hours === 0) {
54
+ break;
55
+ }
56
+ const days = Math.floor(hours / HOURS_PER_DAY);
57
+ hours -= days * HOURS_PER_DAY;
58
+ if (hours > 0) {
59
+ duration["hours"] = hours;
60
+ }
61
+ if (days > 0) {
62
+ duration["days"] = days;
63
+ }
64
+ }
65
+ return duration;
66
+ }
67
+ function durationToMs(duration) {
68
+ const daysMs = (duration.days ?? 0) * MS_PER_DAY;
69
+ const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;
70
+ const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;
71
+ const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;
72
+ const msMs = duration.milliseconds ?? 0;
73
+ return daysMs + hoursMs + minsMs + secsMs + msMs;
74
+ }
75
+ function durationOrMsToMs(duration) {
76
+ return typeof duration === "number" ? duration : durationToMs(duration);
77
+ }
78
+ function formatDuration(duration, style) {
79
+ style = style ?? "short";
80
+ const stylePlural = getDurationStyleForPlural(style);
81
+ const space = getValueAndUnitSeparator(style);
82
+ const a = [];
83
+ for (const unit of DURATION_TYPE_SEQUENCE) {
84
+ const value = duration[unit];
85
+ if (value === void 0) continue;
86
+ const suffixMap = DURATION_STYLE_SUFFIX_MAP[unit];
87
+ const suffix = value === 1 ? suffixMap[style] : suffixMap[stylePlural];
88
+ a.push(value + space + suffix);
89
+ }
90
+ const separator = getDurationTypeSeparator(style);
91
+ return a.join(separator);
92
+ }
93
+ function readableDuration(ms, options) {
94
+ const duration = msToDuration(ms, options?.durationTypeForZero);
95
+ return formatDuration(duration, options?.style);
96
+ }
97
+ function elapsed(ms) {
98
+ if (ms > MS_PER_MINUTE) {
99
+ return readableDuration(ms);
100
+ }
101
+ if (ms > 100) {
102
+ return `${(ms / 1e3).toFixed(3)}s`;
103
+ }
104
+ return ms + "ms";
105
+ }
106
+ var DURATION_TYPE_SEQUENCE, DURATION_STYLE_SUFFIX_MAP;
107
+ var init_duration = __esm({
108
+ "src/duration.ts"() {
109
+ init_timeConstants();
110
+ DURATION_TYPE_SEQUENCE = [
111
+ "days",
112
+ "hours",
113
+ "minutes",
114
+ "seconds",
115
+ "milliseconds"
116
+ ];
117
+ DURATION_STYLE_SUFFIX_MAP = {
118
+ days: {
119
+ short: "day",
120
+ shorts: "days",
121
+ long: "day",
122
+ longs: "days",
123
+ narrow: "d"
124
+ },
125
+ hours: {
126
+ short: "hr",
127
+ shorts: "hrs",
128
+ long: "hour",
129
+ longs: "hours",
130
+ narrow: "h"
131
+ },
132
+ minutes: {
133
+ short: "min",
134
+ shorts: "mins",
135
+ long: "minute",
136
+ longs: "minutes",
137
+ narrow: "m"
138
+ },
139
+ seconds: {
140
+ short: "sec",
141
+ shorts: "secs",
142
+ long: "second",
143
+ longs: "seconds",
144
+ narrow: "s"
145
+ },
146
+ milliseconds: {
147
+ short: "ms",
148
+ shorts: "ms",
149
+ long: "millisecond",
150
+ longs: "milliseconds",
151
+ narrow: "ms"
152
+ }
153
+ };
154
+ }
155
+ });
156
+
157
+ export {
158
+ DURATION_TYPE_SEQUENCE,
159
+ DURATION_STYLE_SUFFIX_MAP,
160
+ msToDuration,
161
+ durationToMs,
162
+ durationOrMsToMs,
163
+ formatDuration,
164
+ readableDuration,
165
+ elapsed,
166
+ init_duration
167
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/asNumber.ts
2
+ function asNumber(u, defaultValue = 0) {
3
+ if (typeof u === "number") {
4
+ return isFinite(u) ? u : defaultValue;
5
+ }
6
+ u = Number(u);
7
+ if (typeof u === "number" && isFinite(u)) {
8
+ return u;
9
+ }
10
+ return defaultValue;
11
+ }
12
+
13
+
14
+
15
+ exports.asNumber = asNumber;
@@ -0,0 +1,9 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/round.ts
2
+ function round(n, numDecimalPlaces = 0) {
3
+ const multipler = Math.pow(10, numDecimalPlaces);
4
+ return Math.round(n * multipler) / multipler;
5
+ }
6
+
7
+
8
+
9
+ exports.round = round;
@@ -0,0 +1,2 @@
1
+ import{e as m,i as I}from"./chunk-Q4WCMSOW.min.mjs";import{d as w}from"./chunk-MN5EYNZN.min.mjs";import{a as O}from"./chunk-UOU6IP3S.min.mjs";function E(r){Object.assign(S,r)}function M(r){if(!(!r||typeof r!="object"||typeof r.key!="string"||r.value===void 0||typeof r.storedMs!="number"||typeof r.expiryMs!="number"||Date.now()>=r.expiryMs))return r}function f(r,i){return r.onerror=c=>{i(c)},r}function P(r,i){let c,g=i?.dbVersion??S.dbVersion,v=i?.storeName??S.storeName,b=i?.defaultExpiryMs?m(i.defaultExpiryMs):S.expiryMs,p=i?.gcIntervalMs?m(i.gcIntervalMs):S.gcIntervalMs,T=`__kvStore:lastGcMs:${r}:v${g}:${v}`;async function D(){return c||(c=await new Promise((e,t)=>{let n=f(indexedDB.open(r,g),t);n.onupgradeneeded=o=>{o.target.result.createObjectStore(v,{keyPath:"key"}).createIndex("key","key",{unique:!0})},n.onsuccess=o=>{let a=o.target.result;e(a)}})),c}async function y(e,t){let n=await D();return await new Promise((o,a)=>{let d=f(n.transaction(v,e),a);d.onabort=l=>{a(l)};let u=d.objectStore(v);t(u,o,a)})}let s={dbName:r,dbVersion:g,storeName:v,defaultExpiryMs:b,gcIntervalMs:p,gcMsStorageKey:T,async set(e,t,n){let o=Date.now(),a={key:e,value:t,storedMs:o,expiryMs:o+m(n??b)};return await y("readwrite",(d,u,l)=>{let x=f(d.put(a),l);x.onsuccess=()=>{u(t),s.gc()}})},async delete(e){return await y("readwrite",(t,n,o)=>{if(t.transaction.oncomplete=()=>{n()},typeof e=="string")f(t.delete(e),o);else for(let a of e)f(t.delete(a),o)})},async getStoredObject(e){let t=await y("readonly",(n,o,a)=>{let d=f(n.get(e),a);d.onsuccess=()=>{o(d.result)}});if(t)try{let n=M(t);if(!n){await s.delete(e),s.gc();return}return n}catch(n){console.error(`Invalid kv value: ${e}=${JSON.stringify(t)}:`,n),await s.delete(e),s.gc();return}},async get(e){return(await s.getStoredObject(e))?.value},async forEach(e){await y("readonly",(t,n,o)=>{let a=f(t.openCursor(),o);a.onsuccess=async d=>{let u=d.target.result;if(u){if(u.key){let l=M(u.value);l!==void 0&&await e(String(u.key),l.value,l.expiryMs,l.storedMs)}u.continue()}else n()}})},async size(){let e=0;return await s.forEach(()=>{e++}),e},async clear(){await y("readwrite",(e,t,n)=>{let o=f(e.clear(),n);o.onsuccess=()=>{t()}})},async asMap(){let e=new Map;return await s.forEach((t,n,o,a)=>{e.set(t,{value:n,expiryMs:o,storedMs:a})}),e},getLastGcMs(){let e=localStorage.getItem(T);if(!e)return 0;let t=Number(e);return isNaN(t)?0:t},setLastGcMs(e){localStorage.setItem(T,String(e))},async gc(){let e=s.getLastGcMs();if(!e){s.setLastGcMs(Date.now());return}Date.now()<e+p||await s.gcNow()},async gcNow(){console.log(`Starting kvStore GC on ${r} v${g}...`),s.setLastGcMs(Date.now());let e=[];await s.forEach(async(t,n,o)=>{(n===void 0||Date.now()>=o)&&e.push(t)}),e.length&&await s.delete(e),console.log(`Finished kvStore GC on ${r} v${g} - deleted ${e.length} keys`),s.setLastGcMs(Date.now())},asStorageAdapter(){return s}};return s}function G(r,i,c=K){let g=i&&m(i);return{key:r,defaultExpiryMs:g,store:c,async set(b,p){await c.set(r,b,p??g)},async getStoredObject(){return await c.getStoredObject(r)},async get(){return await c.get(r)},async delete(){await c.delete(r)}}}var S,K,j=O(()=>{I();S={dbName:"KVStore",dbVersion:1,storeName:"kvStore",expiryMs:864e5*30,gcIntervalMs:864e5};K=P(S.dbName)});export{S as a,E as b,P as c,K as d,G as e,j as f};
2
+ //# sourceMappingURL=chunk-W5I6Y5FK.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kvStore.ts"],"sourcesContent":["/**\n * Indexed DB key-value store with support for auto-expirations.\n *\n * Why use this?\n * 1. Extremely simple interface to use indexed DBs.\n * 2. Auto-expirations with GC frees you from worrying about data clean-up.\n * 3. Any serializable data type can be stored (except undefined).\n *\n * How to use?\n * Just use the `kvStore` global constant like the local storage, but with\n * async interface functions as required by indexed DB.\n *\n * Why not use the indexed DB directly?\n * It will require you to write a lot of code to reinvent the wheel.\n */\n\nimport { Duration, durationOrMsToMs } from \"./duration\";\nimport {\n FullStorageAdapter,\n StorageAdapter,\n StoredObject,\n} from \"./storageAdapter\";\nimport { MS_PER_DAY } from \"./timeConstants\";\n\n/** Global defaults can be updated directly. */\nexport const KvStoreConfig = {\n /**\n * Name of the DB in the indexed DB.\n * Updating the DB name will cause all old entries to be gone.\n */\n dbName: \"KVStore\",\n\n /**\n * Version of the DB schema. Most likely you will never want to change this.\n * Updating the version will cause all old entries to be gone.\n */\n dbVersion: 1,\n\n /**\n * Name of the store within the indexed DB. Each DB can have multiple stores.\n * In practice, it doesn't matter what you name this to be.\n */\n storeName: \"kvStore\",\n\n /** 30 days in ms. */\n expiryMs: MS_PER_DAY * 30,\n\n /** Do GC once per day. */\n gcIntervalMs: MS_PER_DAY,\n};\n\nexport type KvStoreConfig = typeof KvStoreConfig;\n\n/** Convenience function to update global defaults. */\nexport function configureKvStore(config: Partial<KvStoreConfig>) {\n Object.assign(KvStoreConfig, config);\n}\n\n/** Type to represent a full object with metadata stored in the store. */\nexport type KvStoredObject<T> = StoredObject<T> & {\n // The key is required by the ObjectStore.\n key: string;\n};\n\n/**\n * Parse a stored value string. Returns undefined if invalid or expired.\n * Throws an error if the string cannot be parsed as JSON.\n */\nfunction validateStoredObject<T>(\n obj: KvStoredObject<T>,\n): KvStoredObject<T> | undefined {\n if (\n !obj ||\n typeof obj !== \"object\" ||\n typeof obj.key !== \"string\" ||\n obj.value === undefined ||\n typeof obj.storedMs !== \"number\" ||\n typeof obj.expiryMs !== \"number\" ||\n Date.now() >= obj.expiryMs\n ) {\n return undefined;\n }\n\n return obj;\n}\n\n/** Add an `onerror` handler to the request. */\nfunction withOnError<T extends IDBRequest | IDBTransaction>(\n request: T,\n reject: (reason?: unknown) => void,\n): T {\n request.onerror = (event) => {\n reject(event);\n };\n\n return request;\n}\n\n/**\n * You can create multiple KvStores if you want, but most likely you will only\n * need to use the default `kvStore` instance.\n */\nexport function createKvStore(\n dbName: string,\n options?: {\n dbVersion?: number;\n storeName?: string;\n defaultExpiryMs?: number | Duration;\n gcIntervalMs?: number | Duration;\n },\n) {\n /** We'll init the DB only on first use. */\n let db: IDBDatabase | undefined;\n\n const dbVersion = options?.dbVersion ?? KvStoreConfig.dbVersion;\n const storeName = options?.storeName ?? KvStoreConfig.storeName;\n\n const defaultExpiryMs = options?.defaultExpiryMs\n ? durationOrMsToMs(options.defaultExpiryMs)\n : KvStoreConfig.expiryMs;\n\n const gcIntervalMs = options?.gcIntervalMs\n ? durationOrMsToMs(options.gcIntervalMs)\n : KvStoreConfig.gcIntervalMs;\n\n const gcMsStorageKey = `__kvStore:lastGcMs:${dbName}:v${dbVersion}:${storeName}`;\n\n async function getOrCreateDb() {\n if (!db) {\n db = await new Promise<IDBDatabase>((resolve, reject) => {\n const request = withOnError(indexedDB.open(dbName, dbVersion), reject);\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as unknown as { result: IDBDatabase })\n .result;\n\n // Create the store on DB init.\n const objectStore = db.createObjectStore(storeName, {\n keyPath: \"key\",\n });\n\n objectStore.createIndex(\"key\", \"key\", {\n unique: true,\n });\n };\n\n request.onsuccess = (event) => {\n const db = (event.target as unknown as { result: IDBDatabase })\n .result;\n resolve(db);\n };\n });\n }\n\n return db;\n }\n\n async function transact<T>(\n mode: IDBTransactionMode,\n callback: (\n objectStore: IDBObjectStore,\n resolve: (t: T) => void,\n reject: (reason?: unknown) => void,\n ) => void,\n ): Promise<T> {\n const db = await getOrCreateDb();\n\n return await new Promise<T>((resolve, reject) => {\n const transaction = withOnError(db.transaction(storeName, mode), reject);\n\n transaction.onabort = (event) => {\n reject(event);\n };\n\n const objectStore = transaction.objectStore(storeName);\n\n callback(objectStore, resolve, reject);\n });\n }\n\n const obj = {\n /** Input name for the DB. */\n dbName,\n\n /** Input version for the DB. */\n dbVersion,\n\n /** Input name for the DB store. */\n storeName,\n\n /** Default expiry to use if not specified in set(). */\n defaultExpiryMs,\n\n /** Time interval for when GC's occur. */\n gcIntervalMs,\n\n /** Local storage key name for the last GC completed timestamp. */\n gcMsStorageKey,\n\n /** Set a value in the store. */\n async set<T>(\n key: string,\n value: T,\n expiryDeltaMs?: number | Duration,\n ): Promise<T> {\n const nowMs = Date.now();\n const stored: KvStoredObject<T> = {\n key,\n value,\n storedMs: nowMs,\n expiryMs: nowMs + durationOrMsToMs(expiryDeltaMs ?? defaultExpiryMs),\n };\n\n return await transact<T>(\"readwrite\", (objectStore, resolve, reject) => {\n const request = withOnError(objectStore.put(stored), reject);\n\n request.onsuccess = () => {\n resolve(value);\n\n obj.gc(); // check GC on every write\n };\n });\n },\n\n /** Delete one or multiple keys. */\n async delete(key: string | string[]): Promise<void> {\n return await transact<void>(\n \"readwrite\",\n (objectStore, resolve, reject) => {\n objectStore.transaction.oncomplete = () => {\n resolve();\n };\n\n if (typeof key === \"string\") {\n withOnError(objectStore.delete(key), reject);\n } else {\n for (const k of key) {\n withOnError(objectStore.delete(k), reject);\n }\n }\n },\n );\n },\n\n /** Mainly used to get the expiration timestamp of an object. */\n async getStoredObject<T>(\n key: string,\n ): Promise<KvStoredObject<T> | undefined> {\n const stored = await transact<KvStoredObject<T> | undefined>(\n \"readonly\",\n (objectStore, resolve, reject) => {\n const request = withOnError(objectStore.get(key), reject);\n\n request.onsuccess = () => {\n resolve(request.result);\n };\n },\n );\n\n if (!stored) {\n return undefined;\n }\n\n try {\n const valid = validateStoredObject(stored);\n if (!valid) {\n await obj.delete(key);\n\n obj.gc(); // check GC on every read of an expired key\n\n return undefined;\n }\n\n return valid;\n } catch (e) {\n console.error(`Invalid kv value: ${key}=${JSON.stringify(stored)}:`, e);\n await obj.delete(key);\n\n obj.gc(); // check GC on every read of an invalid key\n\n return undefined;\n }\n },\n\n /** Get a value by key, or undefined if it does not exist. */\n async get<T>(key: string): Promise<T | undefined> {\n const stored = await obj.getStoredObject<T>(key);\n\n return stored?.value;\n },\n\n /** Generic way to iterate through all entries. */\n async forEach<T>(\n callback: (\n key: string,\n value: T,\n expiryMs: number,\n storedMs: number,\n ) => void | Promise<void>,\n ): Promise<void> {\n await transact<void>(\"readonly\", (objectStore, resolve, reject) => {\n const request = withOnError(objectStore.openCursor(), reject);\n\n request.onsuccess = async (event) => {\n const cursor = (\n event.target as unknown as { result: IDBCursorWithValue }\n ).result;\n\n if (cursor) {\n if (cursor.key) {\n const valid = validateStoredObject(cursor.value);\n if (valid !== undefined) {\n await callback(\n String(cursor.key),\n valid.value as T,\n valid.expiryMs,\n valid.storedMs,\n );\n }\n }\n cursor.continue();\n } else {\n resolve();\n }\n };\n });\n },\n\n /**\n * Returns the number of items in the store. Note that getting the size\n * requires iterating through the entire store because the items could expire\n * at any time, and hence the size is a dynamic number.\n */\n async size(): Promise<number> {\n let count = 0;\n await obj.forEach(() => {\n count++;\n });\n return count;\n },\n\n /** Remove all items from the store. */\n async clear(): Promise<void> {\n await transact<void>(\"readwrite\", (objectStore, resolve, reject) => {\n const request = withOnError(objectStore.clear(), reject);\n\n request.onsuccess = () => {\n resolve();\n };\n });\n },\n\n /**\n * Returns all items as map of key to value, mainly used for debugging dumps.\n * The type T is applied to all values, even though they might not be of type\n * T (in the case when you store different data types in the same store).\n */\n async asMap<T>(): Promise<Map<string, StoredObject<T>>> {\n const map = new Map<string, StoredObject<T>>();\n await obj.forEach((key, value, expiryMs, storedMs) => {\n map.set(key, { value: value as T, expiryMs, storedMs });\n });\n return map;\n },\n\n /** Returns the ms timestamp for the last GC (garbage collection). */\n getLastGcMs(): number {\n const lastGcMsStr = localStorage.getItem(gcMsStorageKey);\n if (!lastGcMsStr) return 0;\n\n const ms = Number(lastGcMsStr);\n return isNaN(ms) ? 0 : ms;\n },\n\n /** Set the ms timestamp for the last GC (garbage collection). */\n setLastGcMs(ms: number) {\n localStorage.setItem(gcMsStorageKey, String(ms));\n },\n\n /** Perform garbage-collection if due, else do nothing. */\n async gc(): Promise<void> {\n const lastGcMs = obj.getLastGcMs();\n\n // Set initial timestamp - no need GC now.\n if (!lastGcMs) {\n obj.setLastGcMs(Date.now());\n return;\n }\n\n if (Date.now() < lastGcMs + gcIntervalMs) {\n return; // not due for next GC yet\n }\n\n // GC is due now, so run it.\n await obj.gcNow();\n },\n\n /**\n * Perform garbage collection immediately without checking whether we are\n * due for the next GC or not.\n */\n async gcNow(): Promise<void> {\n console.log(`Starting kvStore GC on ${dbName} v${dbVersion}...`);\n\n // Prevent concurrent GC runs.\n obj.setLastGcMs(Date.now());\n\n const keysToDelete: string[] = [];\n await obj.forEach(\n async (key: string, value: unknown, expiryMs: number) => {\n if (value === undefined || Date.now() >= expiryMs) {\n keysToDelete.push(key);\n }\n },\n );\n\n if (keysToDelete.length) {\n await obj.delete(keysToDelete);\n }\n\n console.log(\n `Finished kvStore GC on ${dbName} v${dbVersion} ` +\n `- deleted ${keysToDelete.length} keys`,\n );\n\n // Mark the end time as last GC time.\n obj.setLastGcMs(Date.now());\n },\n\n /** Returns `this` casted into a StorageAdapter<T>. */\n asStorageAdapter<T>(): StorageAdapter<T> {\n return obj as StorageAdapter<T>;\n },\n } as const;\n\n // Using `any` because the store could store any type of data for each key,\n // but the caller can specify a more specific type when calling each of the\n // methods.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return obj satisfies FullStorageAdapter<any>;\n}\n\nexport type KvStore = ReturnType<typeof createKvStore>;\n\n/**\n * Default KV store ready for immediate use. You can create new instances if\n * you want, but most likely you will only need one store instance.\n */\nexport const kvStore = createKvStore(KvStoreConfig.dbName);\n\n/** Create a KV store item with a key and a default expiration. */\nexport function kvStoreItem<T>(\n key: string,\n expiryMs?: number | Duration,\n store: KvStore = kvStore,\n) {\n const defaultExpiryMs = expiryMs && durationOrMsToMs(expiryMs);\n\n const obj = {\n key,\n defaultExpiryMs,\n store,\n\n /** Set a value in the store. */\n async set(value: T, expiryDeltaMs?: number | undefined): Promise<void> {\n await store.set(key, value, expiryDeltaMs ?? defaultExpiryMs);\n },\n\n /**\n * Example usage:\n *\n * const { value, storedMs, expiryMs, storedMs } =\n * await myKvItem.getStoredObject();\n */\n async getStoredObject(): Promise<KvStoredObject<T> | undefined> {\n return await store.getStoredObject(key);\n },\n\n /** Get a value by key, or undefined if it does not exist. */\n async get(): Promise<T | undefined> {\n return await store.get(key);\n },\n\n /** Delete this key from the store. */\n async delete(): Promise<void> {\n await store.delete(key);\n },\n } as const;\n\n return obj;\n}\n\n/** Class to represent one key in the store with a default expiration. */\nexport type KvStoreItem<T> = ReturnType<typeof kvStoreItem<T>>;\n"],"mappings":"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","names":["configureKvStore","config","KvStoreConfig","validateStoredObject","obj","withOnError","request","reject","event","createKvStore","dbName","options","db","dbVersion","storeName","defaultExpiryMs","durationOrMsToMs","gcIntervalMs","gcMsStorageKey","getOrCreateDb","resolve","transact","mode","callback","transaction","objectStore","key","value","expiryDeltaMs","nowMs","stored","k","valid","e","cursor","count","map","expiryMs","storedMs","lastGcMsStr","ms","lastGcMs","keysToDelete","kvStoreItem","store","kvStore","init_kvStore","__esmMin","init_duration"]}
@@ -0,0 +1,42 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkILGTU46Tcjs = require('./chunk-ILGTU46T.cjs');
4
+
5
+ // src/timeConstants.ts
6
+ var MS_PER_SECOND, MS_PER_MINUTE, MS_PER_HOUR, MS_PER_DAY, MS_PER_WEEK, SECONDS_PER_MINUTE, SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, MINUTES_PER_HOUR, MINUTES_PER_DAY, MINUTES_PER_WEEK, HOURS_PER_DAY, HOURS_PER_WEEK;
7
+ var init_timeConstants = _chunkILGTU46Tcjs.__esm.call(void 0, {
8
+ "src/timeConstants.ts"() {
9
+ MS_PER_SECOND = exports.MS_PER_SECOND = 1e3;
10
+ MS_PER_MINUTE = exports.MS_PER_MINUTE = 6e4;
11
+ MS_PER_HOUR = exports.MS_PER_HOUR = 36e5;
12
+ MS_PER_DAY = exports.MS_PER_DAY = 864e5;
13
+ MS_PER_WEEK = exports.MS_PER_WEEK = 6048e5;
14
+ SECONDS_PER_MINUTE = exports.SECONDS_PER_MINUTE = 60;
15
+ SECONDS_PER_HOUR = exports.SECONDS_PER_HOUR = 3600;
16
+ SECONDS_PER_DAY = exports.SECONDS_PER_DAY = 86400;
17
+ SECONDS_PER_WEEK = exports.SECONDS_PER_WEEK = 604800;
18
+ MINUTES_PER_HOUR = exports.MINUTES_PER_HOUR = 60;
19
+ MINUTES_PER_DAY = exports.MINUTES_PER_DAY = 1440;
20
+ MINUTES_PER_WEEK = exports.MINUTES_PER_WEEK = 10080;
21
+ HOURS_PER_DAY = exports.HOURS_PER_DAY = 24;
22
+ HOURS_PER_WEEK = exports.HOURS_PER_WEEK = 168;
23
+ }
24
+ });
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ exports.MS_PER_SECOND = MS_PER_SECOND; exports.MS_PER_MINUTE = MS_PER_MINUTE; exports.MS_PER_HOUR = MS_PER_HOUR; exports.MS_PER_DAY = MS_PER_DAY; exports.MS_PER_WEEK = MS_PER_WEEK; exports.SECONDS_PER_MINUTE = SECONDS_PER_MINUTE; exports.SECONDS_PER_HOUR = SECONDS_PER_HOUR; exports.SECONDS_PER_DAY = SECONDS_PER_DAY; exports.SECONDS_PER_WEEK = SECONDS_PER_WEEK; exports.MINUTES_PER_HOUR = MINUTES_PER_HOUR; exports.MINUTES_PER_DAY = MINUTES_PER_DAY; exports.MINUTES_PER_WEEK = MINUTES_PER_WEEK; exports.HOURS_PER_DAY = HOURS_PER_DAY; exports.HOURS_PER_WEEK = HOURS_PER_WEEK; exports.init_timeConstants = init_timeConstants;