@choksheak/ts-utils 0.2.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/README.md +2 -0
  2. package/{arrayBuffer.js → arrayBuffer.cjs} +0 -1
  3. package/arrayBuffer.d.mts +10 -0
  4. package/arrayBuffer.min.cjs +2 -0
  5. package/arrayBuffer.min.cjs.map +1 -0
  6. package/arrayBuffer.min.mjs +2 -0
  7. package/{arrayBuffer.js.map → arrayBuffer.min.mjs.map} +1 -1
  8. package/arrayBuffer.mjs +14 -0
  9. package/{assert.js → assert.cjs} +0 -1
  10. package/assert.d.mts +7 -0
  11. package/assert.min.cjs +2 -0
  12. package/assert.min.cjs.map +1 -0
  13. package/assert.min.mjs +2 -0
  14. package/{assert.js.map → assert.min.mjs.map} +1 -1
  15. package/assert.mjs +11 -0
  16. package/{average.js → average.cjs} +0 -1
  17. package/average.d.mts +7 -0
  18. package/average.min.cjs +2 -0
  19. package/{average.js.map → average.min.cjs.map} +1 -1
  20. package/average.min.mjs +2 -0
  21. package/average.min.mjs.map +1 -0
  22. package/average.mjs +20 -0
  23. package/{base64Url.js → base64Url.cjs} +0 -1
  24. package/base64Url.d.mts +10 -0
  25. package/base64Url.min.cjs +2 -0
  26. package/base64Url.min.cjs.map +1 -0
  27. package/base64Url.min.mjs +2 -0
  28. package/{base64Url.js.map → base64Url.min.mjs.map} +1 -1
  29. package/base64Url.mjs +14 -0
  30. package/{dateTimeStr.js → dateTimeStr.cjs} +0 -1
  31. package/dateTimeStr.d.mts +85 -0
  32. package/dateTimeStr.min.cjs +2 -0
  33. package/dateTimeStr.min.cjs.map +1 -0
  34. package/dateTimeStr.min.mjs +2 -0
  35. package/{dateTimeStr.js.map → dateTimeStr.min.mjs.map} +1 -1
  36. package/dateTimeStr.mjs +83 -0
  37. package/{duration.js → duration.cjs} +9 -11
  38. package/duration.d.mts +78 -0
  39. package/duration.min.cjs +2 -0
  40. package/duration.min.cjs.map +1 -0
  41. package/duration.min.mjs +2 -0
  42. package/duration.min.mjs.map +1 -0
  43. package/duration.mjs +154 -0
  44. package/{isEmpty.js → isEmpty.cjs} +0 -1
  45. package/isEmpty.d.mts +6 -0
  46. package/isEmpty.min.cjs +2 -0
  47. package/isEmpty.min.cjs.map +1 -0
  48. package/isEmpty.min.mjs +2 -0
  49. package/{isEmpty.js.map → isEmpty.min.mjs.map} +1 -1
  50. package/isEmpty.mjs +22 -0
  51. package/kvStore.cjs +333 -0
  52. package/kvStore.d.mts +97 -0
  53. package/kvStore.min.cjs +2 -0
  54. package/kvStore.min.cjs.map +1 -0
  55. package/kvStore.min.mjs +2 -0
  56. package/kvStore.min.mjs.map +1 -0
  57. package/kvStore.mjs +300 -0
  58. package/{localStorageCache.js → localStorageCache.cjs} +5 -7
  59. package/localStorageCache.d.mts +57 -0
  60. package/localStorageCache.min.cjs +2 -0
  61. package/localStorageCache.min.cjs.map +1 -0
  62. package/localStorageCache.min.mjs +2 -0
  63. package/localStorageCache.min.mjs.map +1 -0
  64. package/localStorageCache.mjs +92 -0
  65. package/{logging.js → logging.cjs} +0 -1
  66. package/logging.d.mts +4 -0
  67. package/logging.min.cjs +2 -0
  68. package/logging.min.cjs.map +1 -0
  69. package/logging.min.mjs +2 -0
  70. package/{logging.js.map → logging.min.mjs.map} +1 -1
  71. package/logging.mjs +21 -0
  72. package/{nonEmpty.js → nonEmpty.cjs} +0 -1
  73. package/nonEmpty.d.mts +10 -0
  74. package/nonEmpty.min.cjs +2 -0
  75. package/{nonEmpty.js.map → nonEmpty.min.cjs.map} +1 -1
  76. package/nonEmpty.min.mjs +2 -0
  77. package/nonEmpty.min.mjs.map +1 -0
  78. package/nonEmpty.mjs +30 -0
  79. package/{nonNil.js → nonNil.cjs} +0 -1
  80. package/{src/nonNil.ts → nonNil.d.mts} +3 -6
  81. package/nonNil.min.cjs +2 -0
  82. package/nonNil.min.cjs.map +1 -0
  83. package/nonNil.min.mjs +2 -0
  84. package/{nonNil.js.map → nonNil.min.mjs.map} +1 -1
  85. package/nonNil.mjs +10 -0
  86. package/package.json +414 -24
  87. package/{round.js → round.cjs} +0 -1
  88. package/{src/round.ts → round.d.mts} +4 -8
  89. package/round.min.cjs +2 -0
  90. package/round.min.cjs.map +1 -0
  91. package/round.min.mjs +2 -0
  92. package/{round.js.map → round.min.mjs.map} +1 -1
  93. package/round.mjs +12 -0
  94. package/{safeBtoa.js → safeBtoa.cjs} +0 -1
  95. package/safeBtoa.d.mts +6 -0
  96. package/safeBtoa.min.cjs +2 -0
  97. package/safeBtoa.min.cjs.map +1 -0
  98. package/safeBtoa.min.mjs +2 -0
  99. package/{safeBtoa.js.map → safeBtoa.min.mjs.map} +1 -1
  100. package/safeBtoa.mjs +9 -0
  101. package/{safeParseFloat.js → safeParseFloat.cjs} +0 -1
  102. package/safeParseFloat.d.mts +6 -0
  103. package/safeParseFloat.min.cjs +2 -0
  104. package/safeParseFloat.min.cjs.map +1 -0
  105. package/safeParseFloat.min.mjs +2 -0
  106. package/{safeParseFloat.js.map → safeParseFloat.min.mjs.map} +1 -1
  107. package/safeParseFloat.mjs +8 -0
  108. package/{safeParseInt.js → safeParseInt.cjs} +0 -1
  109. package/safeParseInt.d.mts +6 -0
  110. package/safeParseInt.min.cjs +2 -0
  111. package/safeParseInt.min.cjs.map +1 -0
  112. package/safeParseInt.min.mjs +2 -0
  113. package/{safeParseInt.js.map → safeParseInt.min.mjs.map} +1 -1
  114. package/safeParseInt.mjs +8 -0
  115. package/sha256.cjs +35 -0
  116. package/sha256.d.mts +6 -0
  117. package/sha256.min.cjs +2 -0
  118. package/sha256.min.cjs.map +1 -0
  119. package/sha256.min.mjs +2 -0
  120. package/{sha256.js.map → sha256.min.mjs.map} +1 -1
  121. package/sha256.mjs +10 -0
  122. package/{sleep.js → sleep.cjs} +0 -1
  123. package/{src/sleep.ts → sleep.d.mts} +3 -3
  124. package/sleep.min.cjs +2 -0
  125. package/sleep.min.cjs.map +1 -0
  126. package/sleep.min.mjs +2 -0
  127. package/{sleep.js.map → sleep.min.mjs.map} +1 -1
  128. package/sleep.mjs +7 -0
  129. package/{sum.js → sum.cjs} +0 -1
  130. package/sum.d.mts +7 -0
  131. package/sum.min.cjs +2 -0
  132. package/sum.min.cjs.map +1 -0
  133. package/sum.min.mjs +2 -0
  134. package/{sum.js.map → sum.min.mjs.map} +1 -1
  135. package/sum.mjs +13 -0
  136. package/{timeConstants.js → timeConstants.cjs} +0 -1
  137. package/timeConstants.d.mts +20 -0
  138. package/timeConstants.min.cjs +2 -0
  139. package/timeConstants.min.cjs.map +1 -0
  140. package/timeConstants.min.mjs +2 -0
  141. package/{timeConstants.js.map → timeConstants.min.mjs.map} +1 -1
  142. package/timeConstants.mjs +31 -0
  143. package/{timer.js → timer.cjs} +6 -6
  144. package/timer.d.mts +13 -0
  145. package/timer.min.cjs +2 -0
  146. package/timer.min.cjs.map +1 -0
  147. package/timer.min.mjs +2 -0
  148. package/timer.min.mjs.map +1 -0
  149. package/timer.mjs +161 -0
  150. package/docs/.nojekyll +0 -1
  151. package/docs/assets/hierarchy.js +0 -1
  152. package/docs/assets/highlight.css +0 -22
  153. package/docs/assets/icons.js +0 -18
  154. package/docs/assets/icons.svg +0 -1
  155. package/docs/assets/main.js +0 -60
  156. package/docs/assets/navigation.js +0 -1
  157. package/docs/assets/search.js +0 -1
  158. package/docs/assets/style.css +0 -1640
  159. package/docs/classes/kvStore.KVStore.html +0 -26
  160. package/docs/classes/kvStore.KVStoreField.html +0 -7
  161. package/docs/classes/timer.Timer.html +0 -8
  162. package/docs/functions/arrayBuffer.arrayBufferToBase64.html +0 -2
  163. package/docs/functions/arrayBuffer.arrayBufferToHex.html +0 -2
  164. package/docs/functions/assert.assert.html +0 -3
  165. package/docs/functions/average.average.html +0 -3
  166. package/docs/functions/base64Url.base64ToBase64URL.html +0 -2
  167. package/docs/functions/base64Url.base64UrlToBase64.html +0 -2
  168. package/docs/functions/dateTimeStr.getDisplayDateTime.html +0 -3
  169. package/docs/functions/dateTimeStr.getLongMonthNameOneIndexed.html +0 -4
  170. package/docs/functions/dateTimeStr.getLongMonthNameZeroIndexed.html +0 -4
  171. package/docs/functions/dateTimeStr.getShortMonthNameOneIndexed.html +0 -4
  172. package/docs/functions/dateTimeStr.getShortMonthNameZeroIndexed.html +0 -4
  173. package/docs/functions/dateTimeStr.hhMm.html +0 -4
  174. package/docs/functions/dateTimeStr.hhMmSs.html +0 -4
  175. package/docs/functions/dateTimeStr.hhMmSsMs.html +0 -5
  176. package/docs/functions/dateTimeStr.toDate.html +0 -4
  177. package/docs/functions/dateTimeStr.tzShort.html +0 -4
  178. package/docs/functions/dateTimeStr.yyyyMm.html +0 -4
  179. package/docs/functions/dateTimeStr.yyyyMmDd.html +0 -4
  180. package/docs/functions/duration.durationOrMsToMs.html +0 -2
  181. package/docs/functions/duration.durationToMs.html +0 -2
  182. package/docs/functions/duration.elapsed.html +0 -2
  183. package/docs/functions/duration.formatDuration.html +0 -4
  184. package/docs/functions/duration.msToDuration.html +0 -5
  185. package/docs/functions/duration.readableDuration.html +0 -4
  186. package/docs/functions/isEmpty.isEmpty.html +0 -2
  187. package/docs/functions/kvStore.kvStoreItem.html +0 -2
  188. package/docs/functions/localStorageCache.storeItem.html +0 -15
  189. package/docs/functions/logging.capLength.html +0 -1
  190. package/docs/functions/logging.stringify.html +0 -1
  191. package/docs/functions/nonEmpty.nonEmpty.html +0 -5
  192. package/docs/functions/nonNil.nonNil.html +0 -5
  193. package/docs/functions/round.round.html +0 -5
  194. package/docs/functions/round.roundS.html +0 -3
  195. package/docs/functions/safeBtoa.safeBtoa.html +0 -2
  196. package/docs/functions/safeParseFloat.safeParseFloat.html +0 -2
  197. package/docs/functions/safeParseInt.safeParseInt.html +0 -2
  198. package/docs/functions/sha256.sha256.html +0 -2
  199. package/docs/functions/sleep.sleep.html +0 -3
  200. package/docs/functions/sum.sum.html +0 -3
  201. package/docs/functions/timer.timer.html +0 -2
  202. package/docs/hierarchy.html +0 -1
  203. package/docs/index.html +0 -4
  204. package/docs/modules/arrayBuffer.html +0 -1
  205. package/docs/modules/assert.html +0 -1
  206. package/docs/modules/average.html +0 -1
  207. package/docs/modules/base64Url.html +0 -1
  208. package/docs/modules/dateTimeStr.html +0 -1
  209. package/docs/modules/duration.html +0 -1
  210. package/docs/modules/isEmpty.html +0 -1
  211. package/docs/modules/kvStore.html +0 -1
  212. package/docs/modules/localStorageCache.html +0 -1
  213. package/docs/modules/logging.html +0 -1
  214. package/docs/modules/nonEmpty.html +0 -1
  215. package/docs/modules/nonNil.html +0 -1
  216. package/docs/modules/round.html +0 -1
  217. package/docs/modules/safeBtoa.html +0 -1
  218. package/docs/modules/safeParseFloat.html +0 -1
  219. package/docs/modules/safeParseInt.html +0 -1
  220. package/docs/modules/sha256.html +0 -1
  221. package/docs/modules/sleep.html +0 -1
  222. package/docs/modules/sum.html +0 -1
  223. package/docs/modules/timeConstants.html +0 -1
  224. package/docs/modules/timer.html +0 -1
  225. package/docs/modules.html +0 -1
  226. package/docs/types/dateTimeStr.AnyDateTime.html +0 -1
  227. package/docs/types/duration.Duration.html +0 -6
  228. package/docs/types/duration.DurationStyle.html +0 -6
  229. package/docs/types/duration.DurationSuffixMap.html +0 -6
  230. package/docs/types/duration.DurationSuffixType.html +0 -1
  231. package/docs/types/duration.DurationType.html +0 -2
  232. package/docs/types/localStorageCache.StoredItem.html +0 -4
  233. package/docs/variables/duration.DURATION_STYLE_SUFFIX_MAP.html +0 -1
  234. package/docs/variables/duration.DURATION_TYPE_SEQUENCE.html +0 -2
  235. package/docs/variables/kvStore.DEFAULT_EXPIRY_DELTA_MS.html +0 -2
  236. package/docs/variables/kvStore.GC_INTERVAL_MS.html +0 -2
  237. package/docs/variables/kvStore.MILLIS_PER_DAY.html +0 -2
  238. package/docs/variables/kvStore.kvStore.html +0 -3
  239. package/docs/variables/timeConstants.HOURS_PER_DAY.html +0 -1
  240. package/docs/variables/timeConstants.HOURS_PER_WEEK.html +0 -1
  241. package/docs/variables/timeConstants.MINUTES_PER_DAY.html +0 -1
  242. package/docs/variables/timeConstants.MINUTES_PER_HOUR.html +0 -1
  243. package/docs/variables/timeConstants.MINUTES_PER_WEEK.html +0 -1
  244. package/docs/variables/timeConstants.MS_PER_DAY.html +0 -1
  245. package/docs/variables/timeConstants.MS_PER_HOUR.html +0 -1
  246. package/docs/variables/timeConstants.MS_PER_MINUTE.html +0 -1
  247. package/docs/variables/timeConstants.MS_PER_SECOND.html +0 -3
  248. package/docs/variables/timeConstants.MS_PER_WEEK.html +0 -1
  249. package/docs/variables/timeConstants.SECONDS_PER_DAY.html +0 -1
  250. package/docs/variables/timeConstants.SECONDS_PER_HOUR.html +0 -1
  251. package/docs/variables/timeConstants.SECONDS_PER_MINUTE.html +0 -1
  252. package/docs/variables/timeConstants.SECONDS_PER_WEEK.html +0 -1
  253. package/duration.js.map +0 -1
  254. package/kvStore.js +0 -383
  255. package/kvStore.js.map +0 -1
  256. package/localStorageCache.js.map +0 -1
  257. package/sha256.js +0 -58
  258. package/src/arrayBuffer.ts +0 -29
  259. package/src/assert.ts +0 -14
  260. package/src/average.ts +0 -13
  261. package/src/base64Url.ts +0 -20
  262. package/src/dateTimeStr.ts +0 -184
  263. package/src/duration.ts +0 -260
  264. package/src/isEmpty.ts +0 -32
  265. package/src/kvStore.ts +0 -444
  266. package/src/localStorageCache.ts +0 -121
  267. package/src/logging.ts +0 -26
  268. package/src/nonEmpty.ts +0 -18
  269. package/src/safeBtoa.ts +0 -15
  270. package/src/safeParseFloat.ts +0 -10
  271. package/src/safeParseInt.ts +0 -10
  272. package/src/sha256.ts +0 -13
  273. package/src/sum.ts +0 -17
  274. package/src/timeConstants.ts +0 -22
  275. package/src/timer.ts +0 -33
  276. package/timer.js.map +0 -1
