zeed 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (535) hide show
  1. package/dist/_experiments/bitcask.cjs +243 -1
  2. package/dist/_experiments/bitcask.cjs.map +1 -1
  3. package/dist/_experiments/bitcask.mjs +230 -1
  4. package/dist/_experiments/bitcask.mjs.map +1 -1
  5. package/dist/bin-BAoS4qtm.mjs +593 -0
  6. package/dist/{bin-SPdenYkw.mjs.map → bin-BAoS4qtm.mjs.map} +1 -1
  7. package/dist/bin-Ddaz2lxM.cjs +862 -0
  8. package/dist/{bin-Ce3i6ABn.cjs.map → bin-Ddaz2lxM.cjs.map} +1 -1
  9. package/dist/browser/base64.cjs +14 -1
  10. package/dist/browser/base64.cjs.map +1 -1
  11. package/dist/browser/base64.mjs +12 -1
  12. package/dist/browser/base64.mjs.map +1 -1
  13. package/dist/browser/gravatar.cjs +186 -1
  14. package/dist/browser/gravatar.cjs.map +1 -1
  15. package/dist/browser/gravatar.mjs +184 -1
  16. package/dist/browser/gravatar.mjs.map +1 -1
  17. package/dist/browser/index.cjs +14 -1
  18. package/dist/browser/index.mjs +8 -1
  19. package/dist/browser/localstorage.cjs +46 -1
  20. package/dist/browser/localstorage.cjs.map +1 -1
  21. package/dist/browser/localstorage.mjs +45 -1
  22. package/dist/browser/localstorage.mjs.map +1 -1
  23. package/dist/browser/log/index.cjs +8 -1
  24. package/dist/browser/log/index.mjs +5 -1
  25. package/dist/browser/log/log-browser-factory.cjs +65 -1
  26. package/dist/browser/log/log-browser-factory.cjs.map +1 -1
  27. package/dist/browser/log/log-browser-factory.mjs +64 -1
  28. package/dist/browser/log/log-browser-factory.mjs.map +1 -1
  29. package/dist/browser/log/log-browser.cjs +72 -1
  30. package/dist/browser/log/log-browser.cjs.map +1 -1
  31. package/dist/browser/log/log-browser.mjs +71 -1
  32. package/dist/browser/log/log-browser.mjs.map +1 -1
  33. package/dist/browser/log/log-colors.cjs +11 -1
  34. package/dist/browser/log/log-colors.cjs.map +1 -1
  35. package/dist/browser/log/log-colors.mjs +9 -1
  36. package/dist/browser/log/log-colors.mjs.map +1 -1
  37. package/dist/browser/log/log-context-browser.cjs +25 -1
  38. package/dist/browser/log/log-context-browser.cjs.map +1 -1
  39. package/dist/browser/log/log-context-browser.mjs +23 -1
  40. package/dist/browser/log/log-context-browser.mjs.map +1 -1
  41. package/dist/chunk-DQk6qfdC.mjs +18 -0
  42. package/dist/chunk-uaV2rQ02.cjs +53 -0
  43. package/dist/common/assert.cjs +22 -1
  44. package/dist/common/assert.cjs.map +1 -1
  45. package/dist/common/assert.mjs +19 -1
  46. package/dist/common/assert.mjs.map +1 -1
  47. package/dist/common/bin/index.cjs +106 -1
  48. package/dist/common/bin/index.cjs.map +1 -1
  49. package/dist/common/bin/index.mjs +98 -1
  50. package/dist/common/bin/index.mjs.map +1 -1
  51. package/dist/common/bin/lib0/binary.cjs +146 -1
  52. package/dist/common/bin/lib0/binary.cjs.map +1 -1
  53. package/dist/common/bin/lib0/binary.mjs +80 -1
  54. package/dist/common/bin/lib0/binary.mjs.map +1 -1
  55. package/dist/common/bin/lib0/buffer.cjs +42 -1
  56. package/dist/common/bin/lib0/buffer.cjs.map +1 -1
  57. package/dist/common/bin/lib0/buffer.mjs +38 -1
  58. package/dist/common/bin/lib0/buffer.mjs.map +1 -1
  59. package/dist/common/bin/lib0/create.cjs +24 -1
  60. package/dist/common/bin/lib0/create.cjs.map +1 -1
  61. package/dist/common/bin/lib0/create.mjs +21 -1
  62. package/dist/common/bin/lib0/create.mjs.map +1 -1
  63. package/dist/common/bin/lib0/decoding.cjs +325 -1
  64. package/dist/common/bin/lib0/decoding.cjs.map +1 -1
  65. package/dist/common/bin/lib0/decoding.mjs +298 -1
  66. package/dist/common/bin/lib0/decoding.mjs.map +1 -1
  67. package/dist/common/bin/lib0/encoding.cjs +404 -1
  68. package/dist/common/bin/lib0/encoding.cjs.map +1 -1
  69. package/dist/common/bin/lib0/encoding.mjs +377 -1
  70. package/dist/common/bin/lib0/encoding.mjs.map +1 -1
  71. package/dist/common/bin/lib0/string.cjs +81 -1
  72. package/dist/common/bin/lib0/string.cjs.map +1 -1
  73. package/dist/common/bin/lib0/string.mjs +71 -1
  74. package/dist/common/bin/lib0/string.mjs.map +1 -1
  75. package/dist/common/crypto/aes-sealed.cjs +34 -1
  76. package/dist/common/crypto/aes-sealed.cjs.map +1 -1
  77. package/dist/common/crypto/aes-sealed.mjs +32 -1
  78. package/dist/common/crypto/aes-sealed.mjs.map +1 -1
  79. package/dist/common/crypto/crypto.cjs +91 -1
  80. package/dist/common/crypto/crypto.cjs.map +1 -1
  81. package/dist/common/crypto/crypto.mjs +80 -1
  82. package/dist/common/crypto/crypto.mjs.map +1 -1
  83. package/dist/common/crypto/index.cjs +23 -1
  84. package/dist/common/crypto/index.mjs +5 -1
  85. package/dist/common/crypto/xaes.cjs +128 -1
  86. package/dist/common/crypto/xaes.cjs.map +1 -1
  87. package/dist/common/crypto/xaes.mjs +123 -1
  88. package/dist/common/crypto/xaes.mjs.map +1 -1
  89. package/dist/common/csv.cjs +49 -4
  90. package/dist/common/csv.cjs.map +1 -1
  91. package/dist/common/csv.mjs +46 -4
  92. package/dist/common/csv.mjs.map +1 -1
  93. package/dist/common/data/array.cjs +299 -1
  94. package/dist/common/data/array.cjs.map +1 -1
  95. package/dist/common/data/array.mjs +274 -1
  96. package/dist/common/data/array.mjs.map +1 -1
  97. package/dist/common/data/basex-secure.cjs +30 -1
  98. package/dist/common/data/basex-secure.mjs +3 -1
  99. package/dist/common/data/basex.cjs +163 -1
  100. package/dist/common/data/basex.cjs.map +1 -1
  101. package/dist/common/data/basex.mjs +152 -1
  102. package/dist/common/data/basex.mjs.map +1 -1
  103. package/dist/common/data/bin-types.mjs +1 -1
  104. package/dist/common/data/bin.cjs +21 -1
  105. package/dist/common/data/bin.mjs +3 -1
  106. package/dist/common/data/camelcase.cjs +27 -1
  107. package/dist/common/data/camelcase.cjs.map +1 -1
  108. package/dist/common/data/camelcase.mjs +22 -1
  109. package/dist/common/data/camelcase.mjs.map +1 -1
  110. package/dist/common/data/convert.cjs +104 -1
  111. package/dist/common/data/convert.cjs.map +1 -1
  112. package/dist/common/data/convert.mjs +88 -1
  113. package/dist/common/data/convert.mjs.map +1 -1
  114. package/dist/common/data/datauri.cjs +32 -1
  115. package/dist/common/data/datauri.cjs.map +1 -1
  116. package/dist/common/data/datauri.mjs +27 -1
  117. package/dist/common/data/datauri.mjs.map +1 -1
  118. package/dist/common/data/day-legacy.cjs +148 -1
  119. package/dist/common/data/day-legacy.cjs.map +1 -1
  120. package/dist/common/data/day-legacy.mjs +143 -1
  121. package/dist/common/data/day-legacy.mjs.map +1 -1
  122. package/dist/common/data/day.cjs +335 -1
  123. package/dist/common/data/day.cjs.map +1 -1
  124. package/dist/common/data/day.mjs +305 -1
  125. package/dist/common/data/day.mjs.map +1 -1
  126. package/dist/common/data/decimal.cjs +28 -1
  127. package/dist/common/data/decimal.cjs.map +1 -1
  128. package/dist/common/data/decimal.mjs +23 -1
  129. package/dist/common/data/decimal.mjs.map +1 -1
  130. package/dist/common/data/deep.cjs +57 -1
  131. package/dist/common/data/deep.cjs.map +1 -1
  132. package/dist/common/data/deep.mjs +54 -1
  133. package/dist/common/data/deep.mjs.map +1 -1
  134. package/dist/common/data/diff.cjs +62 -1
  135. package/dist/common/data/diff.cjs.map +1 -1
  136. package/dist/common/data/diff.mjs +60 -1
  137. package/dist/common/data/diff.mjs.map +1 -1
  138. package/dist/common/data/distributed.cjs +24 -1
  139. package/dist/common/data/distributed.cjs.map +1 -1
  140. package/dist/common/data/distributed.mjs +22 -1
  141. package/dist/common/data/distributed.mjs.map +1 -1
  142. package/dist/common/data/format.cjs +63 -1
  143. package/dist/common/data/format.cjs.map +1 -1
  144. package/dist/common/data/format.mjs +59 -1
  145. package/dist/common/data/format.mjs.map +1 -1
  146. package/dist/common/data/html.cjs +13 -1
  147. package/dist/common/data/html.cjs.map +1 -1
  148. package/dist/common/data/html.mjs +10 -1
  149. package/dist/common/data/html.mjs.map +1 -1
  150. package/dist/common/data/index.cjs +296 -1
  151. package/dist/common/data/index.mjs +37 -1
  152. package/dist/common/data/is.cjs +106 -1
  153. package/dist/common/data/is.cjs.map +1 -1
  154. package/dist/common/data/is.mjs +85 -1
  155. package/dist/common/data/is.mjs.map +1 -1
  156. package/dist/common/data/json.cjs +70 -1
  157. package/dist/common/data/json.cjs.map +1 -1
  158. package/dist/common/data/json.mjs +65 -1
  159. package/dist/common/data/json.mjs.map +1 -1
  160. package/dist/common/data/list.cjs +32 -1
  161. package/dist/common/data/list.cjs.map +1 -1
  162. package/dist/common/data/list.mjs +27 -1
  163. package/dist/common/data/list.mjs.map +1 -1
  164. package/dist/common/data/lru.mjs +1 -1
  165. package/dist/common/data/math.cjs +79 -1
  166. package/dist/common/data/math.cjs.map +1 -1
  167. package/dist/common/data/math.mjs +65 -1
  168. package/dist/common/data/math.mjs.map +1 -1
  169. package/dist/common/data/message.cjs +30 -1
  170. package/dist/common/data/message.cjs.map +1 -1
  171. package/dist/common/data/message.mjs +28 -1
  172. package/dist/common/data/message.mjs.map +1 -1
  173. package/dist/common/data/object-changes.cjs +66 -1
  174. package/dist/common/data/object-changes.cjs.map +1 -1
  175. package/dist/common/data/object-changes.mjs +63 -1
  176. package/dist/common/data/object-changes.mjs.map +1 -1
  177. package/dist/common/data/object.cjs +112 -1
  178. package/dist/common/data/object.cjs.map +1 -1
  179. package/dist/common/data/object.mjs +104 -1
  180. package/dist/common/data/object.mjs.map +1 -1
  181. package/dist/common/data/orderby.cjs +42 -1
  182. package/dist/common/data/orderby.cjs.map +1 -1
  183. package/dist/common/data/orderby.mjs +37 -1
  184. package/dist/common/data/orderby.mjs.map +1 -1
  185. package/dist/common/data/path.cjs +26 -1
  186. package/dist/common/data/path.cjs.map +1 -1
  187. package/dist/common/data/path.mjs +25 -1
  188. package/dist/common/data/path.mjs.map +1 -1
  189. package/dist/common/data/regexp.cjs +12 -1
  190. package/dist/common/data/regexp.cjs.map +1 -1
  191. package/dist/common/data/regexp.mjs +10 -1
  192. package/dist/common/data/regexp.mjs.map +1 -1
  193. package/dist/common/data/rounding.cjs +107 -1
  194. package/dist/common/data/rounding.cjs.map +1 -1
  195. package/dist/common/data/rounding.mjs +95 -1
  196. package/dist/common/data/rounding.mjs.map +1 -1
  197. package/dist/common/data/signal.cjs +39 -1
  198. package/dist/common/data/signal.cjs.map +1 -1
  199. package/dist/common/data/signal.mjs +38 -1
  200. package/dist/common/data/signal.mjs.map +1 -1
  201. package/dist/common/data/sortable.cjs +35 -1
  202. package/dist/common/data/sortable.cjs.map +1 -1
  203. package/dist/common/data/sortable.mjs +31 -1
  204. package/dist/common/data/sortable.mjs.map +1 -1
  205. package/dist/common/data/sorted.cjs +54 -1
  206. package/dist/common/data/sorted.cjs.map +1 -1
  207. package/dist/common/data/sorted.mjs +53 -1
  208. package/dist/common/data/sorted.mjs.map +1 -1
  209. package/dist/common/data/string-deburr.cjs +240 -1
  210. package/dist/common/data/string-deburr.cjs.map +1 -1
  211. package/dist/common/data/string-deburr.mjs +238 -1
  212. package/dist/common/data/string-deburr.mjs.map +1 -1
  213. package/dist/common/data/string-hash-fnv.cjs +69 -1
  214. package/dist/common/data/string-hash-fnv.cjs.map +1 -1
  215. package/dist/common/data/string-hash-fnv.mjs +67 -1
  216. package/dist/common/data/string-hash-fnv.mjs.map +1 -1
  217. package/dist/common/data/string-hash-pool.cjs +28 -1
  218. package/dist/common/data/string-hash-pool.cjs.map +1 -1
  219. package/dist/common/data/string-hash-pool.mjs +27 -1
  220. package/dist/common/data/string-hash-pool.mjs.map +1 -1
  221. package/dist/common/data/url.cjs +98 -2
  222. package/dist/common/data/url.cjs.map +1 -1
  223. package/dist/common/data/url.mjs +91 -2
  224. package/dist/common/data/url.mjs.map +1 -1
  225. package/dist/common/data/utils.cjs +118 -1
  226. package/dist/common/data/utils.cjs.map +1 -1
  227. package/dist/common/data/utils.mjs +107 -1
  228. package/dist/common/data/utils.mjs.map +1 -1
  229. package/dist/common/data/wordlist.cjs +531 -1
  230. package/dist/common/data/wordlist.cjs.map +1 -1
  231. package/dist/common/data/wordlist.mjs +529 -1
  232. package/dist/common/data/wordlist.mjs.map +1 -1
  233. package/dist/common/data/xrx.cjs +96 -1
  234. package/dist/common/data/xrx.cjs.map +1 -1
  235. package/dist/common/data/xrx.mjs +92 -1
  236. package/dist/common/data/xrx.mjs.map +1 -1
  237. package/dist/common/dispose-defer.cjs +133 -1
  238. package/dist/common/dispose-defer.cjs.map +1 -1
  239. package/dist/common/dispose-defer.mjs +130 -1
  240. package/dist/common/dispose-defer.mjs.map +1 -1
  241. package/dist/common/dispose-types.mjs +1 -1
  242. package/dist/common/dispose-utils.cjs +113 -1
  243. package/dist/common/dispose-utils.cjs.map +1 -1
  244. package/dist/common/dispose-utils.mjs +106 -1
  245. package/dist/common/dispose-utils.mjs.map +1 -1
  246. package/dist/common/exec/index.cjs +24 -1
  247. package/dist/common/exec/index.mjs +8 -1
  248. package/dist/common/exec/mutex.cjs +44 -1
  249. package/dist/common/exec/mutex.cjs.map +1 -1
  250. package/dist/common/exec/mutex.mjs +42 -1
  251. package/dist/common/exec/mutex.mjs.map +1 -1
  252. package/dist/common/exec/pool.cjs +181 -1
  253. package/dist/common/exec/pool.cjs.map +1 -1
  254. package/dist/common/exec/pool.mjs +180 -1
  255. package/dist/common/exec/pool.mjs.map +1 -1
  256. package/dist/common/exec/progress.cjs +149 -1
  257. package/dist/common/exec/progress.cjs.map +1 -1
  258. package/dist/common/exec/progress.mjs +148 -1
  259. package/dist/common/exec/progress.mjs.map +1 -1
  260. package/dist/common/exec/promise.cjs +113 -1
  261. package/dist/common/exec/promise.cjs.map +1 -1
  262. package/dist/common/exec/promise.mjs +103 -1
  263. package/dist/common/exec/promise.mjs.map +1 -1
  264. package/dist/common/exec/queue.cjs +125 -1
  265. package/dist/common/exec/queue.cjs.map +1 -1
  266. package/dist/common/exec/queue.mjs +124 -1
  267. package/dist/common/exec/queue.mjs.map +1 -1
  268. package/dist/common/exec/throttle-debounce.cjs +114 -1
  269. package/dist/common/exec/throttle-debounce.cjs.map +1 -1
  270. package/dist/common/exec/throttle-debounce.mjs +112 -1
  271. package/dist/common/exec/throttle-debounce.mjs.map +1 -1
  272. package/dist/common/global.cjs +22 -1
  273. package/dist/common/global.cjs.map +1 -1
  274. package/dist/common/global.mjs +19 -1
  275. package/dist/common/global.mjs.map +1 -1
  276. package/dist/common/index.cjs +559 -1
  277. package/dist/common/index.mjs +89 -1
  278. package/dist/common/localhost.cjs +16 -1
  279. package/dist/common/localhost.cjs.map +1 -1
  280. package/dist/common/localhost.mjs +14 -1
  281. package/dist/common/localhost.mjs.map +1 -1
  282. package/dist/common/log/index.cjs +34 -1
  283. package/dist/common/log/index.mjs +11 -1
  284. package/dist/common/log/log-base.cjs +40 -1
  285. package/dist/common/log/log-base.cjs.map +1 -1
  286. package/dist/common/log/log-base.mjs +31 -1
  287. package/dist/common/log/log-base.mjs.map +1 -1
  288. package/dist/common/log/log-colors.cjs +92 -1
  289. package/dist/common/log/log-colors.cjs.map +1 -1
  290. package/dist/common/log/log-colors.mjs +90 -1
  291. package/dist/common/log/log-colors.mjs.map +1 -1
  292. package/dist/common/log/log-config.cjs +15 -1
  293. package/dist/common/log/log-config.cjs.map +1 -1
  294. package/dist/common/log/log-config.mjs +14 -1
  295. package/dist/common/log/log-config.mjs.map +1 -1
  296. package/dist/common/log/log-console-capture.cjs +33 -1
  297. package/dist/common/log/log-console-capture.cjs.map +1 -1
  298. package/dist/common/log/log-console-capture.mjs +32 -1
  299. package/dist/common/log/log-console-capture.mjs.map +1 -1
  300. package/dist/common/log/log-console-original.cjs +27 -1
  301. package/dist/common/log/log-console-original.cjs.map +1 -1
  302. package/dist/common/log/log-console-original.mjs +26 -1
  303. package/dist/common/log/log-console-original.mjs.map +1 -1
  304. package/dist/common/log/log-console.cjs +39 -1
  305. package/dist/common/log/log-console.cjs.map +1 -1
  306. package/dist/common/log/log-console.mjs +38 -1
  307. package/dist/common/log/log-console.mjs.map +1 -1
  308. package/dist/common/log/log-context.cjs +109 -1
  309. package/dist/common/log/log-context.cjs.map +1 -1
  310. package/dist/common/log/log-context.mjs +108 -1
  311. package/dist/common/log/log-context.mjs.map +1 -1
  312. package/dist/common/log/log-filter.cjs +80 -1
  313. package/dist/common/log/log-filter.cjs.map +1 -1
  314. package/dist/common/log/log-filter.mjs +75 -1
  315. package/dist/common/log/log-filter.mjs.map +1 -1
  316. package/dist/common/log/log-memory.cjs +45 -1
  317. package/dist/common/log/log-memory.cjs.map +1 -1
  318. package/dist/common/log/log-memory.mjs +43 -1
  319. package/dist/common/log/log-memory.mjs.map +1 -1
  320. package/dist/common/log/log-noop.cjs +17 -1
  321. package/dist/common/log/log-noop.cjs.map +1 -1
  322. package/dist/common/log/log-noop.mjs +15 -1
  323. package/dist/common/log/log-noop.mjs.map +1 -1
  324. package/dist/common/log/log.cjs +46 -1
  325. package/dist/common/log/log.cjs.map +1 -1
  326. package/dist/common/log/log.mjs +43 -1
  327. package/dist/common/log/log.mjs.map +1 -1
  328. package/dist/common/msg/channel-debug.cjs +17 -1
  329. package/dist/common/msg/channel-debug.cjs.map +1 -1
  330. package/dist/common/msg/channel-debug.mjs +16 -1
  331. package/dist/common/msg/channel-debug.mjs.map +1 -1
  332. package/dist/common/msg/channel-local.cjs +28 -1
  333. package/dist/common/msg/channel-local.cjs.map +1 -1
  334. package/dist/common/msg/channel-local.mjs +26 -1
  335. package/dist/common/msg/channel-local.mjs.map +1 -1
  336. package/dist/common/msg/channel-resilient.cjs +63 -1
  337. package/dist/common/msg/channel-resilient.cjs.map +1 -1
  338. package/dist/common/msg/channel-resilient.mjs +62 -1
  339. package/dist/common/msg/channel-resilient.mjs.map +1 -1
  340. package/dist/common/msg/channel-wkwebview.cjs +35 -1
  341. package/dist/common/msg/channel-wkwebview.cjs.map +1 -1
  342. package/dist/common/msg/channel-wkwebview.mjs +34 -1
  343. package/dist/common/msg/channel-wkwebview.mjs.map +1 -1
  344. package/dist/common/msg/channel.cjs +23 -1
  345. package/dist/common/msg/channel.cjs.map +1 -1
  346. package/dist/common/msg/channel.mjs +22 -1
  347. package/dist/common/msg/channel.mjs.map +1 -1
  348. package/dist/common/msg/emitter.cjs +141 -1
  349. package/dist/common/msg/emitter.cjs.map +1 -1
  350. package/dist/common/msg/emitter.mjs +139 -1
  351. package/dist/common/msg/emitter.mjs.map +1 -1
  352. package/dist/common/msg/encoder.cjs +38 -1
  353. package/dist/common/msg/encoder.cjs.map +1 -1
  354. package/dist/common/msg/encoder.mjs +35 -1
  355. package/dist/common/msg/encoder.mjs.map +1 -1
  356. package/dist/common/msg/index.cjs +28 -1
  357. package/dist/common/msg/index.mjs +11 -1
  358. package/dist/common/msg/messages.cjs +135 -1
  359. package/dist/common/msg/messages.cjs.map +1 -1
  360. package/dist/common/msg/messages.mjs +133 -1
  361. package/dist/common/msg/messages.mjs.map +1 -1
  362. package/dist/common/msg/pipe.mjs +1 -1
  363. package/dist/common/msg/pubsub.cjs +78 -1
  364. package/dist/common/msg/pubsub.cjs.map +1 -1
  365. package/dist/common/msg/pubsub.mjs +76 -1
  366. package/dist/common/msg/pubsub.mjs.map +1 -1
  367. package/dist/common/msg/rpc.cjs +142 -1
  368. package/dist/common/msg/rpc.cjs.map +1 -1
  369. package/dist/common/msg/rpc.mjs +139 -1
  370. package/dist/common/msg/rpc.mjs.map +1 -1
  371. package/dist/common/network.cjs +129 -1
  372. package/dist/common/network.cjs.map +1 -1
  373. package/dist/common/network.mjs +122 -1
  374. package/dist/common/network.mjs.map +1 -1
  375. package/dist/common/platform.cjs +92 -1
  376. package/dist/common/platform.cjs.map +1 -1
  377. package/dist/common/platform.mjs +84 -1
  378. package/dist/common/platform.mjs.map +1 -1
  379. package/dist/common/schema/_sandbox/sandbox-inherit.mjs +1 -1
  380. package/dist/common/schema/_sandbox/sandbox.mjs +1 -1
  381. package/dist/common/schema/_sandbox/sandbox.xspec.mjs +1 -1
  382. package/dist/common/schema/export-json-schema.cjs +54 -1
  383. package/dist/common/schema/export-json-schema.cjs.map +1 -1
  384. package/dist/common/schema/export-json-schema.mjs +52 -1
  385. package/dist/common/schema/export-json-schema.mjs.map +1 -1
  386. package/dist/common/schema/export-swift.cjs +30 -2
  387. package/dist/common/schema/export-swift.cjs.map +1 -1
  388. package/dist/common/schema/export-swift.mjs +29 -2
  389. package/dist/common/schema/export-swift.mjs.map +1 -1
  390. package/dist/common/schema/export-typescript.cjs +20 -2
  391. package/dist/common/schema/export-typescript.cjs.map +1 -1
  392. package/dist/common/schema/export-typescript.mjs +19 -2
  393. package/dist/common/schema/export-typescript.mjs.map +1 -1
  394. package/dist/common/schema/index.cjs +55 -1
  395. package/dist/common/schema/index.mjs +12 -1
  396. package/dist/common/schema/parse-args.cjs +62 -2
  397. package/dist/common/schema/parse-args.cjs.map +1 -1
  398. package/dist/common/schema/parse-args.mjs +60 -2
  399. package/dist/common/schema/parse-args.mjs.map +1 -1
  400. package/dist/common/schema/parse-env.cjs +48 -3
  401. package/dist/common/schema/parse-env.cjs.map +1 -1
  402. package/dist/common/schema/parse-env.mjs +46 -3
  403. package/dist/common/schema/parse-env.mjs.map +1 -1
  404. package/dist/common/schema/parse-object.cjs +122 -1
  405. package/dist/common/schema/parse-object.cjs.map +1 -1
  406. package/dist/common/schema/parse-object.mjs +119 -1
  407. package/dist/common/schema/parse-object.mjs.map +1 -1
  408. package/dist/common/schema/schema-standard.mjs +1 -1
  409. package/dist/common/schema/schema.cjs +423 -1
  410. package/dist/common/schema/schema.cjs.map +1 -1
  411. package/dist/common/schema/schema.mjs +404 -1
  412. package/dist/common/schema/schema.mjs.map +1 -1
  413. package/dist/common/schema/serialize.cjs +109 -1
  414. package/dist/common/schema/serialize.cjs.map +1 -1
  415. package/dist/common/schema/serialize.mjs +107 -1
  416. package/dist/common/schema/serialize.mjs.map +1 -1
  417. package/dist/common/schema/type-test.mjs +1 -1
  418. package/dist/common/schema/utils.cjs +25 -1
  419. package/dist/common/schema/utils.cjs.map +1 -1
  420. package/dist/common/schema/utils.mjs +19 -1
  421. package/dist/common/schema/utils.mjs.map +1 -1
  422. package/dist/common/schema/z-collection.cjs +51 -1
  423. package/dist/common/schema/z-collection.mjs +27 -1
  424. package/dist/common/schema/z.cjs +9 -1
  425. package/dist/common/schema/z.mjs +3 -1
  426. package/dist/common/storage/index.cjs +4 -1
  427. package/dist/common/storage/index.mjs +3 -1
  428. package/dist/common/storage/memstorage.cjs +26 -1
  429. package/dist/common/storage/memstorage.cjs.map +1 -1
  430. package/dist/common/storage/memstorage.mjs +25 -1
  431. package/dist/common/storage/memstorage.mjs.map +1 -1
  432. package/dist/common/test.cjs +14 -1
  433. package/dist/common/test.cjs.map +1 -1
  434. package/dist/common/test.mjs +13 -1
  435. package/dist/common/test.mjs.map +1 -1
  436. package/dist/common/time.cjs +220 -1
  437. package/dist/common/time.cjs.map +1 -1
  438. package/dist/common/time.mjs +194 -1
  439. package/dist/common/time.mjs.map +1 -1
  440. package/dist/common/timeout.cjs +27 -1
  441. package/dist/common/timeout.cjs.map +1 -1
  442. package/dist/common/timeout.mjs +25 -1
  443. package/dist/common/timeout.mjs.map +1 -1
  444. package/dist/common/types.mjs +1 -1
  445. package/dist/common/utils.cjs +7 -1
  446. package/dist/common/utils.cjs.map +1 -1
  447. package/dist/common/utils.mjs +5 -1
  448. package/dist/common/utils.mjs.map +1 -1
  449. package/dist/common/uuid.cjs +307 -1
  450. package/dist/common/uuid.cjs.map +1 -1
  451. package/dist/common/uuid.mjs +284 -1
  452. package/dist/common/uuid.mjs.map +1 -1
  453. package/dist/index.all.cjs +641 -1
  454. package/dist/index.all.mjs +113 -1
  455. package/dist/index.browser.cjs +576 -1
  456. package/dist/index.browser.mjs +98 -1
  457. package/dist/index.jsr.cjs +57 -1
  458. package/dist/index.jsr.mjs +6 -1
  459. package/dist/index.node.cjs +628 -1
  460. package/dist/index.node.mjs +106 -1
  461. package/dist/node/args.cjs +56 -1
  462. package/dist/node/args.cjs.map +1 -1
  463. package/dist/node/args.mjs +53 -1
  464. package/dist/node/args.mjs.map +1 -1
  465. package/dist/node/clipboard.cjs +18 -1
  466. package/dist/node/clipboard.cjs.map +1 -1
  467. package/dist/node/clipboard.mjs +16 -1
  468. package/dist/node/clipboard.mjs.map +1 -1
  469. package/dist/node/crypto.cjs +28 -1
  470. package/dist/node/crypto.cjs.map +1 -1
  471. package/dist/node/crypto.mjs +24 -1
  472. package/dist/node/crypto.mjs.map +1 -1
  473. package/dist/node/env.cjs +100 -4
  474. package/dist/node/env.cjs.map +1 -1
  475. package/dist/node/env.mjs +90 -4
  476. package/dist/node/env.mjs.map +1 -1
  477. package/dist/node/files-async.cjs +66 -1
  478. package/dist/node/files-async.cjs.map +1 -1
  479. package/dist/node/files-async.mjs +60 -1
  480. package/dist/node/files-async.mjs.map +1 -1
  481. package/dist/node/files.cjs +52 -1
  482. package/dist/node/files.cjs.map +1 -1
  483. package/dist/node/files.mjs +46 -1
  484. package/dist/node/files.mjs.map +1 -1
  485. package/dist/node/filestorage.cjs +100 -1
  486. package/dist/node/filestorage.cjs.map +1 -1
  487. package/dist/node/filestorage.mjs +97 -1
  488. package/dist/node/filestorage.mjs.map +1 -1
  489. package/dist/node/fs.cjs +119 -1
  490. package/dist/node/fs.cjs.map +1 -1
  491. package/dist/node/fs.mjs +101 -1
  492. package/dist/node/fs.mjs.map +1 -1
  493. package/dist/node/glob.cjs +75 -1
  494. package/dist/node/glob.cjs.map +1 -1
  495. package/dist/node/glob.mjs +73 -1
  496. package/dist/node/glob.mjs.map +1 -1
  497. package/dist/node/index.cjs +66 -1
  498. package/dist/node/index.mjs +16 -1
  499. package/dist/node/log/index.cjs +20 -1
  500. package/dist/node/log/index.mjs +7 -1
  501. package/dist/node/log/log-context-node.cjs +39 -1
  502. package/dist/node/log/log-context-node.cjs.map +1 -1
  503. package/dist/node/log/log-context-node.mjs +35 -1
  504. package/dist/node/log/log-context-node.mjs.map +1 -1
  505. package/dist/node/log/log-file-rotation.cjs +71 -1
  506. package/dist/node/log/log-file-rotation.cjs.map +1 -1
  507. package/dist/node/log/log-file-rotation.mjs +68 -1
  508. package/dist/node/log/log-file-rotation.mjs.map +1 -1
  509. package/dist/node/log/log-file.cjs +57 -1
  510. package/dist/node/log/log-file.cjs.map +1 -1
  511. package/dist/node/log/log-file.mjs +54 -1
  512. package/dist/node/log/log-file.mjs.map +1 -1
  513. package/dist/node/log/log-node.cjs +162 -1
  514. package/dist/node/log/log-node.cjs.map +1 -1
  515. package/dist/node/log/log-node.mjs +155 -1
  516. package/dist/node/log/log-node.mjs.map +1 -1
  517. package/dist/node/log/log-rotation.cjs +543 -3
  518. package/dist/node/log/log-rotation.cjs.map +1 -1
  519. package/dist/node/log/log-rotation.mjs +538 -3
  520. package/dist/node/log/log-rotation.mjs.map +1 -1
  521. package/dist/node/log/log-util.cjs +69 -3
  522. package/dist/node/log/log-util.cjs.map +1 -1
  523. package/dist/node/log/log-util.mjs +63 -3
  524. package/dist/node/log/log-util.mjs.map +1 -1
  525. package/dist/node/open-browser.cjs +20 -1
  526. package/dist/node/open-browser.cjs.map +1 -1
  527. package/dist/node/open-browser.mjs +18 -1
  528. package/dist/node/open-browser.mjs.map +1 -1
  529. package/package.json +6 -6
  530. package/src/eslint-defaults.js +4 -0
  531. package/src/index.spec.ts +6 -6
  532. package/dist/bin-Ce3i6ABn.cjs +0 -3
  533. package/dist/bin-SPdenYkw.mjs +0 -3
  534. package/dist/chunk-0Lt9GpW0.mjs +0 -1
  535. package/dist/chunk-D-qHiVGv.cjs +0 -1
