{"_id":"memento","_rev":"65-96ff791cb13352471738e48d22349d74","name":"memento","description":"A Paxos backed replicated state machine key-value store.","dist-tags":{"latest":"0.0.8","canary":"0.1.51"},"versions":{"0.0.1":{"name":"memento","description":"MVCC database for Node.js.","version":"0.0.1","author":{"name":"Alan Gutierrez"},"directories":{"lib":"./lib","bin":"./bin"},"devDependencies":{"coffee-script":">=1.2.0","ace.is.aces.in.my.book":">=0.0.1"},"scripts":{"test":"./bin/ace t/*/*.t.coffee"},"main":"./lib/memento","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"_id":"memento@0.0.1","dependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.1","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"bin":{},"dist":{"shasum":"c78034f692319ccd3c640a0857d3a6b0a48d9a67","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.1.tgz","integrity":"sha512-Q/hPKL8Y9KKjcKgy8A+DqG7eWjqNJoe02Km1EIkTGN28DRldrywmHB5nMijcUDmuJFgVqzmtTOTDcZKW/D1veQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGrpJZ1ecfb3Tz4aWx4INIsDeo9d5nvfHrY/mxYE1KzVAiBPpwSCMlRRXlqgSQhi6QDPYGF1sq4MmDtB7h7Wh+3wTw=="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}]},"0.0.2":{"name":"memento","version":"0.0.2","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"arguable":"2.6.x","cadence":"1.0.x","conference":"0.0.x","inlet":"1.2.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.0.x","compassion.conduit":"0.0.x","prolific":"2.3.x","prolific.logger":"0.0.x","prolific.main":"0.0.x","prolific.shuttle":"2.4.x","prolific.monitor":"2.3.x","prolific.stdio":"0.0.x","prolific.stdout.udp":"0.0.x","prolific.syslog":"0.0.x","prolific.udp":"0.0.x","proof":"1.0.x","vizsla":"1.5.x"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"f5464235b102db4ba3d0b29eaf33a49b4f4b54d0","_id":"memento@0.0.2","_shasum":"f94486adc5092805bf4711f23eedfe7e37a8f522","_from":".","_npmVersion":"2.15.1","_nodeVersion":"4.4.4","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"f94486adc5092805bf4711f23eedfe7e37a8f522","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.2.tgz","integrity":"sha512-8T4jD7gd1E9SmnCJ9BwyVTKMbjKOo+DlWBUGcMglZEv/PSv9V5YiaLb9DJ1mNUTDYweIMjIg4rvE8b/JHCKgwQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHYxQ914V0t0AezP1lgSdJYuC4hyFw4LtXkknBTAupGSAiA9Jp8/EWV8Jyier6GWOfeMnEGoG879MLXqTr6pHQwcgg=="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/memento-0.0.2.tgz_1468843362934_0.0210998454131186"},"directories":{}},"0.0.3":{"name":"memento","version":"0.0.3","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"arguable":"5.0.x","cadence":"1.0.x","colleague":"0.0.8","conference":"0.4.x","destructible":"0.0.2","inlet":"2.0.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.5.x","proof":"1.2.x","vizsla":"2.0.x"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"3bec737cf716ef7760773a5e5c7b00d09fce5a54","_id":"memento@0.0.3","_shasum":"5505372664971a31fa9fe10d29b0f5d5b54e8e7b","_from":".","_npmVersion":"4.0.5","_nodeVersion":"4.7.2","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"5505372664971a31fa9fe10d29b0f5d5b54e8e7b","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.3.tgz","integrity":"sha512-SRTwtUGlonUMC3p4n7oTxa5JHpO2/4KdaGaocrp9E5RG1DdU48TM4Cj3bYw+XgEP5dKPGbzAylNUzZ/ijoTccw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCVw5+O8j2f+GJW/XEQu2yGwDBkc8I1TomO5JJU/s58GAIhAKtMkpXArgverjlKEtLj4Sg/YHzmF7pY2T9xc8QTuoFp"}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/memento-0.0.3.tgz_1487786371932_0.4059782747644931"},"directories":{}},"0.0.4":{"name":"memento","version":"0.0.4","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"abend":"1.0.x","arguable":"5.0.x","cadence":"1.0.x","colleague":"0.4.x","conference":"0.5.x","cubbyhole":"0.0.x","destructible":"0.1.x","reactor":"4.3.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.6.x","proof":"3.0.x","vizsla":"3.4.0"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"d77d9b502efdd27bace5cc9308f9e9e4095a0e54","_id":"memento@0.0.4","_shasum":"a5e56a504dbc94782b8b4cf231942f865c1f0f32","_from":".","_npmVersion":"4.4.4","_nodeVersion":"4.8.1","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"a5e56a504dbc94782b8b4cf231942f865c1f0f32","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.4.tgz","integrity":"sha512-e/ZDHCsU1ZlMg1a/Z8zUPwTb5QRMTif4+TSeC8tYgv8G12g87VU9R0n+1McqAPoSHYOobib0l+VXotwGQ+PVHQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICL4zPIepl631PVVTVDRw3InyC2/bp3M/2H6w5smRpxOAiAxOaumhIcBQ0t1nbovxPMtuwsB2bI13eR/UA0C4IPaFQ=="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/memento-0.0.4.tgz_1491496830202_0.466711102752015"},"directories":{}},"0.0.5":{"name":"memento","version":"0.0.5","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"abend":"1.0.x","arguable":"5.0.x","cadence":"1.0.x","colleague":"0.4.x","conference":"0.5.x","cubbyhole":"0.0.x","destructible":"0.1.x","reactor":"4.3.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.7.x","proof":"3.0.x","vizsla":"3.4.0"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"1e6b98b49f8a05db0d34c9d3846bea7948e7def7","_id":"memento@0.0.5","_shasum":"b510e6724117fb98fc20986100135295c282383d","_from":".","_npmVersion":"4.4.4","_nodeVersion":"4.8.1","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"b510e6724117fb98fc20986100135295c282383d","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.5.tgz","integrity":"sha512-l/C4MQo3apVG3UVZMjN7KzVLWB4TWPaLlB4lTdeVvx/LqXuUeeA05mqeHHT5jN83wsS1WFHU245saXYBrpymKg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAxF5+S4vVNUfiE+Dov0ZhsZnYm50OgMHvfKqU7ISrE1AiEA6xfwexzET6zq5EctNTOgZ1yAmsyUGGdBaghkEanyddE="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/memento-0.0.5.tgz_1491499812056_0.261396566638723"},"directories":{}},"0.0.6":{"name":"memento","version":"0.0.6","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"abend":"1.0.x","arguable":"5.0.x","cadence":"1.0.x","colleague":"0.4.x","conference":"0.5.x","cubbyhole":"0.0.x","destructible":"0.1.x","reactor":"4.4.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.7.x","proof":"3.0.x","vizsla":"3.6.1"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"4a59b0100f9658ada18565e2576cc02f3d3204b0","_id":"memento@0.0.6","_shasum":"2c7926885f19b8c4e41b475e6d70b6f5ce2b4c2c","_from":".","_npmVersion":"4.4.4","_nodeVersion":"4.8.1","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"2c7926885f19b8c4e41b475e6d70b6f5ce2b4c2c","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.6.tgz","integrity":"sha512-J9e7nhCfVOu+y7DNS9JnWNDujSkMCq42vQUr+Zcadob22mGZ3yiAplmEveVMhaTFAFJdEcNoQBIvV0p0rREo1w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKJwJYWQQ65mpyTspgFSk57XHfsBUX6prlugRSdmGpdgIhAIoudNrSPUNnUFXExnB5ZOw3fK1jqYowfxi1aJbtWeiD"}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/memento-0.0.6.tgz_1491551434075_0.8552500039804727"},"directories":{}},"0.0.7":{"name":"memento","version":"0.0.7","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"abend":"1.0.x","arguable":"5.0.x","cadence":"1.0.x","colleague":"0.4.x","conference":"0.5.x","cubbyhole":"0.0.x","destructible":"0.1.x","reactor":"4.4.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.7.x","proof":"3.0.x","vizsla":"3.6.x"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"20858a28b8eb94e60fda155840f237e514da12c4","_id":"memento@0.0.7","_shasum":"cd147aa4c4ed32c202236f6a4b404b25641267e8","_from":".","_npmVersion":"4.4.4","_nodeVersion":"4.8.1","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"cd147aa4c4ed32c202236f6a4b404b25641267e8","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.7.tgz","integrity":"sha512-bX1jvHq/gQqSx4nmH0u2L8XJFsCRsCQ7AuLle1UFQDa9ohBejzFIbxtaTi4GCuxIPMZGOLZDyavOAbt1YoTYBg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE3EMI96pWGQX+q8tSfEx73z57vCbmCLr94PJv/8+vzRAiA01N2nP8DvliyP8H4IGrTog5DNjQ1KyWDW8oHQ7OYkNQ=="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/memento-0.0.7.tgz_1491551462705_0.9414073808584362"},"directories":{}},"0.0.8":{"name":"memento","version":"0.0.8","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"dependencies":{"abend":"1.0.x","arguable":"5.0.x","cadence":"1.0.x","colleague":"0.5.x","conference":"0.6.x","cubbyhole":"0.0.x","destructible":"0.9.x","reactor":"4.6.x","prolific.logger":"3.0.x","prolific.shuttle":"9.0.x","server-destroy":"1.0.1"},"devDependencies":{"compassion.colleague":"0.7.x","proof":"3.0.x","vizsla":"3.6.x"},"main":"memento","scripts":{"test":"proof platform win32 && proof test */*.t.js || t/test"},"gitHead":"461e6f4f953d6a510ff9939a3210d7cc8f50292b","_id":"memento@0.0.8","_shasum":"9bac83edd1022a74a9d829e510cba31b3fc36375","_from":".","_npmVersion":"4.5.0","_nodeVersion":"4.8.1","_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"dist":{"shasum":"9bac83edd1022a74a9d829e510cba31b3fc36375","tarball":"https://registry.npmjs.org/memento/-/memento-0.0.8.tgz","integrity":"sha512-OMB8Vj8svyoSZlre/tF5Wh9e9wEW9q/zI62Tn2wr51BEcy1+zxKJpwhIAK52ejgEuyzeQbYFxGXanA3W0yCX0Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlXKRuAiT868Oyqo0MNwOxiUvNB7yze0Viji0dxYlufwIgWlsILnZgvdjpy3pDXGzWeuT2aQvVRdSA5szpf28OScc="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/memento-0.0.8.tgz_1493039308550_0.19170111254788935"},"directories":{}},"0.1.0":{"name":"memento","version":"0.1.0","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"^0.1.16","ascension":"^1.2.0","avenue":"^0.4.0","b-tree":"^2.0.0-alpha.36","destructible":"^7.0.0-alpha.9","interrupt":"^9.0.0-alpha.5","rescue":"^7.0.0-alpha.1"},"devDependencies":{"proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\n\n```\nnpm install memento\n```\n","readmeFilename":"README.md","gitHead":"618d6031896c8fa3cc480959fcba7cd5c0f382d9","_id":"memento@0.1.0","_nodeVersion":"12.18.1","_npmVersion":"6.14.5","dist":{"integrity":"sha512-KZ93Jy9xw9b7rdV3yI0xEzBfy+X0zYbu1FyYKxWvu6m5ei8GgXBaLX18i2ayqyDwqMTMQY8vzlj6pne2Ib0qPw==","shasum":"dce0ad29a74faf0a094cbfd301d4df683c420130","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.0.tgz","fileCount":5,"unpackedSize":22020,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdAJKCRA9TVsSAnZWagAAO3cP/AnIOFF3wmJl+PLXcto8\nvrGmMWMEyMBFNfCnJrIB/5Mzb12wrLsbYpGuxOVnbIQsfGBNqwbRMclAzJ8m\neC2PGxu1VRkbyBqh1gqffTltRGDiWeYh2e9tBTXKZ1Km5Nz+zeaEeOTuxboo\nTGYDMUHUg8Rv2zuDNst22TXsEWyN+MSPJtG9p3Yh+MPH8+9GSM4MZVblOMoq\nSvCr1/cuuBPnGyDexcsw7npaTySaAtoPGIjGRVzWmFVTNs9VjMbqEdT8+7Ar\nsSxy39JhnW3e6TVHK/aokd3zX/kMHrHzCTlB1FfCc5xSI8zwI6FJDwDtaPVf\n+1n96tNbKNMfOufWD1SgUcpHRbKJysHDnD6ZxZrQL4ouVOVfrk8mXldNs5Ss\n4mFUDsH7nPKPFBP8z9wqv8OGqx4GV5KOJ20FMlX38OXvrL2Jo2T8Yq6Hvqly\nY2pdLiBxbDbrGPihVi+REMHhjoeZEdDIsqAD3GkwQj5+wLgxQaM6XVbParDh\n3Z4Ae4kF3WBSY+FamwPC3WpY4ZN5l6tlo1APxssvMi3tPUSXSMNCe+nv2Y+9\nZOv6f1XfQA4SnQoEYZ4ROo4jUK0LYNKlOOMWvkooCeb4U3CdgCveTP25NsJG\nJcEiDJE+P/VVljitTV6F60d7OjssDPoQ2G83F6kDJPTTh+k74yDKX4iwQapr\nFwS5\r\n=xNy2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA3xeidmqKYZDEXbMVJpv+XZG0ohpWSqils8s2kT3lu/AiEA9/K2GyXkMxfEsopgyYBnkzfhBu38DnT71VVR7ZLAfPM="}]},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.0_1601438282298_0.061301807467254665"},"_hasShrinkwrap":false},"0.1.1":{"name":"memento","version":"0.1.1","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.49","ascension":"^3.0.0-alpha.0","avenue":"0.6.8","b-tree":"2.0.0-alpha.92","constrain":"2.0.0-alpha.2","destructible":"7.0.0-alpha.46","interrupt":"11.0.0-alpha.16","journalist":"0.1.21","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.9","riffle":"2.0.0-alpha.67","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\n\nMemento installs from NPM.\n\n```text\n//{ \"mode\": \"text\" }\nnpm install memento\n```\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\n//{ \"code\": { \"tests\": 6 }, \"text\": { \"tests\": 4  } }\nrequire('proof')(%(tests)d, async okay => {\n    //{ \"include\": \"testRequire\" }\n    //{ \"include\": \"test\" }\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\n//{ \"mode\": \"text\" }\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\n//{ \"name\": \"displayedRequire\", \"mode\": \"text\" }\nconst Memento = require('avenue')\n```\n\n```javascript\n//{ \"name\": \"testRequire\", \"mode\": \"code\" }\nconst Memento = require('..')\n\nconst path = require('path')\nconst fs = require('fs').promises\n\nconst directory = path.resolve(__dirname, './tmp/readme')\nawait fs.rmdir(directory, { recursive: true })\nawait fs.mkdir(directory, { recursive: true })\n```\n\n```javascript\n//{ \"name\": \"test\", \"mode\": \"code\" }\n{\n    //{ \"include\": \"introduction\" }\n}\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\n//{ \"name\": \"introduction\" }\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\n//{ \"name\": \"introduction\" }\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\n//{ \"mode\": \"text\" }\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\n//{ \"name\": \"introduction\" }\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\n//{ \"name\": \"introduction\" }\nawait memento.close()\n```\n","readmeFilename":"README.in.md","gitHead":"17c21005c94dfd25ad01a44895331ce4c06d3f5a","_id":"memento@0.1.1","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-fojQpD0XUm+wxTJa6A1U2Sf+Lr+6O/6AxA0usYIyElRonvHp3ZkR2OyoInEoyb7mGvgKsiHNKZ6K2+TrWxN2JQ==","shasum":"b57967f22769505d4a176d334781e058d1d57ed1","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.1.tgz","fileCount":9,"unpackedSize":88941,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgC43kCRA9TVsSAnZWagAAB5kP/1RPOdp2kZujKC8YBXEQ\n/cN/+KDqB2SUXrBWeusqXmVgeSGZSH+ijApyRA3y5YYVh/2k/+5w30du8qiU\nGokh+vDQIQe6ZMoWXlvZvIpuRkYkTyIyxtS+zHbybACxbuS7NP0T9S3a7qax\nxCw6/RnSqKv4qb/6nRB9CeJVjxKEdSxyF/ODC4GOUEuTU6TuHMfvSVtSPeHa\nNiXlFr4RkhCmAV6j7onOO1dxpRLPRJ2mqIVj1OLG3jn3y9a5eIy7TENm6bXw\n6TLJ9KOJcwk4bUp8Cz1nj6wu22mhNojAPRw83tNwge75jwAhCPf1cMqmrsKP\nFFbFJh2wXdiwAplbDnh8Bhc6IVkeRDzl2D4WWgS7xqM0dFpTI0ZfoSixkSRw\nWfvGGvN/vaPuJn3aTNGogTIpL6b1CMgP87hZPVtiJp+jsETS2cIYhE2Y7Lre\nq/c4IDOli/QHRMTpeYRzFqpfw97EPRzO/to2Z1Uo9misQXJcZV3uPDXx/e20\n+gpSi964ga7MRLoQ44vqupEMb4ALbm1O8K872vvhe8ZEi1nHZV3G+z2ZeMFf\nlL+m7k2C76A4qhn4Ei1ewuXBzQ+UFNf09ARjHHVlXXSXRWB+BdJipPu8TQOz\nSOaK3fMoIqQFkPN8rkxniV/gZT7Heyip+tKLuREU9gR0+Ac+UaHdx9DArAgm\n23DE\r\n=lzF2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDE4p3dZecLevyV5sr2io5wEgA1CswEutAz2MDXZ+jLSAiBc5pKgqXvMA8dv5z1M4mYH3M1lSe5O/kVAd6SZITGVaQ=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.1_1611369956038_0.19297063375530632"},"_hasShrinkwrap":false},"0.1.2":{"name":"memento","version":"0.1.2","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.50","ascension":"^3.0.0-alpha.0","avenue":"0.6.8","b-tree":"2.0.0-alpha.92","constrain":"2.0.0-alpha.2","destructible":"7.0.0-alpha.46","interrupt":"11.0.0-alpha.16","journalist":"0.1.21","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.9","riffle":"2.0.0-alpha.67","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"e875a035e5a86b8e3900cbc10d4258777898746e","_id":"memento@0.1.2","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-+EGnReB61Kfjl9lBlt+/V4zmopxL68SCDoVWYAHo78jejVSVfqSISpTwD/x0V5h5OUrYOADOZTqgtvjE+NbNrw==","shasum":"e8527957a16231ada479811d221d33776ee62f75","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.2.tgz","fileCount":7,"unpackedSize":82202,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgDKDFCRA9TVsSAnZWagAAIH4QAJLOoL+1rJ0PxjKeF6S0\n7inLIeFSDgc2AorpEAE1PEEioilhUmXVdQvSNh0nMCqqZar4TXDtz7L939mi\nQtnhFqB5WW2c7x3XpnX4XLJbleVN+4sy9mFUajcb+liZyTNscq3N6yklP90l\nkblxntptZkf7c6AzPC/79lC1fzK4DNX/J0EeFY+7vTYohDPUCXxA4rZ6LZ5Q\nO0fk8Mk+igNzBejYwW8iDdt0vmuHfZmqiJuch6RIf5pCxdo6k5LBphvnsU3r\n27SKfd0thJSaIReIJEGX/T3doDXmRIeYE/jsMORB+3v9Vy0WjDjdbgsE93ul\nzaS9HXlqN9Iwpiksrc/QNBqNEE+UxXsZy/6LUCn/nGOSml8kalMuB8GtB1Oc\n1wczsbuNID6roqmZw18FdklcbNcMf3kNayp9jCgCH6BaDMHoyR0pXyDinN7+\noW3ZmYX7+6ILHC/L09iZYDnZJtdC17ERt+5/6F3urVn7wehaE3UuR14LlTAD\nia6shuLlnoauPgJhfEWsafIWqFjvnmbSBUMRp62TSmDiWXytlPt1Kto75ThS\nuIzVM946XS5ZDCxORneb5igadKNGpj0RzCQeZoKpJHaSb9nILa2+VakT5g8o\nQk/jbpsedyy9wi2EfSLRmRv4znunTP+V4NU83If07dZlUJMUEVNdlUyjg7o1\nrty7\r\n=Z4E8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFqEDf+Buxyc28zYoVBMtD3uREWBNbnllvjtI37TBBmBAiAIpm35sIL7s8DrL1D5wOZjtMGwulCP6Z+ByTHMYFYCEw=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.2_1611440325115_0.1490897021323403"},"_hasShrinkwrap":false},"0.1.3":{"name":"memento","version":"0.1.3","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.51","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.93","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.48","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","riffle":"2.0.0-alpha.68","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"c89e12aeaece2dbc61f2e0f7803f3a094b35e882","_id":"memento@0.1.3","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-3vv19TQ3RrDFDb1qEItgdsVbUIQ8cFsHhn3vriWT1k/EfqE/szW9tIaP11iCHrXcZMeknq5z8oTqhwNuwRh+gQ==","shasum":"44293db8163b47366136cceba3b21a73dac58ea2","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.3.tgz","fileCount":7,"unpackedSize":82212,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPAZ+CRA9TVsSAnZWagAA4mUQAIiDq2/dS0f8NNarjC6p\nAHuaUR/Bm41PZ0aXdRHlvEo9dVcnOXi0ftZVWRmzzYP1uBuf6NmNmC+/9pjk\n5QVN+BHicvEM7tzHFVrZzXlwgZB7F+uqcBp28fOxOwOB12FQhpstWbg6Y6Xb\ngEd3Urdbl8lM7V9rG7HCuG8YUQb0XSLqojoqUsVFTbp+B5SHpZzEmGziH2Sx\nGXSDrJKwdvYs2tT4kcO56aXqcTxyhydy1h5l6S0cuRPK9dsi64QnDOHU29Vz\n5vRb3pyBac896JauwzPcJRN4mlWBcHfLrpiK0x64Ya81OihRMFqt1NPPwqK2\nUyRI7v4yXq6c82hMA1+OcaOdZdM6qO8GTkhGLp5CU2WRBlL8TOz27xmOrrqT\nl58Kmgega1Ij2YnF/5NTJA+aM6CPeqHi9WJ7+rsPjSlGMu0OmcogJcU5hFA1\n2vKbkr5T0HEjlT7bZCADhGLgOFZ57DjH/3z6P5SH0MJBa2HF18GsH1ItvhC1\n/e8yKL+L5TaVf/uy/lfP0kgQZNOsuYkjqO11mxZR6oriWhyDehT4VvJt91Bp\n6LnJz5ONRGwBWHaWYJFdt38qBx5arKLDZX4LxdTINt0+rNcD0lDKICqau3UJ\nFwcX8i2pdF+IMCZrIHlfwGOBZRd6B2KqyMLLra+E4ipxfIuIcki6GChMnu/+\nFOqT\r\n=x2mp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8LicqV3/w/ZPoY1up19nnp0ekAHu7/9WQCYSuXvYwXQIhAM2JxdezpJU8/Vy97BQgD9AS2wqREefWrloVkVE/1Tus"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.3_1614546557959_0.4375099920910246"},"_hasShrinkwrap":false},"0.1.4":{"name":"memento","version":"0.1.4","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.52","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.95","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.48","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","riffle":"2.0.0-alpha.69","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"ccc63cafccdcbbc1e76ce50ef177661255dd6ac4","_id":"memento@0.1.4","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-dYVGZZsORD8ZjyHWKGm/IE4f2thr477NfoegWddeQfkcEgyf6ib+C5qEoG/KJkLJpriMb83cQSF8O/fAzYvxRA==","shasum":"d553eddf2191166d569b9216eab8fc6d97ecadd5","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.4.tgz","fileCount":7,"unpackedSize":83004,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPimhCRA9TVsSAnZWagAAtgsP/ReFjg/lol9FSphpkwWS\nrqpB22qGQNTfvOoo5gtVdqmPzPaYOTJR3ByUTEvkER/szhcXtO/R3H0rCgFZ\n6se2EPlUk5g8j4xEECjtJGOhUJfbrko078oEc4fRk4j0ElidOsknXiQ9Y6or\n+1OWYsgg99l47XWjJt1qln3sQC9Hq8v2wt2ZLBX/uIBXY+Nh9sbJIx0IDaMc\n4d20TQLaX+dxQ5REBWKWwfIdveeDB0aNlb8TPid00ukYLie9VE9sgQSimYcX\ndHCFhulEJR9zzwzPwdLdWbrf6V8OzZXx+Indy4KJ4+eL9ZMmNkJaeMHfsGXB\nxapC5mRJIesQduqi7HWnYP16e2AkXczG2bpzo2jlADeSk5hXNKw6QRb0DAXp\nu8AhxnSgwohSbWItKVoeJbnrAKFuenugVvLVqIO3dJxA+Vdp4C2JOecQKFOk\n+6Il3owikBEQVTZ5iyZWseewanoxyuZ2kHcurfYEO9rU0GNDg1TLH+i7hPyF\niXpdcYIYc+nqM/3JZ7zbdNmkjO6cZnTo7lgeieIGg3jxII444yVLCi/12UXE\nJ60NSdLYlGWaiYBSLARQ8XDH/5l0h/RTTzFCrVIpNVRcy2pUkG7C2zAkfF9H\nvrrODCJ1Q3IPIb/eliZYD0/mbvDQ0oetw72JsfJks9OEWDQwgwa0ICP3zk5E\nEhhn\r\n=3TZb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnH3wsdwESor3B8pMtSH18gSKJiu2TR998LivzJvucwwIhAJ5pzTANatimp4BUAetta8bpJjd+jrzt+d+U2b6aUQuf"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.4_1614686625207_0.9418256802872456"},"_hasShrinkwrap":false},"0.1.5":{"name":"memento","version":"0.1.5","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.54","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.96","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.48","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"d31f969bce317278173b23b37331db0b1cc62b16","_id":"memento@0.1.5","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-bCm8LpQvBxcK4LZeYcLmOiMecxfbNGMGfhU0caB3oVwZPmMmnFUVYV2VSoqPIHZ5H4cwVfEnyCdwLHdcdYpesg==","shasum":"822ff13a724e67d185fb769411740a8fc604cd92","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.5.tgz","fileCount":7,"unpackedSize":82895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPsUWCRA9TVsSAnZWagAAUsoP/1juRNKVJn8qhz+PZnf0\nP8+Z4mobDPJsNNZdnvHp6gU9wTwxV678wNoEL4UBsExYJbXJxNmSZiVix0Eq\nIADmqe/iHnzBUxEZIgW/EfwG6FGRP3S3cUGVOdKwWo+sQYcXxIyNtYuErjQG\ngbYvPK6lf/V3hreF/OZ1DVkOo0qN1IVf2//byQmrYxu068jAAzxO5i+P8I/r\nd87nhO+06FZIDZOnb6w8J0YF4zMDodprC2rAQb3QLy5Rq1OVd6kCfqyKA4Ic\nz50yPxZ9jnzKPFDSTZ0rCNrDFfN3UjjwJxdDFremkmxasyLec0UqPEV4KfrS\nicatofNP/dqsO8kB/rB61Td7Sbtin/uBiIKyATzHayeRslJvSF5SH3Ugo135\nl6n4ZtDwnzRrQ+ode1BQYCMw5umFGY1rFZnetC7I1uURt9Ee/wWr1V4CFp/W\nhjcfpAzWSzrWlUuz7DsN3AKB4g35suiN795/ZvNB4mO8ccMxXl04VReCuzu9\nQiYBX7H3dCf/9g9mdN+2reyOqfjjiYp68P1u5zduEy6jPGp1baGdIExBRNO/\nIKmhUP3p2kcu03qeYqA/zzZnoM+Q7j/cruOxWC8qAwe4ezPERHRQuzmhnW5D\n645P4LkyRBdyilWEOZ5sQ3AHU+wsiEIZnfSBKDYKVZfahuw/E+9MgKCqD1Kb\np7U1\r\n=8+13\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHncefhbVkAnI+3Ar7Jncjig56zpW+I3XI7iYZqSiWnwIgbjA77G9QMFPQQwqdzAX+Ti23HtjHJdmRqyiODt+qBAQ="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.5_1614726422180_0.048738446542702984"},"_hasShrinkwrap":false},"0.1.6":{"name":"memento","version":"0.1.6","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.57","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.97","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.49","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"9132d0d930b6b657bf1df6c6e914b056260c988a","_id":"memento@0.1.6","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-apg/IcIdbCc/1CKWPbmf5G/jYBXSzfcUjgS3ehuCgOA7fWXfZqHtbeyhFSBzekJz8gK1gnA1ktNckgkvPKvRxw==","shasum":"2af2ac23c19eb8f7cf8cad27511c72475d7ad07a","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.6.tgz","fileCount":7,"unpackedSize":82242,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPvUzCRA9TVsSAnZWagAAY04P/07HpaoS0kLj/JuTST8q\nR60d9JZTjxPcoLv3l+x/WOTgo49TigxyELs5VLVLsDlXgNnFJr2Cxz14FW6A\nL6Xz7xUlgJdgd2ZBLlPuz/7QncPb+nh5F55pvOyM2KzYdfccTrRe522ZnmiU\nRU/4WVqoofHt7OEXDTErMsOSQWwSneBpeJdcI+D0hOHn+6gGPrdS9PQ9Szpi\nGqyXTyCekJ7buuXSKzzTC9A4nxqeOeDnyuIv5xdmdwcDpG+d/g24YaBNgG0l\n6xnt4OLOgslFRBjF6kH4xKEH7SVQ6/t3uX3NXYEAp2VfdEEuMcN4s26L0aQb\nuWg2YcJumsIyiE6rGcDMAnH6KJ/wMQE9PlsWijphwczVncqf19jFSVAG0HRs\n9XwkksGgmGmRqbMpCf7g3ueINILOjneFVrGS1rcbT8ydoDxkWvJFLlHF7Oot\naZH7aSVfP7LRZhYe4mFv4isdeS4rZiYaAsRzISt84cy+GUrc64CLoyrOXWhW\n5AGN3kCSMQibhEpjfbi1itmUcP/K/tT1LRzuyxf/AW5ZX5mmRWZegl7PQXPF\n5jV7zSUfPmhZRyRlMATdWXg3M/ywlfiKSwpP9gzWFmK+O6x9BvqHXVrRhJqI\n3WRxS2q/6wEk/xRcuR1Ge8ZFy6FOwbb11RKUB8XquZKg4bTuQCkkEZmvs1OZ\nhUqS\r\n=qWo9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICv1KtKiqJy/4eR3AFJQ7rCcqp54Fe905U62Ixg7kAJsAiB9DClt9Iha40FawGMIrTOHXPS3X0PKhDKFxuxfrd25vA=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.6_1614738739030_0.8387928229304658"},"_hasShrinkwrap":false},"0.1.7":{"name":"memento","version":"0.1.7","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.58","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.97","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.49","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"62d1ca9db5d9578c9090104ee6ba4d2f8be97ece","_id":"memento@0.1.7","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-K50caBz/3r8zPa2tNFZDbpMm/YcgkGHlWU+uSwW1TlbDzPaf1M3GHZoERWJ2OQkbPL66Ys/Mjcq3XmGFibP3jQ==","shasum":"394df3beed443ead4c1072f0dc33dbc9f2471152","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.7.tgz","fileCount":7,"unpackedSize":82242,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPvbwCRA9TVsSAnZWagAAGXwP+QCF5LE/Grk2qy9eAZ+g\nqtmf53XM12pASgUM/jJ2MiYZz9g+2qs9FbVy0rspsIGCCnVRhjtxLM+k6lNM\n2W077sUqBnNT3DP+J2uNLc/s1w5uattbpWI3fj0jeh5GgAe5fMLHDbvaV5E/\n5LTyc5zZDdwKgAo4px/aooo3V4dl1FvZIoceLzFFnh/DRO3LRMc0A+gAFh5p\nl5GsT+n6aM/zLc/FYAK1AnApQG61p93KKP8DBGYvn01eokE5mgNFw/tj9Uc6\nHElqcvlYuXa5RrS8VZjP7lfJsDtWf1k5yROOZhoMemd3jQhM5BSsOebId6oP\nUTINqBAuiZdrLaf8YQi8lng+5wXSlmbpq1doikcgOpC74fstpiBpuMaS7rCI\nzB08RjfoREgicbwUJk4YfsgWjLwRP1Qt4WVnl4DEoGljZs0FXNKERrNf+i1e\nqTKpiEZ5ErafIpLNuI5BzKFJ9dGPucSt0CPrVZRP7+NsKKYyBj1KxuV9m6oU\n4coOlZszgQtDG8mr1IW7gp6w1jkn6k62S6YVicsCruYbmnDqL1VHKhH1ECju\nmqr+YHJJabcnc/U6YLNufBZOOesE8wiOERagwx3FrXNRs7siw95mRmKM69nQ\nNu6uLQxgYbBtHw6mJeucQq09k6CK2hfDgviqNH3eJU92qfFVabTY/Spo8tYr\nJY9p\r\n=8Hjg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCBAmNOf98l15DZDrmGRj9Y8fhKNMu6uhxgXqRi714JRwIgAKXR0j8CF/+9g/uJWRBAAkTa0wRBiMg7bbZ1WW0cZ7w="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.7_1614739184194_0.2833754546215026"},"_hasShrinkwrap":false},"0.1.8":{"name":"memento","version":"0.1.8","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.59","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.97","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.49","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"9823df1c107188091ad5db1a4bb9ad4c9752106f","_id":"memento@0.1.8","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-dDnQgUUWK4Pdh+KfBqqYwF75XXTMhGe4Oj1wXAGEirdRPGIpkDVnE3dtjTQ10me5glA1/hQaac/1HxdlJpYt+A==","shasum":"3bb166f13b7908592670119207c3311819768958","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.8.tgz","fileCount":7,"unpackedSize":82242,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgPwqiCRA9TVsSAnZWagAA5fMP/i3yCeK7zcsvzQQAiceL\nIuHwydcaIIDi8R/zmFPFAHX+uSEJbs9sU8RC18RDOR1nBe+R2+FUnS82d8MJ\nbaSDIcoJR31UVEOsXes2LyD9VQiWC9miVavq1qUqRQkrNtfyGVdWoKcNufdx\nibjXBmstscr8NwAJI3bMQ+VvnNqukyU0F+BGcorDSQzhRoMAfqgBomMmdBdB\nubjsv/4DctAy872PBQthYo+xGNPlLqc/X/P7RqJtSOTYGKzV7w3hpsnW6d4A\n6XPr4zplr+Qz+D+kZkM/tV6FJ+jmPw/tKTRFEa7oswqzAoD433hedC30iKrh\nZekGLB7gA9Gw8oxE0YEWc+sS0yzkN1X0TMr5bdFG/qlqaw77gbtdbWTElURW\n1KFf1CN6t11EVGlifwr5eRpwhZPPx+crfNgs9CUgqXcBMmKcbPq+ejd0hdLm\nt9ScbbmGXhMdERisMWPM85/3KUGsz4BnhXawbfRCtvjhn+EPrr+KnIaSmryB\nJQ2fw3eMi2B4SmzCBv1ZWV+2u7DpGTM4qP+53GuOkJdPQWLDbHnpLOQdf46+\nEiiEpz01dfWgVuaI5aTO51hl7rZyfe/hJu/tNvUncMJRni5V+Am7aTKG2EpE\nHBroqNBDN1bbfx0QdfwqF1FgXGqVHxKyxdxvsl8JBV5c4Os02qlumhVfxTV2\nJiaq\r\n=VwZ9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGqaa0fbRk64YF3eiUNmfTkFUFpLbTmd22W/Gip2S4hjAiAvbXZc0uBbmu5PLiAHkbH5tBieAtnHQpSWip3sYNpidQ=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.8_1614744226364_0.5203742423965869"},"_hasShrinkwrap":false},"0.1.9":{"name":"memento","version":"0.1.9","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.60","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.98","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.50","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"37cf7c210734ac8cc688c5e9b82f9fa0f1437a34","_id":"memento@0.1.9","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-mzx3paWVA1tsCCkysu90CZwbbYUqdykzuuLSm/ADY1WrwjnJofHXXjKX2sZ8TXUexXUT0MF/sCboz4Ydgq0HZA==","shasum":"379d68389bdbaa95003c1edbab3a311048a70235","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.9.tgz","fileCount":7,"unpackedSize":82252,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgP841CRA9TVsSAnZWagAAEFkP/RuaZEwdhaqZKrVNAKVH\nVRJ30+oHHtzs6NeBWW6bLpWaxUShN8C4XTQlcI9qe81HZyOHD3IHy3mhOGJI\nfJAqEoj/BGi5+Zq53AVVkv0e+Kp9iT8+uEsWoTjemWgCsb68wkmjD4NPVh72\niZurboDgKNLvld65nKWlZ67w1pL7Jq+TSNBeTJMCPaxF8QuQlyjLAPZdMuhP\nl8McaLZ3mnOPRO0F6zGzS8o0sFuyUXrjED08QPLscFp/acYQDFX+XVpxgsPm\nJr2wXOQ2HiPVUw/YptuxF2NEKpg6z7dxxTIHuPYA8AammYyGVFGIVXvue9bE\nkg+S1KWD0rXw9grRkmCeNsVtnTda11LZ/e1PLLnEX7jWNql8lZxkHrqWQFx8\nUBGMHxHHtpsQKnbtGTrBMdbEI9c/76C67am8n92vZrFiult9QUTVKehzpQH9\nEW+aKxj96p8nlRIhcR2wQOKWpJeusnLhquuOpvNX5+TEW3sDluz8jdghMsSt\nGA7sDTzBFQ6abRGYYNdBPEWTM1gCmNb8Cm1RU0QZSE4ue8ooqgSo3MWu2bRy\n6w3Dpeg5y9pqfQFd0DBkHXAdNUWbg6vlu/WHXgo2QOfkkBcpdcjf1PfGTyRC\nqwytmrHjLkvKMROz0jD9VL//l1zLEyYgrFCVhiAz88FE3RtiF/hdfC68UjjP\nW8ML\r\n=d4Q+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGeez0Vf2pt0T9YhtxHKCav4/dSaxcZYmsVInKiywqhWAiEAjuhSvFimckPAnb0NASqQ0c7ZsfDa1cmbBRcjsIS5mKg="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.9_1614794292528_0.08947181443254926"},"_hasShrinkwrap":false},"0.1.10":{"name":"memento","version":"0.1.10","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.61","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.99","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.50","interrupt":"11.0.0-alpha.18","journalist":"0.1.22","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.11","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.6","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"5afb1f3f14c7f7ec7e592df7ce9dd5a46abf1f08","_id":"memento@0.1.10","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-c5xoRAYOC/ZAykTAcElukR2VeSFFZRv+bHSnEaIaFmdZpEvR5pIrtNbIilp7GL4w9c0OxyXxpJqcAZIXigNGbQ==","shasum":"aa3cfce57027ca1e27b878f8d0062a6f8d1636a0","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.10.tgz","fileCount":7,"unpackedSize":82253,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRaW7CRA9TVsSAnZWagAATucP/1ieQcNo5/Cu3pHxmbh2\n8yiDL8aJfbUNnOMSZYHuP1WqTArhY0WWIV2OA8m49h2KPHaaMGGPDKuUUQiX\ns7S8quuMPZW/vN6kcA68hlpiutR+661DvAzs/55bCc3Qe1lDyqPVIxWDeQix\nwadpKzc01PnXKV0OctMQ0zxn8BzIH2/pIXcxz4SPDlgpTkGbzFgFlWS44z7M\nVtPaVneg6C6oDOPmAafc9zy8QRbHgCM4gi9dK8PFMJdA6yoX8nWidJCcrSPJ\nkr/ubVUWDpR0k+4gOiUMbaxxhN9uC+6ybx0z+GNJ12U0Jaif/jCa/2IlE05Q\no+1DCAFYUaHSJh7c+yVOWNV7a4VAWax9K0VkNgOIds5325MRpY3Z2mvJmBy1\ntv3/ZWWX4jKROl7rIuTzxznJ5A7RIIEu8qWzKg5DjyxdYXAIdx5PLHwQ+TRE\naV4selpkWHq26le0oprGlGCYRWOUKNK0lY5KvxeTmcWkmo5x6XYfLEqI9FBF\nmYkTItOsP5OB+yZX6QAPG81S7B+UcFskL64BUTV3iWNpOCgu3vZMVNU9k9ev\n/RGoyT5MffD7oYUr1F5cnC59e+4YO8kWTC5/fNT700f98HB7r08RFMTPpi6L\nH//ThKCwCA1tWCnH7a9RVN0qnwhdjWxwImc4XkMx/fGjvd2You1hiI/CH+7G\nta08\r\n=71yW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICNryAMZoceSfzG1TxSF2SVzcImoL6flJKr/l1/83XfvAiBvC0zTPJTYpyIWKcg3wp1ad4/+x0c2RQG8Ejpm0mKlfA=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.10_1615177146717_0.9858711124713062"},"_hasShrinkwrap":false},"0.1.11":{"name":"memento","version":"0.1.11","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.63","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.105","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.62","interrupt":"11.0.0-alpha.20","journalist":"0.1.23","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.13","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.9","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"1cd9b28da1407d2807f68a6166437ecd99c39461","_id":"memento@0.1.11","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-1ejTctPYjAqRST1vKzXNsDrov676AFnI8x/BqMD75YwT+HSTeeaD5MWE1ykEjWZmP80rZPtiHlsaJNQBN7aVXw==","shasum":"73f8ce5d137d989792ba05fabe6339e3cfa3d970","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.11.tgz","fileCount":7,"unpackedSize":82642,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgTq/FCRA9TVsSAnZWagAAFi4P/1SmW2l7+sSNUMpKuuE3\ntg92Ni58imRGysGxG27CCLdl4ZNdATYcQFO2MbV79UlNoeyedAxpbBLO3NWr\np7wALA3r+0slsCouD+Z8dZbFo/hqxJkVl0yMwb25Qc4h1XmZV/mGegBJ6G2k\npu+EjLNF9B0iqUhMx/Zwt95+aJ9MiFgBFN+KhDDNs/nHtxPWdsjZy3Cem8jr\nOpOmXfwM28rhf69ti30dNjqsxRUPpMESkq5BZDubSpNuXn3kqS8XuctCHD+h\nNnpolx5nLvwl7UrnNM7JVVI2kRHyb2BxCc8p5XFDIEEdNuuoCG18nSPfXzwp\n0SaAvuDvzf2+oyRfVz9QubaeTvN86pgYwn5eFMixHdtGPI3XyJXRW2ohr1wu\nglFDs0q0HzgUjvKgx262oo0qsr4WgtarUs/qn36MlwQY9N8WjbQPtU0MZ/t5\n/1Bcna1SULLfbm/ncG7RIP8sgdu/KjEfmn2/TYQFoWPjNsAwqIcXR1HeghUN\nCDkngSIuLS7NZgs30hWgTb4TkifpI6JfPFro/30i7fFah3j+bZyPEaKxzC8o\n/K4SCbBhbwMaiSm9Xi0mphEBj80YxxWsTP7zk8I/6UjOyy5a+01g48TAWHrm\nzra8syYRrxqDwmIWMolc/mZwshBrNhbjJ1xjDRU0aa0XnIkYSsmGAN2HuASq\n3hc8\r\n=iPRl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVMAD9ZCTClWDVRVuasl9zuM//N28UF3l6oGhLxs4fAwIgZd47P46eiq2E3u1e1wIBDGsqHT+v+2DodmpE4suOJ7E="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.11_1615769540602_0.012509057904110499"},"_hasShrinkwrap":false},"0.1.12":{"name":"memento","version":"0.1.12","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.63","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.105","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.62","interrupt":"11.0.0-alpha.20","journalist":"0.1.23","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.13","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.9","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"b047528e0f4973bdc47efcefebd30255f4af40d9","_id":"memento@0.1.12","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-ne4QDidoGKPCm7nYDB8cvXKXudk+8+sxRmp04fozLRrnHySSI3516Xykz1RvCbaiyBI7+L2RWJHSuiKD2h9eaA==","shasum":"9cd38b28ed06f4190990e13c5dac61d46b631c9a","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.12.tgz","fileCount":7,"unpackedSize":82910,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgTrhXCRA9TVsSAnZWagAAczAP/2GOIgQG2XFZRh19AKaS\nC8uvs28sXNGMd/XZiCenk5E4Qj9qVZ4+vfXssFoUUrdazrNqeoHmm+boWyXL\nadpdlqJtdqFFUqF/gV5Wrzs4QtRtErBDM+Ov/KufTVwald2BechUehGFe555\nieC0BlauNgqfMMtE1yuoraWOFp86zkA++WqcvX8SYWfe/Tnm4kYSVPSzCYP4\nyWRTCDAtAHrNG0eSGhlhhTLyOsyyrWVdNufgODLRNAoiZEks4YrKtzA21lxs\n7BmTaaCZ0ZuTSmU8SYDeMDKBBEythWXPQ1N6WGD8ag9c4dMgq0VBodx7Wxkr\njyH5OThzpHD/SEuRqkVNPrn4bLtm143+3w8kYRsgJ36jIEfnco9bNhs1pwM6\njVWA0Ds/ex90P5g7tBVFfn1MZ7jUOPrsnj6JhvW7GFgBzeSFb8TZdlcjAp82\nhf0cF/ljWje8ysxAOAYVU9S3SJYIq7+1k0MN0wYYInj6sBH0ZkNHLono0VM1\nemNO3nGfo1EsKCCqR3KvbITrr+OSxlG6ID+u4UGnFk8tpM9/tAtbsDw19nc5\nAJOJaTMH6WsKh16glb0RlZ5TagsO73SH2eUg4soTAN3vpCehOkhtsgGGXmqS\nVnjb3iActhnHOpeowVwaDzV83xAkSDI5Nm4kJORRHqAe0afVE4Nkh268Ch0X\nKtX1\r\n=EJ1p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC8QT4Ix0lK1AUBQPso1o+ovjgZb9NJG6EsCP5lds/HiAiA62ju5wNFDSyo3+q8CVt175vcmtkCi39u3juR+rbvWVA=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.12_1615771735311_0.06827649343532105"},"_hasShrinkwrap":false},"0.1.13":{"name":"memento","version":"0.1.13","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.63","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.105","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.62","interrupt":"11.0.0-alpha.20","journalist":"0.1.23","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.13","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.9","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"7464619765a44baa791415dfd52784d65b1351f0","_id":"memento@0.1.13","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-6FnECmlBogGctpk4jNyy68Ueme4wgdKQn2WIyu8R6V9PfjsUGCIXDspAQa9P9Ph2x7PWKWig9S5rCl8LqmLbbA==","shasum":"9ca7a2876d02006af32baefce6a2201cce21f936","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.13.tgz","fileCount":7,"unpackedSize":83316,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgUD6/CRA9TVsSAnZWagAAGY8P/iVnArHkAjshacUHFZEQ\nkQJ3ZY1xGvjifJQmfw8OKwLf8CFwgMzhnpbQSjlw6If5wgH7kdwizi+grnBb\nU0Oib4wDnEdQKePfaNVzHuC+XX7zk6GJRdXLYD+Cq7j4iiUDW9MokFTz4NBx\nkgQnVjnQy/HzKzkOiaIFeKSqUNkEhAHOlLMSNPzl3Xl0C66rv6hVdlVhsC8+\nuxS680FDKDyeN9YXh5vghLPBO3d5Ff+/RlBLX0/Ulw0LDDBWCSa3LN0gvXeX\nw0h/oA0uh4x01h0FLHk22R4Ae9Vy5IEDsp2/uQm0EzcDFL9N5MmSOQmbV8be\nHtCrjv/QyCvwsaT+qb3cFgydQQeYzkMra127z9PY8QM7XgV65Uq14uH/97XF\nrbt+THwKFUsEj+qdfDJkoKtc68j9YL0OUY4kYuBMFos7jFsintApkEbID5T8\nS7taQo9lzSg1iiIwzp/c5MJ73neBU4ZR1P4z/SGfVMlcizYMrd247ZHx3xOP\n6efl8gTCAFt1M/k4LVloK72Za/Q/sJi3UvdDCVfK3RMqMUe8J1xddMCpIjqb\noX54S9xtcBiV9H+U1ubX1rhoN0eLGQWh5Xu3uEMG1e3TX/ezOCcQDvWNoG3S\nWGTbGmm37deLtY7FK5e9gMKWv4wtMd7vvegqk5lGFwg+pgJBPUCal3ptYj1K\n8JDX\r\n=MGit\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF8BphfqiFSUzFq84ISccBQqkDv9r8oKiXYuQjf604a6AiB1QVfRp7aQ/cqCeIo0V2UNLvV2opz/bYJrvc8csFtRfQ=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.13_1615871678781_0.8801859759627495"},"_hasShrinkwrap":false},"0.1.14":{"name":"memento","version":"0.1.14","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.64","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.106","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.63","interrupt":"11.0.0-alpha.20","journalist":"0.1.24","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.14","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.9","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"96d9a18fc07be9cd1d209c3743805e3b7c3b3e72","_id":"memento@0.1.14","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-Sd6kPF+6mcKIHkuHQd2/w/OrIyky06w2SdvdKskFL/C9wBwDfmHLUuUnz9Byvv2w8phlCQ8MfC1ECbJ9PDMlzg==","shasum":"b818eab61868ffec8558632a856ea77a19712220","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.14.tgz","fileCount":7,"unpackedSize":83302,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgWX3VCRA9TVsSAnZWagAAi2cP/02TXvmyh7ieAEwHnjrc\ny3NaGJZ04zISmrJOXOSaiXcUZNLDfO8wYrd0Cm98mbOvedBS2z4O5ha62ekD\nLOumsI40/vCQlwfzCxo9z1PFibh9sHJ6N9eigmcVSotDZ7vHXLDbrmBD1/7q\nAS2XJty2EfOzQm7bmZq9WuQia/ls8c0Ar1VeUcD2eUwG8EfK1j0myzgxq2Nf\nVkh8YTs/kypX8M6OHR+lWYwz7KX65bLKjcA4loI3ulcC0X/roctXKkgsoP3q\nOl7uam71IaaplmZ4RTcT0BGW2PAZzdiMWR7+0YCKeA/5fa2JVQ/rE4PR3+zV\nZQXLMHVekn8K3VVL7dhz/B62OdN9DIM2tge8fQwykWf09xqNbNm762HAYCri\nTztLN0GBYLQ0GTrsb9zmu8+IGjmhWppIj4o23brX8ZR1mlhoCfNXVUJ/7UPR\nKnJarEvwYAw+QEv4wiLRrtleBtODo4GzyMP0N7ihbH8EXRx9ZUQCJhwDM8Yy\nC5YYWYnvH7j5ctjGUvAZqm5x3g53J9YAbCXz5WdSJIpYLdq9bEYg7nsPiq3s\nnK4OYMo1KIoJz2zdOW/SyMkre9OUU8GVuWHfVM8gYhw3p4xnRrtwLjKK4rAQ\nrfY1NXmyBGPnPMVsXlxkNE545GkhQG68fNDF0ddwBM/aClAc/jM9Qw1VIAzK\nzZqs\r\n=sqZS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICQnq7g6EXagkC60IQHrsTkDWLRd6vKUb9Lw1KUtUtYzAiEA32mKhbheRMONaT/CotAUB4EwNJP7AxKJusZqvu/Hux4="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.14_1616477652783_0.34792440321903406"},"_hasShrinkwrap":false},"0.1.15":{"name":"memento","version":"0.1.15","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.64","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.106","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.63","interrupt":"11.0.0-alpha.20","journalist":"0.1.24","keyify":"^2.0.4","reciprocate":"0.0.6","rescue":"7.0.0-alpha.14","satiate":"0.0.2","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"081a79cfaadd641cd2ecfb519c29dd115953d429","_id":"memento@0.1.15","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-GNBf3+2uaNJN/olnQ7/N5wvWAFrZ4IoIjHO1EWqbYX5A/FHkTCv0qbQG+pwFDUbG0HNhqvI3v9iE6B9TjIkOoQ==","shasum":"a3115feccd6ed14e2252e8eec6debd0157f65cfd","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.15.tgz","fileCount":7,"unpackedSize":83303,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgX1sPCRA9TVsSAnZWagAAVfQP/3XrDNZBjHtRgC7FWakt\nPWz5FNg/T7QGO+og2h+B4VXhUuq8b0rZGa9M0gzVWwm8J+JMC0c7TtGAm7Tf\nCfnz6T03va/I4qjdJHHkdfjX5y/QjkdY4ammnmdMtYyfQE56QSoPNuRgPVJT\nRy9YjAn+vMIFjyKskNmKFpV3VPSljqoY4avtjGz7lA3gLFS1TvVp2rLlXm5h\nNWm4630ceF8vZkZPMQtfGOD4lfZBsXQRgTpp8aUOsPtTkwldPOMyOgdC609y\npd5BbYX7IV9PPhi2mI4flD9MCPapefaqdoqRSZpLbs7YJtNF2NJCbKCDcyKG\nrv0RjlXh+1Clal3KftPvcgv1TEx/6hNL+OpNKnP3oes1O6MiH8HfIiQCQ5b0\nB/5yiCbDEwtGo0cAibsB9YDOJ4j4ryZ673BrUOE1h/AZQQUj93hYroGOEbwB\nienyPtqKdFp6ES9TSAov2gGx+/hf87OZFIhq6JJz04y+srsadsl57wQJsvjb\nx250oniVLM9L1dQfl1WtkpJOwpLkoC8KpcOWi5BkPJfwdgG0xegNC+1OmsIC\nWKS6k5JrdQWWBnAtgynaByghltfSmC4FNel/kFOB8/+Vczaa1i+ItAdTPqh7\nW/s49LahZV+VFX03pfQB1XPjpXTIsCQy00qLzdS4n7VT2KdgdNPgHNJ+SiFk\ndAZw\r\n=Cf4V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAGIH/ki9UsH+HPGERT4xBuauBT0t58xUefkdHsEJJ4aAiBYj1HpYssYHguzm4+G6SqzucTnh56AyFqOlUaRSJhBlw=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.15_1616861966793_0.8480452041741999"},"_hasShrinkwrap":false},"0.1.16":{"name":"memento","version":"0.1.16","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.65","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.107","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.64","interrupt":"11.0.0-alpha.20","journalist":"0.1.25","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"ba237e9a0245c40fd1fa81d70ffe91cc49799ba0","_id":"memento@0.1.16","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-SiVPFAhTnXj5N9Zec8smLRxuIMEi0XqaYW8PwrzayvraM2GAOgGirSOSm5FgaS5lzWK4BhfoZMLa3XuGAWlB7A==","shasum":"c00db9e93e52a83a05f655379b70306b919539a2","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.16.tgz","fileCount":7,"unpackedSize":83303,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgX1soCRA9TVsSAnZWagAAaJ8P/A54OCRQ+PX5o2d0zgNo\nmt6oR95y4YcuIxlhBw8e4gylRXq7PL8YLx/wt5+k4V/r4MG+RSkZM5/wmeru\nOn62tGauSTI9Mu1mc7CrxUVWC9I6vHAfboHiy3c6GR6xy0fj3grEQi90WedW\n9ggeaS3uGxtYPfTAV43p03/6EHlptuEErrfB6ns17BzslFcdyejyKMQdvHza\nWwaBROc7oRklodDGpFjVsBZAv6vfCwAkBINovMynJsDyKSd7WoZ1jpz+z0Xt\nRQBZLGV8LOvBHNVRmXIM6nKEW/fAPjcz431hUIeDpZeDT8F47Ni7jSwjZDyS\nzU/pHnjfbuiI3bXVyashWTieMhB7rrQTlxNctmeaAl+GVNnDAYywhTO9WgTQ\nA7waD6Nfuy8HwYMplVS6CWPhI6jBqZjBa8+G3IrxFTVJKoc5eZE+t719RtKp\n676I/2fr3xka95QLGNM9jnN/auvfjvtWQNDjLv6mB4MgwGM4IdBO+w5XHy/9\nXxY28b8HazGBHqdQy1m8PsINqmEgDxzgrR0dww0Xa/UIpq7iTL3nvfNWCiNI\n7fxUOCTGSvc3znDdjRDS67M0yDGF1YqIDMmlA+ga5OKsxzLzsZXkz475dZJh\njF1//7zzqZOk5dJr5U9+jo7ATl5597GG+ZaoUPtEOD+hBE4CCOW7oAiVrlc/\n0Kcg\r\n=TLQ6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCwk19RXQwwF5gEh8VTydzwmJI2iUuXljQd6z09i7MJNwIgGv4p4z/JMT80tadNTOq9DPc51bVLEYzHhmdAL9/cNSA="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.16_1616861992087_0.8707371192362665"},"_hasShrinkwrap":false},"0.1.17":{"name":"memento","version":"0.1.17","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.65","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.107","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.64","interrupt":"11.0.0-alpha.20","journalist":"0.1.25","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"5803f3d658c913b5b169a654249e6749a433f47f","_id":"memento@0.1.17","_nodeVersion":"15.3.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-xSn7V7UkzAjiKnltG8nmdHC5+p2EcoU7nrTXZwgec8SBjSFFYS3xMX2lL709dM0aVNEz6aZJlKUvgkxhO9j4zQ==","shasum":"7c06df382ffcec2bf10256942f2dacf6b1789050","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.17.tgz","fileCount":7,"unpackedSize":85452,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgb9RvCRA9TVsSAnZWagAAb24P/iNNU+xWREmDaxykAqxT\nf4FAPRvT0QjOZ1z0vng06rnOl2slXcF3Co0h3IbNV0INs7OjOOZftSPAaC3C\n/fhils3gIkhCmX+c/y06Bo/kYIWhrfffJvRfVjfpTUOs2yQWI4gnKYw3lyTr\n4MjQByy6UmQ7RidIMtSimPg6lp7IMKctcOa2usnRUpcw6HuOnrzcSTVDcpGP\nNAsSzdt3TSmau4+AN6Uz/IGx8AuSg5tmoeGCIjF//UhACkQ5MovfuaBWD3ik\nScQ2Trm9ej1/zhWTZRGH/2HL+3GK4HgG5UY2YEi0q5uHxJSQzqdNTvCtTtXQ\na+LW7h97t4x4Rop6BVe+L7JZJ6x/gwmNx9gUI1uRb5ZFdgg+SQ1gYWMb61Gp\nWmpImXcD4o2NelHVRbwCXXH/jeQVKv4EW390dRj2ZcA3+GjIVB1ZxO+DDTBh\nPlr51B7A4S52wPNtoJIGvm3OZ3Rkg8OhGB2MKvTbW9Any6bLXWzO0/6tO9uW\nI4BM0B40+AyPJJO/c5ZMRB1TUwzvDFHbN2fjr2ky5AeTYpvHiXeLq3XA68iz\n2oAOou08ZGxoXdNINw6JWZF1iylKAccwGk5ZFKh8OYRL4Pl3vDtAoepif9Fr\nUyTLnpTwb2JLEBdja0aXezVaV1jrGh0LlZ2OzwgQvXCQZHTmsdhzfBAh2wGc\nfx9k\r\n=sMHg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIECilYg8/ObBWL2C2yIpbo3qsGUEzzFzjFWAeBr0DGldAiEAy7v6LmQFXYb2fZ0OWMOJU1YgksXVzx6Tu7RlX+WkPSg="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.17_1617941614899_0.039731859146632686"},"_hasShrinkwrap":false},"0.1.18":{"name":"memento","version":"0.1.18","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.65","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.107","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.64","interrupt":"11.0.0-alpha.20","journalist":"0.1.25","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('avenue')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the the snapshot callback function\nbegins will not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"875c60a8ba6676f9a5ac6543117582dc1a06c9f4","_id":"memento@0.1.18","_nodeVersion":"15.3.0","_npmVersion":"6.14.4","dist":{"integrity":"sha512-RmuDbmwt8Er7a8Lt6rdif7huFiI8CHZZPh2QK1SrGjLg121arkeoavMkbQzvKwhSmLNzZWnk7d0RMvEpT1wcDg==","shasum":"f74104d645da52b3bd0b79802a6dfce03787e6c9","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.18.tgz","fileCount":7,"unpackedSize":85448,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgc6D1CRA9TVsSAnZWagAA8AsP+wZe+a0wA3vviEy6OlcG\nm/i9LI2vTRlYN7k/Qrscn3HVxWIHg8vzZGanysAc45VWnWk55G7/TuFOk/Dq\nB2CWbmXkhQ31AXIUgn2moS8sw5b0xbxEACQm0lI7EVsE7MUgSBLCCwo1ybWc\nAn/eCAJHfDnziZU8Rb1S46GIc96xjRddSw2Cc6c4Aj/9jw8IyjdA7Cu9ZV7v\nRbHLWNjvgW9e7rJsRm60G7duS0/iiBizHgfe6+TBAZ/Bz0OkZaBhE4ndnVp6\ntHZ6SzKdBkLXwqlGYXeb5bx5pus/0ir9zj/dRSDpj3XcVeXZXDeMiCjL+sDg\nR8V9br5/DVJ7LBBIasb+E3WheCnRuxiyL699GOhn4gT7xCZQWSsEW6GKuM8B\nS+r8+mQXs5RkiBwLny2y42il6wLpFhYK2WjFEvQctZSC9MuxjgKPxzfJWNnD\nZ04w+TgtGkHtFP5E2Hb4ijltp/1kb3rR+ixksyTLd+Q9lXgWZrwFu2uW+hzA\n3lVt7zEtbseqARmEGNdwf8qlFpyYkztMWRPnAz/45Hv2OVNGa7QGb0qT5gKg\ncAzaNIcNvRcBaW3cs9NOP8kNwPp+Khuo7nF8e0q3IjO0nQFIpjUbYSStpDAg\ne4ZGbrXFpNi8N4nl2veKTLPuItzGAoiilIN2qbGzIM6tfBBEL/2s0YN8tWts\nRJpl\r\n=yi9t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHW4TNlIHgAxfixsn50+gVCEHjeUB/Nto1uSLUCnW5m4AiEAk0pw5swYWroyyp3BechyqIIuLo5IgYzSme1qJQX3pWI="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.18_1618190581011_0.6433225026210989"},"_hasShrinkwrap":false},"0.1.19":{"name":"memento","version":"0.1.19","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.66","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"891ff0ca554cf1a6ce4f255a43f7ffeb6e8e07ec","_id":"memento@0.1.19","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-xnukkWk4sGhcHhwjA59Gl+U/QapDNX6q8RDYDdpf6bzNyOgs7dCNNoWAZQcu4q1uJJ2B/fcAcWNnf9xybvQwuQ==","shasum":"12bfc67869b5453c485e79633d93b524d6680866","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.19.tgz","fileCount":7,"unpackedSize":84852,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgm+UQCRA9TVsSAnZWagAAGSYP/12c+tNIL/b86Z/uTq1b\ngORGWMDjXQfl+JJo88DIrSHLp2arohUDwIzCFqsRvtI2gp4zvyFHO/iv5ENL\njotBMuAWOqvlfqknLi3KwHUm7/IoyCU1dWKU5lAVYzUFrebKo6vZAx5kyHwU\nYMOxhPsJ8E6bJg56MIM/72Ej/FCZmum51+2+ssXT+1IOl/cjNOM9oEwlLsio\n47ThxFf/PD9/7IGoV2kTEal6b/o76CnITmYzDkAkkbw9DgVUimXKXmjz5bHH\n8uepHaCurj+chgE6Iv9j9KaXMxuFM1mrcjqnK6s6UhraNGaOFpgEELRnZs6P\nwocbTUIhgM0pUBKPOBGelKej4wvKU+4E2P3IVoe/rGYqb91dg8GjrRhIqNCk\nORwvn5HHIIzWFag4QIJSZPwZ8hm1H9pWjvuqkBavGE8yn7GkYSrNZ0qE5Fld\nUM7wdUv9L7JR2qtGcrvtMRnh0F0UotB922/J5BD0zGIWfJ/p+7fjHouGHh7/\nPWQQiCa+2iQtjog1uFF7RLZ1h9P0KaisTPMUCj4m0V9xbkZzOX2sbR9m/xjm\npM7Os0GH9PxfQW+jhssCzNWWSbBPAHiUkFD+2ZhbyEfpdf1atKURIaXNoduX\n8liYj8Qn+FUu4A4RXqB18s8/kKq1xU55rKC4e65xnWiDqBu7kJS3SnbL+DvB\nzfXf\r\n=plHl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqGddg9R2yfkoq5DfYUiTa3eNQxgyQkw9xY4EJv55w/gIgZ0T9FoX07OWpcqWDW9PY9bnzdPfNw1i7OqRIQKYdx1E="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.19_1620829456182_0.0033594672583732166"},"_hasShrinkwrap":false},"0.1.20":{"name":"memento","version":"0.1.20","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.66","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"10016d71da77029184ead43a797373f1612a1221","_id":"memento@0.1.20","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-dPw55RWPUrS+UEgJBgwTVTkSAHw465IQVZ/ltJ0rlwPq/RAUTcIi4NXZ6fmUGYajCsiGU39xvBe6dag1RAMM7Q==","shasum":"0f111031a98f1081dcb2f57b3940a1cb51f0088c","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.20.tgz","fileCount":7,"unpackedSize":85592,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgpeiNCRA9TVsSAnZWagAA44kP/jmFxXRtIc93nlL3yZQb\n2WA6y8aLRKZ1TOp0kIUYiF1s0vKiPfmaG987eqAWy/fEJZIVYAKmIXUc7beR\nJ9lKHmRfk7a7ayKpstYmEJ+wnSbIyIfwiCdks9bXX9LRT3WGEjs4U+f59wcL\n+KrWhuP6Y2E98g80RyZKfAYfkRU+6SKofAhrF7X2fIf3y65tEU+j9Kt3urDZ\nW3d5gkVYKTYwbIUeQWurT+RGZcPJ9v0wP++nnC10cobZVR1Eyefzy0XTMNb+\nz9I7BPmG96H93qPNiwUd99BcTVRukpzGevfa+udtvG2t+atWR5u4ySm87w+e\nG9OCCGcAc7cHiit3sGJPaffWO66gYC9UPzK72Za4RHJeTIeYWeCZzzaYxSNB\nU035GKo0g2C1w/uJGruOsus9BF0yptzWaEkQDNFV1D4PC905PoNPC47bj//r\n0zq5eaQgnWzL49J1b0+O90J/y4IgT5Drlg9ID5dFglUQrA+0l9l5idijlP96\nkNdhr72v48qZDC1DFTF87hM4w3lvyTnXsrcDe4AOss86YDh7+D1XjfV5vfPm\nfY8YgvbDpuNljpZt4KHPyR3XIRd/GImuJ2IpSYcTcCnvCuktAyYw950pen3D\nCXgr6ug4opw3lzZHQeye8e1L3yQ83Xt6eMMJSegkPk4Qbk8DmsXSGEXVrXHZ\nnBR7\r\n=gqWd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChmYgcUJtPT3AknYHW1rYI6fOUUUOu0prY7bhY7HGQdQIgaM/Kl8lWXaOquwp0RiiiEf5ydfHkGuNAlI1O6fhd6aM="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.20_1621485708554_0.09402891368051747"},"_hasShrinkwrap":false},"0.1.21":{"name":"memento","version":"0.1.21","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.66","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"7cbf7a71b5dd97a963378a8fc1d0db10a0f40231","_id":"memento@0.1.21","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-mImEvArkwN07lvFnlYmTA32zd7oap7F91qS5CuyuU0++TcnbrzUTK2+5tzdKii7IAW1jXlpZOeCo4xycgwzccA==","shasum":"b9ff46b37dc91eb5880a64ccf6a6ea6915f6ec01","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.21.tgz","fileCount":7,"unpackedSize":85627,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrurICRA9TVsSAnZWagAA7RwP/RVmtujKg9KjNjqx0zR6\nJaZyBlXHtu40NFJE4RBSwfMfhXAhg8xZ5nBiSCa0B7Hu92zdJ4W4Ihv35fZt\nQQcSAmme6Ob9pzfyd30W8XPORetta72tuCpjctN/95I0tmF+RMCUw5P+p/Kn\niS+ojAsSjEKa5XeX0OVv5MTVLMf2EuaP9uw3Uhg8d1ROj9idzwkre1YD6btS\nym1pOvUXr1XM9z9vrJr12zZ5tJE4GZS+s1RWmFwHeUGmIH5jXSq/v9gqFAk2\nCn18szCANmQV053r+to1fSlKvVXH7BWnf6BITaFW2ZucN6LLTam5qzjUDGUS\nWIe4G5ypMbCmHcACz3y98CoHfEIURvMtLK6gk+dZAcFK5jvHfWxbZGP2m8IX\nJ+3pDKHtwmEtflKTRb7K6tH7OdAOcny9092BEfsFTwfU0slsuRgYGh7As1mT\nBa0z8Hua8YwVfeWW5enE0idhaphrkTmiq345KrRAn82BPLPoZLgDPjeX+XBB\n+FvKcOiwBlEwS43ZF2ynrgcxJj0x0PehDY/JjUo9exrAuDBGWtIXVgXOxx0y\nYVdPE1obv7OVcSDSbGX0R+rK4aPNV4a2XrXAG2+Hp3c2gZQgZp5ug8hBaLLM\nBoxdv3dGPRh2TvVvwLd2z5nGOK8k0ac+DhL4QpjNLia8RJPf/HTW8KwT80cY\nRBBY\r\n=GQNs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBfmEqxqkaTalniecG1Rbo/S+FZnkhhMDQk8IQ6gIXQPAiEAg8TzCjz3jStWB+dIy5s2PQvOw3KvHYWkYsvwbXraJW0="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.21_1622076104228_0.9504255010791411"},"_hasShrinkwrap":false},"0.1.22":{"name":"memento","version":"0.1.22","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.66","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"b7f7c5286ae65715729df980b10fcf742748ada7","_id":"memento@0.1.22","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-sq8/2l1UfuDz7nG3rcocfuY3RzZgropUssy5PPsF4qUxmA2+cLSMDtIu1IZHs6m+tn4C4ZBNEIzDG7bWzLQxug==","shasum":"5613881462e639e165a834d502c464e262808609","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.22.tgz","fileCount":7,"unpackedSize":85683,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgsFDbCRA9TVsSAnZWagAAOAoQAJrtU0Cfzb+t8Ag3LE7f\nn2K70++BQUS4Ny/hrnInZwCz9mLzb/IOck01Jiep1791lycwvmxTk0cAKoPb\n8odbB024HaVuRI0f7JaTgGdD5NZ5+lfzPmLBgZuVYSBDwsj/AA9Hh6CMPgAx\nXHnY69FcOWSpvqvwWbNdjyynHStOp4QIsb9/CWSOL5cBNWLUVDbEQjyxonH7\npZ3lCHRPsdKXeeNpJAETqGWGgV0FdXcE+0C1Om6F99voup1jqZgTTnFJaQqw\nVuHEQC9sJVi9i6mTr62LGW+yrpzKM1YjCQAeE42aN0jgvbtYzg7l7hAcNmOE\nrzbxgGTBN3Z4wRzb3BsexhM06KompDFehXonsfDRqj2lbW1XssaGVQU+0jVf\nrbgQlP9lSzmDLQUBYu6YdTkhqPBaQafkUIr9IYW+7T7Uk5iE+efhBR0wSb0/\nSKpMbhBWRk9ZYAeNk9V0Pg1ecurX2iF7isFsWqQ7IhKcz11FM+Gcw1l+5qwj\nCTmAiUXRGsl5U+G8xZl+dps/RIcbaFVoIfGq58yjAzkixG96rlVOtVls9hlF\nNFovc6f0/LBUNebLTlMEbAn8UQSZE78k8BVaAOeoj+23NpElMjfBn3bJa1Mx\nyH8K7KxEhsgclCdClOabrcgXPlL6EUO7RaoPjGHxu2NwabPMWEJdZcYagGLM\n3oJA\r\n=1p6T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDXVrKbrzZjMzN2npMiX4WXaOUVX0OKC7OJVwSU2YiEtwIgJLIGUbY8A2LtHEueVKCNX1pdUPBMm/qduiSG8ebGOrc="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.22_1622167770974_0.5729055422815879"},"_hasShrinkwrap":false},"0.1.23":{"name":"memento","version":"0.1.23","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.2","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"d402e0cfccf83f45d42713fa5f4ee19c774e65bd","_id":"memento@0.1.23","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-lHxbDRH8tKAQZIMuHqhJDuOWg1xRYPl6lV67vxRlONPoxNwjgkQQEYlvHJSMutu8p/qOXy1dB/Ep2pAbTA45mQ==","shasum":"043d5ac180ffbdbb5175420e932d25501b08a1fa","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.23.tgz","fileCount":7,"unpackedSize":85996,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtEPQCRA9TVsSAnZWagAA9dUP/3SoSgkBcPJZLIlX+gGu\nJcSQMN/d0GwepxoeU2QkWpfNSy1fQP5bb4dDpCWFQ8xlgdZWobQePsCnxBR4\npQcc4fxPWsbbgOa4JtB/FsoB9hrbZr3QnKrs+fPFlBmkvrlnRgZoXP4gz6vA\nECL3EJpRvNqZjJo1w9sPmEHYPTk0TJzI9+Ti3jE/TTSQqHiG3s7IwWdy88s+\nztNyAe+cK4fve2rOa57DK6jNdjSvxuY2VCScDSmWxC5oM69T1kQW0BXi9n9N\n/66KBFzXnJT3WDETyA5zUFv9dAIi6MmeBoqZCwLR30TzjVMSp4oz1hNenMG5\nlr29NqcT7Vvkt4xdBYzBmSOG+t7Kp86MuQxquyOqqylxQ9eBHCEBG8y9LSoN\nKf83NwOVU2Pxr9/HH14jeaywbDS/oDct1viLG6HUzD3fI5uvx82E0nVHzfky\nXvcfyxsBclT7K8tpxdWKXQ0P97GnDDwCtjLZ7onejhq9wWZ/1zVX9FOIBLyW\nJGtuSxr4C2Jv9Shk0iafViiawfyRAAJzarNETlyL1RWW+jpU7aoaZBxj98DR\ndAoHlxmbLtpHzy32S7YsFDT21BVy8s4s6WMC1XJLoVEpNPzJOZOuyR40OwOV\n+6ideZOcqGCj16ZHRaseDuKEoMNW3gm24mgTqNkYmlJLFmLy/qp9og0CX2Rh\n9Ee2\r\n=9Tim\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDz97ieMEW3LO44upM1o8ui35PXhaqQCdtF0iuDKAri2AIhAKzQbLiyTtPCP/u5PbVQXsCzr1ZRrb0jW2BL/x1cEk0z"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.23_1622426576253_0.04299737398527137"},"_hasShrinkwrap":false},"0.1.24":{"name":"memento","version":"0.1.24","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.3","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"a087226b8b41c6bde5d7c45cd22d886692a47986","_id":"memento@0.1.24","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-QNvVuvRzVB1g9xVcsvDu5onEmQ1LfWqdCXg+NK4XJrltxAbTZAqqhPljqBo7vABdMKM1NOGyOBfXdJfJl4aZ5Q==","shasum":"ffe28e499c0c3ee5aaa72e02b100856eefa6fbb1","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.24.tgz","fileCount":7,"unpackedSize":85996,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtgshCRA9TVsSAnZWagAA5RgQAJgc1UQ/JZAZXm7YiiW5\nDiCTY5yLnDRfLwnW/t0R6Z83CdBX5n5KcTYmp7IpiUm9dMWvL8XGyJVkV5Bx\nmUg/K2dRrQnuwgmQNLQfpFQc4S7rC3DF3Py7DJL+jhYyhIqQF9i/YlkekQfa\nDtSgDrQ3kzBHq8Zq/32oCGFFZF0egJIoC+oRVEgPMLKm1BGDmvrD4L8aR9lJ\nyMlpOeKhJvc8amfEAXonc/J1ZEwjJwrA4183REJtKJpj956Tp+rcKojkg3hu\n5AVe1v9AtYAs7j9U6mbYfND5+kr2MfbZXEvYnaJM60mVnuksF8yowBqez5bD\nP6NT9exmahT2GLeqzIcixiu4LP04b44/8erdaFeC79WQCmGhBNz6d5EP0Ik/\nKIrsS7ATLbp3X7fQlqhdmknRhQSdX9/P5OD6ku7BQ8+hKjMRCG69creo87Xu\nsSv5yBnSiXxADgrem05vTUXe9h52IDA9ZswNtIgoDfunNCYZSGCxpZZEF3XQ\nHckdZoc33YSweNYyqBNWJTaZGZ35deukCGKx0ixqWX5ELwkwTAf3gKa/UfMC\nSKAn6i/NnZOPziMaVjUDgck1UYk4gXnkD4KOH8dw3Cu5hTqH5yywLDy68Tqg\ndmS9g6dZMXGwYYpwIZaG4p/YpERGfEM/fVRnIP6RXENpAuskozPquyiISlyh\nux7P\r\n=Az0O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHBSBzQUDn83PRGPeMrzsgoxcJJ+d95OzA3eBkJexVWoAiEA1y5EH9+0lNXsFgGz4FLqwsPzL/wAHFAZKhiJQGDvIX0="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.24_1622543137159_0.35430030700583526"},"_hasShrinkwrap":false},"0.1.25":{"name":"memento","version":"0.1.25","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.3","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"bbe110fa0ed9f6353062ca768cec6620410ea12b","_id":"memento@0.1.25","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-uR+v6fOLzbU9nTFQfhF38akPK+POs0Z3dY9mJ4MDx8JU1pmOvwE65w3fghy1bKbEkvyuXGJ0OYuSX2i6VdmMJQ==","shasum":"2b989e1dfe67c2991f35d8012b1c6ca0627bbfe4","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.25.tgz","fileCount":7,"unpackedSize":87913,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgyudVCRA9TVsSAnZWagAAk44P/0dbv/dla4xIYT6jTcfT\nE7KJZPj0Md1KfFurZKqJbAC08mGG1QdXds36pcLMNu6dGPcgVpUQF+KP256Q\nWD9e0ePZzSPEJlEN/dgFQW0qyHrMj3EYFAxeDTHaYOgRPUrUBeGGckJ+IZdQ\n2Tim4XL28v0c1WT1D1H6eRmy1M4Oy22dU3hBNwS4EppFxt3eUF7i2RDoAthJ\n7CeXEEqY+r7EaLBbzAAwak+VCECDjWglUOa62IO1yiJmTd2tn9YVBfXJLe7k\nHVFvcl5gPzGNfizQdJrP7lzSOYV8KxorMGyX0ntTJDurS4xLQ1+PlpxmINZk\nF5FivRf4q5VPnPWR/stN1IT+0yWzvLoKtgtIS9qIoyOF2hVVCrSe1aitaQKy\nXp0K4ZEHMAZg6qsirxDuXDbR0ZpvT7JukrG1SMGKBCmPQN6HnU5VMX0xVhv4\ncy0Il87ncouJQFf9BBLHeP36FknzqSniUb1PZJ1ocf7ynUMQbCa13GvmS/T9\n62N739DGikXSTwvQfVaUi85IGJoOKt0f+llxyzndohdcGFFz/gikVxkAwrKf\nTVSEGe+9ppPMIvGWfxuQL7cg7EE8bnqcfTFtoypULkcaP9Egrg+0BRfh4oAz\noOA7+Tmcd7Em6J8cpPqtFu8oKEmiFJG1fCo7tT0ukIbqms84psqpeaNLdLVN\nQbsz\r\n=EyZF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfheSKBQF8rTJi2HUSx4ZeakqyAQL8EcmZe6CNruoHKQIgbItRoHtSQnbXg2qanelRPHshV4XKOab4UXjpqhy0ZLM="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.25_1623910229337_0.8769152611135451"},"_hasShrinkwrap":false},"0.1.26":{"name":"memento","version":"0.1.26","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.3","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"f5b6a1890f9bb5deae0793716284f240fdbe8511","_id":"memento@0.1.26","_nodeVersion":"12.16.2","_npmVersion":"6.14.4","dist":{"integrity":"sha512-w1LdudWelAK1Dqcyx4aZ9qN5c9WTPXPmODWILWfoB+oq2soMAf3w06TxERVOKbvf+eutz4C34h4z4Ei36FKziw==","shasum":"32412da6a7f935e2d462bb0661c9c6476b972785","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.26.tgz","fileCount":7,"unpackedSize":87791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgyvUICRA9TVsSAnZWagAA4TAP/ReRuxLB/rq/OY+yMisQ\nGg0AcDSLj4AAbRs3YI0HHiCP2dCSiMkesV48WrwmxDPQGpNu8HnVYtMt44h6\n5tgAo8B3Kp5PaxHAI/gdA07bIgoZEwBuhH58KhMCoT+4CRSkgELq5j6pRfEq\njut+/7yi31diHH64NoJpzcF2fxhedVuELfOVVsAg6gN/eWQ2/CKM0c5V7GE8\nR3/ea7aMSrbr7SKM7a8AoUok/MsLXTOmjMlu6DNT/tmoQ27S+ZC18L3yZbQ0\nbhOJhjYMLmtKY5i1YB9qotoRpzRNbLYEmp1+7ERkYi9+rk+Y75txoDGEYnFu\n64JzFCqK6329oMfiEocnGb8sf9413v9kjBVUn2o1/VsrEfO/TXI885frAB18\nSWvgpTUeRhIQmOlsqx6KQZkDycajfl3qBp9JK5wIJlr8SaFlNG9P16pX7dCo\nhefSj2VoOUHiwkm+UzrDXohcxj9gS/tgl23er7RigfuMvfosVgO6aO8M/oqx\nu/ygdSpnPtC43EBecMT05gCff2IoorgcRzNN4H55yDCMIw9hD/ZJPVg2iBha\n8vnr98c4MsaeutVFFuYlf0A82QjUWzmLVp8UkxHpdZwjH51yL3McGnsJKUEd\nBkfBFb4M5LOX1xERPebZmg8lfgcAG7aif0VAk2U6G88sj7NBw0F8kAYUtSO+\n/qWR\r\n=Mqj+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvG+aJuZ6jzNP21i8wr0/WJN/1r4RQbXZCr45tBgrn+QIgQ/S0Lx1AAq2IH1S4nK1W+EaOTAEQGd22Qp18sYkm3lc="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.26_1623913736271_0.007175401213085353"},"_hasShrinkwrap":false},"0.1.27":{"name":"memento","version":"0.1.27","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.3","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"8f268c5bed64066b735ec456b38867417b286fd3","_id":"memento@0.1.27","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-FaVAvao9b7mpUgFbkAhePm9QTM+PuLAmZdvSU+AfkYDaBjXO4Xd0IvQ1K4XIpqrkFSIKTOk0LwyKK/3fmUBAMA==","shasum":"43aba3abb89dc14e1af02fd8edd46d47c810a14d","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.27.tgz","fileCount":7,"unpackedSize":88120,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzXWQCRA9TVsSAnZWagAAPY4P/2kyceWj+KVdhST7jD14\nSQ1xq4rNO9SJhj2kC6KT0ffRnMh9ND+exwg19ZRmDzZN32u97/sKmI7YiUVW\nn94jA7KzfuC7MiQsV1uhRw1Iugjs23LjY7Sp5AxWmN7+1k6sIFTp8XhBEfvC\nKkuIcWPRK8iEULB+IZ6cxP96FhhkGKoFiMrcpj60hGOjXDTWaDEwmwT5fkPF\nYiACbp+lpZ5njWbEMRIgzP1j8zIKq8W7iDJjZHeY96OJUcEIKONlx+Qdzwuv\nyNHuqOd6cF1RaWCL839aSRE7ZW0daBWGK9y3mOATBDxWumm/IltYvbhuYaFT\nxc6iKX5pGDsogr5GQ08v30bzDW0w/6bDWUuL5u3BkLDeqfMrPH8A1fl+tpqZ\ncJddGR8gpafjgbYC7GYAu2/w+15SRTu7FY1T0hfxCCE3rSiff3Oww1tgLQ5N\nCILAzhUZ5GS8ybCm+xDJyppHxL6Ac5XcpphEypcXgEHxAhkHhJR3QFhllaXd\nZn4Ip2GwVTuhgyXFjFxq5sg4KPFLjT3wdL7xRFPdfXOaJ/sOtsD2oWHyII1x\nPkOyEPVOlfqs/dPHwWCrRP7RegsrdO+Ul0oELjPoQr3+m4IpjHtewBrWZEqJ\nKF+uLK2azPEAJcd9o6fNPhoiVzdA+R2IPocnwXj/wP2APA0sWPqz3Bzi9RwM\n6uib\r\n=nceY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYG+HGQ/IHLbGXA9jlSFHc6RalM0rFrS6bpYJyGA6qbwIhAOdF93nTOxsdJrmw/lk6nUAbkvFZvI27WsV1HEhwBHpl"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.27_1624077712114_0.9422737694288281"},"_hasShrinkwrap":false},"0.1.28":{"name":"memento","version":"0.1.28","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.3","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"dfe912d9cf29159fd2723c41816f6ca49ac5f869","_id":"memento@0.1.28","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-he4G9yYbt/Z0JkA8kw1DfZBrr00OasOe37zHHKtJ4VmNQL/I03sF/Tk5xa4KLnmV7o2hz8groTmd0RdewvZHbg==","shasum":"66e97198f81f0b4ab3815c234e7934a381f7c5d9","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.28.tgz","fileCount":7,"unpackedSize":87611,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzYIrCRA9TVsSAnZWagAAeqcP/AzNMjTuSpKfKUEW9mQ8\nlMwJ0hn4focF2HUu7TqqNS+vqr3xkwt/rfx5jS1tNdGch1Dgb4l6uWYafWkJ\nsgMmIpmU8od8FWiKMVQgCYcm3jQOxkLG4JRJfjzaUFo6PfvM81ZoB4DbcVU0\npycOZfrexoRqcLRainZsZ6L+gSH1+4bTAiE55Q/zUPjZ4+JIrLzcbl4rVwB+\nh8QQlhkuTIAhsbndwlrQ2MneP3qjhiHOJXCbQq1P/7Bl8ySaBaNVzLTUrWwb\nD+4jpxgGrhPBQ+BhvQ5BBY0v+nOyuRDjf60L7UhYpKEXGkS2H9n9z1CI6l0p\nRPbdWKyHjiIjznlVS6MknGQHjZugHwIfL72oIVDX0w0rbqo0rjKBhhMsKj6n\ngJhhAYodl2EYEtBWh2Hs/3GQDZzYJU0lGJQftGRELmty7m+mDZaxlJ+qRTc1\nW3cZHR9Z34+hJAjnxs+v7mBFdPnqQsC3luPuETZxWFe5SEE1zXQ+IHgAJlQ/\nTpIk3obHD+DMqJD0rHNYqhHpXQn/dmT0OSn38SAfDMNnJPmcKhnfAJ2q/G4h\nVReRgSA+9wh/cPiW4cfA2RkfpUPW0BfuztGxSg3W0/A/ouPgw7GHYJcCZT/O\n8bVG/culuE8h6cAg7j9KN/HttfWgpp1WlvIn//zMn35oU9aUTvSQh7eJAGpu\ntrMB\r\n=RzDk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyfmzFQCapbvVUyIIjPxiHboeMLqShIlcw2VrKa3udNQIhAN4ylFPQojuuTe/hLPv2z8G9B6kG0hzC4cGztkNRDN67"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.28_1624080938894_0.007248684806675065"},"_hasShrinkwrap":false},"0.1.29":{"name":"memento","version":"0.1.29","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.4","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"1b4e06d575dcb8b5f8df12c872ff40b07a253a48","_id":"memento@0.1.29","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-/IvvtwizMStpXwafg5hyyZ7e2zBrS1RyYzcI/THHZvRl5HZRRxPOJeRLhXou59YSujK1xVTOCR4GKzcchad0xg==","shasum":"838d12c8fc40852afb9eeecdae3ec43491bf57e1","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.29.tgz","fileCount":7,"unpackedSize":87611,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgz91BCRA9TVsSAnZWagAA3EwP/3k68/kV/3f4x0oWmfZh\nJPxq2Lblmv9Lk47MfbHbvODyN2/97si8RJVT04rNAqLRLDqTtcthDaSXIa9a\nKR95CUpRF0wi7jdp7FDewLge5bETFH6Dc9OmNAQupLUNpcurK1H0vo+jNg7Y\nYv/lYmEhfEW3kz8iWfDZT+phoJykFD0/rKfnPTYMtskF1HEOE10mK24ocHq/\nrWWmq9vTIVyd/Uh8xAdY+AV5kudp80SaqgHiN+i54i0n6HPNgTW4sYO6NugT\niYuAn2li609QFD3r61pPJCf2yotT/ihBdyW3YYdWFYqH7rozhTERfQRN8E97\nmlvDFjh49eyMzXRnuuEsXE1S+Wk0hvMsdZCwExt3kOADBYgJtSjZjJNbacpx\nYBqI65W4R0o+08v97kHjzV1+E4cUij6NuxGK0R4h7GqyU62dZM6qoVTRbrbv\n70ifv+EnsWyMA3gHOn/EHztlEsTevsFG+/5fqmbVWWUuR/orLviU1a0nErkQ\nDEL8LafK6xAVv8WBTqWvpf3NKEXex9Om0+b11QHzgA6YTlp98/80IaGwNLQe\n3UYg6xLh9XKECruWA5ShMbdFH/awVTBJhBQr2cySiJ22AWyMOys4C8gRjFO5\nWGiJlSt6K5/CpFvCbDCJEfoXWBGFItS33iGvrxKEAs+yBuyg6x/YED+X9+y0\nJuoO\r\n=vN+x\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB9sIsismhRNJ9dm7+6WcaptGM5ZosQHAU08OiSpe5vvAiEA7kWlSrDq75cZjHXYYlLRLPME1xZ9ZHOHj7SkIJDJdSc="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.29_1624235329195_0.3044284253943519"},"_hasShrinkwrap":false},"0.1.30":{"name":"memento","version":"0.1.30","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.4","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"190ade03c120c783af136029c91cfb32c98941a3","_id":"memento@0.1.30","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-Hi50qolJaE/hKbW+Y4Aet7R1sbzZIxKNZ+Rf/iof7eQjyghwJHElBHvJW6Am9Kq8n/bWkinnQCnK+1l7ZNpSkA==","shasum":"49af680a76ccf5655f0fdde7817fba08f43a33e3","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.30.tgz","fileCount":7,"unpackedSize":87633,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg0//TCRA9TVsSAnZWagAA1esP/01IsXJ2zC2qH4+/eVhK\ncBYB21iVOrYSlVseGQOnzsDXuFtjz8tfc6lbK7logr5NFt6r2aKZ9Jfuh7A9\n0SjqUlTSHRFM9gYDW1RU4MqgMNZX/7t0Y8jIy6rdaaifW+2YGT3Bj+9sl+It\nVa+lAJ+Oni1aNHGOYBjzQl/X9MHxWsb0jkytYX/DRZg3HKDWVhfpoRO8IBFf\nSa8svhxShLaCq0TCchtMqb0zaHY6edALT320db9rpyaCX8pTLeBxZhYp8OtH\nRLBfPQ5EdG1Txk9jmJokBjSfVEooC+ijRncUaNtdaE9Egn9tZoq+yg8aTmDK\n+IHCkMMC59/5nFR6cDZMsMYOgcYFm3rOIK8wNfffkFm2jFCF7hsenBLWmOZt\nSlecS0Qb7g2OfLksnQqzy1eTFrKm5ie1rXs3JmIxPDMp9Fq6BIBKnwipMdG0\nVTaflGH9pLhq6Pbdln0bM7OYkO7VKSxeQRJz0vGH1tEaxvLNiDj45D6e1f1I\nklh7NRia1YHC6tqm4+O6EiXJQuRmn2hBDHvfubHKn0u1koPE5PjkPgoeELuM\nAeFQaAypZR5XqiSVq0G6PhNSe0Vi8MaC0gZdCGV+EdXn40W5yfvpf932T+SC\nlrJSUilljMJaAMMwCH9fXD/TbJ93fRV91caE0amMlqq9J7rjAdPD5Xs81Hvl\ngnfO\r\n=K87R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBfS9kxjvP8f9LmYvfUfYE10HdoOCv9krDLcITl6OiIuAiEA5qhjS2fDOymcgw03YgXMf895/gHfZmfTazVU0qW6qUo="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.30_1624506322633_0.16165290687114497"},"_hasShrinkwrap":false},"0.1.31":{"name":"memento","version":"0.1.31","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.4","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"1e797ebae3f9c9521fa898ae52a0d91b4fea1d3f","_id":"memento@0.1.31","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-EM6bSUb7RYCnEyheS9ydAme+7o8ZEM9nkn9LwU05oCPHsZUOOUT/XKMp9/6xa97eHvBVlRRX37dJdghpVJgDAw==","shasum":"a44d8a18937cdc450a2824886394d8c833d02ee2","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.31.tgz","fileCount":7,"unpackedSize":88535,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg4bb5CRA9TVsSAnZWagAAJQ4P/2C7Xob7UmyihvJphK3s\nf7+m8Wl9SkC2ppMxnnJdXmLt39gl1BpUXY09nuDsg0vu4KpjdhEcdUKja7LS\n8meZdByaUfwQ0vkWi3bJSKedq2zXHR6ffh2QuLxLvyXa+plX+OslWZwD3oOs\nH0ERT5yTIjpr3ulQheDDBs49qpNufJ54VfavE6KsV8E3xF92doKZVCvrLJJ5\nwF4dr3nx2m8uUIoJX9XzJ16fRYmOB5KxrOILWftgf9aJw8JUGmbTPdrhnEZh\nwBbs2w17tatEXgY5uYlmf6HZ0nfV0lHW+uG+cIPXiEaqSgqq20InHQD/DilL\n20FmZ6fHhyw6+mKHl6KzxYboQogZct6OzspIWGtIB2YSwmwZarHM0n6lwnK2\nHKywUIiFLnZ5WMMSWrWxAsDVZ1RKt7410WvnSA/C+RXC0JoPtgfZzeT1NK31\n0SNheqxDY1A48teLGkuSE4pkdnJKszsWgRDogedB4+dNSHKGy5oJszCmMJ42\nCHUKmuvkZgjbDyOFBz44Y8hALTj+tGzAxOWbcnwqtUVeNAreDZqMEFdjbogK\ncx7fDblE+uqmhauYBrn4L/bfVwiLI0pCNtU2JXgcYribiThNrXW0YdaID26p\nltvAgRSBi9MGObVcEhwXD7Cjsuvm34RprX2NSAK0fmEDjWEx60UGVdo48QT+\nvHjX\r\n=MYRx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC9mL7XmWECcJWlrSfomKnse8DEJo5BvzOL4CGLGhyYtwIgVjg7ntWJWBJH1PnOKq2Z+yksjqOoX3MOcLA7rnnzUrA="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.31_1625405177019_0.2337827782425217"},"_hasShrinkwrap":false},"0.1.32":{"name":"memento","version":"0.1.32","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.67","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.108","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.4","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"e0bdc24ac1cc1ebd238284b8b1513919cff520d8","_id":"memento@0.1.32","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-7wReRClie36hgCB49lWmSMITsKjl3V1agfZquQNIUojBBAq7Lxa/MfQLh8JFRz5Im0XixzFs8L0qZx0IV2nI8Q==","shasum":"e305172ed56ae715fd2304b0bfdbc77861d1d37b","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.32.tgz","fileCount":7,"unpackedSize":89296,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg9Q0pCRA9TVsSAnZWagAATjUP/0HfIdw096g1CvjGjIxz\ndlPeIANdf7DV5PeeoDz6H3JQPnkLgJ1WNeyPF6DhYTFvB9afYoRHbDjWWdSf\nZN94nScb5Z7qlCu6Gu1UkpSEhwJJiJPngx9k4kbj8DEEv/O1Ymi5i9vstiPM\ntDwPi4NO8hqGfEJ2zWh/UAh2ACVEqEpNcauGW14wtEicyylTvrJb6Q+9Z2uk\nCmcXiU9bUONGJ5b19/JNMEu5zG7P0CU9rooYfG67Dr9rQCKlQQTeuFJ4/bvj\nRgEesRFmQrMGGLvDy7tLFDee0LiMrjBsh3u/XxFLTFau3nUVYwZykWL38KgJ\n3970Aqw08qvmWej2RxW8kOOGqZbyEVLbxVoXKzYmu/4b6qY5T/8l/IY3+WqT\nizqw1DhtGdZmc49i4QCMn6gdjmsRLPtPHTRQIlW/jEH+tJ2QIIxeAgXm3J5L\nbThg20fcbkBcfNGnnQVzq6Z2vSJmK8PaE0d93y3x72I7N7k6VealayAYIQHQ\ny73e84VHPln8/ZpZAN/nCdjbxyHxg/q3Xf2il46rlnvyf5FzrI+V/lVc95ee\n8VTIZV8NkHRLRw7qvE1LPK9CgD86qW6+4lMQrdW2/T4QxwHlwf8z52jvnrlg\nHYUXJmLFjnls9rkUtiyQdQ6U5d3EIJ5T3S6n+QyL9/TVkaH8uygBsuNyIXJM\n7xj+\r\n=oIad\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbgbId3WKEdKHPvLLxecHAAfcCFDRd94i8SWfqjQHMtQIgNMAdl6Pq8S/V+1j9DztQTW8mdVZyKrzdqQ9UIIUGRng="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.32_1626672424961_0.08973294061260506"},"_hasShrinkwrap":false},"0.1.33":{"name":"memento","version":"0.1.33","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.68","ascension":"^3.0.0-alpha.0","avenue":"0.6.13","b-tree":"2.0.0-alpha.109","constrain":"2.0.0-alpha.3","destructible":"7.0.0-alpha.65","interrupt":"11.0.0-alpha.20","journalist":"0.1.26","keyify":"^2.0.4","reciprocate":"0.0.7","rescue":"7.0.0-alpha.14","satiate":"0.0.3","verbatim":"0.1.4","whittle":"0.0.1"},"devDependencies":{"perhaps":"0.0.10","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n})\n```\n\n```javascript\nokay('always okay')\nokay(true, 'okay if true')\nokay(1, 1, 'okay if equal')\nokay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"002b3ca7a73215e9b8f4cb3cf82df8b540d89d76","_id":"memento@0.1.33","_nodeVersion":"15.3.0","_npmVersion":"7.0.14","dist":{"integrity":"sha512-Iso352BWibCcpIZjHKrQ9l2k9yhlekAtYMV3EllGog6bth5EswgWvX4edKZERhKX9ysXNoev9hAkB43752lfFA==","shasum":"c94667ece2b12f78b4b4953d0b439c945afd7300","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.33.tgz","fileCount":7,"unpackedSize":89296,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg9m0uCRA9TVsSAnZWagAAyVIP/2koO0Bj9mhOGQ56Ds75\nJvizQV7NDPnADY02LnTIGbMV9wzZ+EwXNRv6A4KpgxyhuvilX8sLIF8uQsQw\nyDBgVHYmEsFSo1CflA2kY3Flk88kxpLxJQQ11YgsX/pR+X/e89eBgD+OuWRP\nHxtxd8ICX3bFpHrruleMevh9H848h+/uISY3A6H9TytCWqPxeDnugklejwqn\nv4SD2hUIELOqJxYU7jhBZM9dE3RAPsgugD8/A8NL22BAJnDqgxBDxPBlho6u\nAtpI3ARJhaJtlVOKYW8fWMc6NzT3e29iJPHN3NjYwsxBHdWOByF2d66wuVrm\n5HcOSDXLE6eteYjVlf2cFICAeUH4F2wg8b34s1RMD8RVExWXa9ucttb5Ghx1\nMkZsi5sbM0/UpSpjPmO3RdexqngC4HLR+fj/ASmdxZi+kSlixCQ/AAtxWMOL\n5J7nSX4o+lEDt0nY46jFtCWlBwgDjv/x6IU4x3Zougq1SBOTcwo/IRvKtFUf\nx3O19hTgQTuzCF1+DFTycEMtXNs81mmDWkj8b0t67JN5J7duhQ7EurUnymeq\nDnw5VaApEJw/X1rFuvuvBgg4x/5IQsQl0QvH+c9BV/CNipwZJTEMgzwdZG3f\nLojuR89V8X7xS42RZtDYmbuBSCFZ670aUhPnlodQgEQ4bYLG/VbTkToehB0h\n2ES4\r\n=0xis\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGORnQbn9hs8oI1suzplIusAXuRTnj6Wt7Nliu2gxaB4AiEApmdK/6odg7oqxjfWqDtduVMdbPjAkefHtaHuSO+rM2s="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.33_1626762541978_0.5320763823274692"},"_hasShrinkwrap":false},"0.1.34":{"name":"memento","version":"0.1.34","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.69","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.5","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"5c28f6dcb5dc22bbf13fc69b4a6aa27265b2f92e","_id":"memento@0.1.34","_nodeVersion":"16.5.0","_npmVersion":"7.19.1","dist":{"integrity":"sha512-UEkXiW8q9WA+UFaSjZb68gnd08oios16UMfvFNaI4wB3bPYIE9ttrTsrH7Ey9haYjbCG83fYbbvw1X3KXmlAlg==","shasum":"7f42627e2048907fbf5b1988e9ae677409ee89ff","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.34.tgz","fileCount":7,"unpackedSize":89380,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg+mn7CRA9TVsSAnZWagAA55YP/2VGc7roKLQzwxdx6OBq\nj1NUgTKNHuzSsNyDop7hs37zZkaHVydA+h47wAXiTO2dMhfzz153gvnS50Yp\n067S/3WFKAfg16zmNerjQVdXZdbNe8xB3OFuy+/NwD8NwCtIm7uNmr/dd5WG\nC+BNwQ98t945bcdV2Rs2eXF8IZmo9ycu50HTG1lXV5C9yEnNOoejOTVEhwti\n5ysYnL44iq2q33TJ0nef/NRR51FabCTYOAZMlCTlS5h7GlxzCOVKwNGKHQJ8\nF6BmmhxhB4P/ZhmIhDa477dOz5Sgw9jiS4k1RJvF0DoixdFockMX+WQt87FM\nSg9nIqRhdhSO6n7Hu16ULD3NJCaeZ5DjjhICuNwyYHwnXs2er5MfzlJK6Mpy\nK2Ah902KEe6T1ar4dZT83w49oGafLky6FAlccQFSF11K++tKvkCG5/ra9+wx\ngvJ8aLV211WM+Z87RwZBfqqx17lodk3S7DGCBJxPo1Y0hnNnmjz7Au+x3hpz\nuinv6ZXZEvgLPXpBZSEQJxv2ph5ZamWrqKcDc+6igQNcb/ytH7exILICHjcV\nuVgd8jc2qUR4lMmLKfwJzDILi0evzSIaVpDLfUeFHuMF73RIZ0luEhZ7lKUA\nKjVNDaicLOAWOAUyogMqjkSaE7iUg9lGv1jn67yc2SsQArhv1+nBgBaA5khc\ntQOg\r\n=srHc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC5NYucUK6+ZEqBqjPgi0Q1vZ+iUwXwTy5GkQXrVIzRQAiAR1H6cw+z37pUFHIxCMs80E/s0xq89CzY14u4aPr0Zng=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.34_1627023867739_0.807720637422014"},"_hasShrinkwrap":false},"0.1.35":{"name":"memento","version":"0.1.35","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.69","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.5","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"9987477d29dbac167cbf9cd1e710eeea598d74fb","_id":"memento@0.1.35","_nodeVersion":"16.5.0","_npmVersion":"7.19.1","dist":{"integrity":"sha512-3JFVuU45ur57pEGq4+PRfRDo37OlcHr2K4p7BV75SSeNY6GO+bYxVj2pgGd3U5ntTbd2ubX5l730zB5PybE81g==","shasum":"9aac5578d6f83ae8b213253698e8a84a1932d0ce","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.35.tgz","fileCount":7,"unpackedSize":89409,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg+nXcCRA9TVsSAnZWagAARvMP/28NIS/G4Lc7EC5GwKJc\ntvtO2Cgr8BzGeHJS7qCc4LDLRRUxZBfXzsb2gnLJJGVRcRQ4gju3t0LKDRPs\n+4Nw3GiRf/FCKNxrPGgiZqeGxgLWkKiZfPChPs2FsNh6OSiiym8HPBeL3qq9\nc61CRgoeohccp6vOh3xFzZ5klybhK65V+DvbCnOoJd6Y/loTc4QCXRIZHLej\nw5jkBLeaK6dYYT8+tWNl3hvhglO0ztzJE6RqZ1B1PMBXNqgW9QYso+PlXqdB\nunsGwuqwNb2SRRxrWQW4vtv0dplG62yGvnitWdWmXeqGzDZObBJFPuawIVXC\nxsY9SG2CbbTGDhglpgQ3gunOYqs7DEJAAE7zoArsrLwU2iA14CdMKDlO3ugz\njlHR5QfsrUO5+w8Ano4BVJ7umhD5t+xXLhUIweYQlPNCVl77KpAdEl3rmkiX\no/0w+SKZahnX3JHBGySxt3emiBlPMkj1z+6Ztwi1QEnMl46qDnL6b6CNCnEe\nj3HKC5V1JQ9cQqM7TeBGbRYeWm3YBt0kPq4z9ouldVYs2zrwCRIJ8CcwN57W\npiPhND7+LWzyhQq12vsEd+a3cYG75o0G9Kg6Orrr3whhVw2F26BvgrbXKB7Z\nRjl6+cyliISneY67vzGOedBqci9Lw63APzGekK7xlJCiMpl3gjgqMFNCpL79\n4GgK\r\n=dtZs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFeXwk9tTJYEZGpT44MQxht+JIj12ad0h3T/St0RkTIJAiBY193/TVzjGXw6nRn4wVanK5+V98SHKVFrRoXoWaEMSg=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.35_1627026907863_0.2719741580483641"},"_hasShrinkwrap":false},"0.1.36":{"name":"memento","version":"0.1.36","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.70","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.5","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"a264b667a9cc41116cacc65a7898ed10ad5f878f","_id":"memento@0.1.36","_nodeVersion":"16.5.0","_npmVersion":"7.19.1","dist":{"integrity":"sha512-r8yWECniweofXdG4gqkiJgBUPFQ6WZzxPifYtgESwi/YIvjTZhH7uzVfIBXJbGQPF8ltY+FS0pDpJECjLle9NA==","shasum":"9b3b04e84fbda352a7884c026dfe13f346ab1ee2","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.36.tgz","fileCount":7,"unpackedSize":89424,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhAxFlCRA9TVsSAnZWagAApn0QAJZInsdUYKNP3+P9wfL0\nLQROdg9nEoexEQ0V+BbJ8Ib87C78OX+XYF1Ppo6Ube7eLvPOnEyKh0KxKzx5\n5b/SxOJ9yEl4KTNdFFm5uVgebHgyg1SJHrGHn+lNW9JDMsFIohn2mRqXWAUm\nrQkLSqs4w4h/o6kJTTESraV603/IetrUq9V/S/ynk2Io/F6dQaGa6bpMTbr/\neyXF9XKzM01T/BL7a30VWqQZrzeY3g3JDNK01ACouk4gFm5cWhlzRjrcqzCR\nggJQOVlmfQBt/IdzJH9KWnG7Rkqh8nDTpr0hhU2prhtyJlN7Ku/FjeFno9zO\nYBdgzRmI7qEmLDp4jxRglJLb5WJ03MM33F4O+UTudSw4mm5RYrSeqcqHn9Z0\nXD7ZKF47uNLk+VB9YTbdCQ6yKmfCoUtbqCSmmHcxGdY4vPEA1J2GDWnPACaA\nXcMFDELgu/KzvNexDH2z22QA8Z83nCqZtvjEZsUqo+X9Z+4pv9vUGLczcg3U\nOlhXU3wWg38K3WbV4fNOJWo/oJORmuSpUtn6M1lVybZPqTcxM/WCohSOWb9K\neweYQCxEqGtOVf+MyWHjtvIkv9rgSNZFBhhR72UAFLESrf3VvfKztG74qIML\n22/7149e3zyg4GxgqbULgy8fOuXtaKlQuoLVkLNmZ9AxjNaqflHqOLM/VrkY\n2asQ\r\n=ELHN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGxs0K6Ie9v7ApvlfEoGnikrms898kQRhv4Aenz/nmRUAiEAisavEogMNPdH8D3IV9ZeUF4vMQ1rWi3tb5mUQ64DByA="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.36_1627591012912_0.7073769867652286"},"_hasShrinkwrap":false},"0.1.37":{"name":"memento","version":"0.1.37","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.70","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.6","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"dc28cb46011164971035f35f0d38ae64f5629037","_id":"memento@0.1.37","_nodeVersion":"16.5.0","_npmVersion":"7.19.1","dist":{"integrity":"sha512-DtHGe8eUmvwByRv6vjF9oFUOZ8jWKSX/HLHNjEI33AkhiM+lxw7i3lm18e0H3xcUX5pN0WdFxr5Bf/jaDl6eAA==","shasum":"1648c9101834f5bb4c32f48942fafd8d6e4f8066","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.37.tgz","fileCount":7,"unpackedSize":89424,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBFxfCRA9TVsSAnZWagAA/zAP/3UTlbIQWz0Jrfv3fyVd\n+1fnoJ6cHKtvbHZltI2WIXVsHr0mhLwMWjQnhgnG2DHj90GVUkkJMicpDSOC\npjVLt5f/GCzVo51mXx5Mxx8MYlFNk2W/UnNzgBfT8ES3lTLlwHmuyzPOqw+m\nJQhq7ZLbPfL3rxwuxnI4lrPDgi+e2LezYG1KEl9+/SfIBkE/ZoINP3db4T6w\nU2E6FOfqwZXeHrhtVVAXVhcEwh3Nz8xsYVKf/wMIEb2wFCTkXG/551NcmoXe\nZHhEReWsD2dVON2Nv0vwqOryj3vLP0P/0duihX5TB3hDWncSzwTXG8hYkhu2\nWmfXVwdSQ8giakwSxqaVALAAFy/gmkoPQshxyT9tb6lQBGIcRrFpRVuHY6Le\nVyQxWKIH4bbRxYNfDyXVgi1uDjcKep57k+el9504I8HLKG7dAJlCNGKIFI9H\nFprrVkZ2jLnohw6RxsPiX7QDXmWZpc19KlazmoEWxaAGaGlWB1mOpjvwC5kH\na3DKYKfoxUZRFD92Pyz3vqOLi7Ak1Tpr14XCEcorerDPrxEAg8emvBXrEbY9\nDRBB06Y2dw58+dtrkRuwXfHvb+VBqzAEAqs8FXlvjKYIvX8RIaYnSGMUnibL\nvFtX3eT/ACGsReMXMR2LA6iDV+ILHXvSrI8lZhcIJ6PIETumS2hf+yde2epa\nYR2M\r\n=viVQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHzFudr5Wmo4vJJ9gBFWpN5OqjLA/pU2CLah5BhqvDaMAiBsKGUzKXjdD8zkzrPEa1x+cr26xXGGGgiYCaGjO7pNDg=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.37_1627675743465_0.6880712034057979"},"_hasShrinkwrap":false},"0.1.38":{"name":"memento","version":"0.1.38","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.70","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"5af9ca261b11182858d398d271e5a164dea0e536","_id":"memento@0.1.38","_nodeVersion":"16.5.0","_npmVersion":"7.19.1","dist":{"integrity":"sha512-CZIFuH7mxZLNlht1ObHrfibc8kGzJ4sI4wAndIsacCKGyaknKulI7052MD6bY3Th8s5SAHXiWGqQoYPPRcyThQ==","shasum":"012c9efcc236b9fb705ae7320c2ea6911bbef2d4","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.38.tgz","fileCount":7,"unpackedSize":89424,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBNHNCRA9TVsSAnZWagAA55MP/iCqIJv1M7GtOhKbOHhJ\n4vM0rCkwLLIDUIx+J1P2M4Jo63cSPBQjk42Q3/d7hSiP3qjmXuJKuEqqDfjb\nDIhK1RnHoZqZnvyGrim3O0ScPLpf3DSJdWzgZarwBzpoyzqHNBn19kXTWV+B\n/4/iB5sUFOywV2/Zpl4MTomfAASBUWr44gSH8ijkuTN48rxKg4OTRFeGsrRz\n2Ce/kXbmlzo2/RiuUUt1TbfUxq4PYSBA9KYDi98NHaxl7M9YoET087MzCyjY\nrS47hKYXlBXUssYuDV0cyM79ga5M1VzHV4k4APMb93DjDb9n9mirEZU/5hQt\ny2GrwOjebV0W5pPXWvDPYpZ19a+Wo83M6wIlYbq3GCEUcd8gbP66Hj40p/5f\nPVMxlAyHDVY7SS8ZNAZMgWW/95wNHHmiG7QuUmPk1/dPkBNJSoJNMC+9Sd33\nliZkVaXWgylz1R6HiytKcS1YvRUQHRp5Cc/2FnqLPXYI6kEwsd6Z0VxiDObr\n6I2L97ce0DZhAmYvVlqs0CCEsXnjkswU8iEh9NhUjYwxP8FQY+2c0/GOIzMi\ntzXXK4Wk5E9FaJ4P+HVtrkMhKg0hAGMVjBggUn3ysce4gh0qNPrbAiTumq8g\nT5vlIXEDpR0328Zqpw52rJZ6JyF2jYnijkKe/K6v0N6YF3Y1d0j4w5bGkMnd\nt8wb\r\n=L7OW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIChhyO+/RiQTzg/6kklYhMgUfpsSmkXMy84HxHiJzpnmAiEAzRR6yBfc5G11yWypH0uBmYxr0EBZA63LkdhW9exz/2Q="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.38_1627705805056_0.5665639483268408"},"_hasShrinkwrap":false},"0.1.39":{"name":"memento","version":"0.1.39","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.70","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.112","constrain":"2.0.0-alpha.4","destructible":"7.0.0-alpha.67","extant":"2.0.0-alpha.2","interrupt":"11.0.0-alpha.23","journalist":"0.1.28","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.16","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n","readmeFilename":"README.md","gitHead":"4f0eacc23c147c3e381c5fee95867f63882a8301","_id":"memento@0.1.39","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-CQNBdj/P0vuqK70VqjUIyJhkxCe86HxPmE2ACdP1iREeb+uJWYGrKZsUdhA5W96cee+7L656BE0kgDPwlz+kfw==","shasum":"7ae54821f96a7d3e210cc44bc65678e21f6866fd","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.39.tgz","fileCount":7,"unpackedSize":89412,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBRjCCRA9TVsSAnZWagAA7HIP/AmntDQQPLTa4VwUOtV6\nKZUoeJCZtoGublqOouqzZ9ynmjAttj/nHXA0pDZQI8vtQO2CK04xZPVU8L75\nlgE/G9f7c6g8BzXPXu3vv3cgOHEm7IMHPMmeqaDOrpeSZ+lmL6ZVw2yE8Ulo\nFYIACq8L/OfszDwFbHks7+4i0o5skjLQFpm/tNTuWVf4nZkj7ZPvHwVlK6ek\nc6WEZceHqVXYJIPAiigBLu0uRsiO0tmyNIyLED5FlsE8nvw8X1jTWMB6R64V\nUe1VFZtihh287Hx9NuxV8KEZHorFV2X05rAQOaaPds8XXdEcjw6Oayexowe1\nT1zXmN6Ux3HmHql8Mzx+7YhxJ79dWsM1+VKimyDtydOPQ7VaU9e61ugO5taA\nGyqLsEzdr7hYfWl6wXRWKuy5sSARWQyuMuiLKNPqJGMBUJrEg8cu6mTrWlAq\n4cUutwKfk2ROVv/Nb3Q4pFmaZw6eULKxGHdlCLN/M098Yu9QoMh9opCRGzUi\nnbUsz09gU6HYmkjjwaO0FBiONc5OzetHy+r4gB0kBOMElPe+ESAp94BAd8b7\nqljOTS5dBZWS7DSuntCpKIW92yvvA4wK3ABFcafXKfd62Oref+4DaRRBacy9\naWxlIOi5idEcE6G7KkwEiRDcvJRyzGd1Fq3n1S6NARrgmgy6p0lg3N0oAHBc\nygqN\r\n=bQLQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBuXNxkIzJg93l2nD0yBgkOXCbejpbrc5dXiMKI+av4DAiEA99NB47mEblZGLDGuB2o2Kmh6HJXRHjZkkUef8kDOa2Q="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.39_1627723969934_0.0374656596559253"},"_hasShrinkwrap":false},"0.1.40":{"name":"memento","version":"0.1.40","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.72","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.114","constrain":"2.0.0-alpha.5","destructible":"7.0.0-alpha.68","extant":"2.0.0-alpha.3","interrupt":"11.0.0-alpha.24","journalist":"0.1.29","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.17","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Insert and Delete\n\n### Stores and Indices\n\n### Cursors and Iteration\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optionsl instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"411f5f216a7503652c912f63ea8e1256ba59a44f","_id":"memento@0.1.40","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-I1sI7AVz9Uyc/3J3QrgOpIGq0s/bW3jfHdzzo//DIY15J0B9SvBlSrh5f1a3vbTrEODlIvk8gsEdkY3xVxeXCA==","shasum":"223c90cd1c879f8d61912ede86c414ee06e25d24","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.40.tgz","fileCount":7,"unpackedSize":90189,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhD6mgCRA9TVsSAnZWagAA9g4P/jOxY0w9pYQ9xmtQBQwJ\n+khGM7EM+vyGDjYlUB5xOZIIYsQEa6mw6lKSdSxNHdsFc5D178Kv/cvNVbSJ\n7L7o8JOeAXX5xYPw8KaAsaf4OYWmmugvW4BiKubnvW2pZhEr06Jm+khxTRUU\n8/FLfnYawtmHwk69xc5H27qbkV9FcKKLRPXhhx+KtUIPQoqIoo7f9l6TqRYJ\n1UQKHxtRumK0RqHJ2k84qV8Oyt9Z+fH4c0g+EpN8lRrcKAOKsXBkbaRNoE9o\nufIt1Nx/b8WWDI3n/wwO/DN6uOpFH5E2j5t4UUBgfLcWIL3xiDc6lAgNoI5p\n2nxK128bOjRfVTQ2ChQZd5D850gM2YRMZbknOuoA3M89rfFzegTWlaj/wdfq\noc+7tYLpYXRMyWhrbSfbf/Mv9NhL474RqlEHojaQ+Wc251MODKUD1TRIGcli\nmSzatZnRY9CP6JnnsBimtnNEhKzI0/ozwhz7oYsm/I0E+kiAIKnHE6JHCP5C\nUONbkNeym83lgo8zJBag+aiuqLlU9A2M+rxay8Urw7xfRs7JaSQY/PwMrSAV\nLR5eb+3ocT1UHvwZVDNAhOXh0UV1dq+ATveIbzrOEPkJdCIUQxDNeq/jpzEp\nhnysaJDy4NdRnyPxDvslA26g1qcEhQ5uoAw7IRTF+/H70C0wRHCP9PsE/R71\nt+zi\r\n=Heh1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrfftpQl+mGeL8SR3St2AAfKvczVgQjBURcl++FrW+egIgeCMgvDXNhfzziiPRDP0QMPlsZI+RmqlrVJqQmYc465A="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.40_1628416416134_0.9266790682936121"},"_hasShrinkwrap":false},"0.1.41":{"name":"memento","version":"0.1.41","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.72","ascension":"^3.0.0-alpha.0","avenue":"0.6.15","b-tree":"2.0.0-alpha.114","constrain":"2.0.0-alpha.5","destructible":"7.0.0-alpha.68","extant":"2.0.0-alpha.3","interrupt":"11.0.0-alpha.24","journalist":"0.1.29","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.17","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.11","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Insert and Delete\n\n### Stores and Indices\n\n### Cursors and Iteration\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"73dca610369bd4b7917322cb1b2c95c0a0f2a3a7","_id":"memento@0.1.41","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-eP511p9b2ou0uLPCXwCVvWEzREQoB4GeXMIxI/VlQC/tsEhUiEN5G3P6TouNlbZel3Mk0q9c+pX8GpyMBIfHtg==","shasum":"cc18135419bd1eede52a5360352d2860f175c0c1","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.41.tgz","fileCount":7,"unpackedSize":90189,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbsy4wvu/taBD4qS8RbsxXsutLZ2u5wKxaWM3ffJTTMgIhAJsN6te93gY+dd1L6KaI3YqG24cnuKdk4r6j90YZG/jJ"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.41_1632164624984_0.1300358545596607"},"_hasShrinkwrap":false},"0.1.42":{"name":"memento","version":"0.1.42","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.73","ascension":"^3.0.0-alpha.0","avenue":"0.6.16","b-tree":"2.0.0-alpha.115","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.70","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.18","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Insert and Delete\n\n### Stores and Indices\n\n### Cursors and Iteration\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"84fa29ab220a4d4a63476bfe18a87f41ea2dc174","_id":"memento@0.1.42","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-WZfgWxQI/fvDWBAarCPyh3IOd53FpeTmYa2S8eZXMltZ+qGj5oUQsk7K43HK7tu/MAmC3ZdZFToj80J+YIOm0Q==","shasum":"77363676cb131e61d34b1029c83b52d78537a856","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.42.tgz","fileCount":7,"unpackedSize":90189,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF60hKPlCBW8bAfsTgKnh4xxwI6m1UusFYpzjsjd9BIxAiAHTzpDfs3MKmUjyuV7FjGC17bifPXuhQMwuI4PouxO5g=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.42_1632165647213_0.15019290670997387"},"_hasShrinkwrap":false},"0.1.43":{"name":"memento","version":"0.1.43","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.74","ascension":"^3.0.0-alpha.7","avenue":"0.6.16","b-tree":"2.0.0-alpha.116","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.70","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.18","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.target) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n        break\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', {\n    firstName: 'John',\n    lastName: 'Adams',\n    terms: [ 1 ]\n})\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Insert and Delete\n\n### Stores and Indices\n\n### Cursors and Iteration\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"b3d7e5af481d35aaed6970f41336ee972bc6a441","_id":"memento@0.1.43","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-HRRUmzYNEUuWzLzAoT+q5aSnY0w8nIsJfB/EdqokAV0hdI9JvR633xxN2tVXLLfxZICBYn5vDaaUKGUfE+yyNA==","shasum":"c02d69c4602365592e08938a88a0ed1fe03aac51","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.43.tgz","fileCount":7,"unpackedSize":90203,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDFk/VQjirpYKEYd9QJayQOeK8nR3hMQxgvfTE5RUusIwIhAOHXQFZkR/koS4pPGcFDlQM6HqK1Has+/otYAThPH1YU"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.43_1633707992240_0.8144704647209506"},"_hasShrinkwrap":false},"0.1.44":{"name":"memento","version":"0.1.44","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.74","ascension":"^3.0.0-alpha.10","avenue":"0.6.16","b-tree":"2.0.0-alpha.117","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.8","rescue":"7.0.0-alpha.18","satiate":"0.0.4","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.index([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    /* TODO Broken! Uncomment to see and fix.\n    okay(gathered, [{\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }], 'cursor')\n    */\n})\n```\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"f6855829f9fd3f63986dcd46c6e3ceeb7902cda9","_id":"memento@0.1.44","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-upfzysR7fb/SaTrJqlBU23LB3zfieT5wtyhgcuNKiZBvqoirTiFyFYn/uPyRJY5z38TttqS63guVIDH+cr8FPw==","shasum":"95a48433fc7f0d207bc86f47d990eed81264ada2","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.44.tgz","fileCount":7,"unpackedSize":95766,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAexUh4Z9eWPQAyTIeNcDU3gq+1KeKbC1lawTqyL6LSKAiEArhlBFTM3SziFpHgRHKutIXZ7/1pkXhpGD8/+lOdnYoo="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.44_1634432841203_0.2027153645099662"},"_hasShrinkwrap":false},"0.1.45":{"name":"memento","version":"0.1.45","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.75","ascension":"^3.0.0-alpha.10","avenue":"0.6.17","b-tree":"2.0.0-alpha.120","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.3"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"gitHead":"cd78e5ff38bcd572aec370dd07a40654548b579d","readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.index([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    /* TODO Broken! Uncomment to see and fix.\n    okay(gathered, [{\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }], 'cursor')\n    */\n})\n```\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","_id":"memento@0.1.45","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-+koWwsntBvkPoxDSoy/Z3rVw9UUr58l0SN+gCQGZnvXEmXunYltLeKi7vmj2tRYw4BiDWaSxpGYPbofEp0+MWw==","shasum":"e2e4ff043946a074cc20b091e9a031b7b8d057a3","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.45.tgz","fileCount":7,"unpackedSize":95818,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsGXBAvkk4HwS59wUaPehhjzwu/cGIDx8gyAkFLLcK3gIhAI4VFEL8DnHyhsbi5OnGGrwONWjM4Jtb5CmBVCAZTt2R"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.45_1634483939512_0.8368238660099141"},"_hasShrinkwrap":false},"0.1.46":{"name":"memento","version":"0.1.46","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.78","ascension":"^3.0.0-alpha.11","avenue":"0.6.17","b-tree":"2.0.0-alpha.124","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.5"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.index([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"fff5df436d63f4da5c6a055141003faab358afca","_id":"memento@0.1.46","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-lTn0AxPgaVQpivVsQgLnd4mu7GNLqrLC2925m+cV8oy2sarzwhc1xTMrJ5VAUn7Umitt64qnF9WCvRcQyoIb+Q==","shasum":"9afe528e41e17e0d8abdc1396d2410006637bd1d","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.46.tgz","fileCount":7,"unpackedSize":96162,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDY7ty3O+e7HKLlKT1MeEi2Ykfk6mGaRZbCLRT0ZB/1cAiBW4UPiU0DF3hW12qlf2ImNTJBZVLkhmMD9Eap2NdOecw=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.46_1634548047881_0.9033270871970644"},"_hasShrinkwrap":false},"0.1.47":{"name":"memento","version":"0.1.47","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.78","ascension":"^3.0.0-alpha.11","avenue":"0.6.17","b-tree":"2.0.0-alpha.124","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.5"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.index([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"c79fac078901490fe1f33c1d321490a7029dbbe9","_id":"memento@0.1.47","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-KCKk8OmivsutEmELe7DjmI+7bRqopW2y33VV80QHC7wigSHNT7ylaBJs27o/LnY2DSvmT6bSIJHkenY8EQoQDA==","shasum":"90991111c4e7f6904f6f81c476bd9768ce017ea1","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.47.tgz","fileCount":7,"unpackedSize":96102,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA+XJOglhz8FM+iikQbn19uci2mWIoKCnFSW57KA9hWLAiEAjkX3YJeioYsy6H3I2HeArJqoPp0S0m1f8VHK/8v+QHU="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.47_1634686091776_0.8692538451267331"},"_hasShrinkwrap":false},"0.1.48":{"name":"memento","version":"0.1.48","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.81","ascension":"^3.0.0-alpha.12","avenue":"0.6.17","b-tree":"2.0.0-alpha.126","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.5"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.store('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.index([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\n### Snapshots versus Mutators\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"e633b74b3ab48e9e3a51076d59ea65b30c9f9848","_id":"memento@0.1.48","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-TV33iBoBmWjRSy93WIh1x9LlLPWQ1J4asj9O0WAHrlKrHpa/ULJ3LWMTLw4elItD8GEGXw0E1cJAx6xS4WanEA==","shasum":"8c26ffb81c7bd0753f303642c268c76ac4ed5d90","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.48.tgz","fileCount":7,"unpackedSize":96102,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCC0ELOYXz4Q8Ys3kSflMOFkB3XZAEw23KbqqyfvwwiEwIhAPK/Y5Ydz52Nb9Bcx9q/PSqGuLp2NFVM+RtECGD7uIE7"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.48_1636346221434_0.8230794406357107"},"_hasShrinkwrap":false},"0.1.49":{"name":"memento","version":"0.1.49","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.81","ascension":"^3.0.0-alpha.12","avenue":"0.6.17","b-tree":"2.0.0-alpha.126","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.5"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\nWe'll shutdown the database before moving onto isolation with snapshots and\nmutators.\n\n```javascript\nawait memento.close()\n```\n\n### Snapshots versus Mutators\n\nYou use mutators to change data. None of the changes made by the mutator are\nvisible to any of the other snapshots or mutators until the mutator returns.\n\nLet's reopen the database. In our program we'll have a single open stanza for a\ndatabase so we'll repeat the schema update block here.\n\n**TODO** Maybe have an `openVersion1` and `openVersion2` function example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\n```javascript\nconst resolves = {}\n\nconst promises = {\n    wrote: new Promise(resolve => resolves.wrote = resolve),\n    reading: new Promise(resolve => resolves.reading = resolve)\n}\n\nconst promise = memento.mutator(async mutator => {\n    await promises.reading\n    mutator.set('president', { firstName: 'Andrew', lastName: 'Jackson', state: 'SC' })\n    resolves.wrote()\n})\n\nawait memento.snapshot(async snapshot => {\n    resolves.reading()\n    await promises.wrote\n    okay(await snapshot.get('president', [ 'Jackson', 'Andrew' ]), null, 'isolated write not visible')\n})\n```\n\nWe'll close the database before moving onto inner and outer joins.\n\n```javascript\nawait memento.close()\n```\n\n### Inner and Outer Joins\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"385db787631b3548b1c5ffa35ee5b32dccbe8f2b","_id":"memento@0.1.49","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-68T+jIqKmYCImjvX02yKMbRx21tJ9QhAPk4eZO9TEbEuYw4tMtR+D718tjQ9rbCNf3YpPNIPOmku7vOKRzDMZQ==","shasum":"c87c21e5a83640e7ed9279e8c140b3eebf92164d","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.49.tgz","fileCount":7,"unpackedSize":97898,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwR8XCRA9TVsSAnZWagAAT3UP/R577yFvSr7HIJgx4QQs\n0eXLsnhyx7it9Nun7nYuLoZ4gDkyw9hMPfrml1t1/cOhoOgWRQbmdW5EaRdU\nfJ8n7VzJx8zE1qiqmFlAx3mSxe5ota25rgAeuqoPsFedaNyQZXEhW18b8I4h\n8lbp6FRacUBJ3U+mJiMErFlnAtewQ4ukZHnBoAd2Yi9duzea5Bq0tgjCkyHo\ndJk3/Uz1UlsQatS8Nf+iQSkbKC5K7Fve2J769diFVyJsqssy8iEWodcPD5sO\nu/BSWj0c0AopOAVIHz/RQEmF8j+/sbX2XzyKfFr3BT0dicAP893sRnZYaxDp\nrIZ9X95PQaR/Ry3TNdwdvKfHmbPSIAiiH9XorGwCOblAUA6bI8/IHRpfYH5Z\njYCpc9V7CRVl80BD9VmqP4gydQFwsx+ZIhjxo59QuXrerWLCzQF7d//5uV5N\ncgTtUWlEJHLL1nqgkU1jnPYZ5J3bYAaytAG4DGA9G2KVYHNL+s9vgFFO0t4f\nel9+rVkodQL9ifirnJB6q44EFiwFxZwRA3d54KHLUvGBVp1IBIB6DQK+M6+n\nz6Ez6/xVRQkYkjWxtmfRGn8gTOi+h8btB0I1ChVZ4bUDSGdxcTPGamBHzwvY\nO6ik0PeTimB3BIXSd3RQNv1swQ3MYziI++0Zg3OD5Cvb+V7vWmrw38J7DFSK\nnX1B\r\n=D84i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCDMVsnGcabflap+UwYzZ/NuTkrH9VAMIQdb4nYUqENrAIhALaQ45/435NtBjFzIEKElfUSjNaEGYFU5eLWCyLixuBz"}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.49_1640046359647_0.12141615335530398"},"_hasShrinkwrap":false},"0.1.50":{"name":"memento","version":"0.1.50","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.81","ascension":"^3.0.0-alpha.12","avenue":"0.6.17","b-tree":"2.0.0-alpha.127","constrain":"2.0.0-alpha.6","destructible":"7.0.0-alpha.71","extant":"2.0.0-alpha.4","interrupt":"11.0.0-alpha.25","journalist":"0.1.30","keyify":"^3.0.0","reciprocate":"0.0.9","rescue":"7.0.0-alpha.18","satiate":"0.0.5","verbatim":"0.1.8","whittle":"0.0.5"},"devDependencies":{"perhaps":"0.0.12","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\nWe'll shutdown the database before moving onto isolation with snapshots and\nmutators.\n\n```javascript\nawait memento.close()\n```\n\n### Snapshots versus Mutators\n\nYou use mutators to change data. None of the changes made by the mutator are\nvisible to any of the other snapshots or mutators until the mutator returns.\n\nLet's reopen the database. In our program we'll have a single open stanza for a\ndatabase so we'll repeat the schema update block here.\n\n**TODO** Maybe have an `openVersion1` and `openVersion2` function example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\n```javascript\nconst resolves = {}\n\nconst promises = {\n    wrote: new Promise(resolve => resolves.wrote = resolve),\n    reading: new Promise(resolve => resolves.reading = resolve)\n}\n\nconst promise = memento.mutator(async mutator => {\n    await promises.reading\n    mutator.set('president', { firstName: 'Andrew', lastName: 'Jackson', state: 'SC' })\n    resolves.wrote()\n})\n\nawait memento.snapshot(async snapshot => {\n    resolves.reading()\n    await promises.wrote\n    okay(await snapshot.get('president', [ 'Jackson', 'Andrew' ]), null, 'isolated write not visible')\n})\n```\n\nWe'll close the database before moving onto inner and outer joins.\n\n```javascript\nawait memento.close()\n```\n\n### Inner and Outer Joins\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    case 3:\n        await schema.create('state', { code: String })\n    }\n})\n```\n\nWe'll close the database before moving onto migrations.\n\n```javascript\nawait memento.close()\n```\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"af30f2d8adb342f8ae6138b02a97f3a7ef3b8760","_id":"memento@0.1.50","_nodeVersion":"16.4.2","_npmVersion":"7.18.1","dist":{"integrity":"sha512-HmrDk5Uym/wh/IUhMmA9/+7rNqO4Vd1Nv6n8rCqt4lZaShiFjW9JzzPrc3DrsAD/UuA77WXSSGhmIiIGyBhkzQ==","shasum":"ee10ca0ed2b71a1ba932453a92edd54a1a710914","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.50.tgz","fileCount":7,"unpackedSize":98450,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhzqUVCRA9TVsSAnZWagAAMkwP/1xMzSk1QI3POkv9CJ3t\nr2OmT5fx3xEFOrw0baNHamA87PstzbytuEk81KyXgYE93/qJGSW744wzV7MM\ncSoU5ezrYOLKiy5QnbAQV569T2VXnSSORqGSyfyYBgfspA285Uw/01x86TOz\nLKynY3gZj3tF5+1VWKhNssi/JMOaJD+C6pN7NsSAubJTpJlhNAS2NM/in/0p\neAYtuPDkbJoigKxkq2hLJ/+7QREWWdWOBfz3a2Wq33MkSq14hcP7faGuEHhZ\njwWW+6oHK1W7CAkVehPFktihKAa3QTWLxaFL84WnjS01Umi+KSnReZ7jP+be\nemIS9CGUsXZdbaX7WJoQUU8r99xNL1Udt8t9rwsdqyN6r1QNCzaYmueZWa8z\nSz0U4jK7CRca3y3+zde6qTlq3nymbJvcxoJXg3fpqasbi7Y4uUVB/CAI/BWt\nHj0w1tNWYJrxaluPN8mkPBKPk9WrTOyU5aciV+DrYR9Lne0yIHMaj77Sf8Pv\nEM9P1eR2/TP7qQr0f2DR4WgF4+e9b7l+FMqH2E5bLUTqJKASiD3TFrZjhLlM\nj5NoehWKd4WP+dxacN/mET14U0jTvoG2RJP74N2Uytf5eULJXo5GwXZ8zpdX\nM6zRUfwPIqkUYdB9c2UOkWPhYOhavLRITnCAN5UvkPVbcLaqHdNnm4sW4zT4\nn3Mv\r\n=2M6i\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGSnrUddOsATCRirS9pgENoE9loEBiigVHui8dmCscSfAiAenFJCfTSSYjrKU5TKGMB3RqSVjjBZlcrDH/0O9IKWZg=="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.50_1640932629080_0.15123086023119514"},"_hasShrinkwrap":false},"0.1.51":{"name":"memento","version":"0.1.51","description":"A Paxos backed replicated state machine key-value store.","keywords":["paxos","rsm","replicated","state","machine","etcd"],"author":{"name":"Alan Gutierrez","email":"alan@prettyrobots.com"},"homepage":"http://bigeasy.github.com/cadence","bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bigeasy/memento.git"},"dependencies":{"amalgamate":"0.1.82","ascension":"^3.0.0-alpha.12","avenue":"0.6.18","b-tree":"2.0.0-alpha.128","constrain":"2.0.0-alpha.7","destructible":"7.0.0-alpha.72","extant":"2.0.0-alpha.5","interrupt":"11.0.0-alpha.26","journalist":"0.1.31","keyify":"^3.0.0","reciprocate":"0.0.10","rescue":"7.0.0-alpha.19","satiate":"0.0.6","verbatim":"0.1.9","whittle":"0.0.6"},"devDependencies":{"perhaps":"0.0.13","proof":"^9.0.2"},"main":"memento","scripts":{"test":"proof test/*.t.js"},"readme":"[![Actions Status](https://github.com/bigeasy/memento/workflows/Node%20CI/badge.svg)](https://github.com/bigeasy/memento/actions)\n[![codecov](https://codecov.io/gh/bigeasy/memento/branch/master/graph/badge.svg)](https://codecov.io/gh/bigeasy/memento)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA pure-JavaScript `async`/`await` indexed, persistant database.\n\n| What          | Where                                         |\n| --- | --- |\n| Discussion    | https://github.com/bigeasy/memento/issues/1   |\n| Documentation | https://bigeasy.github.io/memento             |\n| Source        | https://github.com/bigeasy/memento            |\n| Issues        | https://github.com/bigeasy/memento/issues     |\n| CI            | https://travis-ci.org/bigeasy/memento         |\n| Coverage:     | https://codecov.io/gh/bigeasy/memento         |\n| License:      | MIT                                           |\n\nMemento installs from NPM.\n\n```text\nnpm install memento\n```\n\nMemento is a database that supports atomic, isolated transactions, written to a\nwrite-ahead log and synced for durability in the event of system crash, and\nmerged into b-trees for fast retrieval. It reads from an in memory page cache\nand evicts pages from the cache when they reach a user specified memory limit.\n\nMemento is written in pure JavaScript.\n\nMemento provides a contemporary `async`/`await` interface.\n\nThis `README.md` is also a unit test using the\n[Proof](https://github.com/bigeasy/proof) unit test framework. We'll use the\nProof `okay` function to assert out statements in the readme. A Proof unit test\ngenerally looks like this.\n\n```javascript\nrequire('proof')(4, async okay => {\n    okay('always okay')\n    okay(true, 'okay if true')\n    okay(1, 1, 'okay if equal')\n    okay({ value: 1 }, { value: 1 }, 'okay if deep strict equal')\n})\n```\n\nYou can run this unit test yourself to see the output from the various\ncode sections of the readme.\n\n```text\ngit clone git@github.com:bigeasy/memento.git\ncd memento\nnpm install --no-package-lock --no-save\nnode test/readme.t.js\n```\n\nThe `'memento'` module exports a single `Memento` object.\n\n```javascript\nconst Memento = require('memento')\n```\n\nWe create a database object with the static `async Memento.open` function. It\nreturns an open database ready for use.\n\nThe first argument to `async Memento.open()` is an options object.\n\nThe second argument is an `async` database upgrade function. You are only able\nto create new stores and indices in the update function. Once the database is\nopen you're not allowed to make any schema changes.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    }\n})\n```\n\nIn order to add or remove data from the database you invoke `memento.mutator()`\nwith an `async` mutation callback function. The mutation function will be called\nwith a `Mutator` object.\n\nThe mutator function represents an atomic transaction against the database.\nChanges made within the function are only visible within the function. They only\nbecome visible outside of the function when the function returns successfully.\n\nIf the function raises and exception, the changes are rolled back.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'George', lastName: 'Washington', state: 'VA' })\n    const got = await mutator.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'isolated view of inserted record')\n})\n```\n\nYou'll notice that the `mutator.set()` method is a synchronous function. This is\nbecause we want inserts and deletes to be fast. Rather than performing\nasynchronous file operations for each insert and delete, we cache the changes in\nmemory and write them out in batches.\n\nThe `mutator.get()` method on the other hand is an `async` function. We have to\ngo and check the database to see if the value is there and compare it with our\nwrite cache. Checking the database may require a read operation, or it may not,\ndepending on the database cache.\n\nSo, `mutator.set()` ought to be pretty quick, making batch inserts relatively\npainless. `async mutator.get()` not so quick because it has to go out through\nthe `Promise`s event loop.\n\nWe'll make up for this discrepancy when we look at ranged queries, iterators,\nand joins.\n\nNote that the `Snapshot` object is only valid during the invocation of the\nsnapshot callback function. If you attempt to save it and use later you will get\nundefined behavior. Currently, there are no assertions to keep you from doing\nthis, just don't do it.\n\n```javascript\nlet evilMutator\nawait memento.mutator(async mutator => {\n    evilMutator = mutator\n})\n// No!\nevilMutator.set('president', { firstName: 'John', lastName: 'Adams', state: 'VA' })\n```\n\nWhen we only want to read the database we use a `mutator.snapshot()` with an\n`async` snapshot callback function. The snapshot function will be called with a\n`Snapshot` object.\n\nUse the `Snapshot`, the snapshot function can perform read-only requests on the\ndatabase. The `Snapshot` will have a point in time view of the database. Any\nchanges made by mutators that commit after the snapshot callback function begins\nwill not be visible to the snapshot function.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get('president', [ 'Washington', 'George' ])\n    okay(got, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, 'snapshot view of inserted record')\n})\n```\n\nWhen you are done with Memento you close it.\n\n```javascript\nawait memento.close()\n```\n\n### Create, Retrieve, Update and Delete\n\nLet's create a database.\n\nInsert is done with `set`.\n\nWe're going to reopen the database. Usually you'll only have one spot in your\nprogram where you open your database and it will have a schema function that\nbuilds or migrates the database. In our example we are reopening an existing\ndatabase that has already been built to the schema function should not be\ncalled. In our test here, we're going to assert that it is not called with an\nexception.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory }, async schema => {\n    throw new Error('should not be called')\n})\n```\n\nWe use `set` to insert or update a record into the database. We use `get` to get\na single record out of the database.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'NY' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'isolated retrieve')\n})\n```\n\nOnce the mutator is complete other snapshots and mutators will see the written\nrecord.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'NY' }, 'snapshot retrieve')\n})\n```\n\nWe update records using `set` as well. Let's fix the home state of John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Jack', lastName: 'Adams', state: 'MA' })\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, { firstName: 'Jack', lastName: 'Adams', state: 'MA' }, 'retrieve')\n})\n```\n\nNote that we can't change the name of one of our presidents because we are using\nlast name and first name as the key. You would have to delete and insert.\n\nLet's delete \"Jack Adams\".\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.unset('president', [ 'Adams', 'Jack' ])\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nStill removed when we search in a subsequent snapshot.\n\n```javascript\nawait memento.snapshot(async mutator => {\n    const get = await mutator.get('president', [ 'Adams', 'Jack' ])\n    okay(get, null, 'deleted')\n})\n```\n\nLet's insert John Adams.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { lastName: 'Adams', firstName: 'John', state: 'MA' })\n})\n```\n\n```javascript\n```\n\nClose the database.\n\n```javascript\nawait memento.close()\n```\n\n### Stores and Indices\n\nIndex example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\nWe can use our index immediately after creating it.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const got = await snapshot.get([ 'president', 'state' ], [ 'MA' ])\n    okay(got, { firstName: 'John', lastName: 'Adams', state: 'MA' }, 'get by index')\n})\n```\n\nWhen you get by an index the index can match multiple records. The first one is\nreturned.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' })\n    const got = await mutator.get([ 'president', 'state' ], [ 'VA' ])\n    okay(got, { firstName: 'Thomas', lastName: 'Jefferson', state: 'VA' }, 'get first by index')\n})\n```\n\nTODO Make a point of closing here and opening in the next section.\n\n### Cursors and Iteration\n\nSo far we've only seen get which returns a single entry.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor('president')) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nLet's add some more presidents for the sake of the index search.\n\n```javascript\nawait memento.mutator(async mutator => {\n    mutator.set('president', { firstName: 'James', lastName: 'Monroe', state: 'VA' })\n    mutator.set('president', { firstName: 'John Quincy', lastName: 'Adams', state: 'MA' })\n})\n```\n\nIterating over an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'VA' ])) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }], 'cursor')\n})\n```\n\nReversing an index.\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const gathered = []\n    for await (const presidents of snapshot.cursor([ 'president', 'state' ], [ 'MA' ]).reverse()) {\n        for (const president of presidents) {\n            gathered.push(president)\n        }\n    }\n    okay(gathered, [{\n        firstName: 'John Quincy', lastName: 'Adams', state: 'MA'\n    }, {\n        firstName: 'John', lastName: 'Adams', state: 'MA'\n    }], 'cursor')\n})\n```\n\nWe'll shutdown the database before moving onto isolation with snapshots and\nmutators.\n\n```javascript\nawait memento.close()\n```\n\n### Snapshots versus Mutators\n\nYou use mutators to change data. None of the changes made by the mutator are\nvisible to any of the other snapshots or mutators until the mutator returns.\n\nLet's reopen the database. In our program we'll have a single open stanza for a\ndatabase so we'll repeat the schema update block here.\n\n**TODO** Maybe have an `openVersion1` and `openVersion2` function example.\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 2 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    }\n})\n```\n\n```javascript\nconst resolves = {}\n\nconst promises = {\n    wrote: new Promise(resolve => resolves.wrote = resolve),\n    reading: new Promise(resolve => resolves.reading = resolve)\n}\n\nconst promise = memento.mutator(async mutator => {\n    await promises.reading\n    mutator.set('president', { firstName: 'Andrew', lastName: 'Jackson', state: 'SC' })\n    resolves.wrote()\n})\n\nawait memento.snapshot(async snapshot => {\n    resolves.reading()\n    await promises.wrote\n    okay(await snapshot.get('president', [ 'Jackson', 'Andrew' ]), null, 'isolated write not visible')\n})\n```\n\nTODO Show that we can now do a snapshot and Andrew Jackson is present.\n\nWe'll close the database before moving onto inner and outer joins.\n\n```javascript\nawait memento.close()\n```\n\n### Inner and Outer Joins\n\n```javascript\nconst directory = path.resolve(__dirname, './tmp/readme')\nconst memento = await Memento.open({ directory, version: 3 }, async schema => {\n    switch (schema.version.current + 1) {\n    case 1:\n        await schema.create('president', { lastName: String, firstName: String })\n    case 2:\n        await schema.create([ 'president', 'state' ], { state: String })\n    case 3:\n        await schema.create('state', { code: String })\n        schema.set('state', { code: 'MA', name: 'Massachusettes' })\n        schema.set('state', { code: 'NY', name: 'New York' })\n        schema.set('state', { code: 'SC', name: 'South Carolina' })\n        schema.set('state', { code: 'VA', name: 'Virginia' })\n    }\n})\n```\n\n```javascript\nawait memento.snapshot(async snapshot => {\n    const join = snapshot.cursor('president', [ 'Jackson', 'Andrew' ]).join('state', $ => [ $[0].state ])\n    const gathered = []\n    for await (const items of join) {\n        for (const item of items) {\n            gathered.push(item)\n        }\n    }\n    okay(gathered, [[{\n        firstName: 'Andrew', lastName: 'Jackson', state: 'SC'\n    }, {\n        code: 'SC', name: 'South Carolina'\n    }], [{\n        firstName: 'Thomas', lastName: 'Jefferson', state: 'VA'\n    }, {\n        code: 'VA', name: 'Virginia'\n    }], [{\n        firstName: 'James', lastName: 'Monroe', state: 'VA'\n    }, {\n        code: 'VA', name: 'Virginia'\n    }], [{\n        firstName: 'George', lastName: 'Washington', state: 'VA'\n    }, {\n        code: 'VA', name: 'Virginia'\n    }]], 'inner join')\n})\n```\n\nWe'll close the database before moving onto migrations.\n\n```javascript\nawait memento.close()\n```\n\n### Migrations\n\n### API\n\n`memento = Memento.open(options, async upgrade => {})`\n\n * `options`\n     * `destructible` &mdash; Optional instance of Destructible for structured\n        concurrency management of the Memento instance.\n     * `turnstile` &mdash; Optional Turnstile to manage parallel writes to file\n        system.\n     * `directory` &mdash; Directory in which to store data files.\n     * `version` &mdash; Migration version.\n     * `comparisons` &mdash; Optional of one or more comparision functions to use\n        for collation.\n * `upgrade` &mdash;\n\n`memento.snapshot(async snapshot => {})`\n\n`memento.mutator(async mutator => {})`\n","readmeFilename":"README.md","gitHead":"372f173bd82774930d8f30d8f37ddbb52bcdb423","_id":"memento@0.1.51","_nodeVersion":"12.16.2","_npmVersion":"6.14.4","dist":{"integrity":"sha512-ukGsPn5qkpj7Lg1RlDKku3RXKDCb/cqxlYyPFbQ/ITwP6EfYtlhyv9LOvv04H9/5gORNtLqdlDrgZph4i0TSuw==","shasum":"fd32f9576ebcd5da4b91722fdd36451202e11731","tarball":"https://registry.npmjs.org/memento/-/memento-0.1.51.tgz","fileCount":7,"unpackedSize":99620,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiANA8CRA9TVsSAnZWagAAz90P/0SbNOSPowEDgtgJUGd8\nPNeEOJjiMkcHRrE8MDflMmyMOtS4F0coXKwbsvCmYN9VMrTgAa6hM0ig4aaX\nlUqShmQTb+wQ13GgqSFNpgZtH6UkggFw/pWGCb17wTtw1a1V7nxsV6Lr4SkW\nlN3ZiuOhtyznZX+ojU2u2YewzMyJzK5CYYnpAXQfWQZFXVDmg6xOf7vgR/3m\nI56w31V3nufc1hJKgta4OfDOggpEJbOGubFJ2p1o21ySyoaRNAeZxtQktCj3\n4DyLA7whm/Spn/zlYLL6RtaQ6Mugeh4siy1zwii0YDt5FPVb+lAMl6JijvRy\nda8ymkCMLHs1pT7O2dj26JrdnoaVnuEGJkVMQGFGQorNNAHXfX9YmOx6Ugy2\ngDTae9CEXbu7/2fu9lQPzilSHIc6A7V+61chFvJevZq+fXJ9rbsAQyxqRNFK\nGLaEZBmFjHMm7L3sa3rCtkVJib1o2w2mtzxfVkReGkg8JUgGsykTN6M98bYB\nigLM1dAJh/vNx8XncUdFzOKkBbctU5pfTXsntCt0e47TEYFySHjQ9t7NRag3\nUjFM//aavh6RGUIKaHic146LvtSRm+XgglRBr0sxqsTY164P7irkT2kVJCY2\nsIkDhiDkqAh4taA3jML7CujxXekIHMWcGcG2BRwVwykic0jfL51Z+U8710D4\ngKv4\r\n=pgmW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIALrc5nzvah9QvuLYzztWNE5SIRfBjV4LHip8H35w1RrAiEApXK0lMMX1w3J8uTVgbJm6VkGJ+Q8D24Xm0CCQ5rtq2Y="}]},"_npmUser":{"name":"bigeasy","email":"alan@prettyrobots.com"},"directories":{},"maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/memento_0.1.51_1644220476765_0.4359834099258759"},"_hasShrinkwrap":false}},"readme":"","maintainers":[{"name":"bigeasy","email":"alan@prettyrobots.com"}],"time":{"modified":"2022-06-19T17:43:44.854Z","created":"2012-03-16T06:03:40.971Z","0.0.1":"2012-03-16T06:03:41.464Z","0.0.2":"2016-07-18T12:02:45.237Z","0.0.3":"2017-02-22T17:59:32.474Z","0.0.4":"2017-04-06T16:40:30.878Z","0.0.5":"2017-04-06T17:30:14.152Z","0.0.6":"2017-04-07T07:50:35.956Z","0.0.7":"2017-04-07T07:51:03.480Z","0.0.8":"2017-04-24T13:08:30.284Z","0.1.0":"2020-09-30T03:58:02.446Z","0.1.1":"2021-01-23T02:45:56.214Z","0.1.2":"2021-01-23T22:18:45.244Z","0.1.3":"2021-02-28T21:09:18.092Z","0.1.4":"2021-03-02T12:03:45.386Z","0.1.5":"2021-03-02T23:07:02.374Z","0.1.6":"2021-03-03T02:32:19.274Z","0.1.7":"2021-03-03T02:39:44.344Z","0.1.8":"2021-03-03T04:03:46.583Z","0.1.9":"2021-03-03T17:58:12.769Z","0.1.10":"2021-03-08T04:19:06.893Z","0.1.11":"2021-03-15T00:52:20.769Z","0.1.12":"2021-03-15T01:28:55.670Z","0.1.13":"2021-03-16T05:14:38.927Z","0.1.14":"2021-03-23T05:34:12.960Z","0.1.15":"2021-03-27T16:19:26.973Z","0.1.16":"2021-03-27T16:19:52.259Z","0.1.17":"2021-04-09T04:13:35.079Z","0.1.18":"2021-04-12T01:23:01.149Z","0.1.19":"2021-05-12T14:24:16.570Z","0.1.20":"2021-05-20T04:41:48.731Z","0.1.21":"2021-05-27T00:41:44.415Z","0.1.22":"2021-05-28T02:09:31.118Z","0.1.23":"2021-05-31T02:02:56.490Z","0.1.24":"2021-06-01T10:25:37.284Z","0.1.25":"2021-06-17T06:10:29.499Z","0.1.26":"2021-06-17T07:08:56.389Z","0.1.27":"2021-06-19T04:41:52.258Z","0.1.28":"2021-06-19T05:35:39.025Z","0.1.29":"2021-06-21T00:28:49.342Z","0.1.30":"2021-06-24T03:45:22.761Z","0.1.31":"2021-07-04T13:26:17.184Z","0.1.32":"2021-07-19T05:27:05.201Z","0.1.33":"2021-07-20T06:29:02.165Z","0.1.34":"2021-07-23T07:04:27.877Z","0.1.35":"2021-07-23T07:55:08.034Z","0.1.36":"2021-07-29T20:36:53.114Z","0.1.37":"2021-07-30T20:09:03.628Z","0.1.38":"2021-07-31T04:30:05.179Z","0.1.39":"2021-07-31T09:32:50.054Z","0.1.40":"2021-08-08T09:53:36.276Z","0.1.41":"2021-09-20T19:03:45.112Z","0.1.42":"2021-09-20T19:20:47.459Z","0.1.43":"2021-10-08T15:46:32.395Z","0.1.44":"2021-10-17T01:07:21.364Z","0.1.45":"2021-10-17T15:18:59.689Z","0.1.46":"2021-10-18T09:07:28.067Z","0.1.47":"2021-10-19T23:28:11.897Z","0.1.48":"2021-11-08T04:37:01.646Z","0.1.49":"2021-12-21T00:25:59.865Z","0.1.50":"2021-12-31T06:37:09.216Z","0.1.51":"2022-02-07T07:54:36.902Z"},"author":{"name":"Alan Gutierrez"},"homepage":"http://bigeasy.github.com/cadence","keywords":["paxos","rsm","replicated","state","machine","etcd"],"repository":{"type":"git","url":"git+ssh://git@github.com/bigeasy/memento.git"},"bugs":{"url":"http://bigeasy.github.com/cadence/issues"},"license":"MIT","readmeFilename":""}