package/kvStore.mjs ADDED
@@ -0,0 +1,300 @@
1
+ // src/timeConstants.ts
2
+ var MS_PER_SECOND = 1e3;
3
+ var MS_PER_MINUTE = 6e4;
4
+ var MS_PER_HOUR = 36e5;
5
+ var MS_PER_DAY = 864e5;
6
+
7
+ // src/duration.ts
8
+ function durationToMs(duration) {
9
+ const daysMs = (duration.days ?? 0) * MS_PER_DAY;
10
+ const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;
11
+ const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;
12
+ const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;
13
+ const msMs = duration.milliseconds ?? 0;
14
+ return daysMs + hoursMs + minsMs + secsMs + msMs;
15
+ }
16
+ function durationOrMsToMs(duration) {
17
+ return typeof duration === "number" ? duration : durationToMs(duration);
18
+ }
19
+
20
+ // src/kvStore.ts
21
+ var DEFAULT_DB_NAME = "KVStore";
22
+ var DEFAULT_DB_VERSION = 1;
23
+ var STORE_NAME = "kvStore";
24
+ var MILLIS_PER_DAY = 864e5;
25
+ var DEFAULT_EXPIRY_DELTA_MS = MILLIS_PER_DAY * 30;
26
+ var GC_INTERVAL_MS = MILLIS_PER_DAY;
27
+ function validateStoredObject(obj) {
28
+ 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) {
29
+ return void 0;
30
+ }
31
+ return obj;
32
+ }
33
+ function withOnError(request, reject) {
34
+ request.onerror = (event) => {
35
+ reject(event);
36
+ };
37
+ return request;
38
+ }
39
+ var KVStoreField = class {
40
+ constructor(store, key) {
41
+ this.store = store;
42
+ this.key = key;
43
+ }
44
+ get() {
45
+ return this.store.get(this.key);
46
+ }
47
+ set(t) {
48
+ return this.store.set(this.key, t);
49
+ }
50
+ delete() {
51
+ return this.store.delete(this.key);
52
+ }
53
+ };
54
+ var KVStore = class {
55
+ constructor(dbName, dbVersion, defaultExpiryDeltaMs) {
56
+ this.dbName = dbName;
57
+ this.dbVersion = dbVersion;
58
+ this.defaultExpiryDeltaMs = defaultExpiryDeltaMs;
59
+ this.gcMsStorageKey = `__kvStore:lastGcMs:${dbName}:v${dbVersion}:${STORE_NAME}`;
60
+ }
61
+ // We'll init the DB only on first use.
62
+ db;
63
+ // Local storage key name for the last GC completed timestamp.
64
+ gcMsStorageKey;
65
+ async getOrCreateDb() {
66
+ if (!this.db) {
67
+ this.db = await new Promise((resolve, reject) => {
68
+ const request = withOnError(
69
+ globalThis.indexedDB.open(this.dbName, this.dbVersion),
70
+ reject
71
+ );
72
+ request.onupgradeneeded = (event) => {
73
+ const db = event.target.result;
74
+ const objectStore = db.createObjectStore(STORE_NAME, {
75
+ keyPath: "key"
76
+ });
77
+ objectStore.createIndex("key", "key", {
78
+ unique: true
79
+ });
80
+ };
81
+ request.onsuccess = (event) => {
82
+ const db = event.target.result;
83
+ resolve(db);
84
+ };
85
+ });
86
+ }
87
+ return this.db;
88
+ }
89
+ async transact(mode, callback) {
90
+ const db = await this.getOrCreateDb();
91
+ return await new Promise((resolve, reject) => {
92
+ const transaction = withOnError(db.transaction(STORE_NAME, mode), reject);
93
+ transaction.onabort = (event) => {
94
+ reject(event);
95
+ };
96
+ const objectStore = transaction.objectStore(STORE_NAME);
97
+ callback(objectStore, resolve, reject);
98
+ });
99
+ }
100
+ async set(key, value, expiryDeltaMs = this.defaultExpiryDeltaMs) {
101
+ const nowMs = Date.now();
102
+ const obj = {
103
+ key,
104
+ value,
105
+ storedMs: nowMs,
106
+ expiryMs: nowMs + durationOrMsToMs(expiryDeltaMs)
107
+ };
108
+ return await this.transact(
109
+ "readwrite",
110
+ (objectStore, resolve, reject) => {
111
+ const request = withOnError(objectStore.put(obj), reject);
112
+ request.onsuccess = () => {
113
+ resolve(value);
114
+ this.gc();
115
+ };
116
+ }
117
+ );
118
+ }
119
+ /** Delete one or multiple keys. */
120
+ async delete(key) {
121
+ return await this.transact(
122
+ "readwrite",
123
+ (objectStore, resolve, reject) => {
124
+ objectStore.transaction.oncomplete = () => {
125
+ resolve();
126
+ };
127
+ if (typeof key === "string") {
128
+ withOnError(objectStore.delete(key), reject);
129
+ } else {
130
+ for (const k of key) {
131
+ withOnError(objectStore.delete(k), reject);
132
+ }
133
+ }
134
+ }
135
+ );
136
+ }
137
+ async getStoredObject(key) {
138
+ const stored = await this.transact(
139
+ "readonly",
140
+ (objectStore, resolve, reject) => {
141
+ const request = withOnError(objectStore.get(key), reject);
142
+ request.onsuccess = () => {
143
+ resolve(request.result);
144
+ };
145
+ }
146
+ );
147
+ if (!stored) {
148
+ return void 0;
149
+ }
150
+ try {
151
+ const obj = validateStoredObject(stored);
152
+ if (!obj) {
153
+ await this.delete(key);
154
+ this.gc();
155
+ return void 0;
156
+ }
157
+ return obj;
158
+ } catch (e) {
159
+ console.error(`Invalid kv value: ${key}=${JSON.stringify(stored)}:`, e);
160
+ await this.delete(key);
161
+ this.gc();
162
+ return void 0;
163
+ }
164
+ }
165
+ async get(key) {
166
+ const obj = await this.getStoredObject(key);
167
+ return obj?.value;
168
+ }
169
+ async forEach(callback) {
170
+ await this.transact("readonly", (objectStore, resolve, reject) => {
171
+ const request = withOnError(objectStore.openCursor(), reject);
172
+ request.onsuccess = async (event) => {
173
+ const cursor = event.target.result;
174
+ if (cursor) {
175
+ if (cursor.key) {
176
+ const obj = validateStoredObject(cursor.value);
177
+ if (obj) {
178
+ await callback(String(cursor.key), obj.value, obj.expiryMs);
179
+ } else {
180
+ await callback(String(cursor.key), void 0, 0);
181
+ }
182
+ }
183
+ cursor.continue();
184
+ } else {
185
+ resolve();
186
+ }
187
+ };
188
+ });
189
+ }
190
+ /** Cannot be a getter because this needs to be async. */
191
+ async size() {
192
+ let count = 0;
193
+ await this.forEach(() => {
194
+ count++;
195
+ });
196
+ return count;
197
+ }
198
+ async clear() {
199
+ const keys = [];
200
+ await this.forEach((key) => {
201
+ keys.push(key);
202
+ });
203
+ await this.delete(keys);
204
+ }
205
+ /** Mainly for debugging dumps. */
206
+ async asMap() {
207
+ const map = /* @__PURE__ */ new Map();
208
+ await this.forEach((key, value, expiryMs) => {
209
+ map.set(key, { value, expiryMs });
210
+ });
211
+ return map;
212
+ }
213
+ get lastGcMs() {
214
+ const lastGcMsStr = globalThis.localStorage.getItem(this.gcMsStorageKey);
215
+ if (!lastGcMsStr) return 0;
216
+ const ms = Number(lastGcMsStr);
217
+ return isNaN(ms) ? 0 : ms;
218
+ }
219
+ set lastGcMs(ms) {
220
+ globalThis.localStorage.setItem(this.gcMsStorageKey, String(ms));
221
+ }
222
+ /** Perform garbage-collection if due. */
223
+ async gc() {
224
+ const lastGcMs = this.lastGcMs;
225
+ if (!lastGcMs) {
226
+ this.lastGcMs = Date.now();
227
+ return;
228
+ }
229
+ if (Date.now() < lastGcMs + GC_INTERVAL_MS) {
230
+ return;
231
+ }
232
+ await this.gcNow();
233
+ }
234
+ /** Perform garbage-collection immediately without checking. */
235
+ async gcNow() {
236
+ console.log(`Starting kvStore GC on ${this.dbName} v${this.dbVersion}...`);
237
+ this.lastGcMs = Date.now();
238
+ const keysToDelete = [];
239
+ await this.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 this.delete(keysToDelete);
248
+ }
249
+ console.log(
250
+ `Finished kvStore GC on ${this.dbName} v${this.dbVersion} - deleted ${keysToDelete.length} keys`
251
+ );
252
+ this.lastGcMs = Date.now();
253
+ }
254
+ /** Get an independent store item with a locked key and value type. */
255
+ field(key) {
256
+ return new KVStoreField(this, key);
257
+ }
258
+ };
259
+ var kvStore = new KVStore(
260
+ DEFAULT_DB_NAME,
261
+ DEFAULT_DB_VERSION,
262
+ DEFAULT_EXPIRY_DELTA_MS
263
+ );
264
+ var KvStoreItem = class {
265
+ constructor(key, defaultExpiryDeltaMs, store = kvStore) {
266
+ this.key = key;
267
+ this.defaultExpiryDeltaMs = defaultExpiryDeltaMs;
268
+ this.store = store;
269
+ }
270
+ /**
271
+ * Example usage:
272
+ *
273
+ * const { value, storedMs, expiryMs } = await myKvItem.getStoredObject();
274
+ */
275
+ async getStoredObject() {
276
+ return await this.store.getStoredObject(this.key);
277
+ }
278
+ async get() {
279
+ return await this.store.get(this.key);
280
+ }
281
+ async set(value, expiryDeltaMs = this.defaultExpiryDeltaMs) {
282
+ await this.store.set(this.key, value, expiryDeltaMs);
283
+ }
284
+ async delete() {
285
+ await this.store.delete(this.key);
286
+ }
287
+ };
288
+ function kvStoreItem(key, defaultExpiration) {
289
+ const defaultExpiryDeltaMs = durationOrMsToMs(defaultExpiration);
290
+ return new KvStoreItem(key, defaultExpiryDeltaMs);
291
+ }
292
+ export {
293
+ DEFAULT_EXPIRY_DELTA_MS,
294
+ GC_INTERVAL_MS,
295
+ KVStore,
296
+ KVStoreField,
297
+ MILLIS_PER_DAY,
298
+ kvStore,
299
+ kvStoreItem
300
+ };
@@ -32,12 +32,11 @@ var MS_PER_DAY = 864e5;
32
32
 