@@ -1,2 +1,244 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../chunk-D-qHiVGv.cjs`);let t=require(`fs`);t=e.n(t);let n=require(`path`);n=e.n(n);let r=require(`fs/promises`);var i=class{dirname;readWrite;syncOnPut;keydir=new Map;activeFile=null;activeFileId=0;activeOffset=0;openFiles=new Map;constructor(e,n={}){this.dirname=e,this.readWrite=n.readWrite!==!1,this.syncOnPut=n.syncOnPut===!0,t.existsSync(e)||t.mkdirSync(e,{recursive:!0}),this.loadFiles(),this.readWrite&&this.rollover()}listDataFiles(){return t.readdirSync(this.dirname).filter(e=>e.endsWith(`.data`)).sort()}loadFiles(){for(let e of this.listDataFiles()){let r=parseInt(e.split(`.`)[0],10),i=n.join(this.dirname,e),a=t.openSync(i,`r`),o=0;for(;;){let e=Buffer.alloc(17);if(t.readSync(a,e,0,17,o)<17)break;let n=e.readUInt32BE(0),i=e.readUInt32BE(4),s=e.readUInt8(8)===1,c=e.readBigUInt64BE(9),l=Buffer.alloc(n);t.readSync(a,l,0,n,o+17);let u=17+n+i;this.keydir.set(l.toString(`binary`),{fileId:r,offset:o,size:u,timestamp:c,tombstone:s}),o+=u}t.closeSync(a)}}rollover(){let e=this.listDataFiles().map(e=>parseInt(e.split(`.`)[0],10)),r=e.length?Math.max(...e)+1:1,i=`${r.toString().padStart(8,`0`)}.data`,a=n.join(this.dirname,i);this.activeFile=t.createWriteStream(a,{flags:`a`}),this.activeFileId=r,this.activeOffset=t.existsSync(a)?t.statSync(a).size:0}async put(e,n){if(!this.readWrite)throw Error(`Read-only mode`);let r=Buffer.isBuffer(e)?e:Buffer.from(e),i=Buffer.isBuffer(n)?n:Buffer.from(n),a=BigInt(Date.now()),o=Buffer.alloc(17);o.writeUInt32BE(r.length,0),o.writeUInt32BE(i.length,4),o.writeUInt8(0,8),o.writeBigUInt64BE(a,9);let s=Buffer.concat([o,r,i]),c=this.activeOffset;await new Promise((e,t)=>{this.activeFile.write(s,n=>n?t(n):e())}),this.syncOnPut&&this.activeFile&&t.fsyncSync(this.activeFile.fd),this.keydir.set(r.toString(`binary`),{fileId:this.activeFileId,offset:c,size:s.length,timestamp:a,tombstone:!1}),this.activeOffset+=s.length,this.activeOffset>32*1024*1024&&(this.activeFile.close(),this.rollover())}async get(e){let t=Buffer.isBuffer(e)?e:Buffer.from(e),i=this.keydir.get(t.toString(`binary`));if(!i||i.tombstone)return null;let a=this.openFiles.get(i.fileId);a||(a=await(0,r.open)(n.join(this.dirname,`${i.fileId.toString().padStart(8,`0`)}.data`),`r`),this.openFiles.set(i.fileId,a));let o=Buffer.alloc(17);await a.read(o,0,17,i.offset);let s=o.readUInt32BE(0),c=o.readUInt32BE(4),l=Buffer.alloc(s);await a.read(l,0,s,i.offset+17);let u=Buffer.alloc(c);return await a.read(u,0,c,i.offset+17+s),u}async delete(e){if(!this.readWrite)throw Error(`Read-only mode`);let n=Buffer.isBuffer(e)?e:Buffer.from(e),r=BigInt(Date.now()),i=Buffer.alloc(17);i.writeUInt32BE(n.length,0),i.writeUInt32BE(0,4),i.writeUInt8(1,8),i.writeBigUInt64BE(r,9);let a=Buffer.concat([i,n]),o=this.activeOffset;await new Promise((e,t)=>{this.activeFile.write(a,n=>n?t(n):e())}),this.syncOnPut&&this.activeFile&&t.fsyncSync(this.activeFile.fd),this.keydir.set(n.toString(`binary`),{fileId:this.activeFileId,offset:o,size:a.length,timestamp:r,tombstone:!0}),this.activeOffset+=a.length,this.activeOffset>32*1024*1024&&(this.activeFile.close(),this.rollover())}listKeys(){return Array.from(this.keydir.entries()).filter(([e,t])=>!t.tombstone).map(([e,t])=>e)}async fold(e,t){for(let[n,r]of this.keydir.entries())r.tombstone||(t=e(n,await this.get(n),t));return t}async merge(){let e=new Map;for(let[t,n]of this.keydir.entries())n.tombstone||e.set(t,n);let r=this.listDataFiles().map(e=>parseInt(e.split(`.`)[0],10)),i=r.length?Math.max(...r)+1:1,a=`${i.toString().padStart(8,`0`)}.data`,o=n.join(this.dirname,a),s=t.createWriteStream(o,{flags:`a`});for(let[t,n]of e.entries()){let e=await this.get(t),r=Buffer.from(t,`binary`),i=Buffer.alloc(17);i.writeUInt32BE(r.length,0),i.writeUInt32BE(e.length,4),i.writeUInt8(0,8),i.writeBigUInt64BE(n.timestamp,9);let a=Buffer.concat([i,r,e]);await new Promise((e,t)=>{s.write(a,n=>n?t(n):e())})}s.close();for(let e of r)if(e!==this.activeFileId&&e!==i)try{t.unlinkSync(n.join(this.dirname,`${e.toString().padStart(8,`0`)}.data`))}catch{}this.loadFiles()}sync(){this.activeFile&&t.fsyncSync(this.activeFile.fd)}async close(){this.activeFile&&this.activeFile.end();for(let e of this.openFiles.values())await e.close();this.openFiles.clear()}};function a(e,t){return new i(e,t)}async function o(e,t){let n=await e.get(t);return n===null?`not found`:n}async function s(e,t,n){return await e.put(t,n),`ok`}async function c(e,t){return await e.delete(t),`ok`}function l(e){return e.listKeys()}async function u(e,t,n){return await e.fold(t,n)}async function d(e){let t=new i(e,{readWrite:!0});return await t.merge(),t.close(),`ok`}function f(e){return e.sync(),`ok`}async function p(e){return await e.close(),`ok`}exports.Bitcask=i,exports.close=p,exports.del=c,exports.fold=u,exports.get=o,exports.listKeys=l,exports.merge=d,exports.open=a,exports.put=s,exports.sync=f;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_chunk = require('../chunk-uaV2rQ02.cjs');
3
+ let fs = require("fs");
4
+ fs = require_chunk.__toESM(fs);
5
+ let path = require("path");
6
+ path = require_chunk.__toESM(path);
7
+ let fs_promises = require("fs/promises");
8
+
9
+ //#region src/_experiments/bitcask.ts
10
+ const ENTRY_HEADER_SIZE = 17;
11
+ var Bitcask = class {
12
+ dirname;
13
+ readWrite;
14
+ syncOnPut;
15
+ keydir = /* @__PURE__ */ new Map();
16
+ activeFile = null;
17
+ activeFileId = 0;
18
+ activeOffset = 0;
19
+ openFiles = /* @__PURE__ */ new Map();
20
+ constructor(dirname, opts = {}) {
21
+ this.dirname = dirname;
22
+ this.readWrite = opts.readWrite !== false;
23
+ this.syncOnPut = opts.syncOnPut === true;
24
+ if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });
25
+ this.loadFiles();
26
+ if (this.readWrite) this.rollover();
27
+ }
28
+ listDataFiles() {
29
+ return fs.readdirSync(this.dirname).filter((f) => f.endsWith(".data")).sort();
30
+ }
31
+ loadFiles() {
32
+ for (const fname of this.listDataFiles()) {
33
+ const fileId = parseInt(fname.split(".")[0], 10);
34
+ const filePath = path.join(this.dirname, fname);
35
+ const fd = fs.openSync(filePath, "r");
36
+ let offset = 0;
37
+ while (true) {
38
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
39
+ if (fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset) < ENTRY_HEADER_SIZE) break;
40
+ const keySize = header.readUInt32BE(0);
41
+ const valueSize = header.readUInt32BE(4);
42
+ const tombstone = header.readUInt8(8) === 1;
43
+ const timestamp = header.readBigUInt64BE(9);
44
+ const key = Buffer.alloc(keySize);
45
+ fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE);
46
+ const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize;
47
+ this.keydir.set(key.toString("binary"), {
48
+ fileId,
49
+ offset,
50
+ size: entrySize,
51
+ timestamp,
52
+ tombstone
53
+ });
54
+ offset += entrySize;
55
+ }
56
+ fs.closeSync(fd);
57
+ }
58
+ }
59
+ rollover() {
60
+ const fileIds = this.listDataFiles().map((f) => parseInt(f.split(".")[0], 10));
61
+ const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1;
62
+ const fname = `${nextId.toString().padStart(8, "0")}.data`;
63
+ const filePath = path.join(this.dirname, fname);
64
+ this.activeFile = fs.createWriteStream(filePath, { flags: "a" });
65
+ this.activeFileId = nextId;
66
+ this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0;
67
+ }
68
+ async put(key, value) {
69
+ if (!this.readWrite) throw new Error("Read-only mode");
70
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
71
+ const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value);
72
+ const timestamp = BigInt(Date.now());
73
+ const tombstone = 0;
74
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
75
+ header.writeUInt32BE(keyBuf.length, 0);
76
+ header.writeUInt32BE(valueBuf.length, 4);
77
+ header.writeUInt8(tombstone, 8);
78
+ header.writeBigUInt64BE(timestamp, 9);
79
+ const entry = Buffer.concat([
80
+ header,
81
+ keyBuf,
82
+ valueBuf
83
+ ]);
84
+ const offset = this.activeOffset;
85
+ await new Promise((resolve, reject) => {
86
+ this.activeFile.write(entry, (err) => err ? reject(err) : resolve());
87
+ });
88
+ if (this.syncOnPut && this.activeFile) fs.fsyncSync(this.activeFile.fd);
89
+ this.keydir.set(keyBuf.toString("binary"), {
90
+ fileId: this.activeFileId,
91
+ offset,
92
+ size: entry.length,
93
+ timestamp,
94
+ tombstone: false
95
+ });
96
+ this.activeOffset += entry.length;
97
+ if (this.activeOffset > 32 * 1024 * 1024) {
98
+ this.activeFile.close();
99
+ this.rollover();
100
+ }
101
+ }
102
+ async get(key) {
103
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
104
+ const meta = this.keydir.get(keyBuf.toString("binary"));
105
+ if (!meta || meta.tombstone) return null;
106
+ let fh = this.openFiles.get(meta.fileId);
107
+ if (!fh) {
108
+ fh = await (0, fs_promises.open)(path.join(this.dirname, `${meta.fileId.toString().padStart(8, "0")}.data`), "r");
109
+ this.openFiles.set(meta.fileId, fh);
110
+ }
111
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
112
+ await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset);
113
+ const keySize = header.readUInt32BE(0);
114
+ const valueSize = header.readUInt32BE(4);
115
+ const keyRead = Buffer.alloc(keySize);
116
+ await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE);
117
+ const value = Buffer.alloc(valueSize);
118
+ await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize);
119
+ return value;
120
+ }
121
+ async delete(key) {
122
+ if (!this.readWrite) throw new Error("Read-only mode");
123
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
124
+ const timestamp = BigInt(Date.now());
125
+ const tombstone = 1;
126
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
127
+ header.writeUInt32BE(keyBuf.length, 0);
128
+ header.writeUInt32BE(0, 4);
129
+ header.writeUInt8(tombstone, 8);
130
+ header.writeBigUInt64BE(timestamp, 9);
131
+ const entry = Buffer.concat([header, keyBuf]);
132
+ const offset = this.activeOffset;
133
+ await new Promise((resolve, reject) => {
134
+ this.activeFile.write(entry, (err) => err ? reject(err) : resolve());
135
+ });
136
+ if (this.syncOnPut && this.activeFile) fs.fsyncSync(this.activeFile.fd);
137
+ this.keydir.set(keyBuf.toString("binary"), {
138
+ fileId: this.activeFileId,
139
+ offset,
140
+ size: entry.length,
141
+ timestamp,
142
+ tombstone: true
143
+ });
144
+ this.activeOffset += entry.length;
145
+ if (this.activeOffset > 32 * 1024 * 1024) {
146
+ this.activeFile.close();
147
+ this.rollover();
148
+ }
149
+ }
150
+ listKeys() {
151
+ return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k);
152
+ }
153
+ async fold(fn, acc0) {
154
+ for (const [k, meta] of this.keydir.entries()) if (!meta.tombstone) acc0 = fn(k, await this.get(k), acc0);
155
+ return acc0;
156
+ }
157
+ async merge() {
158
+ const live = /* @__PURE__ */ new Map();
159
+ for (const [k, meta] of this.keydir.entries()) if (!meta.tombstone) live.set(k, meta);
160
+ const fileIds = this.listDataFiles().map((f) => parseInt(f.split(".")[0], 10));
161
+ const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1;
162
+ const fname = `${nextId.toString().padStart(8, "0")}.data`;
163
+ const filePath = path.join(this.dirname, fname);
164
+ const f = fs.createWriteStream(filePath, { flags: "a" });
165
+ for (const [k, meta] of live.entries()) {
166
+ const v = await this.get(k);
167
+ const keyBuf = Buffer.from(k, "binary");
168
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
169
+ header.writeUInt32BE(keyBuf.length, 0);
170
+ header.writeUInt32BE(v.length, 4);
171
+ header.writeUInt8(0, 8);
172
+ header.writeBigUInt64BE(meta.timestamp, 9);
173
+ const entry = Buffer.concat([
174
+ header,
175
+ keyBuf,
176
+ v
177
+ ]);
178
+ await new Promise((resolve, reject) => {
179
+ f.write(entry, (err) => err ? reject(err) : resolve());
180
+ });
181
+ }
182
+ f.close();
183
+ for (const fid of fileIds) if (fid !== this.activeFileId && fid !== nextId) try {
184
+ fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, "0")}.data`));
185
+ } catch {}
186
+ this.loadFiles();
187
+ }
188
+ sync() {
189
+ if (this.activeFile) fs.fsyncSync(this.activeFile.fd);
190
+ }
191
+ async close() {
192
+ if (this.activeFile) this.activeFile.end();
193
+ for (const fh of this.openFiles.values()) await fh.close();
194
+ this.openFiles.clear();
195
+ }
196
+ };
197
+ function open(dirname, opts) {
198
+ return new Bitcask(dirname, opts);
199
+ }
200
+ async function get(handle, key) {
201
+ const v = await handle.get(key);
202
+ return v === null ? "not found" : v;
203
+ }
204
+ async function put(handle, key, value) {
205
+ await handle.put(key, value);
206
+ return "ok";
207
+ }
208
+ async function del(handle, key) {
209
+ await handle.delete(key);
210
+ return "ok";
211
+ }
212
+ function listKeys(handle) {
213
+ return handle.listKeys();
214
+ }
215
+ async function fold(handle, fn, acc0) {
216
+ return await handle.fold(fn, acc0);
217
+ }
218
+ async function merge(dirname) {
219
+ const h = new Bitcask(dirname, { readWrite: true });
220
+ await h.merge();
221
+ h.close();
222
+ return "ok";
223
+ }
224
+ function sync(handle) {
225
+ handle.sync();
226
+ return "ok";
227
+ }
228
+ async function close(handle) {
229
+ await handle.close();
230
+ return "ok";
231
+ }
232
+
233
+ //#endregion
234
+ exports.Bitcask = Bitcask;
235
+ exports.close = close;
236
+ exports.del = del;
237
+ exports.fold = fold;
238
+ exports.get = get;
239
+ exports.listKeys = listKeys;
240
+ exports.merge = merge;
241
+ exports.open = open;
242
+ exports.put = put;
243
+ exports.sync = sync;
2
244
  //# sourceMappingURL=bitcask.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"bitcask.cjs","names":[],"sources":["../../src/_experiments/bitcask.ts"],"sourcesContent":["// Bitcask-inspired key-value store (minimal, single-process, single-writer)\n// Copyright 2024\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { FileHandle, open as openFile } from 'fs/promises'\n\nconst ENTRY_HEADER_SIZE = 17 // 4 (key) + 4 (value) + 1 (tombstone) + 8 (timestamp)\n\ninterface KeyDirEntry {\n fileId: number\n offset: number\n size: number\n timestamp: bigint\n tombstone: boolean\n}\n\nexport class Bitcask {\n private dirname: string\n private readWrite: boolean\n private syncOnPut: boolean\n private keydir: Map<string, KeyDirEntry> = new Map();\n private activeFile: fs.WriteStream | null = null;\n private activeFileId: number = 0;\n private activeOffset: number = 0;\n private openFiles: Map<number, FileHandle> = new Map();\n\n constructor(dirname: string, opts: { readWrite?: boolean; syncOnPut?: boolean } = {}) {\n this.dirname = dirname\n this.readWrite = opts.readWrite !== false\n this.syncOnPut = opts.syncOnPut === true\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true })\n this.loadFiles()\n if (this.readWrite) this.rollover()\n }\n\n private listDataFiles(): string[] {\n return fs.readdirSync(this.dirname).filter(f => f.endsWith('.data')).sort()\n }\n\n private loadFiles() {\n for (const fname of this.listDataFiles()) {\n const fileId = parseInt(fname.split('.')[0], 10)\n const filePath = path.join(this.dirname, fname)\n const fd = fs.openSync(filePath, 'r')\n let offset = 0\n while (true) {\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n const bytesRead = fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset)\n if (bytesRead < ENTRY_HEADER_SIZE) break\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const tombstone = header.readUInt8(8) === 1\n const timestamp = header.readBigUInt64BE(9)\n const key = Buffer.alloc(keySize)\n fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE)\n // skip value\n const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize\n this.keydir.set(key.toString('binary'), {\n fileId,\n offset,\n size: entrySize,\n timestamp,\n tombstone,\n })\n offset += entrySize\n }\n fs.closeSync(fd)\n }\n }\n\n private rollover() {\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n this.activeFile = fs.createWriteStream(filePath, { flags: 'a' })\n this.activeFileId = nextId\n this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0\n }\n\n async put(key: string | Buffer, value: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value)\n const timestamp = BigInt(Date.now())\n const tombstone = 0\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(valueBuf.length, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, valueBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: false,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n async get(key: string | Buffer): Promise<Buffer | null> {\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const meta = this.keydir.get(keyBuf.toString('binary'))\n if (!meta || meta.tombstone) return null\n let fh = this.openFiles.get(meta.fileId)\n if (!fh) {\n const fname = path.join(this.dirname, `${meta.fileId.toString().padStart(8, '0')}.data`)\n fh = await openFile(fname, 'r')\n this.openFiles.set(meta.fileId, fh)\n }\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset)\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const keyRead = Buffer.alloc(keySize)\n await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE)\n const value = Buffer.alloc(valueSize)\n await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize)\n return value\n }\n\n async delete(key: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const timestamp = BigInt(Date.now())\n const tombstone = 1\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(0, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: true,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n listKeys(): string[] {\n return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k)\n }\n\n async fold<T>(fn: (k: string, v: Buffer, acc: T) => T, acc0: T): Promise<T> {\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) {\n const v = await this.get(k)\n acc0 = fn(k, v!, acc0)\n }\n }\n return acc0\n }\n\n async merge() {\n // Compact all but active file\n const live: Map<string, KeyDirEntry> = new Map()\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) live.set(k, meta)\n }\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n const f = fs.createWriteStream(filePath, { flags: 'a' })\n for (const [k, meta] of live.entries()) {\n const v = await this.get(k)\n const keyBuf = Buffer.from(k, 'binary')\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(v!.length, 4)\n header.writeUInt8(0, 8)\n header.writeBigUInt64BE(meta.timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, v!])\n await new Promise<void>((resolve, reject) => {\n f.write(entry, err => (err ? reject(err) : resolve()))\n })\n }\n f.close()\n for (const fid of fileIds) {\n if (fid !== this.activeFileId && fid !== nextId) {\n try {\n fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, '0')}.data`))\n } catch { }\n }\n }\n this.loadFiles()\n }\n\n sync() {\n if (this.activeFile) fs.fsyncSync((this.activeFile as any).fd)\n }\n\n async close() {\n if (this.activeFile) this.activeFile.end()\n for (const fh of this.openFiles.values()) await fh.close()\n this.openFiles.clear()\n }\n}\n\n// API functions\nexport function open(dirname: string, opts?: { readWrite?: boolean; syncOnPut?: boolean }) {\n return new Bitcask(dirname, opts)\n}\nexport async function get(handle: Bitcask, key: string | Buffer) {\n const v = await handle.get(key)\n return v === null ? 'not found' : v\n}\nexport async function put(handle: Bitcask, key: string | Buffer, value: string | Buffer) {\n await handle.put(key, value)\n return 'ok'\n}\nexport async function del(handle: Bitcask, key: string | Buffer) {\n await handle.delete(key)\n return 'ok'\n}\nexport function listKeys(handle: Bitcask) {\n return handle.listKeys()\n}\nexport async function fold<T>(handle: Bitcask, fn: (k: string, v: Buffer, acc: T) => T, acc0: T) {\n return await handle.fold(fn, acc0)\n}\nexport async function merge(dirname: string) {\n const h = new Bitcask(dirname, { readWrite: true })\n await h.merge()\n h.close()\n return 'ok'\n}\nexport function sync(handle: Bitcask) {\n handle.sync()\n return 'ok'\n}\nexport async function close(handle: Bitcask) {\n await handle.close()\n return 'ok'\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bitcask.cjs","names":[],"sources":["../../src/_experiments/bitcask.ts"],"sourcesContent":["// Bitcask-inspired key-value store (minimal, single-process, single-writer)\n// Copyright 2024\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { FileHandle, open as openFile } from 'fs/promises'\n\nconst ENTRY_HEADER_SIZE = 17 // 4 (key) + 4 (value) + 1 (tombstone) + 8 (timestamp)\n\ninterface KeyDirEntry {\n fileId: number\n offset: number\n size: number\n timestamp: bigint\n tombstone: boolean\n}\n\nexport class Bitcask {\n private dirname: string\n private readWrite: boolean\n private syncOnPut: boolean\n private keydir: Map<string, KeyDirEntry> = new Map();\n private activeFile: fs.WriteStream | null = null;\n private activeFileId: number = 0;\n private activeOffset: number = 0;\n private openFiles: Map<number, FileHandle> = new Map();\n\n constructor(dirname: string, opts: { readWrite?: boolean; syncOnPut?: boolean } = {}) {\n this.dirname = dirname\n this.readWrite = opts.readWrite !== false\n this.syncOnPut = opts.syncOnPut === true\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true })\n this.loadFiles()\n if (this.readWrite) this.rollover()\n }\n\n private listDataFiles(): string[] {\n return fs.readdirSync(this.dirname).filter(f => f.endsWith('.data')).sort()\n }\n\n private loadFiles() {\n for (const fname of this.listDataFiles()) {\n const fileId = parseInt(fname.split('.')[0], 10)\n const filePath = path.join(this.dirname, fname)\n const fd = fs.openSync(filePath, 'r')\n let offset = 0\n while (true) {\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n const bytesRead = fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset)\n if (bytesRead < ENTRY_HEADER_SIZE) break\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const tombstone = header.readUInt8(8) === 1\n const timestamp = header.readBigUInt64BE(9)\n const key = Buffer.alloc(keySize)\n fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE)\n // skip value\n const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize\n this.keydir.set(key.toString('binary'), {\n fileId,\n offset,\n size: entrySize,\n timestamp,\n tombstone,\n })\n offset += entrySize\n }\n fs.closeSync(fd)\n }\n }\n\n private rollover() {\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n this.activeFile = fs.createWriteStream(filePath, { flags: 'a' })\n this.activeFileId = nextId\n this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0\n }\n\n async put(key: string | Buffer, value: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value)\n const timestamp = BigInt(Date.now())\n const tombstone = 0\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(valueBuf.length, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, valueBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: false,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n async get(key: string | Buffer): Promise<Buffer | null> {\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const meta = this.keydir.get(keyBuf.toString('binary'))\n if (!meta || meta.tombstone) return null\n let fh = this.openFiles.get(meta.fileId)\n if (!fh) {\n const fname = path.join(this.dirname, `${meta.fileId.toString().padStart(8, '0')}.data`)\n fh = await openFile(fname, 'r')\n this.openFiles.set(meta.fileId, fh)\n }\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset)\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const keyRead = Buffer.alloc(keySize)\n await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE)\n const value = Buffer.alloc(valueSize)\n await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize)\n return value\n }\n\n async delete(key: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const timestamp = BigInt(Date.now())\n const tombstone = 1\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(0, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: true,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n listKeys(): string[] {\n return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k)\n }\n\n async fold<T>(fn: (k: string, v: Buffer, acc: T) => T, acc0: T): Promise<T> {\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) {\n const v = await this.get(k)\n acc0 = fn(k, v!, acc0)\n }\n }\n return acc0\n }\n\n async merge() {\n // Compact all but active file\n const live: Map<string, KeyDirEntry> = new Map()\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) live.set(k, meta)\n }\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n const f = fs.createWriteStream(filePath, { flags: 'a' })\n for (const [k, meta] of live.entries()) {\n const v = await this.get(k)\n const keyBuf = Buffer.from(k, 'binary')\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(v!.length, 4)\n header.writeUInt8(0, 8)\n header.writeBigUInt64BE(meta.timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, v!])\n await new Promise<void>((resolve, reject) => {\n f.write(entry, err => (err ? reject(err) : resolve()))\n })\n }\n f.close()\n for (const fid of fileIds) {\n if (fid !== this.activeFileId && fid !== nextId) {\n try {\n fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, '0')}.data`))\n } catch { }\n }\n }\n this.loadFiles()\n }\n\n sync() {\n if (this.activeFile) fs.fsyncSync((this.activeFile as any).fd)\n }\n\n async close() {\n if (this.activeFile) this.activeFile.end()\n for (const fh of this.openFiles.values()) await fh.close()\n this.openFiles.clear()\n }\n}\n\n// API functions\nexport function open(dirname: string, opts?: { readWrite?: boolean; syncOnPut?: boolean }) {\n return new Bitcask(dirname, opts)\n}\nexport async function get(handle: Bitcask, key: string | Buffer) {\n const v = await handle.get(key)\n return v === null ? 'not found' : v\n}\nexport async function put(handle: Bitcask, key: string | Buffer, value: string | Buffer) {\n await handle.put(key, value)\n return 'ok'\n}\nexport async function del(handle: Bitcask, key: string | Buffer) {\n await handle.delete(key)\n return 'ok'\n}\nexport function listKeys(handle: Bitcask) {\n return handle.listKeys()\n}\nexport async function fold<T>(handle: Bitcask, fn: (k: string, v: Buffer, acc: T) => T, acc0: T) {\n return await handle.fold(fn, acc0)\n}\nexport async function merge(dirname: string) {\n const h = new Bitcask(dirname, { readWrite: true })\n await h.merge()\n h.close()\n return 'ok'\n}\nexport function sync(handle: Bitcask) {\n handle.sync()\n return 'ok'\n}\nexport async function close(handle: Bitcask) {\n await handle.close()\n return 'ok'\n}\n"],"mappings":"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"}
