{"_id":"abstract-level","_rev":"13-fe4fc0abe6f6199c58668f9d09501753","name":"abstract-level","dist-tags":{"latest":"3.1.1"},"versions":{"1.0.0":{"name":"abstract-level","version":"1.0.0","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@1.0.0","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"d69f67b1fc0f828bf5e395b63194b293a122728e","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.0.tgz","fileCount":68,"integrity":"sha512-/fdWtnlL275662mhqUPP6xMRSsjLNudztzGoymdVRlMZWiEw9asODN+UzEH0bYu5NbYSleqCNXYgmzfB6aeALA==","signatures":[{"sig":"MEQCIGHXqsPlZ0kG3+nrWUs15RWALfIpoZDQdwPkHddO114VAiBM0DLCN1w+uRbgrL78JAqTBauSUB/4qmpjfIEZVZpO3w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":484121,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh9v3BCRA9TVsSAnZWagAARr0P/326u/J1TEGpSlmlzzlH\nfusLU5GGa5L8LCajn3wa8hI7HNQKCb/N8kD9ACIntCZwbMMrwnVLxpNXvasP\nmyiuX9T1btbfdE1m7x1kaK5DQb07HcJXhf+wlEHqQy5nlwIzuLZ+xBrp8w1s\n6suj5Ffy9LzVoM56gLfjwEvu/U0DH8Yuyar/RfQQjgbBKsPwrySXaOL3DP60\nSEP+XNPxIYweVRD3jnfZtZImFmSmNmsk4uok9RivVekWbjBI5slXt95UoH7D\nL35FETUx60VxFiKL/WwdGB4MuCZ6GE6NMnP+Xta77z8n397xyS53LhXQzscL\nnE7duB1zUGx3/nrWoXpOLD1FydhNMl46lM427bhWdfzVpVlwvnwIQNsWRmxS\nosaKOgz7bemzLf1QjTjjMye2h7yScYiUaJgL31xUl1jI+hR4JzV4zf4cL+sn\nbpQtxOiDJa15STuKQyA06ay8hOrUaM0A3CsX68DGbCKPFQQkJCi99Z+BkvHH\nTJd6LQDUPrNVymftYIexMkGgpbHm6WROhAP7pNDAUz2IyRo/MNc/PFhBU1fr\n20fqKzKuZEbrVmyEiwPVR6TFzGfsXBxE9tL8kcF5MSRaHgVj+el6VWhS6ZB9\naIk2UejdAiJ84q2yFlfBRriMLWu1/mn/FpZkiurKiHsg644WudiKKBDEU4dc\nc7Sl\r\n=5Bc5\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","types":"./index.d.ts","browser":{"./lib/next-tick.js":"./lib/next-tick-browser.js"},"engines":{"node":">=12"},"gitHead":"d7e0181216c607babdcde9b1b223b9db034b5af4","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | faucet) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-browsers-local":"airtap --coverage -p local test/self.js"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"7.21.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"16.9.1","dependencies":{"buffer":"^6.0.3","catering":"^2.1.0","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^4.0.0","queue-microtask":"^1.2.3","level-transcoder":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.4.0","sinon":"^13.0.0","airtap":"^4.0.4","faucet":"^0.0.1","hallmark":"^4.0.0","standard":"^16.0.4","typescript":"^4.5.5","@types/node":"^17.0.6","ts-standard":"^11.0.0","airtap-sauce":"^1.1.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_1.0.0_1643576769438_0.1185336210275354","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"abstract-level","version":"1.0.1","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@1.0.1","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"6d15a5f1653dbcaa7d1d0d706c4444deff508d0b","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.1.tgz","fileCount":68,"integrity":"sha512-cnSbkJ3Ro9mLgC+kMooTFqgqbPhFgwLW+m4+K2ck8Op+zlwW8K92kLaAM3+7WMZD6o4yLMs8+j4wENpPKFK1Cw==","signatures":[{"sig":"MEUCIHfeYNixSBiMHvwtrixER6y7XhuGHxXOVm2INUTfflxzAiEAqjAb6Ef5FwRL9rE0d/FgB+9T9VH3fyDFtYf+jN2b0EE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":485139,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiAEJoCRA9TVsSAnZWagAAeV8P/Rs/vaqYvwXRBHIVdyn2\n/8c6FDkE6AAUdaxeVKly4kEGlEY+0PY8Zicfs/ENWcVjxmiYtuhd6k9fdLNT\nYp8RbgCwoQvlng8J7106qYLeTnztc5Dr81DDK1M+KXHjZs0TMB1OstOnghrS\nISJGhhVIp0yB+1/19osDLBmVeCCWC2PPPCQ4zouFiLlvkRmShZluFDQuWGrS\ndgiLVC6kx6wwhWcX4fV9qd3pHKEnxDirC6CnE2P6OTRoS/fH4ySrzaw17ZvN\n7FElFSWP+yV/IkNIgoUckZaDl7FHBlGf4e9e0DhMhK2YMo167OrnULO6LUNm\n+X+Nb/CFaqbd1gjIxckpCKrZBnEK7ptKuhDGNS/BRgM9aabVQFMj+h74Vqd/\nJLX9xDM3wvJXj1VaB/HbPlj5d7SjfmBK6V6JETjY67GLgGJKDjue6QapEQCa\n3UB0trRdJRjJ5tGcdPnI08/jOhtFIUVqrhhEIwtVbGhmVHGynLLGNMRKWix2\n4jhwtXDU4tidGbghURd88YRuxqQWuyiqdnmcPcKPD7tnpIym3/AZEgCaBFYm\nwKDNT0KCTwe8T+z/+dLQ5+7wHYHQRkreZ6LmBL5Ufi1V5SGQ2IYhVcitoFUr\n/CDjui3mGcpN8xRdHYrxZWUdlq56BMLWFNPTwn+volmu59ELEUOWyQfaJMjR\nyFmH\r\n=mbxk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","types":"./index.d.ts","browser":{"./lib/next-tick.js":"./lib/next-tick-browser.js"},"engines":{"node":">=12"},"gitHead":"971c349de8affc7eecdfd05d0f0bd7696c510c4c","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | faucet) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-browsers-local":"airtap --coverage -p local test/self.js"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"7.21.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"16.9.1","dependencies":{"buffer":"^6.0.3","catering":"^2.1.0","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^4.0.0","queue-microtask":"^1.2.3","level-transcoder":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.4.0","sinon":"^13.0.0","airtap":"^4.0.4","faucet":"^0.0.1","hallmark":"^4.0.0","standard":"^16.0.4","typescript":"^4.5.5","@types/node":"^17.0.6","ts-standard":"^11.0.0","airtap-sauce":"^1.1.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_1.0.1_1644184168276_0.6367845474289646","host":"s3://npm-registry-packages"}},"1.0.2":{"name":"abstract-level","version":"1.0.2","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@1.0.2","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"b4af0f9c28e5d75879cb309d68d2d3a352f43e6d","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.2.tgz","fileCount":68,"integrity":"sha512-IF8ZUQxmQ65Zv6TxDeH2JHFZDxJeC8Tg/4pWaY2YL+QLSEgkEommKv8DmaE/YLgG2fqEHdUD+Y95aK9Y6sni6Q==","signatures":[{"sig":"MEQCIFSD34eyR/YbjOzymkKXEki3Yf6uMwv4cEMYn/FT3Sv6AiBip/H4kVQHglGlVa4s+E1I8FRpLILAPxhw0wig9YHwTw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":486170,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJLlrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrfOBAAm6wvoq6XXbv4gkJF+9cRZ193B0Hmcdb5riBezeujoHqQltkY\r\njs+YOAbN2qnbkFKGyAYs3mm1bnmOatdJiEatA37WqEdHtrnRKGk+9qybKUEa\r\nBpk69F0yE+bXHtrqyrIQI+8hdu9I4eaxbMBPVy4mkbtEP+NN/obYRp9pt4tw\r\nG+oTRtGTIJyNN/sNO9PnwehYFkAR6Reu+uzQn7WSXg5DyMZUN6Qx/IoIqNAv\r\nKs0ss/3FkSIhqp89lCG4WN+2neAgEWm6swm5v8lA5aVBgwzLohnIx1cmlb4i\r\n0D8HiHbEjU11CIEpTENlytFWQ28JIf48iDyQxWnnrWCZ0nELyrj+PJymDIOJ\r\nTisLgqmhG5cD7/Uc+4ppYiTb5oIcjIDmZFZsGbyqiVcScCxwMEbriVWooJHi\r\nL3h7whNbYZXF+R9UfaskTsmGJoicJ966y+DWGrHw54n5qmqYEc5s3NSEBmE0\r\n/2MbxaBn6DEk4ACXXQE+qu+1QFN0T9cEmgzz+r2g3+PpBZGv7IhdtIP9dLJy\r\nQk+RQP+wyC+mzKrNhbj/fbuGcUgySRRed6xOkODSpsdOndfyx4tClR0NizWr\r\nGIdO0NJbGPidtUYSOFGv2BhBPw1od3qJEs5n/hPKhGCnFmg1IZqK4TOb+/tt\r\n2vPyTzSKPPCM+npAcqq7OLZTm9fR47a9O2E=\r\n=RyXQ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","types":"./index.d.ts","browser":{"./lib/next-tick.js":"./lib/next-tick-browser.js"},"engines":{"node":">=12"},"gitHead":"601b47c36903760c3232907423645833206871f5","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | faucet) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-browsers-local":"airtap --coverage -p local test/self.js"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"7.21.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"16.9.1","dependencies":{"buffer":"^6.0.3","catering":"^2.1.0","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^4.0.0","queue-microtask":"^1.2.3","level-transcoder":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.4.0","sinon":"^13.0.0","airtap":"^4.0.4","faucet":"^0.0.1","hallmark":"^4.0.0","standard":"^16.0.4","typescript":"^4.5.5","@types/node":"^17.0.6","ts-standard":"^11.0.0","airtap-sauce":"^1.1.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_1.0.2_1646573931080_0.6989634732212147","host":"s3://npm-registry-packages"}},"1.0.3":{"name":"abstract-level","version":"1.0.3","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@1.0.3","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"78a67d3d84da55ee15201486ab44c09560070741","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz","fileCount":67,"integrity":"sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==","signatures":[{"sig":"MEQCIGako8NheuVRuIaFis0RUS5rp6zpcwMb9r9mRR5V/ySiAiA2wuguyFCDO6BQKwa82i/aZuYY0sGoYcwV/+sK+eU2TA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":483900,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiNuq1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoasQ/+NzBydmDo/4F6Jg3qCUnnY6fbEmyjKvElHriguRdUKHI6pb8V\r\nO6pbrQXmpfrF84oS/8STQD0wj5d6cgMFklGlVBrshoQItlttl21q/dZSQIRE\r\n81F0vF5wgEg5c4KOlzLKVarai+EefE+BdInr0V7QRNBmzwely/eFCWH7PYGy\r\nWyFiLuZvtY24NzA0tjDebMStuvLuABS7iuuuwaWXSsMwuZ/n/Cxvu6Iaq9B4\r\nm4csfY2Q5g87cLnRTTe1Drdlalvrnm2tmxO/8xK4y0ixKEeHEHpiXijBTmbo\r\n6oO+RWtUYLB6DnM3bmZfOz4E1gfir8+BIrjGypk1mo8Lku3xXmwWyVFqq/wO\r\nSjaFDKUzSTtRAeW9tdEfsyy7iICRBfSFgUdwk2NW5IKK1gEIPJgXCrfeou6h\r\nbeDvC4qMc1Td1QtvcdoW2vIkFxvK5Oiueyr/iVDNchBNJGIzN3nyh0DIO3Rs\r\nbv8uS8cRUAJeh768NaD4Aefc5t7TlzTFk2JY2HKkGanYn2OuGxkFgmXApCmY\r\nRl9Gd0Dhn+sPBiRefH8/cNytg6NEXAO6X3ILncPLTxKqrhf7dtP0vCRwVPnJ\r\nwy6SFyQdFdZZW373qKnSltDqupur5Wpn5+doEZscUTJhSyw5zZOeYptstsaR\r\nVjVSGo26beio7mkjx1mGdhPgK6VPF+zZKKc=\r\n=lqfD\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","types":"./index.d.ts","browser":{"./lib/next-tick.js":"./lib/next-tick-browser.js"},"engines":{"node":">=12"},"gitHead":"34e1918ac8865baf9a4e03fc67703ad783b034f6","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | faucet) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-browsers-local":"airtap --coverage -p local test/self.js"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"7.21.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"16.9.1","dependencies":{"buffer":"^6.0.3","catering":"^2.1.0","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^4.0.0","queue-microtask":"^1.2.3","level-transcoder":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.4.0","sinon":"^13.0.0","airtap":"^4.0.4","faucet":"^0.0.1","hallmark":"^4.0.0","standard":"^16.0.4","typescript":"^4.5.5","@types/node":"^17.0.6","ts-standard":"^11.0.0","airtap-sauce":"^1.1.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_1.0.3_1647766197818_0.1533354604939623","host":"s3://npm-registry-packages"}},"1.0.4":{"name":"abstract-level","version":"1.0.4","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@1.0.4","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"3ad8d684c51cc9cbc9cf9612a7100b716c414b57","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.4.tgz","fileCount":66,"integrity":"sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg==","signatures":[{"sig":"MEYCIQDBe260QTNJ2lZfCW5FJILxw4wG9NCndTP8coqdJskU/wIhANCFIZR/4CB1jkx3wn/bwQ92dINFIGF/CFLpkcHXr3y0","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":478610},"main":"index.js","types":"./index.d.ts","browser":{"./lib/next-tick.js":"./lib/next-tick-browser.js"},"engines":{"node":">=12"},"gitHead":"a56d2aed981da27fb467501d598356cc3f8e4949","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | faucet) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"9.8.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"18.18.0","dependencies":{"buffer":"^6.0.3","catering":"^2.1.0","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^4.0.0","queue-microtask":"^1.2.3","level-transcoder":"^1.0.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.4.0","sinon":"^14.0.0","airtap":"^4.0.4","faucet":"^0.0.3","hallmark":"^4.0.0","standard":"^16.0.4","typescript":"^4.5.5","@types/node":"^18.0.0","ts-standard":"^11.0.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_1.0.4_1705763562686_0.21095725356395412","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"abstract-level","version":"2.0.0","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@2.0.0","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"3895bc87e36905871acc25f507d45dfe438ef153","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-2.0.0.tgz","fileCount":78,"integrity":"sha512-8vjY8/cluwJhbYyE1JjPMTPslT8bpkFF/Oe24KiW3jUAwV9hleHilw3ipHPK5w2pyvOYDnmUSC7w1/aKLzgi/Q==","signatures":[{"sig":"MEYCIQCHEeSkNcpIGubG1XtEC0N9UzC7gP+TJBXaqAO/7Tj+5gIhAIvdYxPO55/gH8QHKmb8inVRZh9ux1OpRnIMqbLaBVxp","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":550420},"main":"index.js","types":"./index.d.ts","engines":{"node":">=16"},"gitHead":"aab772193257299b07f31ab6c926fce660985f05","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"9.8.1","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"18.18.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.0.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.7.4","sinon":"^17.0.1","airtap":"^4.0.4","tap-arc":"^1.2.2","electron":"^28.2.0","hallmark":"^4.0.0","standard":"^17.1.0","typescript":"^5.3.3","@types/node":"^20.11.8","ts-standard":"^12.0.2","airtap-electron":"^1.0.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_2.0.0_1706976706723_0.777443773402779","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"abstract-level","version":"2.0.1","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@2.0.1","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"00a2afe24f30a22c973c7bc13c1cebf9353fabf7","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-2.0.1.tgz","fileCount":78,"integrity":"sha512-Btj350DnlLiEvcEli64YG2jwoCUdoYoxELcfJBIE6QC+1Gjk+IEuqlY2TWS5eoGa5W+fCwHu3+fLLDSdOmsklg==","signatures":[{"sig":"MEQCICyjxA4z62OhPBxvtxIx7tXE4WvJeTpEm/yJZKv/ps5lAiAsvSCFD8a8jhVOCSUVohAFmNBS48mjjLQT6x9Hfqzh7Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":542246},"main":"index.js","types":"./index.d.ts","engines":{"node":">=16"},"gitHead":"c46178b8a6afe497fb66593ccbde6bbf30bc042f","scripts":{"test":"standard && ts-standard *.ts types/*.ts && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"10.8.2","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"22.7.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.0.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.9.0","airtap":"^4.0.4","tap-arc":"^1.3.2","electron":"^30.5.1","hallmark":"^5.0.1","standard":"^17.1.2","typescript":"^5.6.3","@types/node":"^22.7.7","ts-standard":"^12.0.2","airtap-electron":"^1.0.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_2.0.1_1729546706770_0.7954442690084043","host":"s3://npm-registry-packages"}},"2.0.2":{"name":"abstract-level","version":"2.0.2","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@2.0.2","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"8d965e731afb42a72f163874410c1687fb2e4bdb","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-2.0.2.tgz","fileCount":78,"integrity":"sha512-pPJixmXk/kTKLB2sSue7o4Uj6TlLD2XfaP2gWZomHVCC6cuUGX/VslQqKG1yZHfXwBb/3lS6oSTMPGzh1P1iig==","signatures":[{"sig":"MEUCICK/h3Z7XJVUNi256JTLmOPa1P6ohcFjsQ42nPVYDdG4AiEA4T2kxbKSWIgnAdD1eT5dVVeS8QA5Sk09yeW7oaGWxC8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":542549},"main":"index.js","types":"./index.d.ts","engines":{"node":">=16"},"gitHead":"7ffb7b25f82b6c461d058092441daf5767765c80","scripts":{"test":"standard && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"10.8.2","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"22.7.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.0.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","tape":"^5.9.0","airtap":"^4.0.4","tap-arc":"^1.3.2","electron":"^30.5.1","hallmark":"^5.0.1","standard":"^17.1.2","typescript":"^5.6.3","@types/node":"^22.7.7","airtap-electron":"^1.0.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_2.0.2_1733767509625_0.26784666520158384","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"abstract-level","version":"3.0.0","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@3.0.0","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"ee11570b923c81a3fe170911600e57070663fd9d","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-3.0.0.tgz","fileCount":83,"integrity":"sha512-mTfG64Si0S7Y65tgBHFaSwa5vh6lM8ewg97XZ0KK5i43YYtBFRlYwXs1EyO8v2OOzLEbPZ5f2iX5ies8CAn27Q==","signatures":[{"sig":"MEUCIQC5osiEootVXE3DqaJfsmSR4qwlLxhYW5lhrBP2ae9gNwIgdsoGr9TsFM+gfCcAMg9TnFXTWcAMEDvndhWpCvRZaec=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":580731},"main":"index.js","types":"./index.d.ts","engines":{"node":">=18"},"gitHead":"6e72c9dbd65f7ee9be1b0bcea437d67dbd01c738","scripts":{"test":"standard && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"10.8.2","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"22.7.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.2.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^17.1.0","tape":"^5.9.0","airtap":"^5.0.0","tap-arc":"^1.3.2","babelify":"^10.0.0","electron":"^33.2.1","hallmark":"^5.0.1","standard":"^17.1.2","typescript":"^5.7.2","@types/node":"^22.10.2","airtap-electron":"^1.0.0","@babel/preset-env":"^7.26.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^15.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_3.0.0_1736104210103_0.9749682080154431","host":"s3://npm-registry-packages-npm-production"}},"3.0.1":{"name":"abstract-level","version":"3.0.1","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@3.0.1","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"12f24cf9ef265d2dfd3523638fa5feb609f7ec9f","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-3.0.1.tgz","fileCount":83,"integrity":"sha512-DpAkolwLhCoB7SZpCQyZk2yRw76XpjdNZ3BhEnaKdtYNnm/i8tSq7kXCnpz23ddPXeAOEYKVvWsFKpz00V9dLw==","signatures":[{"sig":"MEUCIA0MYyJdD1VEAVPI6rnNjYdHUib00kpKzSdvqVvBj4qgAiEAsGaC3FjnPVZ8l3Gd28HHWvrV9DR05Onexn33NZncq8E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":582344},"main":"index.js","types":"./index.d.ts","engines":{"node":">=18"},"gitHead":"c35ab16d884a76f2baebf8fb9dd981c32b4b14d0","scripts":{"test":"standard && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"10.8.2","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"22.7.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.2.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^17.1.0","tape":"^5.9.0","airtap":"^5.0.0","tap-arc":"^1.3.2","babelify":"^10.0.0","electron":"^33.2.1","hallmark":"^5.0.1","standard":"^17.1.2","typescript":"^5.7.2","@types/node":"^22.10.2","airtap-electron":"^1.0.0","@babel/preset-env":"^7.26.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^15.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_3.0.1_1737906902352_0.6831555311495128","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"abstract-level","version":"3.1.0","keywords":["abstract-level","level","leveldb"],"license":"MIT","_id":"abstract-level@3.1.0","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"homepage":"https://github.com/Level/abstract-level","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"dist":{"shasum":"4d5ddf4f515c871ae22c5c7f9c7c91e067de9bd8","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-3.1.0.tgz","fileCount":84,"integrity":"sha512-j2e+TsAxy7Ri+0h7dJqwasymgt0zHBWX4+nMk3XatyuqgHfdstBJ9wsMfbiGwE1O+QovRyPcVAqcViMYdyPaaw==","signatures":[{"sig":"MEQCIDtgPegGpq55ws6QCsCygfHZiSepFpi24UpfvtAd/wabAiB8FN9JUDIg2mgJVSpMhRKFM7xJRrIwpMiXTK+vR6QcIA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":593393},"main":"index.js","types":"./index.d.ts","engines":{"node":">=18"},"gitHead":"c5dd82bfc2f34b47963e8cea1e032ec6853bce4d","scripts":{"test":"standard && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","coverage":"nyc report -r lcovonly","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","test-pessimistic":"node test/self.js | tap-arc -pv"},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"repository":{"url":"git+https://github.com/Level/abstract-level.git","type":"git"},"_npmVersion":"10.8.2","description":"Abstract class for a lexicographically sorted key-value database","directories":{},"_nodeVersion":"22.7.0","dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","module-error":"^1.0.1","level-supports":"^6.2.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^17.1.0","tape":"^5.9.0","airtap":"^5.0.0","tap-arc":"^1.3.2","babelify":"^10.0.0","electron":"^33.2.1","hallmark":"^5.0.1","standard":"^17.1.2","typescript":"^5.7.2","@types/node":"^22.10.2","airtap-electron":"^1.0.0","@babel/preset-env":"^7.26.0","airtap-playwright":"^1.0.1","@voxpelli/tsconfig":"^15.1.0"},"_npmOperationalInternal":{"tmp":"tmp/abstract-level_3.1.0_1744476512043_0.9617350618160765","host":"s3://npm-registry-packages-npm-production"}},"3.1.1":{"name":"abstract-level","version":"3.1.1","description":"Abstract class for a lexicographically sorted key-value database","license":"MIT","main":"index.js","types":"./index.d.ts","scripts":{"test":"eslint && hallmark && (nyc -s node test/self.js | tap-arc) && nyc report","test-pessimistic":"node test/self.js | tap-arc -pv","test-browsers":"airtap --coverage test/self.js","test-electron":"airtap -p electron --coverage test/self.js | tap-arc","coverage":"nyc report -r lcovonly"},"dependencies":{"buffer":"^6.0.3","is-buffer":"^2.0.5","level-supports":"^6.2.0","level-transcoder":"^1.0.1","maybe-combine-errors":"^1.0.0","module-error":"^1.0.1"},"devDependencies":{"@babel/preset-env":"^7.28.3","@types/node":"^24.6.0","@voxpelli/tsconfig":"^16.1.0","airtap":"^5.0.0","airtap-electron":"^1.0.0","airtap-playwright":"^1.0.1","babelify":"^10.0.0","electron":"^33.2.1","eslint":"^9.36.0","hallmark":"^5.0.1","neostandard":"^0.12.2","nyc":"^17.1.0","tap-arc":"^1.3.2","tape":"^5.9.0","typescript":"^5.9.2"},"repository":{"type":"git","url":"git+https://github.com/Level/abstract-level.git"},"homepage":"https://github.com/Level/abstract-level","keywords":["abstract-level","level","leveldb"],"engines":{"node":">=18"},"_id":"abstract-level@3.1.1","gitHead":"17d1925df02eda8185d1c91498edccbf3a6ea63f","bugs":{"url":"https://github.com/Level/abstract-level/issues"},"_nodeVersion":"22.7.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-CW2gKbJFTuX1feMvOrvsVMmijAOgI9kg2Ie9Dq3gOcMt/dVVoVmqNlLcEUCT13NxHFMEajcUcVBIplbyDroDiw==","shasum":"d61a7ae1a5cff15f315592a4cfa3259489ac2388","tarball":"https://registry.npmjs.org/abstract-level/-/abstract-level-3.1.1.tgz","fileCount":84,"unpackedSize":593830,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICYNMcNWATFBckXBoka737FIxbasSc4l6BG/HSI/XSe0AiBqklsglifZ3z2sg+AHisL/Zv0fUwDZoudQPNnStBdGJw=="}]},"_npmUser":{"name":"vweevers","email":"dev@vincentweevers.nl"},"directories":{},"maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/abstract-level_3.1.1_1759174849876_0.657480533250469"},"_hasShrinkwrap":false}},"time":{"created":"2022-01-30T21:06:09.437Z","modified":"2025-09-29T19:40:50.323Z","1.0.0":"2022-01-30T21:06:09.633Z","1.0.1":"2022-02-06T21:49:28.456Z","1.0.2":"2022-03-06T13:38:51.174Z","1.0.3":"2022-03-20T08:49:57.943Z","1.0.4":"2024-01-20T15:12:42.881Z","2.0.0":"2024-02-03T16:11:46.886Z","2.0.1":"2024-10-21T21:38:27.086Z","2.0.2":"2024-12-09T18:05:09.881Z","3.0.0":"2025-01-05T19:10:10.382Z","3.0.1":"2025-01-26T15:55:02.648Z","3.1.0":"2025-04-12T16:48:32.221Z","3.1.1":"2025-09-29T19:40:50.130Z"},"bugs":{"url":"https://github.com/Level/abstract-level/issues"},"license":"MIT","homepage":"https://github.com/Level/abstract-level","keywords":["abstract-level","level","leveldb"],"repository":{"type":"git","url":"git+https://github.com/Level/abstract-level.git"},"description":"Abstract class for a lexicographically sorted key-value database","maintainers":[{"name":"vweevers","email":"dev@vincentweevers.nl"}],"readme":"# abstract-level\n\n**Abstract class for a lexicographically sorted key-value database.** Provides encodings, sublevels, events and hooks. If you are upgrading, please see [`UPGRADING.md`](UPGRADING.md).\n\n> :pushpin: Wondering what happened to `levelup`? Visit [Frequently Asked Questions](https://github.com/Level/community#faq).\n\n[![level badge][level-badge]](https://github.com/Level/awesome)\n[![npm](https://img.shields.io/npm/v/abstract-level.svg)](https://www.npmjs.com/package/abstract-level)\n[![Node version](https://img.shields.io/node/v/abstract-level.svg)](https://www.npmjs.com/package/abstract-level)\n[![Test](https://img.shields.io/github/actions/workflow/status/Level/abstract-level/test.yml?branch=main\\&label=test)](https://github.com/Level/abstract-level/actions/workflows/test.yml)\n[![Coverage](https://img.shields.io/codecov/c/github/Level/abstract-level?label=\\&logo=codecov\\&logoColor=fff)](https://codecov.io/gh/Level/abstract-level)\n[![Standard](https://img.shields.io/badge/standard-informational?logo=javascript\\&logoColor=fff)](https://standardjs.com)\n[![Common Changelog](https://common-changelog.org/badge.svg)](https://common-changelog.org)\n[![Donate](https://img.shields.io/badge/donate-orange?logo=open-collective\\&logoColor=fff)](https://opencollective.com/level)\n\n## Usage\n\nThis module exports an abstract class. End users should instead use modules like [`level`](https://github.com/Level/level) that export a concrete implementation. The purpose of the abstract class is to provide a common interface that looks like this:\n\n```js\n// Create a database\nconst db = new Level('./db', { valueEncoding: 'json' })\n\n// Add an entry with key 'a' and value 1\nawait db.put('a', 1)\n\n// Add multiple entries\nawait db.batch([{ type: 'put', key: 'b', value: 2 }])\n\n// Get value of key 'a': 1\nconst value = await db.get('a')\n\n// Iterate entries with keys that are greater than 'a'\nfor await (const [key, value] of db.iterator({ gt: 'a' })) {\n  console.log(value) // 2\n}\n```\n\nUsage from TypeScript requires generic type parameters.\n\n<details><summary>TypeScript example</summary>\n\n```ts\n// Specify types of keys and values (any, in the case of json).\n// The generic type parameters default to Level<string, string>.\nconst db = new Level<string, any>('./db', { valueEncoding: 'json' })\n\n// All relevant methods then use those types\nawait db.put('a', { x: 123 })\n\n// Specify different types when overriding encoding per operation\nawait db.get<string, string>('a', { valueEncoding: 'utf8' })\n\n// Though in some cases TypeScript can infer them\nawait db.get('a', { valueEncoding: db.valueEncoding('utf8') })\n\n// It works the same for sublevels\nconst abc = db.sublevel('abc')\nconst xyz = db.sublevel<string, any>('xyz', { valueEncoding: 'json' })\n```\n\n</details>\n\nTypeScript users can benefit from the `using` keyword because `abstract-level` implements [`Symbol.asyncDispose`](https://github.com/tc39/proposal-explicit-resource-management) on its resources. For example:\n\n<details><summary>Using example</summary>\n\n```ts\nawait db.put('example', 'before')\nawait using snapshot = db.snapshot()\nawait db.put('example', 'after')\nawait db.get('example', { snapshot })) // Returns 'before'\n```\n\nThe equivalent in JavaScript would be:\n\n```js\nawait db.put('example', 'before')\nconst snapshot = db.snapshot()\n\ntry {\n  await db.put('example', 'after')\n  await db.get('example', { snapshot })) // Returns 'before'\n} finally {\n  await snapshot.close()\n}\n```\n\n</details>\n\n## Install\n\nWith [npm](https://npmjs.org) do:\n\n```shell\nnpm install abstract-level\n```\n\n## Supported Platforms\n\nWe aim to support Active LTS and Current Node.js releases, as well as evergreen browsers that are based on Chromium, Firefox or Webkit. Features that the runtime must support include [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask#browser_compatibility), [`Promise.allSettled()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled#browser_compatibility), [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility) and [async generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function*#browser_compatibility). Supported runtimes may differ per implementation.\n\n## Public API For Consumers\n\nThis module has a public API for consumers of a database and a [private API](#private-api-for-implementors) for concrete implementations. The public API, as documented in this section, offers a simple yet rich interface that is common between all implementations. Implementations may have additional options or methods. TypeScript [type declarations](https://www.typescriptlang.org/docs/handbook/2/type-declarations.html) are [included](./index.d.ts) (and exported for reuse) only for the public API.\n\nAn `abstract-level` database is at its core a [key-value database](https://en.wikipedia.org/wiki/Key%E2%80%93value_database). A key-value pair is referred to as an _entry_ here and typically returned as an array, comparable to [`Object.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries).\n\n### `db = new Level(...[, options])`\n\nCreating a database is done by calling a class constructor. Implementations export a class that extends the [`AbstractLevel`](./abstract-level.js) class and has its own constructor with an implementation-specific signature. All constructors should have an `options` argument as the last. Typically, constructors take a `location` as their first argument, pointing to where the data will be stored. That may be a file path, URL, something else or none at all, since not all implementations are disk-based or persistent. Others take another database rather than a location as their first argument.\n\nThe optional `options` object may contain:\n\n- `keyEncoding` (string or object, default `'utf8'`): encoding to use for keys\n- `valueEncoding` (string or object, default `'utf8'`): encoding to use for values.\n\nSee [Encodings](#encodings) for a full description of these options. Other `options` (except `passive`) are forwarded to `db.open()` which is automatically called in a next tick after the constructor returns. Any read & write operations are queued internally until the database has finished opening. If opening fails, those queued operations will yield errors.\n\n### `db.status`\n\nGetter that returns a string reflecting the current state of the database:\n\n- `'opening'` - waiting for the database to be opened\n- `'open'` - successfully opened the database\n- `'closing'` - waiting for the database to be closed\n- `'closed'` - database is closed.\n\n### `db.open([options])`\n\nOpen the database. Returns a promise. Options passed to `open()` take precedence over options passed to the database constructor. Not all implementations support the `createIfMissing` and `errorIfExists` options (notably [`memory-level`](https://github.com/Level/memory-level) and [`browser-level`](https://github.com/Level/browser-level)) and will indicate so via `db.supports.createIfMissing` and `db.supports.errorIfExists`.\n\nThe optional `options` object may contain:\n\n- `createIfMissing` (boolean, default: `true`): If `true`, create an empty database if one doesn't already exist. If `false` and the database doesn't exist, opening will fail.\n- `errorIfExists` (boolean, default: `false`): If `true` and the database already exists, opening will fail.\n- `passive` (boolean, default: `false`): Wait for, but do not initiate, opening of the database.\n\nIt's generally not necessary to call `open()` because it's automatically called by the database constructor. It may however be useful to capture an error from failure to open, that would otherwise not surface until another method like `db.get()` is called. It's also possible to reopen the database after it has been closed with [`close()`](#dbclose). Once `open()` has then been called, any read & write operations will again be queued internally until opening has finished.\n\nThe `open()` and `close()` methods are idempotent. If the database is already open, the promise returned by `open()` will resolve without delay. If opening is already in progress, the promise will resolve when that has finished. If closing is in progress, the database will be reopened once closing has finished. Likewise, if `close()` is called after `open()`, the database will be closed once opening has finished.\n\n### `db.close()`\n\nClose the database. Returns a promise.\n\nA database may have associated resources like file handles and locks. When the database is no longer needed (for the remainder of a program) it's recommended to call `db.close()` to free up resources.\n\nAfter `db.close()` has been called, no further read & write operations are allowed unless and until `db.open()` is called again. For example, `db.get(key)` will yield an error with code [`LEVEL_DATABASE_NOT_OPEN`](#errors). Any unclosed iterators, snapshots and chained batches will be closed by `db.close()` and can then no longer be used even when `db.open()` is called again.\n\n### `db.get(key[, options])`\n\nGet a value from the database by `key`. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n- `valueEncoding`: custom value encoding for this operation, used to decode the value.\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from.\n\nReturns a promise for the value. If the `key` was not found then the value will be `undefined`.\n\n### `db.getSync(key[, options])`\n\nSynchronously get a value from the database by `key`. This blocks the event loop but can be significantly faster than `db.get()`. Options are the same. Returns the value, or `undefined` if not found.\n\n### `db.getMany(keys[, options])`\n\nGet multiple values from the database by an array of `keys`. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `keys`.\n- `valueEncoding`: custom value encoding for this operation, used to decode values.\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from.\n\nReturns a promise for an array of values with the same order as `keys`. If a key was not found, the relevant value will be `undefined`.\n\n### `db.has(key[, options])`\n\nCheck if the database has an entry with the given `key`. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from.\n\nReturns a promise for a boolean. For example:\n\n```js\nif (await db.has('fruit')) {\n  console.log('We have fruit')\n}\n```\n\nIf the value of the entry is needed, instead do:\n\n```js\nconst value = await db.get('fruit')\n\nif (value !== undefined) {\n  console.log('We have fruit: %o', value)\n}\n```\n\n### `db.hasMany(keys[, options])`\n\nCheck if the database has entries with the given keys. The `keys` argument must be an array. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `keys`.\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from.\n\nReturns a promise for an array of booleans with the same order as `keys`. For example:\n\n```js\nawait db.put('a', '123')\nawait db.hasMany(['a', 'b']) // [true, false]\n```\n\n### `db.put(key, value[, options])`\n\nAdd a new entry or overwrite an existing entry. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n- `valueEncoding`: custom value encoding for this operation, used to encode the `value`.\n\nReturns a promise.\n\n### `db.del(key[, options])`\n\nDelete an entry by `key`. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n\nReturns a promise.\n\n### `db.batch(operations[, options])`\n\nPerform multiple _put_ and/or _del_ operations in bulk. Returns a promise. The `operations` argument must be an array containing a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation.\n\nEach operation must be an object with at least a `type` property set to either `'put'` or `'del'`. If the `type` is `'put'`, the operation must have `key` and `value` properties. It may optionally have `keyEncoding` and / or `valueEncoding` properties to encode keys or values with a custom encoding for just that operation. If the `type` is `'del'`, the operation must have a `key` property and may optionally have a `keyEncoding` property.\n\nAn operation of either type may also have a `sublevel` property, to prefix the key of the operation with the prefix of that sublevel. This allows atomically committing data to multiple sublevels. The given `sublevel` must have the same _root_ (i.e. top-most) database as `db`. Keys and values will be encoded by the sublevel, to the same effect as a `sublevel.batch(..)` call. In the following example, the first `value` will be encoded with `'json'` rather than the default encoding of `db`:\n\n```js\nconst people = db.sublevel('people', { valueEncoding: 'json' })\nconst nameIndex = db.sublevel('names')\n\nawait db.batch([{\n  type: 'put',\n  sublevel: people,\n  key: '123',\n  value: {\n    name: 'Alice'\n  }\n}, {\n  type: 'put',\n  sublevel: nameIndex,\n  key: 'Alice',\n  value: '123'\n}])\n```\n\nThe optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this batch, used to encode keys.\n- `valueEncoding`: custom value encoding for this batch, used to encode values.\n\nEncoding properties on individual operations take precedence. In the following example, the first value will be encoded with the `'utf8'` encoding and the second with `'json'`.\n\n```js\nawait db.batch([\n  { type: 'put', key: 'a', value: 'foo' },\n  { type: 'put', key: 'b', value: 123, valueEncoding: 'json' }\n], { valueEncoding: 'utf8' })\n```\n\n### `chainedBatch = db.batch()`\n\nCreate a [chained batch](#chainedbatch), when `batch()` is called with zero arguments. A chained batch can be used to build and eventually commit an atomic batch of operations:\n\n```js\nconst chainedBatch = db.batch()\n  .del('bob')\n  .put('alice', 361)\n  .put('kim', 220)\n\n// Commit\nawait chainedBatch.write()\n```\n\nDepending on how it's used, it is possible to obtain greater overall performance with this form of `batch()`, mainly because its methods like `put()` can immediately copy the data of that singular operation to the underlying storage, rather than having to block the event loop while copying the data of multiple operations. However, on several `abstract-level` implementations, chained batch is just sugar and has no performance benefits.\n\nDue to its synchronous nature, it is not possible to create a chained batch before the database has finished opening. Be sure to call `await db.open()` before `chainedBatch = db.batch()`. This does not apply to other database methods.\n\n### `iterator = db.iterator([options])`\n\nCreate an [iterator](#iterator). The optional `options` object may contain the following _range options_ to control the range of entries to be iterated:\n\n- `gt` (greater than) or `gte` (greater than or equal): define the lower bound of the range to be iterated. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse` is true the order will be reversed, but the entries iterated will be the same.\n- `lt` (less than) or `lte` (less than or equal): define the higher bound of the range to be iterated. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse` is true the order will be reversed, but the entries iterated will be the same.\n- `reverse` (boolean, default: `false`): iterate entries in reverse order. Beware that a reverse seek can be slower than a forward seek.\n- `limit` (number, default: `Infinity`): limit the number of entries yielded. This number represents a _maximum_ number of entries and will not be reached if the end of the range is reached first. A value of `Infinity` or `-1` means there is no limit. When `reverse` is true the entries with the highest keys will be returned instead of the lowest keys.\n\nThe `gte` and `lte` range options take precedence over `gt` and `lt` respectively. If no range options are provided, the iterator will visit all entries of the database, starting at the lowest key and ending at the highest key (unless `reverse` is true). In addition to range options, the `options` object may contain:\n\n- `keys` (boolean, default: `true`): whether to return the key of each entry. If set to `false`, the iterator will yield keys that are `undefined`. Prefer to use `db.keys()` instead.\n- `values` (boolean, default: `true`): whether to return the value of each entry. If set to `false`, the iterator will yield values that are `undefined`. Prefer to use `db.values()` instead.\n- `keyEncoding`: custom key encoding for this iterator, used to encode range options, to encode `seek()` targets and to decode keys.\n- `valueEncoding`: custom value encoding for this iterator, used to decode values.\n- `signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to [abort read operations on the iterator](#aborting-iterators).\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from.\n\nLastly, an implementation is free to add its own options.\n\n> :pushpin: To instead consume data using streams, see [`level-read-stream`](https://github.com/Level/read-stream) and [`level-web-stream`](https://github.com/Level/web-stream).\n\n### `keyIterator = db.keys([options])`\n\nCreate a [key iterator](#keyiterator), having the same interface as `db.iterator()` except that it yields keys instead of entries. If only keys are needed, using `db.keys()` may increase performance because values won't have to fetched, copied or decoded. Options are the same as for `db.iterator()` except that `db.keys()` does not take `keys`, `values` and `valueEncoding` options.\n\n```js\n// Iterate lazily\nfor await (const key of db.keys({ gt: 'a' })) {\n  console.log(key)\n}\n\n// Get all at once. Setting a limit is recommended.\nconst keys = await db.keys({ gt: 'a', limit: 10 }).all()\n```\n\n### `valueIterator = db.values([options])`\n\nCreate a [value iterator](#valueiterator), having the same interface as `db.iterator()` except that it yields values instead of entries. If only values are needed, using `db.values()` may increase performance because keys won't have to fetched, copied or decoded. Options are the same as for `db.iterator()` except that `db.values()` does not take `keys` and `values` options. Note that it _does_ take a `keyEncoding` option, relevant for the encoding of range options.\n\n```js\n// Iterate lazily\nfor await (const value of db.values({ gt: 'a' })) {\n  console.log(value)\n}\n\n// Get all at once. Setting a limit is recommended.\nconst values = await db.values({ gt: 'a', limit: 10 }).all()\n```\n\n### `db.clear([options])`\n\nDelete all entries or a range. Not guaranteed to be atomic. Returns a promise. Accepts the following options (with the same rules as on iterators):\n\n- `gt` (greater than) or `gte` (greater than or equal): define the lower bound of the range to be deleted. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse` is true the order will be reversed, but the entries deleted will be the same.\n- `lt` (less than) or `lte` (less than or equal): define the higher bound of the range to be deleted. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse` is true the order will be reversed, but the entries deleted will be the same.\n- `reverse` (boolean, default: `false`): delete entries in reverse order. Only effective in combination with `limit`, to delete the last N entries.\n- `limit` (number, default: `Infinity`): limit the number of entries to be deleted. This number represents a _maximum_ number of entries and will not be reached if the end of the range is reached first. A value of `Infinity` or `-1` means there is no limit. When `reverse` is true the entries with the highest keys will be deleted instead of the lowest keys.\n- `keyEncoding`: custom key encoding for this operation, used to encode range options.\n- `snapshot`: explicit [snapshot](#snapshot--dbsnapshotoptions) to read from, such that entries not present in the snapshot will not be deleted. If no `snapshot` is provided, the database may create its own internal snapshot but (unlike on other methods) this is currently not a hard requirement for implementations.\n\nThe `gte` and `lte` range options take precedence over `gt` and `lt` respectively. If no options are provided, all entries will be deleted.\n\n### `sublevel = db.sublevel(name[, options])`\n\nCreate a [sublevel](#sublevel) that has the same interface as `db` (except for additional, implementation-specific methods) and prefixes the keys of operations before passing them on to `db`. The `name` argument is required and must be a string, or an array of strings (explained further below).\n\n```js\nconst example = db.sublevel('example')\n\nawait example.put('hello', 'world')\nawait db.put('a', '1')\n\n// Prints ['hello', 'world']\nfor await (const [key, value] of example.iterator()) {\n  console.log([key, value])\n}\n```\n\nSublevels effectively separate a database into sections. Think SQL tables, but evented, ranged and realtime! Each sublevel is an `AbstractLevel` instance with its own keyspace, [encodings](https://github.com/Level/abstract-level#encodings), [hooks](https://github.com/Level/abstract-level#hooks) and [events](https://github.com/Level/abstract-level#events). For example, it's possible to have one sublevel with `'buffer'` keys and another with `'utf8'` keys. The same goes for values. Like so:\n\n```js\ndb.sublevel('one', { valueEncoding: 'json' })\ndb.sublevel('two', { keyEncoding: 'buffer' })\n```\n\nAn own keyspace means that `sublevel.iterator()` only includes entries of that sublevel, `sublevel.clear()` will only delete entries of that sublevel, and so forth. Range options get prefixed too.\n\nFully qualified keys (as seen from the parent database) take the form of `prefix + key` where `prefix` is `separator + name + separator`. If `name` is empty, the effective prefix is two separators. Sublevels can be nested: if `db` is itself a sublevel then the effective prefix is a combined prefix, e.g. `'!one!!two!'`. Note that a parent database will see its own keys as well as keys of any nested sublevels:\n\n```js\n// Prints ['!example!hello', 'world'] and ['a', '1']\nfor await (const [key, value] of db.iterator()) {\n  console.log([key, value])\n}\n```\n\n> :pushpin: The key structure is equal to that of [`subleveldown`](https://github.com/Level/subleveldown) which offered sublevels before they were built-in to `abstract-level`. This means that an `abstract-level` sublevel can read sublevels previously created with (and populated by) `subleveldown`.\n\nInternally, sublevels operate on keys that are either a string, Buffer or Uint8Array, depending on parent database and choice of encoding. Which is to say: binary keys are fully supported. The `name` must however always be a string and can only contain ASCII characters.\n\nThe optional `options` object may contain:\n\n- `separator` (string, default: `'!'`): Character for separating sublevel names from user keys and each other. Must sort before characters used in `name`. An error will be thrown if that's not the case.\n- `keyEncoding` (string or object, default `'utf8'`): encoding to use for keys\n- `valueEncoding` (string or object, default `'utf8'`): encoding to use for values.\n\nThe `keyEncoding` and `valueEncoding` options are forwarded to the `AbstractLevel` constructor and work the same, as if a new, separate database was created. They default to `'utf8'` regardless of the encodings configured on `db`. Other options are forwarded too but `abstract-level` has no relevant options at the time of writing. For example, setting the `createIfMissing` option will have no effect. Why is that?\n\nLike regular databases, sublevels open themselves, but they do not affect the state of the parent database. This means a sublevel can be individually closed and (re)opened. If the sublevel is created while the parent database is opening, it will wait for that to finish. Closing the parent database will automatically close the sublevel, along with other resources like iterators.\n\nLastly, the `name` argument can be an array as a shortcut to create nested sublevels. Those are normally created like so:\n\n```js\nconst indexes = db.sublevel('idx')\nconst colorIndex = indexes.sublevel('colors')\n```\n\nHere, the parent database of `colorIndex` is `indexes`. Operations made on `colorIndex` are thus forwarded from that sublevel to `indexes` and from there to `db`. At each step, hooks and events are available to transform and react to data from a different perspective. Which comes at a (typically small) performance cost that increases with further nested sublevels. If the `indexes` sublevel is only used to organize keys and not directly interfaced with, operations on `colorIndex` can be made faster by skipping `indexes`:\n\n```js\nconst colorIndex = db.sublevel(['idx', 'colors'])\n```\n\nIn this case, the parent database of `colorIndex` is `db`. Note that it's still possible to separately create the `indexes` sublevel, but it will be disconnected from `colorIndex`, meaning that `indexes` will not see (live) operations made on `colorIndex`.\n\n### `encoding = db.keyEncoding([encoding])`\n\nReturns the given `encoding` argument as a normalized encoding object that follows the [`level-transcoder`](https://github.com/Level/transcoder) encoding interface. See [Encodings](#encodings) for an introduction. The `encoding` argument may be:\n\n- A string to select a known encoding by its name\n- An object that follows one of the following interfaces: [`level-transcoder`](https://github.com/Level/transcoder#encoding-interface), [`level-codec`](https://github.com/Level/codec#encoding-format), [`abstract-encoding`](https://github.com/mafintosh/abstract-encoding), [`multiformats`](https://github.com/multiformats/js-multiformats/blob/master/src/codecs/interface.ts)\n- A previously normalized encoding, such that `keyEncoding(x)` equals `keyEncoding(keyEncoding(x))`\n- Omitted, `null` or `undefined`, in which case the default `keyEncoding` of the database is returned.\n\nOther methods that take `keyEncoding` or `valueEncoding` options, accept the same as above. Results are cached. If the `encoding` argument is an object and it has a name then subsequent calls can refer to that encoding by name.\n\nDepending on the encodings supported by a database, this method may return a _transcoder encoding_ that translates the desired encoding from / to an encoding supported by the database. Its `encode()` and `decode()` methods will have respectively the same input and output types as a non-transcoded encoding, but its `name` property will differ.\n\nAssume that e.g. `db.keyEncoding().encode(key)` is safe to call at any time including if the database isn't open, because encodings must be stateless. If the given encoding is not found or supported, a [`LEVEL_ENCODING_NOT_FOUND` or `LEVEL_ENCODING_NOT_SUPPORTED` error](#errors) is thrown.\n\n### `encoding = db.valueEncoding([encoding])`\n\nSame as `db.keyEncoding([encoding])` except that it returns the default `valueEncoding` of the database (if the `encoding` argument is omitted, `null` or `undefined`).\n\n### `key = db.prefixKey(key, keyFormat[, local])`\n\nAdd sublevel prefix to the given `key`, which must be already-encoded. If this database is not a sublevel, the given `key` is returned as-is. The `keyFormat` must be one of `'utf8'`, `'buffer'`, `'view'`. If `'utf8'` then `key` must be a string and the return value will be a string. If `'buffer'` then Buffer, if `'view'` then Uint8Array.\n\n```js\nconst sublevel = db.sublevel('example')\n\nconsole.log(db.prefixKey('a', 'utf8')) // 'a'\nconsole.log(sublevel.prefixKey('a', 'utf8')) // '!example!a'\n```\n\nBy default, the given `key` will be prefixed to form a fully-qualified key in the context of the _root_ (i.e. top-most) database, as the following example will demonstrate. If `local` is true, the given `key` will instead be prefixed to form a fully-qualified key in the context of the _parent_ database.\n\n```js\nconst sublevel = db.sublevel('example')\nconst nested = sublevel.sublevel('nested')\n\nconsole.log(nested.prefixKey('a', 'utf8')) // '!example!!nested!a'\nconsole.log(nested.prefixKey('a', 'utf8', true)) // '!nested!a'\n```\n\n### `snapshot = db.snapshot(options)`\n\nCreate an explicit [snapshot](#snapshot). Throws a [`LEVEL_NOT_SUPPORTED`](#level_not_supported) error if `db.supports.explicitSnapshots` is false ([Level/community#118](https://github.com/Level/community/issues/118)). For details, see [Reading From Snapshots](#reading-from-snapshots).\n\nThere are currently no options but specific implementations may add their own.\n\n### `db.supports`\n\nA [manifest](https://github.com/Level/supports) describing the features supported by this database. Might be used like so:\n\n```js\nif (!db.supports.permanence) {\n  throw new Error('Persistent storage is required')\n}\n```\n\n### `db.defer(fn[, options])`\n\nCall the function `fn` at a later time when [`db.status`](#dbstatus) changes to `'open'` or `'closed'`. Known as a _deferred operation_. Used by `abstract-level` itself to implement \"deferred open\" which is a feature that makes it possible to call methods like `db.put()` before the database has finished opening. The `defer()` method is exposed for implementations and plugins to achieve the same on their custom methods:\n\n```js\ndb.foo = function (key) {\n  if (this.status === 'opening') {\n    this.defer(() => this.foo(key))\n  } else {\n    // ..\n  }\n}\n```\n\nThe optional `options` object may contain:\n\n- `signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the deferred operation. When aborted (now or later) the `fn` function will not be called.\n\nWhen deferring a custom operation, do it early: after normalizing optional arguments but before encoding (to avoid double encoding and to emit original input if the operation has events) and before any _fast paths_ (to avoid calling back before the database has finished opening). For example, `db.batch([])` has an internal fast path where it skips work if the array of operations is empty. Resources that can be closed on their own (like iterators) should however first check such state before deferring, in order to reject operations after close (including when the database was reopened).\n\n### `db.deferAsync(fn[, options])`\n\nSimilar to `db.defer(fn)` but for asynchronous work. Returns a promise, which waits for [`db.status`](#dbstatus) to change to `'open'` or `'closed'` and then calls `fn` which itself must return a promise. This allows for recursion:\n\n```js\ndb.foo = async function (key) {\n  if (this.status === 'opening') {\n    return this.deferAsync(() => this.foo(key))\n  } else {\n    // ..\n  }\n}\n```\n\nThe optional `options` object may contain:\n\n- `signal`: an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to abort the deferred operation. When aborted (now or later) the `fn` function will not be called, and the promise returned by `deferAsync()` will be rejected with a [`LEVEL_ABORTED`](#level_aborted) error.\n\n### `db.attachResource(resource)`\n\nKeep track of the given `resource` in order to call its `close()` method when the database is closed. Once successfully closed, the resource will no longer be tracked, to the same effect as manually calling [`db.detachResource()`](#dbdetachresourceresource). When given multiple resources, the database will close them in parallel. Resources are kept in a [set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) so that the same object will not be attached (and closed) twice.\n\nIntended for objects that rely on an open database. Used internally for built-in resources like iterators and sublevels, and is publicly exposed for custom resources.\n\n### `db.detachResource(resource)`\n\nStop tracking the given `resource`.\n\n### `iterator`\n\nAn iterator allows one to lazily read a range of entries stored in the database. The entries will be sorted by keys in [lexicographic order](https://en.wikipedia.org/wiki/Lexicographic_order) (in other words: byte order) which in short means key `'a'` comes before `'b'` and key `'10'` comes before `'2'`.\n\nIterators can be consumed with [`for await...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) and `iterator.all()`, or by manually calling `iterator.next()` or `nextv()` in succession. In the latter case, `iterator.close()` must always be called. In contrast, finishing, throwing, breaking or returning from a `for await...of` loop automatically calls `iterator.close()`, as does `iterator.all()`.\n\nAn iterator reaches its natural end in the following situations:\n\n- The end of the database has been reached\n- The end of the range has been reached\n- The last `iterator.seek()` was out of range.\n\nAn iterator keeps track of calls that are in progress. It doesn't allow concurrent `next()`, `nextv()` or `all()` calls (including a combination thereof) and will throw an error with code [`LEVEL_ITERATOR_BUSY`](#level_iterator_busy) if that happens:\n\n```js\n// Not awaited\niterator.next()\n\ntry {\n  // Which means next() is still in progress here\n  iterator.all()\n} catch (err) {\n  console.log(err.code) // 'LEVEL_ITERATOR_BUSY'\n}\n```\n\n#### `for await...of iterator`\n\nYields entries, which are arrays containing a `key` and `value`. The type of `key` and `value` depends on the options passed to `db.iterator()`.\n\n```js\ntry {\n  for await (const [key, value] of db.iterator()) {\n    console.log(key)\n  }\n} catch (err) {\n  console.error(err)\n}\n```\n\nNote for implementors: this uses `iterator.next()` and `iterator.close()` under the hood so no further method implementations are needed to support `for await...of`.\n\n#### `iterator.next()`\n\nAdvance to the next entry and yield that entry. Returns a promise for either an entry array (containing a `key` and `value`) or for `undefined` if the iterator reached its natural end. The type of `key` and `value` depends on the options passed to `db.iterator()`.\n\n**Note:** `iterator.close()` must always be called once there's no intention to call `next()` or `nextv()` again. Even if such calls yielded an error and even if the iterator reached its natural end. Not closing the iterator will result in memory leaks and may also affect performance of other operations if many iterators are unclosed and each is holding a snapshot of the database.\n\n#### `iterator.nextv(size[, options])`\n\nAdvance repeatedly and get at most `size` amount of entries in a single call. Can be faster than repeated `next()` calls. The `size` argument must be an integer and has a soft minimum of 1. There are no `options` by default but implementations may add theirs.\n\nReturns a promise for an array of entries, where each entry is an array containing a key and value. The natural end of the iterator will be signaled by yielding an empty array.\n\n```js\nconst iterator = db.iterator()\n\nwhile (true) {\n  const entries = await iterator.nextv(100)\n\n  if (entries.length === 0) {\n    break\n  }\n\n  for (const [key, value] of entries) {\n    // ..\n  }\n}\n\nawait iterator.close()\n```\n\n#### `iterator.all([options])`\n\nAdvance repeatedly and get all (remaining) entries as an array, automatically closing the iterator. Assumes that those entries fit in memory. If that's not the case, instead use `next()`, `nextv()` or `for await...of`. There are no `options` by default but implementations may add theirs. Returns a promise for an array of entries, where each entry is an array containing a key and value.\n\n```js\nconst entries = await db.iterator({ limit: 100 }).all()\n\nfor (const [key, value] of entries) {\n  // ..\n}\n```\n\n#### `iterator.seek(target[, options])`\n\nSeek to the key closest to `target`. This method is synchronous, but the actual work may happen lazily. Subsequent calls to `iterator.next()`, `nextv()` or `all()` (including implicit calls in a `for await...of` loop) will yield entries with keys equal to or larger than `target`, or equal to or smaller than `target` if the `reverse` option passed to `db.iterator()` was true.\n\nThe optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding, used to encode the `target`. By default the `keyEncoding` option of the iterator is used or (if that wasn't set) the `keyEncoding` of the database.\n\nIf range options like `gt` were passed to `db.iterator()` and `target` does not fall within that range, the iterator will reach its natural end.\n\n#### `iterator.close()`\n\nFree up underlying resources. Returns a promise. Closing the iterator is an idempotent operation, such that calling `close()` more than once is allowed and makes no difference.\n\nIf a `next()` ,`nextv()` or `all()` call is in progress, closing will wait for that to finish. After `close()` has been called, further calls to `next()` ,`nextv()` or `all()` will yield an error with code [`LEVEL_ITERATOR_NOT_OPEN`](#level_iterator_not_open).\n\n#### `iterator.db`\n\nA reference to the database that created this iterator.\n\n#### `iterator.count`\n\nRead-only getter that indicates how many entries have been yielded so far (by any method) excluding calls that errored or yielded `undefined`.\n\n#### `iterator.limit`\n\nRead-only getter that reflects the `limit` that was set in options. Greater than or equal to zero. Equals `Infinity` if no limit, which allows for easy math:\n\n```js\nconst hasMore = iterator.count < iterator.limit\nconst remaining = iterator.limit - iterator.count\n```\n\n#### Aborting Iterators\n\nIterators take an experimental `signal` option that, once signaled, aborts an in-progress read operation (if any) and rejects subsequent reads. The relevant promise will be rejected with a [`LEVEL_ABORTED`](#level_aborted) error. Aborting does not close the iterator, because closing is asynchronous and may result in an error that needs a place to go. This means signals should be used together with a pattern that automatically closes the iterator:\n\n```js\nconst abortController = new AbortController()\nconst signal = abortController.signal\n\n// Will result in 'aborted' log\nabortController.abort()\n\ntry {\n  for await (const entry of db.iterator({ signal })) {\n    console.log(entry)\n  }\n} catch (err) {\n  if (err.code === 'LEVEL_ABORTED') {\n    console.log('aborted')\n  }\n}\n```\n\nOtherwise, close the iterator explicitly:\n\n```js\nconst iterator = db.iterator({ signal })\n\ntry {\n  const entries = await iterator.nextv(10)\n} catch (err) {\n  if (err.code === 'LEVEL_ABORTED') {\n    console.log('aborted')\n  }\n} finally {\n  await iterator.close()\n}\n```\n\nSupport of signals is indicated via [`db.supports.signals.iterators`](https://github.com/Level/supports#signals-object).\n\n### `keyIterator`\n\nA key iterator has the same interface as `iterator` except that its methods yield keys instead of entries. Usage is otherwise the same.\n\n### `valueIterator`\n\nA value iterator has the same interface as `iterator` except that its methods yield values instead of entries. Usage is otherwise the same.\n\n### `chainedBatch`\n\n#### `chainedBatch.put(key, value[, options])`\n\nAdd a `put` operation to this chained batch, not committed until `write()` is called. This will throw a [`LEVEL_INVALID_KEY`](#level_invalid_key) or [`LEVEL_INVALID_VALUE`](#level_invalid_value) error if `key` or `value` is invalid. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n- `valueEncoding`: custom value encoding for this operation, used to encode the `value`.\n- `sublevel` (sublevel instance): act as though the `put` operation is performed on the given sublevel, to similar effect as `sublevel.batch().put(key, value)`. This allows atomically committing data to multiple sublevels. The given `sublevel` must have the same _root_ (i.e. top-most) database as `chainedBatch.db`. The `key` will be prefixed with the prefix of the sublevel, and the `key` and `value` will be encoded by the sublevel (using the default encodings of the sublevel unless `keyEncoding` and / or `valueEncoding` are provided).\n\n#### `chainedBatch.del(key[, options])`\n\nAdd a `del` operation to this chained batch, not committed until `write()` is called. This will throw a [`LEVEL_INVALID_KEY`](#level_invalid_key) error if `key` is invalid. The optional `options` object may contain:\n\n- `keyEncoding`: custom key encoding for this operation, used to encode the `key`.\n- `sublevel` (sublevel instance): act as though the `del` operation is performed on the given sublevel, to similar effect as `sublevel.batch().del(key)`. This allows atomically committing data to multiple sublevels. The given `sublevel` must have the same _root_ (i.e. top-most) database as `chainedBatch.db`. The `key` will be prefixed with the prefix of the sublevel, and the `key` will be encoded by the sublevel (using the default key encoding of the sublevel unless `keyEncoding` is provided).\n\n#### `chainedBatch.clear()`\n\nRemove all operations from this chained batch, so that they will not be committed.\n\n#### `chainedBatch.write([options])`\n\nCommit the operations. Returns a promise. All operations will be written atomically, that is, they will either all succeed or fail with no partial commits.\n\nThere are no `options` by default but implementations may add theirs. Note that `write()` does not take encoding options. Those can only be set on `put()` and `del()` because implementations may synchronously forward such calls to an underlying store and thus need keys and values to be encoded at that point.\n\nAfter `write()` or `close()` has been called, no further operations are allowed.\n\n#### `chainedBatch.close()`\n\nFree up underlying resources. This should be done even if the chained batch has zero operations. Automatically called by `write()` so normally not necessary to call, unless the intent is to discard a chained batch without committing it. Closing the batch is an idempotent operation, such that calling `close()` more than once is allowed and makes no difference. Returns a promise.\n\n#### `chainedBatch.length`\n\nThe number of operations in this chained batch, including operations that were added by [`prewrite`](#hook--dbhooksprewrite) hook functions if any.\n\n#### `chainedBatch.db`\n\nA reference to the database that created this chained batch.\n\n### `sublevel`\n\nA sublevel is an instance of the `AbstractSublevel` class, which extends `AbstractLevel` and thus has the same API. Sublevels have a few additional properties and methods.\n\n#### `sublevel.prefix`\n\nPrefix of the sublevel. A read-only string property.\n\n```js\nconst example = db.sublevel('example')\nconst nested = example.sublevel('nested')\n\nconsole.log(example.prefix) // '!example!'\nconsole.log(nested.prefix) // '!example!!nested!'\n```\n\n#### `sublevel.parent`\n\nParent database. A read-only property.\n\n```js\nconst example = db.sublevel('example')\nconst nested = example.sublevel('nested')\n\nconsole.log(example.parent === db) // true\nconsole.log(nested.parent === example) // true\n```\n\n#### `sublevel.db`\n\nRoot database. A read-only property.\n\n```js\nconst example = db.sublevel('example')\nconst nested = example.sublevel('nested')\n\nconsole.log(example.db === db) // true\nconsole.log(nested.db === db) // true\n```\n\n#### `sublevel.path([local])`\n\nGet the path of this sublevel, which is its prefix without separators. If `local` is true, exclude path of parent database. If false (the default) then recurse to form a fully-qualified path that travels from the root database to this sublevel.\n\n```js\nconst example = db.sublevel('example')\nconst nested = example.sublevel('nested')\nconst foo = db.sublevel(['example', 'nested', 'foo'])\n\n// Get global or local path\nconsole.log(nested.path()) // ['example', 'nested']\nconsole.log(nested.path(true)) // ['nested']\n\n// Has no intermediary sublevels, so the local option has no effect\nconsole.log(foo.path()) // ['example', 'nested', 'foo']\nconsole.log(foo.path(true)) // ['example', 'nested', 'foo']\n```\n\n### `snapshot`\n\n#### `snapshot.ref()`\n\nIncrement reference count, to register work that should delay closing until `snapshot.unref()` is called an equal amount of times. The promise that will be returned by `snapshot.close()` will not resolve until the reference count returns to 0. This prevents prematurely closing underlying resources while the snapshot is in use.\n\nIt is normally not necessary to call `snapshot.ref()` and `snapshot.unref()` because builtin database methods automatically do.\n\n#### `snapshot.unref()`\n\nDecrement reference count, to indicate that the work has finished.\n\n#### `snapshot.close()`\n\nFree up underlying resources. Be sure to call this when the snapshot is no longer needed, because snapshots may cause the database to temporarily pause internal storage optimizations. Returns a promise. Closing the snapshot is an idempotent operation, such that calling `snapshot.close()` more than once is allowed and makes no difference.\n\nAfter `snapshot.close()` has been called, no further operations are allowed. For example, `db.get(key, { snapshot })` will throw an error with code [`LEVEL_SNAPSHOT_NOT_OPEN`](#level_snapshot_not_open).\n\n### Encodings\n\nAny database method that takes a `key` argument, `value` argument or range options like `gte`, hereby jointly referred to as `data`, runs that `data` through an _encoding_. This means to encode input `data` and decode output `data`.\n\n[Several encodings](https://github.com/Level/transcoder#built-in-encodings) are builtin courtesy of [`level-transcoder`](https://github.com/Level/transcoder) and can be selected by a short name like `'utf8'` or `'json'`. The default encoding is `'utf8'` which ensures you'll always get back a string. Encodings can be specified for keys and values independently with `keyEncoding` and `valueEncoding` options, either in the database constructor or per method to apply an encoding selectively. For example:\n\n```js\nconst db = level('./db', {\n  keyEncoding: 'view',\n  valueEncoding: 'json'\n})\n\n// Use binary keys\nconst key = Uint8Array.from([1, 2])\n\n// Encode the value with JSON\nawait db.put(key, { x: 2 })\n\n// Decode the value with JSON. Yields { x: 2 }\nconst obj = await db.get(key)\n\n// Decode the value with utf8. Yields '{\"x\":2}'\nconst str = await db.get(key, { valueEncoding: 'utf8' })\n```\n\nThe `keyEncoding` and `valueEncoding` options accept a string to select a known encoding by its name, or an object to use a custom encoding like [`charwise`](https://github.com/dominictarr/charwise). See [`keyEncoding()`](#encoding--dbkeyencodingencoding) for details. If a custom encoding is passed to the database constructor, subsequent method calls can refer to that encoding by name. Supported encodings are exposed in the `db.supports` manifest:\n\n```js\nconst db = level('./db', {\n  keyEncoding: require('charwise'),\n  valueEncoding: 'json'\n})\n\n// Includes builtin and custom encodings\nconsole.log(db.supports.encodings.utf8) // true\nconsole.log(db.supports.encodings.charwise) // true\n```\n\nAn encoding can both widen and limit the range of `data` types. The default `'utf8'` encoding can only store strings. Other types, though accepted, are irreversibly stringified before storage. That includes JavaScript primitives which are converted with [`String(x)`](https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value), Buffer which is converted with [`x.toString('utf8')`](https://nodejs.org/api/buffer.html#buftostringencoding-start-end) and Uint8Array converted with [`TextDecoder#decode(x)`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode). Use other encodings for a richer set of `data` types, as well as binary data without a conversion cost - or loss of non-unicode bytes.\n\nFor binary data two builtin encodings are available: `'buffer'` and `'view'`. They use a Buffer or Uint8Array respectively. To some extent these encodings are interchangeable, as the `'buffer'` encoding also accepts Uint8Array as input `data` (and will convert that to a Buffer without copying the underlying ArrayBuffer), the `'view'` encoding also accepts Buffer as input `data` and so forth. Output `data` will be either a Buffer or Uint8Array respectively and can also be converted:\n\n```js\nconst db = level('./db', { valueEncoding: 'view' })\nconst buffer = await db.get('example', { valueEncoding: 'buffer' })\n```\n\nIn browser environments it may be preferable to only use `'view'`. When bundling JavaScript with Webpack, Browserify or other, you can choose not to use the `'buffer'` encoding and (through configuration of the bundler) exclude the [`buffer`](https://github.com/feross/buffer) shim in order to reduce bundle size.\n\nRegardless of the choice of encoding, a `key` or `value` may not be `null` or `undefined` due to preexisting significance in iterators and streams. No such restriction exists on range options because `null` and `undefined` are significant types in encodings like [`charwise`](https://github.com/dominictarr/charwise) as well as some underlying stores like IndexedDB. Consumers of an `abstract-level` implementation must assume that range options like `{ gt: undefined }` are _not_ the same as `{}`. The [abstract test suite](#test-suite) does not test these types. Whether they are supported or how they sort may differ per implementation. An implementation can choose to:\n\n- Encode these types to make them meaningful\n- Have no defined behavior (moving the concern to a higher level)\n- Delegate to an underlying database (moving the concern to a lower level).\n\nLastly, one way or another, every implementation _must_ support `data` of type String and _should_ support `data` of type Buffer or Uint8Array.\n\n### Events\n\nAn `abstract-level` database is an [`EventEmitter`](https://nodejs.org/api/events.html) and emits the events listed below.\n\n#### `opening`\n\nEmitted when database is opening. Receives 0 arguments:\n\n```js\ndb.once('opening', function () {\n  console.log('Opening...')\n})\n```\n\n#### `open`\n\nEmitted when database has successfully opened. Receives 0 arguments:\n\n```js\ndb.once('open', function () {\n  console.log('Opened!')\n})\n```\n\n#### `closing`\n\nEmitted when database is closing. Receives 0 arguments.\n\n#### `closed`\n\nEmitted when database has successfully closed. Receives 0 arguments.\n\n#### `write`\n\nEmitted when data was successfully written to the database as the result of `db.batch()`, `db.put()` or `db.del()`. Receives a single `operations` argument, which is an array containing normalized operation objects. The array will contain at least one operation object and reflects modifications made (and operations added) by the [`prewrite`](#hook--dbhooksprewrite) hook. Normalized means that every operation object has `keyEncoding` and (if `type` is `'put'`) `valueEncoding` properties and these are always encoding objects, rather than their string names like `'utf8'` or whatever was given in the input.\n\nOperation objects also include userland options that were provided in the `options` argument of the originating call, for example the `options` in a `db.put(key, value, options)` call:\n\n```js\ndb.on('write', function (operations) {\n  for (const op of operations) {\n    if (op.type === 'put') {\n      console.log(op.key, op.value, op.foo)\n    }\n  }\n})\n\n// Put with a userland 'foo' option\nawait db.put('abc', 'xyz', { foo: true })\n```\n\nThe `key` and `value` of the operation object match the original input, before having encoded it. To provide access to encoded data, the operation object additionally has `encodedKey` and (if `type` is `'put'`) `encodedValue` properties. Event listeners can inspect [`keyEncoding.format`](https://github.com/Level/transcoder#encodingformat) and `valueEncoding.format` to determine the data type of `encodedKey` and `encodedValue`.\n\nAs an example, given a sublevel created with `users = db.sublevel('users', { valueEncoding: 'json' })`, a call like `users.put('isa', { score: 10 })` will emit a `write` event from the sublevel with an `operations` argument that looks like the following. Note that specifics (in data types and encodings) may differ per database at it depends on which encodings an implementation supports and uses internally. This example assumes that the database uses `'utf8'`.\n\n```js\n[{\n  type: 'put',\n  key: 'isa',\n  value: { score: 10 },\n  keyEncoding: users.keyEncoding('utf8'),\n  valueEncoding: users.valueEncoding('json'),\n  encodedKey: 'isa', // No change (was already utf8)\n  encodedValue: '{\"score\":10}', // JSON-encoded\n}]\n```\n\nBecause sublevels encode and then forward operations to their parent database, a separate `write` event will be emitted from `db` with:\n\n```js\n[{\n  type: 'put',\n  key: '!users!isa', // Prefixed\n  value: '{\"score\":10}', // No change\n  keyEncoding: db.keyEncoding('utf8'),\n  valueEncoding: db.valueEncoding('utf8'),\n  encodedKey: '!users!isa',\n  encodedValue: '{\"score\":10}'\n}]\n```\n\nSimilarly, if a `sublevel` option was provided:\n\n```js\nawait db.batch()\n  .del('isa', { sublevel: users })\n  .write()\n```\n\nWe'll get:\n\n```js\n[{\n  type: 'del',\n  key: '!users!isa', // Prefixed\n  keyEncoding: db.keyEncoding('utf8'),\n  encodedKey: '!users!isa'\n}]\n```\n\nLastly, newly added `write` event listeners are only called for subsequently created batches (including chained batches):\n\n```js\nconst promise = db.batch([{ type: 'del', key: 'abc' }])\ndb.on('write', listener) // Too late\nawait promise\n```\n\nFor the event listener to be called it must be added earlier:\n\n```js\ndb.on('write', listener)\nawait db.batch([{ type: 'del', key: 'abc' }])\n```\n\nThe same is true for `db.put()` and `db.del()`.\n\n#### `clear`\n\nEmitted when a `db.clear()` call completed and entries were thus successfully deleted from the database. Receives a single `options` argument, which is the verbatim `options` argument that was passed to `db.clear(options)` (or an empty object if none) before having encoded range options.\n\n### Order Of Operations\n\nThere is no defined order between parallel write operations. Consider:\n\n```js\nawait Promise.all([\n  db.put('example', 1),\n  db.put('example', 2)\n])\n\nconst result = await db.get('example')\n```\n\nThe value of `result` could be either `1` or `2`, because the `db.put()` calls are asynchronous and awaited in parallel. Some implementations of `abstract-level` may unintentionally exhibit a \"defined\" order due to internal details. Implementations are free to change such details at any time, because per the asynchronous `abstract-level` interface that they follow, the order is theoretically random.\n\nRemoving this concern (if necessary) must be done on an application-level. For example, the application could have a queue of operations, or per-key locks, or implement transactions on top of snapshots, or a versioning mechanism in its keyspace, or specialized data types like CRDT, or just say that conflicts are acceptable for that particular application, and so forth. The abundance of examples should explain why `abstract-level` itself doesn't enter this opinionated and application-specific problem space. Each solution has tradeoffs and `abstract-level`, being the core of a modular database, cannot decide which tradeoff to make.\n\n### Reading From Snapshots\n\nA snapshot is a lightweight \"token\" that represents a version of a database at a particular point in time. This allows for reading data without seeing subsequent writes made on the database. It comes in two forms:\n\n1. Implicit snapshots: created internally by the database and not visible to the outside world.\n2. Explicit snapshots: created with `snapshot = db.snapshot()`. Because it acts as a token, `snapshot` has no read methods of its own. Instead the snapshot is to be passed to database methods like `db.get()` and `db.iterator()`. This also works on sublevels.\n\nUse explicit snapshots wisely, because their lifetime must be managed manually. Implicit snapshots are typically more convenient and possibly more performant because they can handled natively and have their lifetime limited by the surrounding operation. That said, explicit snapshots can be useful to make multiple read operations that require a shared, consistent view of the data.\n\nMost but not all `abstract-level` implementations support snapshots. They can be divided into three groups.\n\n#### 1. Implementation does not support snapshots\n\nAs indicated by `db.supports.implicitSnapshots` and `db.supports.explicitSnapshots` being false. In this case, operations read from the latest version of the database. This most notably affects iterators:\n\n```js\nawait db.put('example', 'a')\nconst it = db.iterator()\nawait db.del('example')\nconst entries = await it.all() // Likely an empty array\n```\n\nThe `db.supports.implicitSnapshots` property is aliased as `db.supports.snapshots` for backwards compatibility.\n\n#### 2. Implementation supports implicit snapshots\n\nAs indicated by `db.supports.implicitSnapshots` being true. An iterator, upon creation, will synchronously create a snapshot and subsequently read from that snapshot rather than the latest version of the database. There are no actual numerical versions, but let's say there are in order to clarify the behavior:\n\n```js\nawait db.put('example', 'a')   // Results in v1\nconst it = db.iterator()       // Creates snapshot of v1\nawait db.del('example')        // Results in v2\nconst entries = await it.all() // Reads from snapshot and thus v1\n```\n\nThe `entries` array thus includes the deleted entry, because the snapshot of the iterator represents the database version from before the entry was deleted.\n\nOther read operations like `db.get()` also use a snapshot. Such calls synchronously create a snapshot and then asynchronously read from it. This means a write operation (to the same key) may not be visible unless awaited:\n\n```js\nawait db.put('example', 1) // Awaited\ndb.put('example', 2)       // Not awaited\nawait db.get('example')    // Yields 1 (typically)\n```\n\nIn other words, once a write operation has _finished_ (including having communicated that to the main thread of JavaScript, i.e. by resolving the promise in the above example) subsequent reads are guaranteed to include that data. That's because those reads use a snapshot created in the main thread which is aware of the finished write at this point. Before that point, no guarantee can be given.\n\n#### 3. Implementation supports explicit snapshots\n\nAs indicated by `db.supports.explicitSnapshots` being true. This is the most precise and flexible way to control the version of the data to read. The previous example can be modified to get a consistent result:\n\n```js\nawait db.put('example', 1)\nconst snapshot = db.snapshot()\ndb.put('example', 2)\nawait db.get('example', { snapshot })) // Yields 1 (always)\nawait snapshot.close()\n```\n\nThe main use case for explicit snapshots is retrieving data from an index.\n\n```js\n// We'll use charwise to encode \"compound\" keys\nconst charwise = require('charwise-compact')\nconst players = db.sublevel('players', { valueEncoding: 'json' })\nconst index = db.sublevel('scores', { keyEncoding: charwise })\n\n// Write sample data (using an atomic batch so that the index remains in-sync)\nawait db.batch()\n  .put('alice', { score: 620 }, { sublevel: players })\n  .put([620, 'alice'], '', { sublevel: index })\n  .write()\n\n// Iterate players that have a score higher than 100\nconst snapshot = db.snapshot()\nconst iterator = index.keys({ gt: [100, charwise.HI], snapshot })\n\nfor await (const key of iterator) {\n  // Index key is [620, 'alice'] so key[1] gives us 'alice'\n  const player = await players.get(key[1], { snapshot })\n}\n\n// Don't forget to close (and try/catch/finally)\nawait snapshot.close()\n```\n\nOn implementations that support implicit but not explicit snapshots, some of the above can be simulated. In particular, to get multiple entries from a snapshot, one could create an iterator and then repeatedly `seek()` to the desired entries.\n\n### Hooks\n\n**Hooks are experimental and subject to change without notice.**\n\nHooks allow userland _hook functions_ to customize behavior of the database. Each hook is a different extension point, accessible via `db.hooks`. Some are shared between database methods to encapsulate common behavior. A hook is either synchronous or asynchronous, and functions added to a hook must respect that trait.\n\n#### `hook = db.hooks.prewrite`\n\nA synchronous hook for modifying or adding operations to [`db.batch([])`](#dbbatchoperations-options), [`db.batch().put()`](#chainedbatchputkey-value-options), [`db.batch().del()`](#chainedbatchdelkey-options), [`db.put()`](#dbputkey-value-options) and [`db.del()`](#dbdelkey-options) calls. It does not include [`db.clear()`](#dbclearoptions) because the entries deleted by such a call are not communicated back to `db`.\n\nFunctions added to this hook will receive two arguments: `op` and `batch`.\n\n##### Example\n\n```js\nconst charwise = require('charwise-compact')\nconst books = db.sublevel('books', { valueEncoding: 'json' })\nconst index = db.sublevel('authors', { keyEncoding: charwise })\n\nbooks.hooks.prewrite.add(function (op, batch) {\n  if (op.type === 'put') {\n    batch.add({\n      type: 'put',\n      key: [op.value.author, op.key],\n      value: '',\n      sublevel: index\n    })\n  }\n})\n\n// Will atomically commit it to the author index as well\nawait books.put('12', { title: 'Siddhartha', author: 'Hesse' })\n```\n\n##### Arguments\n\n###### `op` (object)\n\nThe `op` argument reflects the input operation and has the following properties: `type`, `key`, `keyEncoding`, an optional `sublevel`, and if `type` is `'put'` then also `value` and `valueEncoding`. It can also include userland options, that were provided either in the input operation object (if it originated from [`db.batch([])`](#db_batchoperations-options)) or in the `options` argument of the originating call, for example the `options` in `db.del(key, options)`.\n\nThe `key` and `value` have not yet been encoded at this point. The `keyEncoding` and `valueEncoding` properties are always encoding objects (rather than encoding names like `'json'`) which means hook functions can call (for example) `op.keyEncoding.encode(123)`.\n\nHook functions can modify the `key`, `value`, `keyEncoding` and `valueEncoding` properties, but not `type` or `sublevel`. If a hook function modifies `keyEncoding` or `valueEncoding` it can use either encoding names or encoding objects, which will subsequently be normalized to encoding objects. Hook functions can also add custom properties to `op` which will be visible to other hook functions, the private API of the database and in the [`write`](#write) event.\n\n###### `batch` (object)\n\nThe `batch` argument of the hook function is an interface to add operations, to be committed in the same batch as the input operation(s). This also works if the originating call was a singular operation like `db.put()` because the presence of one or more hook functions will change `db.put()` and `db.del()` to internally use a batch. For originating calls like [`db.batch([])`](#dbbatchoperations-options) that provide multiple input operations, operations will be added after the last input operation, rather than interleaving. The hook function will not be called for operations that were added by either itself or other hook functions.\n\n###### `batch = batch.add(op)`\n\nAdd a batch operation, using the same format as the operations that [`db.batch([])`](#dbbatchoperations-options) takes. However, it is assumed that `op` can be freely mutated by `abstract-level`. Unlike input operations it will not be cloned before doing so. The `add` method returns `batch` which allows for chaining, similar to the [chained batch](#chainedbatch) API.\n\nFor hook functions to be generic, it is recommended to explicitly define `keyEncoding` and `valueEncoding` properties on `op` (instead of relying on database defaults) or to use an isolated sublevel with known defaults.\n\n#### `hook = db.hooks.postopen`\n\nAn asynchronous hook that runs after the database has succesfully opened, but before deferred operations are executed and before events are emitted. It thus allows for additional initialization, including reading and writing data that deferred operations might need. The postopen hook always runs before the prewrite hook.\n\nFunctions added to this hook must return a promise and will receive one argument: `options`. If one of the hook functions yields an error then the database will be closed. In the rare event that closing also fails, which means there's no safe state to return to, the database will enter an internal locked state where `db.status` is `'closed'` and subsequent calls to `db.open()` or `db.close()` will be met with a [`LEVEL_STATUS_LOCKED`](#errors) error. This locked state is also used during the postopen hook itself, meaning hook functions are not allowed to call `db.open()` or `db.close()`.\n\n##### Example\n\n```js\ndb.hooks.postopen.add(async function (options) {\n  // Can read and write like usual\n  return db.put('example', 123, {\n    valueEncoding: 'json'\n  })\n})\n```\n\n##### Arguments\n\n###### `options` (object)\n\nThe `options` that were provided in the originating [`db.open(options)`](#dbopenoptions) call, merged with constructor opti","readmeFilename":"README.md"}