33
33
  // src/duration.ts
34
34
  function durationToMs(duration) {
35
- var _a, _b, _c, _d, _e;
36
- const daysMs = ((_a = duration.days) != null ? _a : 0) * MS_PER_DAY;
37
- const hoursMs = ((_b = duration.hours) != null ? _b : 0) * MS_PER_HOUR;
38
- const minsMs = ((_c = duration.minutes) != null ? _c : 0) * MS_PER_MINUTE;
39
- const secsMs = ((_d = duration.seconds) != null ? _d : 0) * MS_PER_SECOND;
40
- const msMs = (_e = duration.milliseconds) != null ? _e : 0;
35
+ const daysMs = (duration.days ?? 0) * MS_PER_DAY;
36
+ const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;
37
+ const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;
38
+ const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;
39
+ const msMs = duration.milliseconds ?? 0;
41
40
  return daysMs + hoursMs + minsMs + secsMs + msMs;
42
41
  }
43
42
  function durationOrMsToMs(duration) {
@@ -118,4 +117,3 @@ var CacheItem = class {
118
117
  0 && (module.exports = {
119
118
  storeItem
120
119
  });
121
- //# sourceMappingURL=localStorageCache.js.map
@@ -0,0 +1,57 @@
1
+ import { Duration } from './duration.mjs';
2
+
3
+ type StoredItem<T> = {
4
+ value: T;
5
+ storedMs: number;
6
+ expiryMs: number;
7
+ };
8
+ /**
9
+ * Simple local storage cache with support for auto-expiration.
10
+ * Note that this works in the browser context only because nodejs does not
11
+ * have local storage.
12
+ *
13
+ * Create a cache item accessor object with auto-expiration. The value will
14
+ * always be stored as a string by applying JSON.stringify(), and will be
15
+ * returned in the same object type by applying JSON.parse().
16
+ *
17
+ * In order to provide proper type-checking, please always specify the T
18
+ * type parameter. E.g. const item = storeItem<string>("name", 10_000);
19
+ *
20
+ * @param key The store key in local storage.
21
+ * @param expires Either a number in milliseconds, or a Duration object
22
+ * @param logError Log an error if we found an invalid object in the store.
23
+ * The invalid object is usually a string that cannot be parsed as JSON.
24
+ * @param defaultValue Specify a default value to use for the object. Defaults
25
+ * to undefined.
26
+ */
27
+ declare function storeItem<T>(key: string, expires: number | Duration, logError?: boolean, defaultValue?: T): CacheItem<T>;
28
+ declare class CacheItem<T> {
29
+ readonly key: string;
30
+ readonly expireDeltaMs: number;
31
+ readonly logError: boolean;
32
+ readonly defaultValue: T | undefined;
33
+ /**
34
+ * Create a cache item accessor object with auto-expiration.
35
+ */
36
+ constructor(key: string, expireDeltaMs: number, logError: boolean, defaultValue: T | undefined);
37
+ /**
38
+ * Set the value of this item with auto-expiration.
39
+ */
40
+ set(value: T, expiryDelta?: number | Duration): void;
41
+ /**
42
+ * Example usage:
43
+ *
44
+ * const { value, storedMs, expiryMs } = await myItem.getStoredItem();
45
+ */
46
+ getStoredItem(): StoredItem<T> | undefined;
47
+ /**
48
+ * Get the value of this item, or undefined if value is not set or expired.
49
+ */
50
+ get(): T | undefined;
51
+ /**
52
+ * Remove the value of this item.
53
+ */
54
+ remove(): void;
55
+ }
56
+
57
+ export { type StoredItem, storeItem };
@@ -0,0 +1,2 @@
1
+ "use strict";var i=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var d=(r,o)=>{for(var t in o)i(r,t,{get:o[t],enumerable:!0})},f=(r,o,t,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of c(o))!p.call(r,e)&&e!==t&&i(r,e,{get:()=>o[e],enumerable:!(n=l(o,e))||n.enumerable});return r};var S=r=>f(i({},"__esModule",{value:!0}),r);var h={};d(h,{storeItem:()=>M});module.exports=S(h);function y(r){let o=(r.days??0)*864e5,t=(r.hours??0)*36e5,n=(r.minutes??0)*6e4,e=(r.seconds??0)*1e3,s=r.milliseconds??0;return o+t+n+e+s}function u(r){return typeof r=="number"?r:y(r)}function M(r,o,t=!0,n){let e=u(o);return new a(r,e,t,n)}var a=class{constructor(o,t,n,e){this.key=o;this.expireDeltaMs=t;this.logError=n;this.defaultValue=e}set(o,t=this.expireDeltaMs){let n=Date.now(),e={value:o,storedMs:n,expiryMs:n+u(t)},s=JSON.stringify(e);globalThis.localStorage.setItem(this.key,s)}getStoredItem(){let o=globalThis.localStorage.getItem(this.key);if(o)try{let t=JSON.parse(o);if(!t||typeof t!="object"||!("value"in t)||!("storedMs"in t)||typeof t.storedMs!="number"||!("expiryMs"in t)||typeof t.expiryMs!="number"||Date.now()>=t.expiryMs){this.remove();return}return t}catch(t){this.logError&&console.error(`Found invalid storage value: ${this.key}=${o}:`,t),this.remove();return}}get(){let o=this.getStoredItem();return o!==void 0?o.value:this.defaultValue}remove(){globalThis.localStorage.removeItem(this.key)}};0&&(module.exports={storeItem});
2
+ //# sourceMappingURL=localStorageCache.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/localStorageCache.ts","../src/duration.ts"],"sourcesContent":["import { Duration, durationOrMsToMs } from \"./duration\";\n\nexport type StoredItem<T> = { value: T; storedMs: number; expiryMs: number };\n\n/**\n * Simple local storage cache with support for auto-expiration.\n * Note that this works in the browser context only because nodejs does not\n * have local storage.\n *\n * Create a cache item accessor object with auto-expiration. The value will\n * always be stored as a string by applying JSON.stringify(), and will be\n * returned in the same object type by applying JSON.parse().\n *\n * In order to provide proper type-checking, please always specify the T\n * type parameter. E.g. const item = storeItem<string>(\"name\", 10_000);\n *\n * @param key The store key in local storage.\n * @param expires Either a number in milliseconds, or a Duration object\n * @param logError Log an error if we found an invalid object in the store.\n * The invalid object is usually a string that cannot be parsed as JSON.\n * @param defaultValue Specify a default value to use for the object. Defaults\n * to undefined.\n */\nexport function storeItem<T>(\n key: string,\n expires: number | Duration,\n logError = true,\n defaultValue?: T,\n) {\n const expireDeltaMs = durationOrMsToMs(expires);\n\n return new CacheItem<T>(key, expireDeltaMs, logError, defaultValue);\n}\n\nclass CacheItem<T> {\n /**\n * Create a cache item accessor object with auto-expiration.\n */\n public constructor(\n public readonly key: string,\n public readonly expireDeltaMs: number,\n public readonly logError: boolean,\n public readonly defaultValue: T | undefined,\n ) {}\n\n /**\n * Set the value of this item with auto-expiration.\n */\n public set(\n value: T,\n expiryDelta: number | Duration = this.expireDeltaMs,\n ): void {\n const nowMs = Date.now();\n const toStore: StoredItem<T> = {\n value,\n storedMs: nowMs,\n expiryMs: nowMs + durationOrMsToMs(expiryDelta),\n };\n const valueStr = JSON.stringify(toStore);\n\n globalThis.localStorage.setItem(this.key, valueStr);\n }\n\n /**\n * Example usage:\n *\n * const { value, storedMs, expiryMs } = await myItem.getStoredItem();\n */\n public getStoredItem(): StoredItem<T> | undefined {\n const jsonStr = globalThis.localStorage.getItem(this.key);\n\n if (!jsonStr) {\n return undefined;\n }\n\n try {\n const obj: StoredItem<T> | undefined = JSON.parse(jsonStr);\n\n if (\n !obj ||\n typeof obj !== \"object\" ||\n !(\"value\" in obj) ||\n !(\"storedMs\" in obj) ||\n typeof obj.storedMs !== \"number\" ||\n !(\"expiryMs\" in obj) ||\n typeof obj.expiryMs !== \"number\" ||\n Date.now() >= obj.expiryMs\n ) {\n this.remove();\n return undefined;\n }\n\n return obj;\n } catch (e) {\n if (this.logError) {\n console.error(\n `Found invalid storage value: ${this.key}=${jsonStr}:`,\n e,\n );\n }\n this.remove();\n return undefined;\n }\n }\n\n /**\n * Get the value of this item, or undefined if value is not set or expired.\n */\n public get(): T | undefined {\n const stored = this.getStoredItem();\n\n return stored !== undefined ? stored.value : this.defaultValue;\n }\n\n /**\n * Remove the value of this item.\n */\n public remove(): void {\n globalThis.localStorage.removeItem(this.key);\n }\n}\n","/**\n * Bunch of miscellaneous constants and utility functions related to handling\n * date and time durations.\n *\n * Note that month and year do not have fixed durations, and hence are excluded\n * from this file. Weeks have fixed durations, but are excluded because we\n * use days as the max duration supported.\n */\n\nimport {\n HOURS_PER_DAY,\n MINUTES_PER_HOUR,\n MS_PER_DAY,\n MS_PER_HOUR,\n MS_PER_MINUTE,\n MS_PER_SECOND,\n SECONDS_PER_MINUTE,\n} from \"./timeConstants\";\n\nexport type Duration = {\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n};\n\n/**\n * One of: days, hours, minutes, seconds, milliseconds\n */\nexport type DurationType = keyof Duration;\n\n/**\n * Order in which the duration type appears in the duration string.\n */\nexport const DURATION_TYPE_SEQUENCE: DurationType[] = [\n \"days\",\n \"hours\",\n \"minutes\",\n \"seconds\",\n \"milliseconds\",\n];\n\n/**\n * Follows the same format as Intl.DurationFormat.prototype.format().\n *\n * Short: 1 yr, 2 mths, 3 wks, 3 days, 4 hr, 5 min, 6 sec, 7 ms, 8 μs, 9 ns\n * Long: 1 year, 2 months, 3 weeks, 3 days, 4 hours, 5 minutes, 6 seconds,\n * 7 milliseconds, 8 microseconds, 9 nanoseconds\n * Narrow: 1y 2mo 3w 3d 4h 5m 6s 7ms 8μs 9ns\n */\nexport type DurationStyle = \"short\" | \"long\" | \"narrow\";\n\nexport type DurationSuffixMap = {\n short: string;\n shorts: string;\n long: string;\n longs: string;\n narrow: string;\n};\n\nexport type DurationSuffixType = keyof DurationSuffixMap;\n\nexport const DURATION_STYLE_SUFFIX_MAP: Record<\n DurationType,\n DurationSuffixMap\n> = {\n days: {\n short: \"day\",\n shorts: \"days\",\n long: \"day\",\n longs: \"days\",\n narrow: \"d\",\n },\n hours: {\n short: \"hr\",\n shorts: \"hrs\",\n long: \"hour\",\n longs: \"hours\",\n narrow: \"h\",\n },\n minutes: {\n short: \"min\",\n shorts: \"mins\",\n long: \"minute\",\n longs: \"minutes\",\n narrow: \"m\",\n },\n seconds: {\n short: \"sec\",\n shorts: \"secs\",\n long: \"second\",\n longs: \"seconds\",\n narrow: \"s\",\n },\n milliseconds: {\n short: \"ms\",\n shorts: \"ms\",\n long: \"millisecond\",\n longs: \"milliseconds\",\n narrow: \"ms\",\n },\n};\n\nfunction getDurationStyleForPlural(style: DurationStyle): DurationSuffixType {\n return style == \"short\" ? \"shorts\" : style === \"long\" ? \"longs\" : style;\n}\n\nfunction getValueAndUnitSeparator(style: DurationStyle): string {\n return style === \"narrow\" ? \"\" : \" \";\n}\n\nfunction getDurationTypeSeparator(style: DurationStyle): string {\n return style === \"narrow\" ? \" \" : \", \";\n}\n\n/**\n * Convert a milliseconds duration into a Duration object. If the given ms is\n * zero, then return an object with a single field of zero with duration type\n * of durationTypeForZero.\n *\n * @param durationTypeForZero Defaults to 'milliseconds'\n */\nexport function msToDuration(\n ms: number,\n durationTypeForZero?: DurationType,\n): Duration {\n if (ms === 0) {\n durationTypeForZero = durationTypeForZero ?? \"milliseconds\";\n return { [durationTypeForZero]: 0 };\n }\n\n const duration: Duration = {};\n\n for (let i = 0; i < 1; i++) {\n let seconds = Math.floor(ms / MS_PER_SECOND);\n const millis = ms - seconds * MS_PER_SECOND;\n\n if (millis > 0) {\n duration[\"milliseconds\"] = millis;\n }\n\n if (seconds === 0) {\n break;\n }\n\n let minutes = Math.floor(seconds / SECONDS_PER_MINUTE);\n seconds -= minutes * SECONDS_PER_MINUTE;\n\n if (seconds > 0) {\n duration[\"seconds\"] = seconds;\n }\n\n if (minutes === 0) {\n break;\n }\n\n let hours = Math.floor(minutes / MINUTES_PER_HOUR);\n minutes -= hours * MINUTES_PER_HOUR;\n\n if (minutes > 0) {\n duration[\"minutes\"] = minutes;\n }\n\n if (hours === 0) {\n break;\n }\n\n const days = Math.floor(hours / HOURS_PER_DAY);\n hours -= days * HOURS_PER_DAY;\n\n if (hours > 0) {\n duration[\"hours\"] = hours;\n }\n\n if (days > 0) {\n duration[\"days\"] = days;\n }\n }\n\n return duration;\n}\n\n/**\n * Returns the number of milliseconds for the given duration.\n */\nexport function durationToMs(duration: Duration): number {\n const daysMs = (duration.days ?? 0) * MS_PER_DAY;\n const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;\n const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;\n const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;\n const msMs = duration.milliseconds ?? 0;\n\n return daysMs + hoursMs + minsMs + secsMs + msMs;\n}\n\n/**\n * Convenience function to return a duration given an ms or Duration.\n */\nexport function durationOrMsToMs(duration: number | Duration): number {\n return typeof duration === \"number\" ? duration : durationToMs(duration);\n}\n\n/**\n * Format a given Duration object into a string. If the object has no fields,\n * then returns an empty string.\n *\n * @param style Defaults to 'short'\n */\nexport function formatDuration(duration: Duration, style?: DurationStyle) {\n style = style ?? \"short\";\n const stylePlural = getDurationStyleForPlural(style);\n\n const space = getValueAndUnitSeparator(style);\n\n const a: string[] = [];\n\n for (const unit of DURATION_TYPE_SEQUENCE) {\n const value = duration[unit];\n if (value === undefined) continue;\n\n const suffixMap = DURATION_STYLE_SUFFIX_MAP[unit];\n const suffix = value === 1 ? suffixMap[style] : suffixMap[stylePlural];\n a.push(value + space + suffix);\n }\n\n const separator = getDurationTypeSeparator(style);\n return a.join(separator);\n}\n\n/**\n * Convert a millisecond duration into a human-readable duration string.\n *\n * @param options.durationTypeForZero - Defaults to 'milliseconds'\n * @param options.style - Defaults to 'short'\n */\nexport function readableDuration(\n ms: number,\n options?: { durationTypeForZero?: DurationType; style?: DurationStyle },\n): string {\n const duration = msToDuration(ms, options?.durationTypeForZero);\n\n return formatDuration(duration, options?.style);\n}\n\n/** A shortened duration string useful for logging timings. */\nexport function elapsed(ms: number): string {\n // Use long format for 1 minute or over.\n if (ms > MS_PER_MINUTE) {\n return readableDuration(ms);\n }\n\n // Use seconds format for over 100ms.\n if (ms > 100) {\n return `${(ms / 1000).toFixed(3)}s`;\n }\n\n // Use milliseconds format.\n return ms + \"ms\";\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GC0LO,SAASI,EAAaC,EAA4B,CACvD,IAAMC,GAAUD,EAAS,MAAQ,GAAK,MAChCE,GAAWF,EAAS,OAAS,GAAK,KAClCG,GAAUH,EAAS,SAAW,GAAK,IACnCI,GAAUJ,EAAS,SAAW,GAAK,IACnCK,EAAOL,EAAS,cAAgB,EAEtC,OAAOC,EAASC,EAAUC,EAASC,EAASC,CAC9C,CAKO,SAASC,EAAiBN,EAAqC,CACpE,OAAO,OAAOA,GAAa,SAAWA,EAAWD,EAAaC,CAAQ,CACxE,CDlLO,SAASO,EACdC,EACAC,EACAC,EAAW,GACXC,EACA,CACA,IAAMC,EAAgBC,EAAiBJ,CAAO,EAE9C,OAAO,IAAIK,EAAaN,EAAKI,EAAeF,EAAUC,CAAY,CACpE,CAEA,IAAMG,EAAN,KAAmB,CAIV,YACWN,EACAI,EACAF,EACAC,EAChB,CAJgB,SAAAH,EACA,mBAAAI,EACA,cAAAF,EACA,kBAAAC,CACf,CAKI,IACLI,EACAC,EAAiC,KAAK,cAChC,CACN,IAAMC,EAAQ,KAAK,IAAI,EACjBC,EAAyB,CAC7B,MAAAH,EACA,SAAUE,EACV,SAAUA,EAAQJ,EAAiBG,CAAW,CAChD,EACMG,EAAW,KAAK,UAAUD,CAAO,EAEvC,WAAW,aAAa,QAAQ,KAAK,IAAKC,CAAQ,CACpD,CAOO,eAA2C,CAChD,IAAMC,EAAU,WAAW,aAAa,QAAQ,KAAK,GAAG,EAExD,GAAKA,EAIL,GAAI,CACF,IAAMC,EAAiC,KAAK,MAAMD,CAAO,EAEzD,GACE,CAACC,GACD,OAAOA,GAAQ,UACf,EAAE,UAAWA,IACb,EAAE,aAAcA,IAChB,OAAOA,EAAI,UAAa,UACxB,EAAE,aAAcA,IAChB,OAAOA,EAAI,UAAa,UACxB,KAAK,IAAI,GAAKA,EAAI,SAClB,CACA,KAAK,OAAO,EACZ,MACF,CAEA,OAAOA,CACT,OAASC,EAAG,CACN,KAAK,UACP,QAAQ,MACN,gCAAgC,KAAK,GAAG,IAAIF,CAAO,IACnDE,CACF,EAEF,KAAK,OAAO,EACZ,MACF,CACF,CAKO,KAAqB,CAC1B,IAAMC,EAAS,KAAK,cAAc,EAElC,OAAOA,IAAW,OAAYA,EAAO,MAAQ,KAAK,YACpD,CAKO,QAAe,CACpB,WAAW,aAAa,WAAW,KAAK,GAAG,CAC7C,CACF","names":["localStorageCache_exports","__export","storeItem","__toCommonJS","durationToMs","duration","daysMs","hoursMs","minsMs","secsMs","msMs","durationOrMsToMs","storeItem","key","expires","logError","defaultValue","expireDeltaMs","durationOrMsToMs","CacheItem","value","expiryDelta","nowMs","toStore","valueStr","jsonStr","obj","e","stored"]}
@@ -0,0 +1,2 @@
1
+ function d(r){let t=(r.days??0)*864e5,o=(r.hours??0)*36e5,e=(r.minutes??0)*6e4,n=(r.seconds??0)*1e3,s=r.milliseconds??0;return t+o+e+n+s}function i(r){return typeof r=="number"?r:d(r)}function h(r,t,o=!0,e){let n=i(t);return new u(r,n,o,e)}var u=class{constructor(t,o,e,n){this.key=t;this.expireDeltaMs=o;this.logError=e;this.defaultValue=n}set(t,o=this.expireDeltaMs){let e=Date.now(),n={value:t,storedMs:e,expiryMs:e+i(o)},s=JSON.stringify(n);globalThis.localStorage.setItem(this.key,s)}getStoredItem(){let t=globalThis.localStorage.getItem(this.key);if(t)try{let o=JSON.parse(t);if(!o||typeof o!="object"||!("value"in o)||!("storedMs"in o)||typeof o.storedMs!="number"||!("expiryMs"in o)||typeof o.expiryMs!="number"||Date.now()>=o.expiryMs){this.remove();return}return o}catch(o){this.logError&&console.error(`Found invalid storage value: ${this.key}=${t}:`,o),this.remove();return}}get(){let t=this.getStoredItem();return t!==void 0?t.value:this.defaultValue}remove(){globalThis.localStorage.removeItem(this.key)}};export{h as storeItem};
2
+ //# sourceMappingURL=localStorageCache.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/duration.ts","../src/localStorageCache.ts"],"sourcesContent":["/**\n * Bunch of miscellaneous constants and utility functions related to handling\n * date and time durations.\n *\n * Note that month and year do not have fixed durations, and hence are excluded\n * from this file. Weeks have fixed durations, but are excluded because we\n * use days as the max duration supported.\n */\n\nimport {\n HOURS_PER_DAY,\n MINUTES_PER_HOUR,\n MS_PER_DAY,\n MS_PER_HOUR,\n MS_PER_MINUTE,\n MS_PER_SECOND,\n SECONDS_PER_MINUTE,\n} from \"./timeConstants\";\n\nexport type Duration = {\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n};\n\n/**\n * One of: days, hours, minutes, seconds, milliseconds\n */\nexport type DurationType = keyof Duration;\n\n/**\n * Order in which the duration type appears in the duration string.\n */\nexport const DURATION_TYPE_SEQUENCE: DurationType[] = [\n \"days\",\n \"hours\",\n \"minutes\",\n \"seconds\",\n \"milliseconds\",\n];\n\n/**\n * Follows the same format as Intl.DurationFormat.prototype.format().\n *\n * Short: 1 yr, 2 mths, 3 wks, 3 days, 4 hr, 5 min, 6 sec, 7 ms, 8 μs, 9 ns\n * Long: 1 year, 2 months, 3 weeks, 3 days, 4 hours, 5 minutes, 6 seconds,\n * 7 milliseconds, 8 microseconds, 9 nanoseconds\n * Narrow: 1y 2mo 3w 3d 4h 5m 6s 7ms 8μs 9ns\n */\nexport type DurationStyle = \"short\" | \"long\" | \"narrow\";\n\nexport type DurationSuffixMap = {\n short: string;\n shorts: string;\n long: string;\n longs: string;\n narrow: string;\n};\n\nexport type DurationSuffixType = keyof DurationSuffixMap;\n\nexport const DURATION_STYLE_SUFFIX_MAP: Record<\n DurationType,\n DurationSuffixMap\n> = {\n days: {\n short: \"day\",\n shorts: \"days\",\n long: \"day\",\n longs: \"days\",\n narrow: \"d\",\n },\n hours: {\n short: \"hr\",\n shorts: \"hrs\",\n long: \"hour\",\n longs: \"hours\",\n narrow: \"h\",\n },\n minutes: {\n short: \"min\",\n shorts: \"mins\",\n long: \"minute\",\n longs: \"minutes\",\n narrow: \"m\",\n },\n seconds: {\n short: \"sec\",\n shorts: \"secs\",\n long: \"second\",\n longs: \"seconds\",\n narrow: \"s\",\n },\n milliseconds: {\n short: \"ms\",\n shorts: \"ms\",\n long: \"millisecond\",\n longs: \"milliseconds\",\n narrow: \"ms\",\n },\n};\n\nfunction getDurationStyleForPlural(style: DurationStyle): DurationSuffixType {\n return style == \"short\" ? \"shorts\" : style === \"long\" ? \"longs\" : style;\n}\n\nfunction getValueAndUnitSeparator(style: DurationStyle): string {\n return style === \"narrow\" ? \"\" : \" \";\n}\n\nfunction getDurationTypeSeparator(style: DurationStyle): string {\n return style === \"narrow\" ? \" \" : \", \";\n}\n\n/**\n * Convert a milliseconds duration into a Duration object. If the given ms is\n * zero, then return an object with a single field of zero with duration type\n * of durationTypeForZero.\n *\n * @param durationTypeForZero Defaults to 'milliseconds'\n */\nexport function msToDuration(\n ms: number,\n durationTypeForZero?: DurationType,\n): Duration {\n if (ms === 0) {\n durationTypeForZero = durationTypeForZero ?? \"milliseconds\";\n return { [durationTypeForZero]: 0 };\n }\n\n const duration: Duration = {};\n\n for (let i = 0; i < 1; i++) {\n let seconds = Math.floor(ms / MS_PER_SECOND);\n const millis = ms - seconds * MS_PER_SECOND;\n\n if (millis > 0) {\n duration[\"milliseconds\"] = millis;\n }\n\n if (seconds === 0) {\n break;\n }\n\n let minutes = Math.floor(seconds / SECONDS_PER_MINUTE);\n seconds -= minutes * SECONDS_PER_MINUTE;\n\n if (seconds > 0) {\n duration[\"seconds\"] = seconds;\n }\n\n if (minutes === 0) {\n break;\n }\n\n let hours = Math.floor(minutes / MINUTES_PER_HOUR);\n minutes -= hours * MINUTES_PER_HOUR;\n\n if (minutes > 0) {\n duration[\"minutes\"] = minutes;\n }\n\n if (hours === 0) {\n break;\n }\n\n const days = Math.floor(hours / HOURS_PER_DAY);\n hours -= days * HOURS_PER_DAY;\n\n if (hours > 0) {\n duration[\"hours\"] = hours;\n }\n\n if (days > 0) {\n duration[\"days\"] = days;\n }\n }\n\n return duration;\n}\n\n/**\n * Returns the number of milliseconds for the given duration.\n */\nexport function durationToMs(duration: Duration): number {\n const daysMs = (duration.days ?? 0) * MS_PER_DAY;\n const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;\n const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;\n const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;\n const msMs = duration.milliseconds ?? 0;\n\n return daysMs + hoursMs + minsMs + secsMs + msMs;\n}\n\n/**\n * Convenience function to return a duration given an ms or Duration.\n */\nexport function durationOrMsToMs(duration: number | Duration): number {\n return typeof duration === \"number\" ? duration : durationToMs(duration);\n}\n\n/**\n * Format a given Duration object into a string. If the object has no fields,\n * then returns an empty string.\n *\n * @param style Defaults to 'short'\n */\nexport function formatDuration(duration: Duration, style?: DurationStyle) {\n style = style ?? \"short\";\n const stylePlural = getDurationStyleForPlural(style);\n\n const space = getValueAndUnitSeparator(style);\n\n const a: string[] = [];\n\n for (const unit of DURATION_TYPE_SEQUENCE) {\n const value = duration[unit];\n if (value === undefined) continue;\n\n const suffixMap = DURATION_STYLE_SUFFIX_MAP[unit];\n const suffix = value === 1 ? suffixMap[style] : suffixMap[stylePlural];\n a.push(value + space + suffix);\n }\n\n const separator = getDurationTypeSeparator(style);\n return a.join(separator);\n}\n\n/**\n * Convert a millisecond duration into a human-readable duration string.\n *\n * @param options.durationTypeForZero - Defaults to 'milliseconds'\n * @param options.style - Defaults to 'short'\n */\nexport function readableDuration(\n ms: number,\n options?: { durationTypeForZero?: DurationType; style?: DurationStyle },\n): string {\n const duration = msToDuration(ms, options?.durationTypeForZero);\n\n return formatDuration(duration, options?.style);\n}\n\n/** A shortened duration string useful for logging timings. */\nexport function elapsed(ms: number): string {\n // Use long format for 1 minute or over.\n if (ms > MS_PER_MINUTE) {\n return readableDuration(ms);\n }\n\n // Use seconds format for over 100ms.\n if (ms > 100) {\n return `${(ms / 1000).toFixed(3)}s`;\n }\n\n // Use milliseconds format.\n return ms + \"ms\";\n}\n","import { Duration, durationOrMsToMs } from \"./duration\";\n\nexport type StoredItem<T> = { value: T; storedMs: number; expiryMs: number };\n\n/**\n * Simple local storage cache with support for auto-expiration.\n * Note that this works in the browser context only because nodejs does not\n * have local storage.\n *\n * Create a cache item accessor object with auto-expiration. The value will\n * always be stored as a string by applying JSON.stringify(), and will be\n * returned in the same object type by applying JSON.parse().\n *\n * In order to provide proper type-checking, please always specify the T\n * type parameter. E.g. const item = storeItem<string>(\"name\", 10_000);\n *\n * @param key The store key in local storage.\n * @param expires Either a number in milliseconds, or a Duration object\n * @param logError Log an error if we found an invalid object in the store.\n * The invalid object is usually a string that cannot be parsed as JSON.\n * @param defaultValue Specify a default value to use for the object. Defaults\n * to undefined.\n */\nexport function storeItem<T>(\n key: string,\n expires: number | Duration,\n logError = true,\n defaultValue?: T,\n) {\n const expireDeltaMs = durationOrMsToMs(expires);\n\n return new CacheItem<T>(key, expireDeltaMs, logError, defaultValue);\n}\n\nclass CacheItem<T> {\n /**\n * Create a cache item accessor object with auto-expiration.\n */\n public constructor(\n public readonly key: string,\n public readonly expireDeltaMs: number,\n public readonly logError: boolean,\n public readonly defaultValue: T | undefined,\n ) {}\n\n /**\n * Set the value of this item with auto-expiration.\n */\n public set(\n value: T,\n expiryDelta: number | Duration = this.expireDeltaMs,\n ): void {\n const nowMs = Date.now();\n const toStore: StoredItem<T> = {\n value,\n storedMs: nowMs,\n expiryMs: nowMs + durationOrMsToMs(expiryDelta),\n };\n const valueStr = JSON.stringify(toStore);\n\n globalThis.localStorage.setItem(this.key, valueStr);\n }\n\n /**\n * Example usage:\n *\n * const { value, storedMs, expiryMs } = await myItem.getStoredItem();\n */\n public getStoredItem(): StoredItem<T> | undefined {\n const jsonStr = globalThis.localStorage.getItem(this.key);\n\n if (!jsonStr) {\n return undefined;\n }\n\n try {\n const obj: StoredItem<T> | undefined = JSON.parse(jsonStr);\n\n if (\n !obj ||\n typeof obj !== \"object\" ||\n !(\"value\" in obj) ||\n !(\"storedMs\" in obj) ||\n typeof obj.storedMs !== \"number\" ||\n !(\"expiryMs\" in obj) ||\n typeof obj.expiryMs !== \"number\" ||\n Date.now() >= obj.expiryMs\n ) {\n this.remove();\n return undefined;\n }\n\n return obj;\n } catch (e) {\n if (this.logError) {\n console.error(\n `Found invalid storage value: ${this.key}=${jsonStr}:`,\n e,\n );\n }\n this.remove();\n return undefined;\n }\n }\n\n /**\n * Get the value of this item, or undefined if value is not set or expired.\n */\n public get(): T | undefined {\n const stored = this.getStoredItem();\n\n return stored !== undefined ? stored.value : this.defaultValue;\n }\n\n /**\n * Remove the value of this item.\n */\n public remove(): void {\n globalThis.localStorage.removeItem(this.key);\n }\n}\n"],"mappings":"AA0LO,SAASA,EAAaC,EAA4B,CACvD,IAAMC,GAAUD,EAAS,MAAQ,GAAK,MAChCE,GAAWF,EAAS,OAAS,GAAK,KAClCG,GAAUH,EAAS,SAAW,GAAK,IACnCI,GAAUJ,EAAS,SAAW,GAAK,IACnCK,EAAOL,EAAS,cAAgB,EAEtC,OAAOC,EAASC,EAAUC,EAASC,EAASC,CAC9C,CAKO,SAASC,EAAiBN,EAAqC,CACpE,OAAO,OAAOA,GAAa,SAAWA,EAAWD,EAAaC,CAAQ,CACxE,CClLO,SAASO,EACdC,EACAC,EACAC,EAAW,GACXC,EACA,CACA,IAAMC,EAAgBC,EAAiBJ,CAAO,EAE9C,OAAO,IAAIK,EAAaN,EAAKI,EAAeF,EAAUC,CAAY,CACpE,CAEA,IAAMG,EAAN,KAAmB,CAIV,YACWN,EACAI,EACAF,EACAC,EAChB,CAJgB,SAAAH,EACA,mBAAAI,EACA,cAAAF,EACA,kBAAAC,CACf,CAKI,IACLI,EACAC,EAAiC,KAAK,cAChC,CACN,IAAMC,EAAQ,KAAK,IAAI,EACjBC,EAAyB,CAC7B,MAAAH,EACA,SAAUE,EACV,SAAUA,EAAQJ,EAAiBG,CAAW,CAChD,EACMG,EAAW,KAAK,UAAUD,CAAO,EAEvC,WAAW,aAAa,QAAQ,KAAK,IAAKC,CAAQ,CACpD,CAOO,eAA2C,CAChD,IAAMC,EAAU,WAAW,aAAa,QAAQ,KAAK,GAAG,EAExD,GAAKA,EAIL,GAAI,CACF,IAAMC,EAAiC,KAAK,MAAMD,CAAO,EAEzD,GACE,CAACC,GACD,OAAOA,GAAQ,UACf,EAAE,UAAWA,IACb,EAAE,aAAcA,IAChB,OAAOA,EAAI,UAAa,UACxB,EAAE,aAAcA,IAChB,OAAOA,EAAI,UAAa,UACxB,KAAK,IAAI,GAAKA,EAAI,SAClB,CACA,KAAK,OAAO,EACZ,MACF,CAEA,OAAOA,CACT,OAASC,EAAG,CACN,KAAK,UACP,QAAQ,MACN,gCAAgC,KAAK,GAAG,IAAIF,CAAO,IACnDE,CACF,EAEF,KAAK,OAAO,EACZ,MACF,CACF,CAKO,KAAqB,CAC1B,IAAMC,EAAS,KAAK,cAAc,EAElC,OAAOA,IAAW,OAAYA,EAAO,MAAQ,KAAK,YACpD,CAKO,QAAe,CACpB,WAAW,aAAa,WAAW,KAAK,GAAG,CAC7C,CACF","names":["durationToMs","duration","daysMs","hoursMs","minsMs","secsMs","msMs","durationOrMsToMs","storeItem","key","expires","logError","defaultValue","expireDeltaMs","durationOrMsToMs","CacheItem","value","expiryDelta","nowMs","toStore","valueStr","jsonStr","obj","e","stored"]}
@@ -0,0 +1,92 @@
1
+ // src/timeConstants.ts
2
+ var MS_PER_SECOND = 1e3;
3
+ var MS_PER_MINUTE = 6e4;
4
+ var MS_PER_HOUR = 36e5;
5
+ var MS_PER_DAY = 864e5;
6
+
7
+ // src/duration.ts
8
+ function durationToMs(duration) {
9
+ const daysMs = (duration.days ?? 0) * MS_PER_DAY;
10
+ const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;
11
+ const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;
12
+ const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;
13
+ const msMs = duration.milliseconds ?? 0;
14
+ return daysMs + hoursMs + minsMs + secsMs + msMs;
15
+ }
16
+ function durationOrMsToMs(duration) {
17
+ return typeof duration === "number" ? duration : durationToMs(duration);
18
+ }
19
+
20
+ // src/localStorageCache.ts
21
+ function storeItem(key, expires, logError = true, defaultValue) {
22
+ const expireDeltaMs = durationOrMsToMs(expires);
23
+ return new CacheItem(key, expireDeltaMs, logError, defaultValue);
24
+ }
25
+ var CacheItem = class {
26
+ /**
27
+ * Create a cache item accessor object with auto-expiration.
28
+ */
29
+ constructor(key, expireDeltaMs, logError, defaultValue) {
30
+ this.key = key;
31
+ this.expireDeltaMs = expireDeltaMs;
32
+ this.logError = logError;
33
+ this.defaultValue = defaultValue;
34
+ }
35
+ /**
36
+ * Set the value of this item with auto-expiration.
37
+ */
38
+ set(value, expiryDelta = this.expireDeltaMs) {
39
+ const nowMs = Date.now();
40
+ const toStore = {
41
+ value,
42
+ storedMs: nowMs,
43
+ expiryMs: nowMs + durationOrMsToMs(expiryDelta)
44
+ };
45
+ const valueStr = JSON.stringify(toStore);
46
+ globalThis.localStorage.setItem(this.key, valueStr);
47
+ }
48
+ /**
49
+ * Example usage:
50
+ *
51
+ * const { value, storedMs, expiryMs } = await myItem.getStoredItem();
52
+ */
53
+ getStoredItem() {
54
+ const jsonStr = globalThis.localStorage.getItem(this.key);
55
+ if (!jsonStr) {
56
+ return void 0;
57
+ }
58
+ try {
59
+ const obj = JSON.parse(jsonStr);
60
+ if (!obj || typeof obj !== "object" || !("value" in obj) || !("storedMs" in obj) || typeof obj.storedMs !== "number" || !("expiryMs" in obj) || typeof obj.expiryMs !== "number" || Date.now() >= obj.expiryMs) {
61
+ this.remove();
62
+ return void 0;
63
+ }
64
+ return obj;
65
+ } catch (e) {
66
+ if (this.logError) {
67
+ console.error(
68
+ `Found invalid storage value: ${this.key}=${jsonStr}:`,
69
+ e
70
+ );
71
+ }
72
+ this.remove();
73
+ return void 0;
74
+ }
75
+ }
76
+ /**
77
+ * Get the value of this item, or undefined if value is not set or expired.
78
+ */
79
+ get() {
80
+ const stored = this.getStoredItem();
81
+ return stored !== void 0 ? stored.value : this.defaultValue;
82
+ }
83
+ /**
84
+ * Remove the value of this item.
85
+ */
86
+ remove() {
87
+ globalThis.localStorage.removeItem(this.key);
88
+ }
89
+ };
90
+ export {
91
+ storeItem
92
+ };
@@ -45,4 +45,3 @@ function capLength(u, maxLength = 400) {
45
45
  capLength,
46
46
  stringify
47
47
  });