@@ -1,2 +1,231 @@
1
- import*as e from"fs";import*as t from"path";import{open as n}from"fs/promises";var r=class{dirname;readWrite;syncOnPut;keydir=new Map;activeFile=null;activeFileId=0;activeOffset=0;openFiles=new Map;constructor(t,n={}){this.dirname=t,this.readWrite=n.readWrite!==!1,this.syncOnPut=n.syncOnPut===!0,e.existsSync(t)||e.mkdirSync(t,{recursive:!0}),this.loadFiles(),this.readWrite&&this.rollover()}listDataFiles(){return e.readdirSync(this.dirname).filter(e=>e.endsWith(`.data`)).sort()}loadFiles(){for(let n of this.listDataFiles()){let r=parseInt(n.split(`.`)[0],10),i=t.join(this.dirname,n),a=e.openSync(i,`r`),o=0;for(;;){let t=Buffer.alloc(17);if(e.readSync(a,t,0,17,o)<17)break;let n=t.readUInt32BE(0),i=t.readUInt32BE(4),s=t.readUInt8(8)===1,c=t.readBigUInt64BE(9),l=Buffer.alloc(n);e.readSync(a,l,0,n,o+17);let u=17+n+i;this.keydir.set(l.toString(`binary`),{fileId:r,offset:o,size:u,timestamp:c,tombstone:s}),o+=u}e.closeSync(a)}}rollover(){let n=this.listDataFiles().map(e=>parseInt(e.split(`.`)[0],10)),r=n.length?Math.max(...n)+1:1,i=`${r.toString().padStart(8,`0`)}.data`,a=t.join(this.dirname,i);this.activeFile=e.createWriteStream(a,{flags:`a`}),this.activeFileId=r,this.activeOffset=e.existsSync(a)?e.statSync(a).size:0}async put(t,n){if(!this.readWrite)throw Error(`Read-only mode`);let r=Buffer.isBuffer(t)?t:Buffer.from(t),i=Buffer.isBuffer(n)?n:Buffer.from(n),a=BigInt(Date.now()),o=Buffer.alloc(17);o.writeUInt32BE(r.length,0),o.writeUInt32BE(i.length,4),o.writeUInt8(0,8),o.writeBigUInt64BE(a,9);let s=Buffer.concat([o,r,i]),c=this.activeOffset;await new Promise((e,t)=>{this.activeFile.write(s,n=>n?t(n):e())}),this.syncOnPut&&this.activeFile&&e.fsyncSync(this.activeFile.fd),this.keydir.set(r.toString(`binary`),{fileId:this.activeFileId,offset:c,size:s.length,timestamp:a,tombstone:!1}),this.activeOffset+=s.length,this.activeOffset>32*1024*1024&&(this.activeFile.close(),this.rollover())}async get(e){let r=Buffer.isBuffer(e)?e:Buffer.from(e),i=this.keydir.get(r.toString(`binary`));if(!i||i.tombstone)return null;let a=this.openFiles.get(i.fileId);a||(a=await n(t.join(this.dirname,`${i.fileId.toString().padStart(8,`0`)}.data`),`r`),this.openFiles.set(i.fileId,a));let o=Buffer.alloc(17);await a.read(o,0,17,i.offset);let s=o.readUInt32BE(0),c=o.readUInt32BE(4),l=Buffer.alloc(s);await a.read(l,0,s,i.offset+17);let u=Buffer.alloc(c);return await a.read(u,0,c,i.offset+17+s),u}async delete(t){if(!this.readWrite)throw Error(`Read-only mode`);let n=Buffer.isBuffer(t)?t:Buffer.from(t),r=BigInt(Date.now()),i=Buffer.alloc(17);i.writeUInt32BE(n.length,0),i.writeUInt32BE(0,4),i.writeUInt8(1,8),i.writeBigUInt64BE(r,9);let a=Buffer.concat([i,n]),o=this.activeOffset;await new Promise((e,t)=>{this.activeFile.write(a,n=>n?t(n):e())}),this.syncOnPut&&this.activeFile&&e.fsyncSync(this.activeFile.fd),this.keydir.set(n.toString(`binary`),{fileId:this.activeFileId,offset:o,size:a.length,timestamp:r,tombstone:!0}),this.activeOffset+=a.length,this.activeOffset>32*1024*1024&&(this.activeFile.close(),this.rollover())}listKeys(){return Array.from(this.keydir.entries()).filter(([e,t])=>!t.tombstone).map(([e,t])=>e)}async fold(e,t){for(let[n,r]of this.keydir.entries())r.tombstone||(t=e(n,await this.get(n),t));return t}async merge(){let n=new Map;for(let[e,t]of this.keydir.entries())t.tombstone||n.set(e,t);let r=this.listDataFiles().map(e=>parseInt(e.split(`.`)[0],10)),i=r.length?Math.max(...r)+1:1,a=`${i.toString().padStart(8,`0`)}.data`,o=t.join(this.dirname,a),s=e.createWriteStream(o,{flags:`a`});for(let[e,t]of n.entries()){let n=await this.get(e),r=Buffer.from(e,`binary`),i=Buffer.alloc(17);i.writeUInt32BE(r.length,0),i.writeUInt32BE(n.length,4),i.writeUInt8(0,8),i.writeBigUInt64BE(t.timestamp,9);let a=Buffer.concat([i,r,n]);await new Promise((e,t)=>{s.write(a,n=>n?t(n):e())})}s.close();for(let n of r)if(n!==this.activeFileId&&n!==i)try{e.unlinkSync(t.join(this.dirname,`${n.toString().padStart(8,`0`)}.data`))}catch{}this.loadFiles()}sync(){this.activeFile&&e.fsyncSync(this.activeFile.fd)}async close(){this.activeFile&&this.activeFile.end();for(let e of this.openFiles.values())await e.close();this.openFiles.clear()}};function i(e,t){return new r(e,t)}async function a(e,t){let n=await e.get(t);return n===null?`not found`:n}async function o(e,t,n){return await e.put(t,n),`ok`}async function s(e,t){return await e.delete(t),`ok`}function c(e){return e.listKeys()}async function l(e,t,n){return await e.fold(t,n)}async function u(e){let t=new r(e,{readWrite:!0});return await t.merge(),t.close(),`ok`}function d(e){return e.sync(),`ok`}async function f(e){return await e.close(),`ok`}export{r as Bitcask,f as close,s as del,l as fold,a as get,c as listKeys,u as merge,i as open,o as put,d as sync};
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { open as open$1 } from "fs/promises";
4
+
5
+ //#region src/_experiments/bitcask.ts
6
+ const ENTRY_HEADER_SIZE = 17;
7
+ var Bitcask = class {
8
+ dirname;
9
+ readWrite;
10
+ syncOnPut;
11
+ keydir = /* @__PURE__ */ new Map();
12
+ activeFile = null;
13
+ activeFileId = 0;
14
+ activeOffset = 0;
15
+ openFiles = /* @__PURE__ */ new Map();
16
+ constructor(dirname, opts = {}) {
17
+ this.dirname = dirname;
18
+ this.readWrite = opts.readWrite !== false;
19
+ this.syncOnPut = opts.syncOnPut === true;
20
+ if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true });
21
+ this.loadFiles();
22
+ if (this.readWrite) this.rollover();
23
+ }
24
+ listDataFiles() {
25
+ return fs.readdirSync(this.dirname).filter((f) => f.endsWith(".data")).sort();
26
+ }
27
+ loadFiles() {
28
+ for (const fname of this.listDataFiles()) {
29
+ const fileId = parseInt(fname.split(".")[0], 10);
30
+ const filePath = path.join(this.dirname, fname);
31
+ const fd = fs.openSync(filePath, "r");
32
+ let offset = 0;
33
+ while (true) {
34
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
35
+ if (fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset) < ENTRY_HEADER_SIZE) break;
36
+ const keySize = header.readUInt32BE(0);
37
+ const valueSize = header.readUInt32BE(4);
38
+ const tombstone = header.readUInt8(8) === 1;
39
+ const timestamp = header.readBigUInt64BE(9);
40
+ const key = Buffer.alloc(keySize);
41
+ fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE);
42
+ const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize;
43
+ this.keydir.set(key.toString("binary"), {
44
+ fileId,
45
+ offset,
46
+ size: entrySize,
47
+ timestamp,
48
+ tombstone
49
+ });
50
+ offset += entrySize;
51
+ }
52
+ fs.closeSync(fd);
53
+ }
54
+ }
55
+ rollover() {
56
+ const fileIds = this.listDataFiles().map((f) => parseInt(f.split(".")[0], 10));
57
+ const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1;
58
+ const fname = `${nextId.toString().padStart(8, "0")}.data`;
59
+ const filePath = path.join(this.dirname, fname);
60
+ this.activeFile = fs.createWriteStream(filePath, { flags: "a" });
61
+ this.activeFileId = nextId;
62
+ this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0;
63
+ }
64
+ async put(key, value) {
65
+ if (!this.readWrite) throw new Error("Read-only mode");
66
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
67
+ const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value);
68
+ const timestamp = BigInt(Date.now());
69
+ const tombstone = 0;
70
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
71
+ header.writeUInt32BE(keyBuf.length, 0);
72
+ header.writeUInt32BE(valueBuf.length, 4);
73
+ header.writeUInt8(tombstone, 8);
74
+ header.writeBigUInt64BE(timestamp, 9);
75
+ const entry = Buffer.concat([
76
+ header,
77
+ keyBuf,
78
+ valueBuf
79
+ ]);
80
+ const offset = this.activeOffset;
81
+ await new Promise((resolve, reject) => {
82
+ this.activeFile.write(entry, (err) => err ? reject(err) : resolve());
83
+ });
84
+ if (this.syncOnPut && this.activeFile) fs.fsyncSync(this.activeFile.fd);
85
+ this.keydir.set(keyBuf.toString("binary"), {
86
+ fileId: this.activeFileId,
87
+ offset,
88
+ size: entry.length,
89
+ timestamp,
90
+ tombstone: false
91
+ });
92
+ this.activeOffset += entry.length;
93
+ if (this.activeOffset > 32 * 1024 * 1024) {
94
+ this.activeFile.close();
95
+ this.rollover();
96
+ }
97
+ }
98
+ async get(key) {
99
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
100
+ const meta = this.keydir.get(keyBuf.toString("binary"));
101
+ if (!meta || meta.tombstone) return null;
102
+ let fh = this.openFiles.get(meta.fileId);
103
+ if (!fh) {
104
+ fh = await open$1(path.join(this.dirname, `${meta.fileId.toString().padStart(8, "0")}.data`), "r");
105
+ this.openFiles.set(meta.fileId, fh);
106
+ }
107
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
108
+ await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset);
109
+ const keySize = header.readUInt32BE(0);
110
+ const valueSize = header.readUInt32BE(4);
111
+ const keyRead = Buffer.alloc(keySize);
112
+ await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE);
113
+ const value = Buffer.alloc(valueSize);
114
+ await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize);
115
+ return value;
116
+ }
117
+ async delete(key) {
118
+ if (!this.readWrite) throw new Error("Read-only mode");
119
+ const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key);
120
+ const timestamp = BigInt(Date.now());
121
+ const tombstone = 1;
122
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
123
+ header.writeUInt32BE(keyBuf.length, 0);
124
+ header.writeUInt32BE(0, 4);
125
+ header.writeUInt8(tombstone, 8);
126
+ header.writeBigUInt64BE(timestamp, 9);
127
+ const entry = Buffer.concat([header, keyBuf]);
128
+ const offset = this.activeOffset;
129
+ await new Promise((resolve, reject) => {
130
+ this.activeFile.write(entry, (err) => err ? reject(err) : resolve());
131
+ });
132
+ if (this.syncOnPut && this.activeFile) fs.fsyncSync(this.activeFile.fd);
133
+ this.keydir.set(keyBuf.toString("binary"), {
134
+ fileId: this.activeFileId,
135
+ offset,
136
+ size: entry.length,
137
+ timestamp,
138
+ tombstone: true
139
+ });
140
+ this.activeOffset += entry.length;
141
+ if (this.activeOffset > 32 * 1024 * 1024) {
142
+ this.activeFile.close();
143
+ this.rollover();
144
+ }
145
+ }
146
+ listKeys() {
147
+ return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k);
148
+ }
149
+ async fold(fn, acc0) {
150
+ for (const [k, meta] of this.keydir.entries()) if (!meta.tombstone) acc0 = fn(k, await this.get(k), acc0);
151
+ return acc0;
152
+ }
153
+ async merge() {
154
+ const live = /* @__PURE__ */ new Map();
155
+ for (const [k, meta] of this.keydir.entries()) if (!meta.tombstone) live.set(k, meta);
156
+ const fileIds = this.listDataFiles().map((f) => parseInt(f.split(".")[0], 10));
157
+ const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1;
158
+ const fname = `${nextId.toString().padStart(8, "0")}.data`;
159
+ const filePath = path.join(this.dirname, fname);
160
+ const f = fs.createWriteStream(filePath, { flags: "a" });
161
+ for (const [k, meta] of live.entries()) {
162
+ const v = await this.get(k);
163
+ const keyBuf = Buffer.from(k, "binary");
164
+ const header = Buffer.alloc(ENTRY_HEADER_SIZE);
165
+ header.writeUInt32BE(keyBuf.length, 0);
166
+ header.writeUInt32BE(v.length, 4);
167
+ header.writeUInt8(0, 8);
168
+ header.writeBigUInt64BE(meta.timestamp, 9);
169
+ const entry = Buffer.concat([
170
+ header,
171
+ keyBuf,
172
+ v
173
+ ]);
174
+ await new Promise((resolve, reject) => {
175
+ f.write(entry, (err) => err ? reject(err) : resolve());
176
+ });
177
+ }
178
+ f.close();
179
+ for (const fid of fileIds) if (fid !== this.activeFileId && fid !== nextId) try {
180
+ fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, "0")}.data`));
181
+ } catch {}
182
+ this.loadFiles();
183
+ }
184
+ sync() {
185
+ if (this.activeFile) fs.fsyncSync(this.activeFile.fd);
186
+ }
187
+ async close() {
188
+ if (this.activeFile) this.activeFile.end();
189
+ for (const fh of this.openFiles.values()) await fh.close();
190
+ this.openFiles.clear();
191
+ }
192
+ };
193
+ function open(dirname, opts) {
194
+ return new Bitcask(dirname, opts);
195
+ }
196
+ async function get(handle, key) {
197
+ const v = await handle.get(key);
198
+ return v === null ? "not found" : v;
199
+ }
200
+ async function put(handle, key, value) {
201
+ await handle.put(key, value);
202
+ return "ok";
203
+ }
204
+ async function del(handle, key) {
205
+ await handle.delete(key);
206
+ return "ok";
207
+ }
208
+ function listKeys(handle) {
209
+ return handle.listKeys();
210
+ }
211
+ async function fold(handle, fn, acc0) {
212
+ return await handle.fold(fn, acc0);
213
+ }
214
+ async function merge(dirname) {
215
+ const h = new Bitcask(dirname, { readWrite: true });
216
+ await h.merge();
217
+ h.close();
218
+ return "ok";
219
+ }
220
+ function sync(handle) {
221
+ handle.sync();
222
+ return "ok";
223
+ }
224
+ async function close(handle) {
225
+ await handle.close();
226
+ return "ok";
227
+ }
228
+
229
+ //#endregion
230
+ export { Bitcask, close, del, fold, get, listKeys, merge, open, put, sync };
2
231
  //# sourceMappingURL=bitcask.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"bitcask.mjs","names":["openFile"],"sources":["../../src/_experiments/bitcask.ts"],"sourcesContent":["// Bitcask-inspired key-value store (minimal, single-process, single-writer)\n// Copyright 2024\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { FileHandle, open as openFile } from 'fs/promises'\n\nconst ENTRY_HEADER_SIZE = 17 // 4 (key) + 4 (value) + 1 (tombstone) + 8 (timestamp)\n\ninterface KeyDirEntry {\n fileId: number\n offset: number\n size: number\n timestamp: bigint\n tombstone: boolean\n}\n\nexport class Bitcask {\n private dirname: string\n private readWrite: boolean\n private syncOnPut: boolean\n private keydir: Map<string, KeyDirEntry> = new Map();\n private activeFile: fs.WriteStream | null = null;\n private activeFileId: number = 0;\n private activeOffset: number = 0;\n private openFiles: Map<number, FileHandle> = new Map();\n\n constructor(dirname: string, opts: { readWrite?: boolean; syncOnPut?: boolean } = {}) {\n this.dirname = dirname\n this.readWrite = opts.readWrite !== false\n this.syncOnPut = opts.syncOnPut === true\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true })\n this.loadFiles()\n if (this.readWrite) this.rollover()\n }\n\n private listDataFiles(): string[] {\n return fs.readdirSync(this.dirname).filter(f => f.endsWith('.data')).sort()\n }\n\n private loadFiles() {\n for (const fname of this.listDataFiles()) {\n const fileId = parseInt(fname.split('.')[0], 10)\n const filePath = path.join(this.dirname, fname)\n const fd = fs.openSync(filePath, 'r')\n let offset = 0\n while (true) {\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n const bytesRead = fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset)\n if (bytesRead < ENTRY_HEADER_SIZE) break\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const tombstone = header.readUInt8(8) === 1\n const timestamp = header.readBigUInt64BE(9)\n const key = Buffer.alloc(keySize)\n fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE)\n // skip value\n const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize\n this.keydir.set(key.toString('binary'), {\n fileId,\n offset,\n size: entrySize,\n timestamp,\n tombstone,\n })\n offset += entrySize\n }\n fs.closeSync(fd)\n }\n }\n\n private rollover() {\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n this.activeFile = fs.createWriteStream(filePath, { flags: 'a' })\n this.activeFileId = nextId\n this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0\n }\n\n async put(key: string | Buffer, value: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value)\n const timestamp = BigInt(Date.now())\n const tombstone = 0\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(valueBuf.length, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, valueBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: false,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n async get(key: string | Buffer): Promise<Buffer | null> {\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const meta = this.keydir.get(keyBuf.toString('binary'))\n if (!meta || meta.tombstone) return null\n let fh = this.openFiles.get(meta.fileId)\n if (!fh) {\n const fname = path.join(this.dirname, `${meta.fileId.toString().padStart(8, '0')}.data`)\n fh = await openFile(fname, 'r')\n this.openFiles.set(meta.fileId, fh)\n }\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset)\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const keyRead = Buffer.alloc(keySize)\n await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE)\n const value = Buffer.alloc(valueSize)\n await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize)\n return value\n }\n\n async delete(key: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const timestamp = BigInt(Date.now())\n const tombstone = 1\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(0, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: true,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n listKeys(): string[] {\n return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k)\n }\n\n async fold<T>(fn: (k: string, v: Buffer, acc: T) => T, acc0: T): Promise<T> {\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) {\n const v = await this.get(k)\n acc0 = fn(k, v!, acc0)\n }\n }\n return acc0\n }\n\n async merge() {\n // Compact all but active file\n const live: Map<string, KeyDirEntry> = new Map()\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) live.set(k, meta)\n }\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n const f = fs.createWriteStream(filePath, { flags: 'a' })\n for (const [k, meta] of live.entries()) {\n const v = await this.get(k)\n const keyBuf = Buffer.from(k, 'binary')\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(v!.length, 4)\n header.writeUInt8(0, 8)\n header.writeBigUInt64BE(meta.timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, v!])\n await new Promise<void>((resolve, reject) => {\n f.write(entry, err => (err ? reject(err) : resolve()))\n })\n }\n f.close()\n for (const fid of fileIds) {\n if (fid !== this.activeFileId && fid !== nextId) {\n try {\n fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, '0')}.data`))\n } catch { }\n }\n }\n this.loadFiles()\n }\n\n sync() {\n if (this.activeFile) fs.fsyncSync((this.activeFile as any).fd)\n }\n\n async close() {\n if (this.activeFile) this.activeFile.end()\n for (const fh of this.openFiles.values()) await fh.close()\n this.openFiles.clear()\n }\n}\n\n// API functions\nexport function open(dirname: string, opts?: { readWrite?: boolean; syncOnPut?: boolean }) {\n return new Bitcask(dirname, opts)\n}\nexport async function get(handle: Bitcask, key: string | Buffer) {\n const v = await handle.get(key)\n return v === null ? 'not found' : v\n}\nexport async function put(handle: Bitcask, key: string | Buffer, value: string | Buffer) {\n await handle.put(key, value)\n return 'ok'\n}\nexport async function del(handle: Bitcask, key: string | Buffer) {\n await handle.delete(key)\n return 'ok'\n}\nexport function listKeys(handle: Bitcask) {\n return handle.listKeys()\n}\nexport async function fold<T>(handle: Bitcask, fn: (k: string, v: Buffer, acc: T) => T, acc0: T) {\n return await handle.fold(fn, acc0)\n}\nexport async function merge(dirname: string) {\n const h = new Bitcask(dirname, { readWrite: true })\n await h.merge()\n h.close()\n return 'ok'\n}\nexport function sync(handle: Bitcask) {\n handle.sync()\n return 'ok'\n}\nexport async function close(handle: Bitcask) {\n await handle.close()\n return 'ok'\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bitcask.mjs","names":["openFile"],"sources":["../../src/_experiments/bitcask.ts"],"sourcesContent":["// Bitcask-inspired key-value store (minimal, single-process, single-writer)\n// Copyright 2024\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { FileHandle, open as openFile } from 'fs/promises'\n\nconst ENTRY_HEADER_SIZE = 17 // 4 (key) + 4 (value) + 1 (tombstone) + 8 (timestamp)\n\ninterface KeyDirEntry {\n fileId: number\n offset: number\n size: number\n timestamp: bigint\n tombstone: boolean\n}\n\nexport class Bitcask {\n private dirname: string\n private readWrite: boolean\n private syncOnPut: boolean\n private keydir: Map<string, KeyDirEntry> = new Map();\n private activeFile: fs.WriteStream | null = null;\n private activeFileId: number = 0;\n private activeOffset: number = 0;\n private openFiles: Map<number, FileHandle> = new Map();\n\n constructor(dirname: string, opts: { readWrite?: boolean; syncOnPut?: boolean } = {}) {\n this.dirname = dirname\n this.readWrite = opts.readWrite !== false\n this.syncOnPut = opts.syncOnPut === true\n if (!fs.existsSync(dirname)) fs.mkdirSync(dirname, { recursive: true })\n this.loadFiles()\n if (this.readWrite) this.rollover()\n }\n\n private listDataFiles(): string[] {\n return fs.readdirSync(this.dirname).filter(f => f.endsWith('.data')).sort()\n }\n\n private loadFiles() {\n for (const fname of this.listDataFiles()) {\n const fileId = parseInt(fname.split('.')[0], 10)\n const filePath = path.join(this.dirname, fname)\n const fd = fs.openSync(filePath, 'r')\n let offset = 0\n while (true) {\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n const bytesRead = fs.readSync(fd, header, 0, ENTRY_HEADER_SIZE, offset)\n if (bytesRead < ENTRY_HEADER_SIZE) break\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const tombstone = header.readUInt8(8) === 1\n const timestamp = header.readBigUInt64BE(9)\n const key = Buffer.alloc(keySize)\n fs.readSync(fd, key, 0, keySize, offset + ENTRY_HEADER_SIZE)\n // skip value\n const entrySize = ENTRY_HEADER_SIZE + keySize + valueSize\n this.keydir.set(key.toString('binary'), {\n fileId,\n offset,\n size: entrySize,\n timestamp,\n tombstone,\n })\n offset += entrySize\n }\n fs.closeSync(fd)\n }\n }\n\n private rollover() {\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n this.activeFile = fs.createWriteStream(filePath, { flags: 'a' })\n this.activeFileId = nextId\n this.activeOffset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0\n }\n\n async put(key: string | Buffer, value: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const valueBuf = Buffer.isBuffer(value) ? value : Buffer.from(value)\n const timestamp = BigInt(Date.now())\n const tombstone = 0\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(valueBuf.length, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, valueBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: false,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n async get(key: string | Buffer): Promise<Buffer | null> {\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const meta = this.keydir.get(keyBuf.toString('binary'))\n if (!meta || meta.tombstone) return null\n let fh = this.openFiles.get(meta.fileId)\n if (!fh) {\n const fname = path.join(this.dirname, `${meta.fileId.toString().padStart(8, '0')}.data`)\n fh = await openFile(fname, 'r')\n this.openFiles.set(meta.fileId, fh)\n }\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n await fh.read(header, 0, ENTRY_HEADER_SIZE, meta.offset)\n const keySize = header.readUInt32BE(0)\n const valueSize = header.readUInt32BE(4)\n const keyRead = Buffer.alloc(keySize)\n await fh.read(keyRead, 0, keySize, meta.offset + ENTRY_HEADER_SIZE)\n const value = Buffer.alloc(valueSize)\n await fh.read(value, 0, valueSize, meta.offset + ENTRY_HEADER_SIZE + keySize)\n return value\n }\n\n async delete(key: string | Buffer) {\n if (!this.readWrite) throw new Error('Read-only mode')\n const keyBuf = Buffer.isBuffer(key) ? key : Buffer.from(key)\n const timestamp = BigInt(Date.now())\n const tombstone = 1\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(0, 4)\n header.writeUInt8(tombstone, 8)\n header.writeBigUInt64BE(timestamp, 9)\n const entry = Buffer.concat([header, keyBuf])\n const offset = this.activeOffset\n await new Promise<void>((resolve, reject) => {\n this.activeFile!.write(entry, err => (err ? reject(err) : resolve()))\n })\n if (this.syncOnPut && this.activeFile) {\n fs.fsyncSync((this.activeFile as any).fd)\n }\n this.keydir.set(keyBuf.toString('binary'), {\n fileId: this.activeFileId,\n offset,\n size: entry.length,\n timestamp,\n tombstone: true,\n })\n this.activeOffset += entry.length\n if (this.activeOffset > 32 * 1024 * 1024) {\n this.activeFile!.close()\n this.rollover()\n }\n }\n\n listKeys(): string[] {\n return Array.from(this.keydir.entries()).filter(([_, v]) => !v.tombstone).map(([k, _]) => k)\n }\n\n async fold<T>(fn: (k: string, v: Buffer, acc: T) => T, acc0: T): Promise<T> {\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) {\n const v = await this.get(k)\n acc0 = fn(k, v!, acc0)\n }\n }\n return acc0\n }\n\n async merge() {\n // Compact all but active file\n const live: Map<string, KeyDirEntry> = new Map()\n for (const [k, meta] of this.keydir.entries()) {\n if (!meta.tombstone) live.set(k, meta)\n }\n const fileIds = this.listDataFiles().map(f => parseInt(f.split('.')[0], 10))\n const nextId = fileIds.length ? Math.max(...fileIds) + 1 : 1\n const fname = `${nextId.toString().padStart(8, '0')}.data`\n const filePath = path.join(this.dirname, fname)\n const f = fs.createWriteStream(filePath, { flags: 'a' })\n for (const [k, meta] of live.entries()) {\n const v = await this.get(k)\n const keyBuf = Buffer.from(k, 'binary')\n const header = Buffer.alloc(ENTRY_HEADER_SIZE)\n header.writeUInt32BE(keyBuf.length, 0)\n header.writeUInt32BE(v!.length, 4)\n header.writeUInt8(0, 8)\n header.writeBigUInt64BE(meta.timestamp, 9)\n const entry = Buffer.concat([header, keyBuf, v!])\n await new Promise<void>((resolve, reject) => {\n f.write(entry, err => (err ? reject(err) : resolve()))\n })\n }\n f.close()\n for (const fid of fileIds) {\n if (fid !== this.activeFileId && fid !== nextId) {\n try {\n fs.unlinkSync(path.join(this.dirname, `${fid.toString().padStart(8, '0')}.data`))\n } catch { }\n }\n }\n this.loadFiles()\n }\n\n sync() {\n if (this.activeFile) fs.fsyncSync((this.activeFile as any).fd)\n }\n\n async close() {\n if (this.activeFile) this.activeFile.end()\n for (const fh of this.openFiles.values()) await fh.close()\n this.openFiles.clear()\n }\n}\n\n// API functions\nexport function open(dirname: string, opts?: { readWrite?: boolean; syncOnPut?: boolean }) {\n return new Bitcask(dirname, opts)\n}\nexport async function get(handle: Bitcask, key: string | Buffer) {\n const v = await handle.get(key)\n return v === null ? 'not found' : v\n}\nexport async function put(handle: Bitcask, key: string | Buffer, value: string | Buffer) {\n await handle.put(key, value)\n return 'ok'\n}\nexport async function del(handle: Bitcask, key: string | Buffer) {\n await handle.delete(key)\n return 'ok'\n}\nexport function listKeys(handle: Bitcask) {\n return handle.listKeys()\n}\nexport async function fold<T>(handle: Bitcask, fn: (k: string, v: Buffer, acc: T) => T, acc0: T) {\n return await handle.fold(fn, acc0)\n}\nexport async function merge(dirname: string) {\n const h = new Bitcask(dirname, { readWrite: true })\n await h.merge()\n h.close()\n return 'ok'\n}\nexport function sync(handle: Bitcask) {\n handle.sync()\n return 'ok'\n}\nexport async function close(handle: Bitcask) {\n await handle.close()\n return 'ok'\n}\n"],"mappings":"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"}