48
- //# sourceMappingURL=logging.js.map
package/logging.d.mts ADDED
@@ -0,0 +1,4 @@
1
+ declare function stringify(u: unknown): string;
2
+ declare function capLength(u: unknown, maxLength?: number): string;
3
+
4
+ export { capLength, stringify };
@@ -0,0 +1,2 @@
1
+ "use strict";var o=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var p=(t,n)=>{for(var r in n)o(t,r,{get:n[r],enumerable:!0})},l=(t,n,r,e)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of s(n))!c.call(t,i)&&i!==r&&o(t,i,{get:()=>n[i],enumerable:!(e=g(n,i))||e.enumerable});return t};var y=t=>l(o({},"__esModule",{value:!0}),t);var S={};p(S,{capLength:()=>u,stringify:()=>f});module.exports=y(S);function f(t){return typeof t=="string"?t:t!==null&&typeof t=="object"&&t.toString!==Object.prototype.toString?t.toString():JSON.stringify(t)}function u(t,n=400){let r=f(t);return r.length<=n?r:r.slice(0,n)+` ... (${r.length-n} more)`}0&&(module.exports={capLength,stringify});
2
+ //# sourceMappingURL=logging.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/logging.ts"],"sourcesContent":["export function stringify(u: unknown): string {\n if (typeof u === \"string\") {\n return u;\n }\n\n // If the object has a custom toString(), then use it.\n if (\n u !== null &&\n typeof u === \"object\" &&\n u.toString !== Object.prototype.toString\n ) {\n return u.toString();\n }\n\n return JSON.stringify(u);\n}\n\nexport function capLength(u: unknown, maxLength = 400): string {\n const s = stringify(u);\n\n if (s.length <= maxLength) {\n return s;\n }\n\n return s.slice(0, maxLength) + ` ... (${s.length - maxLength} more)`;\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,EAAA,cAAAC,IAAA,eAAAC,EAAAJ,GAAO,SAASG,EAAUE,EAAoB,CAC5C,OAAI,OAAOA,GAAM,SACRA,EAKPA,IAAM,MACN,OAAOA,GAAM,UACbA,EAAE,WAAa,OAAO,UAAU,SAEzBA,EAAE,SAAS,EAGb,KAAK,UAAUA,CAAC,CACzB,CAEO,SAASH,EAAUG,EAAYC,EAAY,IAAa,CAC7D,IAAMC,EAAIJ,EAAUE,CAAC,EAErB,OAAIE,EAAE,QAAUD,EACPC,EAGFA,EAAE,MAAM,EAAGD,CAAS,EAAI,SAASC,EAAE,OAASD,CAAS,QAC9D","names":["logging_exports","__export","capLength","stringify","__toCommonJS","u","maxLength","s"]}
@@ -0,0 +1,2 @@
1
+ function i(t){return typeof t=="string"?t:t!==null&&typeof t=="object"&&t.toString!==Object.prototype.toString?t.toString():JSON.stringify(t)}function o(t,r=400){let n=i(t);return n.length<=r?n:n.slice(0,r)+` ... (${n.length-r} more)`}export{o as capLength,i as stringify};
2
+ //# sourceMappingURL=logging.min.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logging.ts"],"sourcesContent":["export function stringify(u: unknown): string {\n if (typeof u === \"string\") {\n return u;\n }\n\n // If the object has a custom toString(), then use it.\n if (\n u !== null &&\n typeof u === \"object\" &&\n u.toString !== Object.prototype.toString\n ) {\n return u.toString();\n }\n\n return JSON.stringify(u);\n}\n\nexport function capLength(u: unknown, maxLength = 400): string {\n const s = stringify(u);\n\n if (s.length <= maxLength) {\n return s;\n }\n\n return s.slice(0, maxLength) + ` ... (${s.length - maxLength} more)`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,UAAU,GAAoB;AAC5C,MAAI,OAAO,MAAM,UAAU;AACzB,WAAO;AAAA,EACT;AAGA,MACE,MAAM,QACN,OAAO,MAAM,YACb,EAAE,aAAa,OAAO,UAAU,UAChC;AACA,WAAO,EAAE,SAAS;AAAA,EACpB;AAEA,SAAO,KAAK,UAAU,CAAC;AACzB;AAEO,SAAS,UAAU,GAAY,YAAY,KAAa;AAC7D,QAAM,IAAI,UAAU,CAAC;AAErB,MAAI,EAAE,UAAU,WAAW;AACzB,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,MAAM,GAAG,SAAS,IAAI,SAAS,EAAE,SAAS,SAAS;AAC9D;","names":[]}
1
+ {"version":3,"sources":["../src/logging.ts"],"sourcesContent":["export function stringify(u: unknown): string {\n if (typeof u === \"string\") {\n return u;\n }\n\n // If the object has a custom toString(), then use it.\n if (\n u !== null &&\n typeof u === \"object\" &&\n u.toString !== Object.prototype.toString\n ) {\n return u.toString();\n }\n\n return JSON.stringify(u);\n}\n\nexport function capLength(u: unknown, maxLength = 400): string {\n const s = stringify(u);\n\n if (s.length <= maxLength) {\n return s;\n }\n\n return s.slice(0, maxLength) + ` ... (${s.length - maxLength} more)`;\n}\n"],"mappings":"AAAO,SAASA,EAAUC,EAAoB,CAC5C,OAAI,OAAOA,GAAM,SACRA,EAKPA,IAAM,MACN,OAAOA,GAAM,UACbA,EAAE,WAAa,OAAO,UAAU,SAEzBA,EAAE,SAAS,EAGb,KAAK,UAAUA,CAAC,CACzB,CAEO,SAASC,EAAUD,EAAYE,EAAY,IAAa,CAC7D,IAAMC,EAAIJ,EAAUC,CAAC,EAErB,OAAIG,EAAE,QAAUD,EACPC,EAGFA,EAAE,MAAM,EAAGD,CAAS,EAAI,SAASC,EAAE,OAASD,CAAS,QAC9D","names":["stringify","u","capLength","maxLength","s"]}
package/logging.mjs ADDED
@@ -0,0 +1,21 @@
1
+ // src/logging.ts
2
+ function stringify(u) {
3
+ if (typeof u === "string") {
4
+ return u;
5
+ }
6
+ if (u !== null && typeof u === "object" && u.toString !== Object.prototype.toString) {
7
+ return u.toString();
8
+ }
9
+ return JSON.stringify(u);
10
+ }
11
+ function capLength(u, maxLength = 400) {
12
+ const s = stringify(u);
13
+ if (s.length <= maxLength) {
14
+ return s;
15
+ }
16
+ return s.slice(0, maxLength) + ` ... (${s.length - maxLength} more)`;
17
+ }
18
+ export {
19
+ capLength,
20
+ stringify
21
+ };
@@ -55,4 +55,3 @@ function nonEmpty(t, varName = "value") {
55
55
  0 && (module.exports = {
56
56
  nonEmpty
57
57
  });
58
- //# sourceMappingURL=nonEmpty.js.map
package/nonEmpty.d.mts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Type asserts that `t` is truthy.
3
+ * Throws an error if `t` is null or undefined.
4
+ *
5
+ * @param varName The variable name to include in the error to throw when t is
6
+ * empty. Defaults to 'value'.
7
+ */
8
+ declare function nonEmpty<T>(t: T | null | undefined | "" | 0 | -0 | 0n | false | typeof NaN, varName?: string): T;
9
+
10
+ export { nonEmpty };
@@ -0,0 +1,2 @@
1
+ "use strict";var t=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var s=(n,e)=>{for(var o in e)t(n,o,{get:e[o],enumerable:!0})},a=(n,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of l(e))!p.call(n,r)&&r!==o&&t(n,r,{get:()=>e[r],enumerable:!(i=u(e,r))||i.enumerable});return n};var m=n=>a(t({},"__esModule",{value:!0}),n);var E={};s(E,{nonEmpty:()=>y});module.exports=m(E);function f(n){if(!n)return!0;if(typeof n!="object")return!1;if("length"in n)return n.length===0;if("size"in n)return n.size===0;for(let e in n)return!1;return!0}function y(n,e="value"){if(f(n))throw new Error(`Empty ${e}: ${n}`);return n}0&&(module.exports={nonEmpty});
2
+ //# sourceMappingURL=nonEmpty.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/nonEmpty.ts","../src/isEmpty.ts"],"sourcesContent":["import { isEmpty } from \"./isEmpty\";\n\n/**\n * Type asserts that `t` is truthy.\n * Throws an error if `t` is null or undefined.\n *\n * @param varName The variable name to include in the error to throw when t is\n * empty. Defaults to 'value'.\n */\nexport function nonEmpty<T>(\n t: T | null | undefined | \"\" | 0 | -0 | 0n | false | typeof NaN,\n varName = \"value\",\n): T {\n if (isEmpty(t)) {\n throw new Error(`Empty ${varName}: ${t}`);\n }\n return t as T;\n}\n","/**\n * Returns true if `t` is empty.\n */\nexport function isEmpty(t: unknown): boolean {\n // Anything falsy is considered empty.\n if (!t) {\n return true;\n }\n\n // Arrays are also of type `object`.\n if (typeof t !== \"object\") {\n return false;\n }\n\n // `length` includes arrays as well.\n if (\"length\" in t) {\n return t.length === 0;\n }\n\n // `size` is for Set, Map, Blob etc.\n if (\"size\" in t) {\n return t.size === 0;\n }\n\n // Super fast check for object emptiness.\n // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object\n for (const k in t) {\n return false;\n }\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,SAAS,QAAQ,GAAqB;AAE3C,MAAI,CAAC,GAAG;AACN,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,MAAM,UAAU;AACzB,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,GAAG;AACjB,WAAO,EAAE,WAAW;AAAA,EACtB;AAGA,MAAI,UAAU,GAAG;AACf,WAAO,EAAE,SAAS;AAAA,EACpB;AAIA,aAAW,KAAK,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ADtBO,SAAS,SACd,GACA,UAAU,SACP;AACH,MAAI,QAAQ,CAAC,GAAG;AACd,UAAM,IAAI,MAAM,SAAS,OAAO,KAAK,CAAC,EAAE;AAAA,EAC1C;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/nonEmpty.ts","../src/isEmpty.ts"],"sourcesContent":["import { isEmpty } from \"./isEmpty\";\n\n/**\n * Type asserts that `t` is truthy.\n * Throws an error if `t` is null or undefined.\n *\n * @param varName The variable name to include in the error to throw when t is\n * empty. Defaults to 'value'.\n */\nexport function nonEmpty<T>(\n t: T | null | undefined | \"\" | 0 | -0 | 0n | false | typeof NaN,\n varName = \"value\",\n): T {\n if (isEmpty(t)) {\n throw new Error(`Empty ${varName}: ${t}`);\n }\n return t as T;\n}\n","/**\n * Returns true if `t` is empty.\n */\nexport function isEmpty(t: unknown): boolean {\n // Anything falsy is considered empty.\n if (!t) {\n return true;\n }\n\n // Arrays are also of type `object`.\n if (typeof t !== \"object\") {\n return false;\n }\n\n // `length` includes arrays as well.\n if (\"length\" in t) {\n return t.length === 0;\n }\n\n // `size` is for Set, Map, Blob etc.\n if (\"size\" in t) {\n return t.size === 0;\n }\n\n // Super fast check for object emptiness.\n // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object\n for (const k in t) {\n return false;\n }\n\n return true;\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,IAAA,eAAAC,EAAAH,GCGO,SAASI,EAAQC,EAAqB,CAE3C,GAAI,CAACA,EACH,MAAO,GAIT,GAAI,OAAOA,GAAM,SACf,MAAO,GAIT,GAAI,WAAYA,EACd,OAAOA,EAAE,SAAW,EAItB,GAAI,SAAUA,EACZ,OAAOA,EAAE,OAAS,EAKpB,QAAWC,KAAKD,EACd,MAAO,GAGT,MAAO,EACT,CDtBO,SAASE,EACdC,EACAC,EAAU,QACP,CACH,GAAIC,EAAQF,CAAC,EACX,MAAM,IAAI,MAAM,SAASC,CAAO,KAAKD,CAAC,EAAE,EAE1C,OAAOA,CACT","names":["nonEmpty_exports","__export","nonEmpty","__toCommonJS","isEmpty","t","k","nonEmpty","t","varName","isEmpty"]}
@@ -0,0 +1,2 @@
1
+ function r(n){if(!n)return!0;if(typeof n!="object")return!1;if("length"in n)return n.length===0;if("size"in n)return n.size===0;for(let e in n)return!1;return!0}function i(n,e="value"){if(r(n))throw new Error(`Empty ${e}: ${n}`);return n}export{i as nonEmpty};
2
+ //# sourceMappingURL=nonEmpty.min.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/isEmpty.ts","../src/nonEmpty.ts"],"sourcesContent":["/**\n * Returns true if `t` is empty.\n */\nexport function isEmpty(t: unknown): boolean {\n // Anything falsy is considered empty.\n if (!t) {\n return true;\n }\n\n // Arrays are also of type `object`.\n if (typeof t !== \"object\") {\n return false;\n }\n\n // `length` includes arrays as well.\n if (\"length\" in t) {\n return t.length === 0;\n }\n\n // `size` is for Set, Map, Blob etc.\n if (\"size\" in t) {\n return t.size === 0;\n }\n\n // Super fast check for object emptiness.\n // https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object\n for (const k in t) {\n return false;\n }\n\n return true;\n}\n","import { isEmpty } from \"./isEmpty\";\n\n/**\n * Type asserts that `t` is truthy.\n * Throws an error if `t` is null or undefined.\n *\n * @param varName The variable name to include in the error to throw when t is\n * empty. Defaults to 'value'.\n */\nexport function nonEmpty<T>(\n t: T | null | undefined | \"\" | 0 | -0 | 0n | false | typeof NaN,\n varName = \"value\",\n): T {\n if (isEmpty(t)) {\n throw new Error(`Empty ${varName}: ${t}`);\n }\n return t as T;\n}\n"],"mappings":"AAGO,SAASA,EAAQC,EAAqB,CAE3C,GAAI,CAACA,EACH,MAAO,GAIT,GAAI,OAAOA,GAAM,SACf,MAAO,GAIT,GAAI,WAAYA,EACd,OAAOA,EAAE,SAAW,EAItB,GAAI,SAAUA,EACZ,OAAOA,EAAE,OAAS,EAKpB,QAAWC,KAAKD,EACd,MAAO,GAGT,MAAO,EACT,CCtBO,SAASE,EACdC,EACAC,EAAU,QACP,CACH,GAAIC,EAAQF,CAAC,EACX,MAAM,IAAI,MAAM,SAASC,CAAO,KAAKD,CAAC,EAAE,EAE1C,OAAOA,CACT","names":["isEmpty","t","k","nonEmpty","t","varName","isEmpty"]}