{"_id":"refinerdb","_rev":"28-6dabfbbc773640369e1f6ab2bc5162b2","name":"refinerdb","dist-tags":{"latest":"2.0.2","next":"2.0.0"},"versions":{"0.0.2-0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"0.0.2-0","main":"lib/index.js","directories":{"lib":"lib"},"scripts":{"test":"jest","test:watch":"jest --watch","test:ui":"majestic","prebuild":"npm run clean","build":"tsc --build tsconfig.lib.json","clean":"rimraf lib","prerelease":"npm run build","release":"np --no-cleanup"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"dexie":"^3.0.0-rc.1","lodash":"^4.17.15","xstate":"^4.7.6"},"devDependencies":{"@types/jest":"^24.9.0","@types/node":"^13.1.8","fake-indexeddb":"^3.0.0","jest":"^24.9.0","majestic":"^1.6.2","np":"^5.2.1","rimraf":"^3.0.0","ts-jest":"^24.3.0","typescript":"^3.7.5"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"0d561b67b2f00a5292a29133f80fe11097e5e49a","_id":"refinerdb@0.0.2-0","_nodeVersion":"8.17.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-oz+SBwHPONw6ckTtptBLPWVgdvGzLXpveio+FbLfe8cGFXgHVleJ4LOZzsiAt3kjcC3QrvxrMVJAJ8tq3ycCuQ==","shasum":"7ec3bc4c3e72e3453b1092d26f0ba989947f4bce","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-0.0.2-0.tgz","fileCount":33,"unpackedSize":75736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeIhqYCRA9TVsSAnZWagAAbF4P/jYclkjiNoBQ6ao6tTA5\nDWfzaHgLVfNbfqZDpKmVoY/RFctTvpN+dhqDzbjc1NfiiMtgVExn9OrTAXq8\nnlO2pAgeaLl3sJCLSZKzR/TP0r3c7UGj8DynSaxwjwvoJA/3+aL//sDnkwqT\nL77AzmnXWKS+NNxwy88rsVR84uJJO5PO35FXsuhWTITobU3X9rClvKGm4j9t\noEOiEZzWbfKXqHfn4vaw9cpTBi8h2MJME623ZplbM2eIq+SySpjJBCXhtyuP\nGCEHEPZViSNcd6cQEcPj/ogMnO/W20NUeBNSS/Cg0xmCSKgr1DyOHy+G7604\nVEgmrLRkBqphKbSy2tkN6zdy5p5h/D99CfOO1p1ar8W3Vu/WmURLIDspU2Rm\nfzmJNAlNVq8LzAOikc/VzPL5H+9cu7ATfJ4GFUt0hzNNm+3/tUUyw5Oaiqh5\ngmPHSsOeCJgwKIuVqSTFyukrP34DSz46jf9/P/B5ea6k8Uk+84OosGGn94jb\nqgk1f8lZwKsTPxyKVM7nnH83LQbx0EZ0LqyIrgcE9RjciLvSJWY2vI4rZRuk\nYkaTbV3KpVSxikAMPiRfNuxVBa52oJNP0UxxXZ9Bv0dRLBWVsNxegIrt/hAR\nHqNzdYU3yHXh1PSbYs7NDvTbLM8dNYIdmEeTqPUZufhG03mOlOCJkZB1aaQS\nI14h\r\n=qq48\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE+36dDBwmv2pLMMt1WvA4IGrbctUOFLEwtwD5jifXVbAiEA0iRnbbmNtmIPR5nY5Ia7dIbaDXQJKC/oPgO4M8anoPo="}]},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_0.0.2-0_1579293336108_0.28184620649935166"},"_hasShrinkwrap":false},"0.0.2-2":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"0.0.2-2","main":"lib/index.js","directories":{"lib":"lib"},"scripts":{"test":"jest","test:watch":"jest --watch","test:ui":"majestic","prebuild":"npm run clean","build":"tsc --build tsconfig.lib.json","clean":"rimraf lib","prerelease":"npm run build","release":"np --no-cleanup --no-publish && npm publish"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"dexie":"^3.0.0-rc.1","lodash":"^4.17.15","xstate":"^4.7.6"},"devDependencies":{"@types/jest":"^24.9.0","@types/node":"^13.1.8","fake-indexeddb":"^3.0.0","jest":"^24.9.0","majestic":"^1.6.2","np":"^5.2.1","rimraf":"^3.0.0","ts-jest":"^24.3.0","typescript":"^3.7.5"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"0c22daf4450babe615fc2699fa6d097feff4ffaf","_id":"refinerdb@0.0.2-2","_nodeVersion":"8.17.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-COVpRWUDuS2CUyrroRXfRHMY4pQVBDQ20/PUx8cjlhx7L2NFrQxLU3jLIsv8vIIvBrX9nZEQ3nCsi/I+AH2XnA==","shasum":"50000e9e19be3cf39cfdf1caf06641546767dcef","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-0.0.2-2.tgz","fileCount":33,"unpackedSize":75764,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeIhwFCRA9TVsSAnZWagAAY54QAKE3Qyk4muY+0xDWWiQk\nENwBMOrK0QvW0O7z54cU2W37Ig45kaLMGkyFcE6hBez04c1Pp8MfmHsZ8CT+\nfI0fxdlwbBLuqbRdPc+N2q24q7ZiLpQ6Ls18swuNzykbiOLCQznZOnvNWNmn\n3S3KRRRGI964KfF0JcfkzeKEwAdUstvqkrDR4Xe5BkR8iPJ3hQK5dTCQ+KqV\njhxo72WPw9g75Tti2lirse5kX7lMIS4QmXejy/SilMC/km93gSuB54DkODQP\nds1Lj3U+ZEE4RIzQPB9P48QrWjgsmvpL0tl5Vvpw1SVNWZlLuhQBKMarVnZq\nGA4IUoK7aLXzBbZODU72ju5wDKzd07HVZPSS6VaORSGkXC3MjADMBkLss71K\n1jnStBtc9IFK0f+2irjHltO4uVVVfVvyUg2FWiWu0C2ElhASoamiavgr6ohK\nt3pQfU97Sy8ZK0022C/44WyCFVjwOsuwncUzheYKIspQE5tG5HNJCu9ZYzMi\nhIhLMjY/ucEfhHOlHjNc9OxkgrKFbY50zvvP8a62FJH9Mi4zmxTnHo1voDMw\n14U21PCHyai5N6bfTxeFCLlvofL11eS15uGd7BuBurqcj04dmWa+Dly4Xqap\n7oppiL+v21eLCOFSAOgfRtj8aDZYHLQYuEv2rQ9WEXFQyJYuT4m5f5M7Kyvq\n2IEM\r\n=XFhz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhgrFbyun5T1nIGSgMHRXyYziYB/Lw+zpaKJCbt/BiFAIgUC++o7ORwCbATw+49uqPZPZYVtO6Oe0nVCzp7ADUqeM="}]},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_0.0.2-2_1579293700599_0.9926096265154529"},"_hasShrinkwrap":false},"0.1.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"0.1.0","main":"lib/index.js","directories":{"lib":"lib"},"scripts":{"test":"jest","test:watch":"jest --watch","test:ui":"majestic","prebuild":"npm run clean","build":"tsc --build tsconfig.lib.json","clean":"rimraf lib","prerelease":"npm run build","release":"np --no-cleanup --no-publish && npm publish"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"dexie":"^3.0.0-rc.1","lodash":"^4.17.15","xstate":"^4.7.6"},"devDependencies":{"@types/jest":"^24.9.0","@types/node":"^13.1.8","fake-indexeddb":"^3.0.0","jest":"^24.9.0","majestic":"^1.6.2","np":"^5.2.1","rimraf":"^3.0.0","ts-jest":"^24.3.0","typescript":"^3.7.5"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"5328198e611b708ba881ca21c747e7e2dee1d32d","_id":"refinerdb@0.1.0","_nodeVersion":"8.17.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-bA9CTHmpHoZR8+o1cP0CN6BA7HEuIWUuli42Kx3h/N+oZUi/k+JEwZ/L70aq7smj3ghq2ZYzlsDGU5jXs7nZjA==","shasum":"da579a9ff8bad425883ec2bd1ce2d0b995f49651","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-0.1.0.tgz","fileCount":45,"unpackedSize":15173046,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeI0RQCRA9TVsSAnZWagAApJMP/A5kLaqoooVRHdWee6OL\nUDkXUa2Z/eWnyH66HEF0bdr7qX8uNls76YAM/938K26ALUq0mSYrCIBA0JTW\npRbLU4faOc0ULsTdAIhVnMAn2chUSel5K+53sbA0sJZdXjx5f3OLSMUNFkMg\n9og5MToour9BYJCdVTPIDVCNxfjcNI8gkv6Pcr5Ni1Hc2fmakb5TTOmBEp5z\nmWC4aPBqloI+up1b6oeY2jat6HLat/xNLaZHNLR1p9do0F3nFsEoL9Zugqvs\nI3cs/ugG4riGwVd3lwnJCe72IdhlIRksDGBLbjblOp3fw5tqu+elJKDB6OuR\n5R2kMt5FhZQXMuKCGSBg8NUV3+vaxZItm0HMNoC+Jr/g0+SPaiNVZOngZu7k\nBdIKphGDKmE372VIArUKmEdMK3lGS4+5LAVjdgUpA1/sM13NPHOqyVZr2FbB\nDiEo8nvXIL7yIIuyenX8P1uBFWryqdRRQlnTUHJtXocDFaHsFLYVwRy/ceRJ\npdeD9yfkGmEF+MHKBTC6pThYXKeCS2j8EXJfIxTRmrMEtHQXs6E9gW4cxouu\nLzMnqUH0HlTCoIeQ+fLw+zitxTE4khmaO0dRijXWQmTE4ec/rySy9kA1o7cB\nGlR1XVEupJqQB3lR2kWVm2eo9zvjSNFUAvdoGA4lc65We9upAtkxnFKsePYH\nBE2H\r\n=ANU8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGtA9hCBKfuJ0UlhAgajUbjJ7G3vFhOlX10itMLfSEFeAiA8pkHHkPvO9QKlADmpq7HDNmurXki36aFY2xLGaT+Sgg=="}]},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_0.1.0_1579369551747_0.6278747166418805"},"_hasShrinkwrap":false},"0.2.1":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"0.2.1","main":"lib/index.js","scripts":{"test":"jest","test:watch":"jest --watch","test:ui":"majestic","build":"tsc --build tsconfig.lib.json","postbuild":"npm run build:worker","build:worker":"parcel build src/workers/refinerdb.worker.ts","clean":"rimraf lib","prerelease":"npm run build","release":"np --no-cleanup --no-publish && npm publish"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"dexie":"^3.0.0-rc.1","lodash":"^4.17.15","threads":"^1.0.0","xstate":"^4.7.6"},"devDependencies":{"@types/jest":"^24.9.0","@types/node":"^13.1.8","fake-indexeddb":"^3.0.0","jest":"^24.9.0","majestic":"^1.6.2","np":"^5.2.1","parcel-bundler":"^1.12.4","rimraf":"^3.0.0","ts-jest":"^24.3.0","typescript":"^3.7.5"},"license":"MIT","keywords":["indexeddb","refiners","search"],"licenseText":"MIT License\n\nCopyright (c) 2020 Andrew Petersen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"refinerdb@0.2.1","dist":{"shasum":"75df2edf3b091b5a65d9034233065dc62155e2b6","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-0.2.1.tgz","integrity":"sha512-rLDS6V5Np8SV3f2VoksNI8K8qZnJWjpPi19u7zb/5OVkiT3t2D3thOPKvoslyKVm1mK6x4504ExWazGeOiI1Gw==","fileCount":49,"unpackedSize":16335062,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeJ3hXCRA9TVsSAnZWagAAVioP/3FSf52RM5ZBpIyVfukT\n19h12uV63W/egd3grWsAGcWtT8Uw2qqN/8hfz1iYco2GxQJ6k+QAHgnHkDuF\nGkEcHygnROwFH0jM+TQiAaMnBLImWT4bQWA9Cb2zFaZL364pysZy3EuGZ9kr\ntiXoBT6XmShv4Mep6zAgTts52Qvxk/sCqinGcGINyrK3YGEqa1Ovl+OE8M3P\nx80Dmm6eb9FiazbzDN5UimuhfdElif3hrsxhMLTM4G1nwJlyy1u+tM+aXmkT\nFTU6JYwGtUy4L2OUhO34w8I1wM9r1kICcOk2bisnTwnfX4CJpSkNFbrVYbxD\nYxEvy2h8fCONZXBUJNoRPdY8t7I91BpMAZxAKf24+YBSNonWIRSgW3hIS6N8\n+sDOHGEdjB33GSnmfkfUTy3vc1DKZwux0S8PiDiEWorim2AO2rE2e8duGKSz\nCDgwHGBRbUbI11FMfDYHf05Va5JG5kxSs61eOvatPvG4PlScMSToF5zaz2dk\nmfFuzkcItwC2XN6gYg5ba2ENgtRZ+/t9RfwOS0pSFau5YxucXxwHPj7wiRO0\n87wR8l3QBfH7QtGxnH+MtknYYwifdPJx4sPYoFy6eSFN78PeajxtEYx8nuPs\ncPrF+6HMoqKMqi/GD3Scw4leRIprO5ubCDSMdRL9/aFz2Ga8BSmtuR6LExWq\n7A4p\r\n=mzIY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC8HYnjMO/3bZiWC2/MUN5TCwgCD4X8V1iWRlfTklDWYAiAYzr/U+xK4Y/l48YSyERbO4vOymCcOQjhfnnrZYyeX3g=="}]},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_0.2.1_1579645014946_0.4465951381343234"},"_hasShrinkwrap":false},"1.0.1-2":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.0.1-2","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","prebuild":"npm run clean","build":"npm run build:esm && npm run build:cjs && npm run build:worker","postbuild":"npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/workers/refinerdb.worker.ts --bundle --minify --sourcemap --outfile=lib/refinderdb.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --no-publish && npm publish"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","dexie":"^3.0.3","lodash":"^4.17.15","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"readmeFilename":"README.md","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","licenseText":"MIT License\n\nCopyright (c) 2020 Andrew Petersen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"refinerdb@1.0.1-2","dist":{"shasum":"c209cf5100b340b39b80f5d2477a23ef2709c23b","integrity":"sha512-Dj0WKknPig+JjiC2f5ozdmBo3ebM/+fqx/3Ho97LxQqfTiVZkr8lq/VDJX2+dmARPUyzZyAQk22ev6/xIehJsg==","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.0.1-2.tgz","fileCount":79,"unpackedSize":1128708,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEXtMw6Rzoi+zzt0HLxjleK14VR00hku7mW/LZE5G9CzAiAvyTKRMH83ExpvHTtbSM8kwvcFOEa6laSlk4ktwr5v9Q=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.0.1-2_1636045159742_0.2851989165562159"},"_hasShrinkwrap":false},"1.1.0-0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.0-0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","directories":{"lib":"lib","dist":"dist"},"scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","prebuild":"npm run clean","build":"npm run build:esm && npm run build:cjs && npm run build:worker","postbuild":"npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/workers/refinerdb.worker.ts --bundle --minify --sourcemap --outfile=lib/refinderdb.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","dexie":"^3.0.3","lodash":"^4.17.15","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"747e38f4f976c2c011970569a49670257048f986","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.0-0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-ocLrh5jQZQyu77YRPy+Xad6srx8a4g8dxqTYjzxIf7LnePsDZQUXvxeK3qVgiZhTPenp6UwCDc1STT62dBBOOg==","shasum":"bcf000f3659cacde0abe829bc4b061dc0d5543d2","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.0-0.tgz","fileCount":91,"unpackedSize":1177087,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDSQj36RTGKzYkzEghbp0jCQg1zueiy72uCM8CgBWA7DAiB/BbWD7dk87seXng2LQtAprjr6NykB/YQTCbq0C34EIQ=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.0-0_1636225417692_0.26986788727121347"},"_hasShrinkwrap":false},"1.1.1-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.1-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","prebuild":"npm run clean","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/workers/refinerdb.worker.ts --bundle --minify --sourcemap --outfile=lib/refinderdb.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","lodash":"^4.17.15","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"69079860a49383b6ca8066a60d6b69a79ec70e39","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.1-alpha.0","_nodeVersion":"16.9.0","_npmVersion":"lerna/4.0.0/node@v16.9.0+arm64 (darwin)","dist":{"integrity":"sha512-2GHWZh2Iw5Mwm2qDV3e36oFeC8I7tAkVGMpKFvBVKT3tLy+fAKmjOw5TmcNR+1HXEw6+IuYvP7MEJTlhJTu6+A==","shasum":"eec1e8b3eff79771fd3a2248da951e192c0980dd","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.1-alpha.0.tgz","fileCount":83,"unpackedSize":750622,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCy0f3uTixFXc6w+BRKZXj+KoF/GlfRihsvfk5TNvt+9wIhAOP/vq8PrmxbWN6WoVlKKSjYCyn7XeGWktYGMxb3BG9O"}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.1-alpha.0_1636234645499_0.8002938884753528"},"_hasShrinkwrap":false},"1.1.3-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.3-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","prebuild":"npm run clean","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/workers/refinerdb.worker.ts --bundle --minify --sourcemap --outfile=lib/refinderdb.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"0002f02bb2ff87efc51357e4f4a7ee2deceb029f","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.3-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-VvSZ797AM0hRzMlUar7Dz9k88Ax9+fYXxShueUZZcCh65aUSGZN9OgAbuXhXc7sY1ItvOUqe9VRLVpe0DLnOfg==","shasum":"b9aa10a787f86d58a58e05382169c14c266fc0f9","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.3-alpha.0.tgz","fileCount":83,"unpackedSize":586897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAIfYTErr426MAXZQM8KpBzG6ZowTr9t3jtl3Id7DcqQIhALs0umJmJ+RE3XCPaTa/nKYIp3dPuUwJsjN+wacCvVyN"}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.3-alpha.0_1636243662082_0.3223137128444671"},"_hasShrinkwrap":false},"1.1.4-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.4-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --minify --sourcemap --outfile=lib/refinderdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"75bffe2a40d987de7d819f2b3c099c5bb3b1d204","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.4-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-7LyaKFFsCNZhm273IXogPpLSByfL0eNSXZrw8kmyn9JTJmMO+TJ8w1oLLJcQtztDw12+ws3uTPuhRnAKzreyww==","shasum":"d82fe4f9f597c114a9e5d55e678d0016aa565dec","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.4-alpha.0.tgz","fileCount":87,"unpackedSize":294847,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID6HoV76ZdCF+helNX+ujqIaXVzJ2QNKVIpXs2DnW1YnAiAl6VwPvq8I24j+Qr5hdr/W7rAoBLi0fOqbPh0NbL2yGg=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.4-alpha.0_1636326250081_0.5654538557319391"},"_hasShrinkwrap":false},"1.1.5-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.5-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","xstate":"^4.26.0"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"72f582abbd6a85a717de03a630bac8688c8aa2f9","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.5-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-/qDzkDzjzdKI7e5LuYj8euNHmJNi/IHV7bXMc2jydx1PieHAYgOAuZ6u7MTdj62ldgEDQn2Ia6sBy+EJsPkI7A==","shasum":"1d8d27e827d9198359449e2fbcb646cb9b4f6edc","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.5-alpha.0.tgz","fileCount":86,"unpackedSize":246367,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAXhuRx5bSBxaJVwIvLyAOnOoKwng9z8rAvOEMSTDFLAAiAUHVbCgtmdVEg7009qjaIadKQSPc8x7f5eKAMxWzX47A=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.5-alpha.0_1636681308389_0.6991897210007196"},"_hasShrinkwrap":false},"1.1.6-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.6-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"199a76f7f949c1d9ac7b539e3927b793b14abbbf","readme":"# RefinerDB\n\nA browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start \n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\n// Setup DB\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String, hashFn: (item) => item.title },\n  { key: \"genre\", type: IndexType.String, hashFn: (item) => item.genres },\n  { key: \"released\", type: IndexType.Date, hashFn: (item) => item.released_date },\n  { key: \"score\", type: IndexType.Number, hashFn: (item) => item.vote_average },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 6.5 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\nTOOD: Show a quick example of using it\n\n## Setup\n\n### Create the Database\n\n```javascript\nimport RefinerDB from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n### Define your indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then setup two `IndexConfig` definitions, one for `title`, and one for `id`.\n\n```javascript\nimport RefinerDB, { IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", hashFn: (item) => item.title, type: IndexType.String },\n  { key: \"id\", hashFn: (item) => item.id, type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nexport enum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\nexport interface IndexConfig {\n  key: string;\n  type: IndexType;\n  hashFn: (item: any) => any;\n  // For things like dates with timestamps, or really long strings, do you really need to calculate refiner option?\n  skipRefinerOptions?: boolean;\n}\n```\n\n## Query Syntax\n\nTo query, you create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// You then pass your filter to the query method inside the QueryCriteria object\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nYou can pass multiple values to the to match on any they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n### String contains\n\nYou can query string indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Query a string Index by \"contains\". Put as asterisk at the end\n//   Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n//   Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min / Max\n\nYou can query number and date indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n","readmeFilename":"README.md","_id":"refinerdb@1.1.6-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-+xrcOuu+Y4Pjs8eavCVsX5QjJhen4ZKee9Rd80z0fVFncAXpKGzXHXtDZpY5kMsaYWHfbMZHt61yj1AjBMZ1wg==","shasum":"aa18d1e7b710abc3c1e2e03eb761f425f6cd852e","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.6-alpha.0.tgz","fileCount":86,"unpackedSize":248679,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICFlnDfrUeUURJNVkntQcQtJSi35TkNj26IIgkIYObmnAiEA1GLjsJmT3uhaQee+173gETWOjBX8LflZK825gsrxSsA="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.6-alpha.0_1636689342086_0.7947848029295126"},"_hasShrinkwrap":false},"1.1.7-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.7-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"91c8c03c73404a18c55525c3f17ae07b2c276a8e","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, itemCount, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create the Database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nTODO: Describe `refinderDB.setItems(items)`\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an `IndexConfig`.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"one\", id: 1 },\n  { title: \"two\", id: 2 },\n  { title: \"four\", id: 4 },\n  { title: \"three\", id: 3 },\n  { title: \"one\", id: 11 },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `id`.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"title\", type: IndexType.String },\n  { key: \"id\", type: IndexType.Number, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn this example the are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes the text \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n","readmeFilename":"README.md","_id":"refinerdb@1.1.7-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-749BTJKcS3v0wM2KLXVTIara2ZVYkl9FluZyqbC0x44DGZnKqNZ1Qrt1JekAjysSqp3VCaAVkBC37wjdxI87AQ==","shasum":"5d9b2cfd96d38966231b49fb3b36653789dcbe1a","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.7-alpha.0.tgz","fileCount":87,"unpackedSize":822372,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD56/XCGQ9HtlcQ5A3bFNu1siDKLXSQStpIbOCq/qtGIwIhAP4SgkIV1Q+WlipWS4lw9iQC2WUpJHvy7ionEjlvCoGV"}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.7-alpha.0_1636764307552_0.6815911709506566"},"_hasShrinkwrap":false},"1.1.8-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.8-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","generateTypes":"node tasks/generateTypes.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"753a00c6a2134ef7629515a1322f3c8a59797065","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.8-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-3GYvzUNxgdoqePkbNUrX9s37k3hNsqK2EqWCqoee/yoBuKlIsuPDUdsbkFYVRpqlm7V3muP4e0aToycayleR1w==","shasum":"f1414fb2ced4ff21994b87a3cf7994ec456036df","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.8-alpha.0.tgz","fileCount":88,"unpackedSize":1019507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhnzrvCRA9TVsSAnZWagAAdgcP/Rv0oZ+FSjlIuQrs65Dt\n+p0iSAtAcfXegJugnHVanowGvCdrt00fcXU0yLaLWYjzY3TEC3J5NKA+/Cv6\nmHxTJ1M0sD3nvQmtxWGrJLSxG7jZRuv3EOiRFjex7vk3eccZxuItph50OLow\nOW2LxJ20w7eRztLZPsxRdrVP1KVZgNqKO2bJP3R/rXOQx+g03hbS4UVf2mww\nGBiI/T2QaluwRpnOu5mpYX4kTTselRjYaqre1zP/EtTqaiRfouOZ2EPq5HYJ\nYx/FXHeu0/hjf2rEr7X80C4CsOs/AZVxKZ3PTQK3gUwvdl7px4wMqKnYx1U8\nzUp9LPnCv+1TKKtuGS9NWNCNll+n0FDoXZ0dVtcqk778weLIUTSlHAy4ZOaz\n3ceq4RM9Kk7oLQkPU15X52vAW6RFj0mDkngZK48NoHLuA6Kn5o5HpslLhr5s\nJhjwTg5+is6mv2xUOdWxvtYfU228hWKiT8A8t5ujWCHZAg2jElCYFMNcLtyF\nxqU95WrGTPrh5KrV6WL6fQ1CaWPQW90WOpqaeXtWcsZVamuJHywLTm2KASkp\nXdnFO2HcoMyUmX6Exl31Q5Crlv8q8ZtJT+1SlULkXydURuhZj/V1xP7AMj3d\nza8dky+sH2rmUxmm04Ty+xclLnlEArVNDOm2zSdezjrv0DWW3E8tFmRHkFaC\ndDdV\r\n=w69/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD4i4gxJDM2SpYfnD9HOzaaxbSfkHnuEekN10F7pjQ7WgIgNdyciEQ/Ua9ys+zmKHQru0t9MNkp/+mD8Cmay2bpGzs="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.8-alpha.0_1637825262820_0.28744655915132755"},"_hasShrinkwrap":false},"1.1.9-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.9-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","generateTypes":"node tasks/generateTypes.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"9c1963a37e7bf4a0ae8b20c78ae1dbd71bc75309","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.9-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-wq37lRMueTgXFROwtIyESx3RYP09YZGUaHUPU7Sg2LQInC1NAoczyZRNQtbjuWkqy2bj3o9tauxm50FNPJnldg==","shasum":"c96b94e73779c564c693680606af682f34353df4","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.9-alpha.0.tgz","fileCount":92,"unpackedSize":1024691,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJho73FCRA9TVsSAnZWagAAJxkP/jYv8db9nJoIgZWPT+dB\nt9TJ6Un+1NBGtCVcqQ83+Vqfr/12jfIfDLizEA6U3Pme2kO4GNZR2EL+LOUE\n/1b7h27GcAKhbjVgZvPmr0FdX3CKoxKEUmOtdZJvpOS5APP7eawyN36tQMe7\nGqjsI8NPOpjpItfGMlfDq/qzFFQ5nOZr+olM8s6iRrDpYbneBJ1J46FgIhS0\nZJ+c0+bfExDXz+NMVC7vxh0Z546JpBNCHSpD3B60yfYqjXgvDhgMLs1UqBJ2\nC0XhIbIH+ciX31bKhwOqixFP/pYYEGJTJ/cHIh5i2sp2Bed8ilEFO7OtBXC6\nuKA+bUVOVhtx5zPoBoWNfsiZl89vOBbP1FC3OPrcGrKTqeKlI5MB+Wv1GKk1\nIGkjyqID1l6JE4I6ELLCfqlDU8sUDrmmFDGzW1pBiKfjP8+QwjeI56i3iIph\nyQwH2wQTKXKAIygOOryzruqsgV4SV3SDwDg0rUXC284cQAKsyVdFaSMWkxZ7\ndefNmZ/3bdvybWn9lOT8BbC34uSHMaEoYWn5EMJRB8hzsbvZuajVXMMXzGns\nFb5dMA2ivW+oHU1MfcLeBheTI8TnOLNauuJvfStf8MGUAf4wSyfEWSAp6nXn\nIX7en0yLS5SQ14zrbgV0DknNwpCVSvbrDh4WYzY+vJUT92r6/Z8anAbRGO8E\nBgKu\r\n=aqB8\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBQz7m8roXda5aKyEHZ1x5JEG/gNWClpOD962y7LP/GhAiEAzVEzJDfXBVtWx4GMHzL01bgyYXMwnR1HOZietk+VuYY="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.9-alpha.0_1638120901449_0.19500453295778652"},"_hasShrinkwrap":false},"1.1.10-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.10-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"209911c0500c103d3a9ab95152c1632a42464790","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.10-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-mD10iQZSu7AexYRNannTXg31oXqid1kimYdxJ9ZyjREnpuY8FPq3v4xtdlzIKCJ9UCnkJVW1ECt9RD25yOkX+g==","shasum":"12299fa7492ed048a91294b544c1ac318d51d45f","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.10-alpha.0.tgz","fileCount":91,"unpackedSize":840496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhslWHCRA9TVsSAnZWagAA360QAIzPJsF0jKsQOQkhwtcK\nc++7rXIenwN10Jh7SAI5D4N8blYUT3/XxPqqcK7zGSa9uKB6drAvpUznMX8P\nZbVAUqcJQh+Nmgl4py15a3e4tA1dqVS9nsUlWLtgNXg73zMO8889CjVbXPGK\nrBUlBkskPXq6o2PK6B8IEeSsM9ExJMjJEJuUbuK1zQfx9jyb/O5bAn7OjZV9\nYXnu/jhWOCp+XDVPAVU5uaaFCfd7qf/sTP0cqqNGLTw0qAJfl2TF7lvu+UJO\nsm810lZJpuiprFFCnw0e60X1l28OUmT39+TxgSrBs1lPGVayHUItCz4ir9/m\n1YKNfg4c6Pu0u/LEf+QiEOib04Bn2zBhmNfZRSt+y0x+LM3walaGRBUrGdrN\n4AszRl0/bN5DRM6ASpBYMxRVLPC5FeCxBilAQ9WuIZ7ecnTHgKDpNe19OkTY\nCj2cJJiq0cVjCfgycicP/AJTBoTaPSPt6JPexwHij8OFZ0aq0ISKwCb019g8\nyzollztOW6a926o+wsxim59Cx8e8z02tWCV9eHLhqtEyi4aoW5W/tKNuf/+J\nnu+KxCRx/2VyFV/z1GpwexMV5+C/9ANlQd3LkeX7FxH0cqZPbOiTtO3wMyxx\nU9jtPLx2mpz8gNx3mXoaeGJ7BD5c7MJT3OqebQI35K3bhFmK4+IB78X6yMsN\noaEa\r\n=9yNN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDQfsVhlIAMfdnlXNfZmo0x04CWhFurKEr6Rr97kyAZBAiA1c081WQP4tXWj1WKvtQB0grxE7rRWiNyvbPgOAPwiMw=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.10-alpha.0_1639077255536_0.5124972999578583"},"_hasShrinkwrap":false},"1.1.13-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.13-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"48aaad22510e3e64bcfbbc4190e983aa3e2865f9","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.13-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-ji1pSfb2SPlMVoqGmkIwD6OAMR0yCDu/PZsqEqkQlAc5rArXhhp/sshsyCU1ye1cT55zR0lPh2CbXNzxnVxmHg==","shasum":"991194096ae3e4cf8653f4aba3301e69af9a73d4","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.13-alpha.0.tgz","fileCount":91,"unpackedSize":840814,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJht71uCRA9TVsSAnZWagAAHcYP+QBqh8QRQ/30GV8d1QN1\nbhGXP2Tcpd57RtnEMzheXHPEXfWk5TpnOeK/lGMlPWpr3gHeuJlWCeakIQ32\n+bxco5xovoH9yqKWbaGKI3Csz8/d4MmDbMFi8WcOF3usTpFBN2HhhlBXZ/A5\nug/rXtdHosZ0kZ1cNdB3vRof21837jb323Zr0A9w/z3Ar0y8h/Gi358cIdPG\nD2tBgsMAZDds7UzmIZUmMwu1FeL8WEXe+7jiK+fpI5b+RQlbX/bIlCk/1uKN\nblHTc1l1MLE54u7DPAtM4/76QkvLspLWoCFPCE+cmU9gm/NztJlyOzFE9sdY\nFc31f9FLOOjeeZa/5BboSbfcQcxskr6Jk3sAoMa3tnhJXy/51KkjGyMnpIjo\nBvW97eQ3Ppt/u41iItxppZHyr1Ug6vUDrVBXhB+N4lDS3uAaMH8/V03dCRjS\nyihqO58ec3wH1DI+3/w9Iu7a+LIGFGs4wBI+nQbKDbJq9hwQ/xtKqO+BInnD\nXKmeQYHYNih2zbDnNl2iLS9aKVu9XTC9PUdRadWhNwyfmQ0LJ7SWKqb5aQ4z\nIsUSHrvTkl8qUdU+GYmgSoiHu9o3kXXpz6qRlF8MuO3TuaH9oxv2WiLK/jFJ\nSb3hRMkMN/dzijjm5jnNQffc0oo+qNi5A9h/5JhJl9J8SMHPByRtFYg8qwwt\na0MH\r\n=ZHrt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBn8Qq3XeyW6Py+G/Tdf6vTQCw/5Vp6HcZn1T6z/MijdAiEA96WoT2GTQgOFp4U58pB2XbFLabXtOX0mSWaT6sIy76U="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.13-alpha.0_1639431534178_0.44020234702966254"},"_hasShrinkwrap":false},"1.1.14-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.14-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"f94aca66122cc3967db50b3d94ab04c51a6f7efd","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.14-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-J/2iacxnH67QkovetlcS3PAlgCMX0gzES1paKc8binIlWGqjHM5/TZ11zJpa2mOk4UcNFvQGImSeoVKDB34ZwQ==","shasum":"59df6e5eb1fb6093a9cea1b32c4950d012063bb4","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.14-alpha.0.tgz","fileCount":91,"unpackedSize":841305,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJht9SVCRA9TVsSAnZWagAAbQAP/ia92OojCK9qp9lSZYzU\n11Lf6JyqZri/uFIaNxrDimodtWhRFwc/IoI5LMvlGvD5jjH+uKEry6SUCJ5+\n9zmjp3ajUwgcOwfnDqxU5BW6vsWojzeak0ktdRVqsst29Vl8qkyp1EFZe+jZ\ntE5J5DbZdYFr3mcCreAl2BYItC93/xhadvriharLCrQeU5r2T8yzH9o8THaq\n0SUiAJEIT8OH/G+B9baRfPB5u9OCEz+q8Qvrn1cJFWiSOa3bT642mXdMtGyp\nAR+BSpUe2gnat0s9P9B5qjwHyuAbMjrVucJ5qC+RtcPio5NiC163s5dKhypb\nGFno3l9YQZZZIyfn+PBJOU/zfZzMrsBhY6GJdu506Ty5lhtiqgXE/2y1D6kK\nhwDEHLgCVJTg9ARNtmSV9l7DVY0/0WiUn9mAyALL6LjgSEQtUx26zMX3KnyN\na/QpRKISpPwMAIw6v+eEmGcO+/IxLAFrLr9AOIMC7n11EJN5t69HKeNu/j7s\nTb4l3yCcymkMSbddHRDzH3SqAcyi4yllDq0rnRgO72F+H3GgPYgdYrnA48zp\nSBiIh7Rc7CRCFWJocqYSjbq6IlbUw54kctM+hzUOxsUpTWA3N7rOBFwIsLYJ\njz6tCOYo48rWzjmYr2e5+3yZ58trbotlUcWNh/4W7wXn+cozM+3Phua2NqmI\nNzIG\r\n=GZ3I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCn+FVlh1SzR1UliveEqRVO6eTKtW+GsvppsK6C8bxJlQIgA711lvVnlKx82QkHzmQzaE2C8py007DXNvx4vNngRug="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.14-alpha.0_1639437461178_0.9591998934980328"},"_hasShrinkwrap":false},"1.1.15-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.1.15-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"6226262c9f125c7430fff05b221cf20e38c1fd85","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.1.15-alpha.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+arm64 (darwin)","dist":{"integrity":"sha512-PjkwfKHGVf6/myKMNmeCYPRfV6PFYbGn66Ysyu8zobst33U6ulh4SUzezjRowUUdeBomfEGrSfoU3U0MIxFTUA==","shasum":"cb34b925aba8628c7bcd7635a783d81a7595268d","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.1.15-alpha.0.tgz","fileCount":91,"unpackedSize":841296,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhu33jCRA9TVsSAnZWagAAN/oQAIYqj5VNpXZe3fygz7FR\nlGdtyWXu9ehuKLbeATpzLWqxh/HdlyZIDR6RjlvilGn0bpSI67O4jN8wHYUl\nrPSCPSa6lVxfiuUDaVPNtzNnGj+R5EsAu+tyxFBg277jWRPgMI4O3RZMZVvQ\n9V8C/1vb21iEzVP5bxBmIeTN5YbtePGmZy1bDnPTYKiYfceW8iqXFvX8b7r2\nHrXY+WNr4JOlZhn9BJi5tbpSHvNsewdG5TRZeNw5K90RfuqPYnQxPC6LITVg\nYVDmMkhtfAuKDgf4CwjXetH2+nA/iakjcyRnP7Qxhy6RPkiW9aXNflFCF3eT\nqumPjmAy5L/TGeI8IgoEK5UBBo+YHJaqmZNljSxXGXr0PhhSQHUzDXs1SyPC\nG53ijdRX/e+VwUg535l2WNjg0T8BLbNOxj4nurm+u+blnb2a+mn+qFBkvMQv\naLVf5Od27tTM4NqljdQw6HPThRJl3k/EcAD5yS+PlBbsXzH00kHJ01BAljjB\njhNO7FwBEPrzh+FRCAxL3sm63SM77e1LPpy2KQ0phnnPuBJglHyUX+acjkT8\nMkQvOFWEVii1sCQm5rR+b8+metA4lJho89Odg0hDkRvv7vFWPAo2VQ8Idlc7\nKADsHhwei5aiOnzZbVHK4IEYVv2yMAh1sxc+Tg2QH95cSWcV+NTJRlld/MTx\nsnz9\r\n=QUsR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAd9CBQjEMDl6Ge2l1FF2zLkJvAmwNHWB64VJ6XkkSmbAiBkwYTMGxasMEDw9xAtM+igWLGWvclBO0KG4G69/0Dwqw=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.1.15-alpha.0_1639677410949_0.0009983159031443645"},"_hasShrinkwrap":false},"1.2.1-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.1-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"c1974b80733f28a2065ed9d85743dee5d6f0c6e0","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.1-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-7UP7XcnwwdX57sbcOQob+XOh4iRGZgPD8aCjSnOyb5CN+Y+M1k/haR4qJ4h0eGHPlkAGUVVi9ZEvmSUdlUwThQ==","shasum":"f48f1ba90cbf55261268bbf711e6d0d34cf0a3ce","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.1-alpha.0.tgz","fileCount":91,"unpackedSize":841326,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiGTdzACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoAZQ/9EYBVb4mSemUyjHFtciVClBtl5KznAkBSdXHAWFVA7BMhTBUo\r\nzUjmfWZ/guNzMzyYrKldnmAqbVJRkx+wIF9GJ6o2g7JPs+xgssynI9jZ3tR4\r\nK17Uy5dPMAAX5XZfeZjRqcvEkww2qxtmcHiyf7T9bZ5QeWOWz5v5nGaoAeEt\r\nH6xaNlnpjOK8dba6N9acWTG7HaxjBW08dxI3O4c9anLz7jvvrWKP2As/Kwnl\r\n/TFlvUtIr8ZHA+1BJ2UfsS00y95fvMZ9l0RA6BUWv07xuC38iAJI6lCgXGh0\r\n2FlHJ5+KSvsA8iXDGIZb89sEJ5DAOM++K0EwoKrnKUFpUEKpfvkCG8BbbhJP\r\nVEqUUChQawmuiBoSdghidg1CFN9XlMx1RK35zfIOnHC5lGuEBUU5GmsHgKZf\r\niAhvfV/GG6OfyUCILhdMmyZrGb/g4vzoxfzHCDbLzhn8aNsEBc+RUz6m2ywX\r\nU71XlIzkCS9GEb6k7M2fpGmVPKYrg1aJrJ40jM4LvjN0ydhSuW6BFFF9MxdH\r\nSVIz1YuVxnOOPdppxZ/LNkqTL7GI6g1UZLrd7NEhY9BBEnG+QiXgBZmRYzNw\r\nQClHwHSjX6dXwHSDJw44Tmo78hdKK1k/5IyIUdc2EKykvXzO4s04H8fwNvHT\r\nYGGPkhMGCoBvOc9cO2FrxLsfU1oXuhSnUUU=\r\n=+WLw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwLDC/7y+GRTj9x6PdakmKpp96ZNKiGCsWsSR/MR/SaAIgDfXnhLN5YeEosdFBnHsWsMj6F1KFROsYAINXdHPgl+U="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.1-alpha.0_1645819763022_0.7446022024148453"},"_hasShrinkwrap":false},"1.2.2-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.2-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"49f848c3f336567d3db795ecb14395cec05235dd","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.2-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-WlMsSgvhaoAFGNfE5o2STGvSCULiDS6/gHuJg3Gn566b50zAzrFF0lVD4kcjDxml/DH27T8CKukBvMjpgtHaYA==","shasum":"d32bd8d586fda5708a012b359c7fa639140d8d58","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.2-alpha.0.tgz","fileCount":103,"unpackedSize":865466,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiIpDlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoZyA//SfFr7Hd2Misv8KQmnMK/NmaWrqRcl8GcHuCFQ5B9+Xbl9EsM\r\noxnkid1MpDlN23gzx3hY7qr9h6D/ZqS3IhlZfitrY0aRvENhouIh1sRDjLbk\r\neBVhxqlEvALWiJRmhvep/RZG37qwIdmfl/4HfSMRT/szmPFwsI3pPH8yP5xb\r\nKcAtQzn7CvhQgze3VSsiyMOQSVaqVzECpPuRfjqguJTikIW1Cs9EmieMRme1\r\naYnCdIJXCL0e2p/wC2gr/GAU52StH4mnDznQAKPDz3IFXW2B8DoOVcBWgEda\r\nJ5I2pb5HNnBYnBsdcMkwgZ1g1iS/aY888EQFsNyk8vQJ6dtudwgE1ThCGZIo\r\n2y8Ip7Sne9LF7MZ2SLO2/BWEJWEMLNSu+sZ/SybuVdljszLvS1FgXCm2FSsp\r\nxKpy5F2i6W5wjcUp6CnanBR+eo8oHc85/ALHzGWDLmJOPhfsYV6m1RoiR3xT\r\nWYUznVpaoXE/N6JhVTSTFpXfC98utYTtqhvHNGPcYyIzJjiDJxujOwiNLqo6\r\nmlVGrC7+c0TTPyBnfdDAjALX0fBpPODkImtS4JsjxLhfg5z/zBHhMf0Q/TWq\r\nNbOtcNd9f5scjUfMEoUyAy/Fvv/nh9DsBNwQUcVnwL8AtquG1gMA9/CgXKgX\r\n+EkApMAJAVRSXCnLbLrcz7UpkuMt9r8oQSY=\r\n=KwrN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIQD8dPhmWZp8xgkXQMjrZC76uftL9lR9cB3pG64TKmaO4gIfI1EEjwOciJ1gS+mM1McHAkeKIOkvlvV7tuPxWrY9oQ=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.2-alpha.0_1646432485218_0.3083564864168138"},"_hasShrinkwrap":false},"1.2.4-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.4-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"66eb1b7aaddef345d4bc34ae4b39c8cfce6e03be","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.4-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-vQTDlvPR9+CytZkx4+M1zg+lG/126OKHG4+meuidroZelr9b5vvxz3BkNX12y1DiL46U34FdMeCihE/6xzwiYQ==","shasum":"5ee47063c418ed7300aa71e3dfef0063de2448f8","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.4-alpha.0.tgz","fileCount":103,"unpackedSize":867343,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiIpzNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq5uw/+NtoqA2HMOh3Y5cE9uZCBHxlBeOsrNMAhWGVuybvNqbAluGSJ\r\nn86AmlbMKHePz4I8gSDVIEBnKeAV4AU9FDlc8rGBhmUpVsBD0C6/oGLPG9SI\r\nTrcXD6LBsBXxGEzX1OtYTiobCXkpyM7HMxVYUDIS1ukluas/CdgFhKjl8kGb\r\nvWCYEDPGf1qBuUuAp2kCCO6V8JY6e28UNkRcLnqPnyLfDz7L8TbFAqwufemU\r\nwRTuEIqk3WP9inh5IuzZOOcgVSCd7RKnKCc9jsjlYsfih2DHu2biUnHfCm2E\r\niMXpEFOvMrmrRghJzzgNfR/P2qLWasSYLdQPVNOvF6DAAgQEYZThpWmQfj+T\r\nrTttWrgrpcEjL6+myW8NJe6EN3A5aXOiAtZL7FIuWRoTQW/EU8qZxIctBV5z\r\nd7tIhDJ3p7KTbOvUgsy2QnO3F5hI+KdckUgiQFU2MYIfypoK404PRQ/2Feq6\r\n1OzRYDx41oCordjv+Y1czmvRhsm3otWnyEoqT4lq5ASgbW2SOQateevLVKEv\r\nbJE8FHIQXGp7ni+OKxssR06yOvBaEE0snbzNFTAHa6XUcnhkkEnSSERv1oIX\r\n+t0CIGxsQTKZK36d4huCSuNI0Yfj/HuSx37Gb2cdTeohP4XiqOuCLOysHfsZ\r\n1JAw/KynG3KlB0x6gxMWAcEtOp1LKWX8l5U=\r\n=2TM9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCFTlgG20+fxakihvNfuVAdQMZ3AanK5Gpwm9Y7IAJ1dwIgZqQ9fqBunsmDjQ6c6iyNrDRU9P7iyH+D/acVGYS5VU0="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.4-alpha.0_1646435533689_0.28074520763726696"},"_hasShrinkwrap":false},"1.2.5-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.5-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"fb4f3bea3b6c1c9a6584266d7b5bc3e2a69fd48d","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.5-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-TbM80c9cv++2kwDyEnnzJjFVlFO01x9CLM3V0FWp+qAt70fjAXh99VB93Om72hFejS6sOxIFpUlKP0/+727ktA==","shasum":"44b42a36e782a7038129c54362c88f61f588c5b2","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.5-alpha.0.tgz","fileCount":103,"unpackedSize":868891,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiI7QJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrvhhAAo4mTnleMInDWIMBvC14q9HcBrw4ZF4yHfuPzehRg6iMZaUpB\r\nXtF5faUgbWFWgaiKUlVMpyLl+B6FZdHM7kWw3ZhBfDu+RDyJSnsZ7/MqBjV3\r\nY3V0G8RaUZaeFShBnyu1hRBAwMsB1n8/V93gZOp+xk1NofpoXFB3tK5N8G8X\r\nEGddkHXj+q6mRw6WhHATBm+ZYcudaS6zwoN6QXm0PH6LRyeCEU2DXr2w6RlP\r\n8jmvOdyi6w/8RVrWDFqbSywAbLOWWfmvt/dtpo5lMK7yzPW3aFbq4mg3W/vf\r\nXRUA+miw22keVbrciaoVR/cWc+OiV8calo0K5XSiLnvzmmj0TKBZb3+ulww9\r\nEhCpssJ8FidN1zMc82HPljQuAGhQKfZzPLoqOs9aVJMGtqGlbb2YkYw5HOkS\r\nkBnKFDd2DBiYD/ut12/N5/gvO0PFF4EOjT8tCVv/wzkmAVpdhqmLgNmnB/4q\r\nab4A1DzhBnpfn1YhZBoyqz0Y7bkX8tWXbFH01aV19g4nyi+zTw70KJqMfz6b\r\nIwp1VfenBmM/5r0Fq088rv0w7rmixNjxOPojzv2eaNm+uCSLg6LvykklwO0Y\r\nmeH3Byev6tRjgcznHZgjJWZYl3EJ1eYQYY24XOpCHHHPglJWch4p32H4mTfz\r\njx0PSLlyfYHofEvIlPe0j2yQdCS+2/Ecdp4=\r\n=ygFC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBe23+hE8BgOw6j7GaJuyPK8AbAOsPoXFVCFZfS+k4WiAiEA17zAfz9hATo+1WsD9C3IJXx3KXFLH00SgQt4zqX/L94="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.5-alpha.0_1646507017328_0.9044273669984924"},"_hasShrinkwrap":false},"1.2.6-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.6-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"80e337c3f59ba6a8a421184647ef0b996ce65ef9","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.6-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-xhRe4MW1xqz4ZSlXLqjCvEhQIxDXkGM9P7chthzlonLkovqXgNzryBgovMN+vKALy5UVb+qQsvTnTaJzR2x0Tg==","shasum":"7cbebe38271a96baf60e1d53edb617456f6d2757","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.6-alpha.0.tgz","fileCount":103,"unpackedSize":868980,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJk9qACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrpRg/+LgUsdT/x60G3clJ3OJUCqBgDqSEjsPo3OwF1rFce0JmvweYz\r\nDRnJUCMigF9Zbsr/XYd8mdYrZK2gDXaJAsG93sczT7wCXkPTc6GrdYR4ZqDz\r\nA9l9eVGVuZIIFw+hgfO+Z7QPDzCnhY8M0BdsDnMWX4Z+ZE5DJSgF+YW/tHlM\r\n1mUbQtT2Mt1CJH6BqGcQXDJ/t3mgCiY059/5ag63XbYFYRU44QFB4YqFMApt\r\nFmUMhiVKolaii2YnIKIy4vImIAtAbkQ2AIjVZ5XLqyERyywbyPEUjiHIvuVV\r\nIFRK1uJv+4R1krqIIbCh1vYtNRSg/fQwVXgaU5sx7tX7qf6A1Y2bhZTTsWB/\r\nXt0RDMnE7D9UTZV3iqSeqsYxv5NFrL7dZdMU/mDx5s11S4qnTme4fVE7s3eI\r\na+yrX4JrHx0UUgdrZLYlDG7TDpt2J8q1vn9mgETUB+pTHHgjxFWc6DTqLsBL\r\nJPZece8Wea7J6ZXCTl/E3kOPsiZCO9FjIa/EXrM36WO8c7i4athd+NfAbRut\r\nE+c6XMNBnBBKJK7dMw0382GsmXiwuKwQGuYJi9AfmWXA5WQ1EIQodC5kf8xP\r\nLvgxCDvFb6opoPfITMqS7LJHbzGzlU9qyOHVDNKbzj8Vb2aZPchot2Hwk5af\r\n+FYPSC2OH1pBOzBwHO4qR098xzWFTFPaP0Y=\r\n=FWg/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFUzSbxVLGMshcib9PwQbn1EmYuluA96iO3OV7qAjbnvAiB9igxbNX0Aadhyy0oHubkIe9PHMVpKIbQjrhUJderklQ=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.6-alpha.0_1646677865840_0.7977682734112799"},"_hasShrinkwrap":false},"1.2.7-alpha.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"1.2.7-alpha.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"140cdfbffb256071ce1818614b740bb0acb53e06","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@1.2.7-alpha.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-MKQxtOHWfEgh06gptljVTEtSX47xQQH7cApKPs83m8K3WMZK0K3QoVLKfuV0dML4tuJ5TXwTSqMEF5xi83AFsA==","shasum":"33edf9f2b39db40d301e70f2da4dc3420858682d","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-1.2.7-alpha.0.tgz","fileCount":103,"unpackedSize":865652,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiJobKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpvnA/+Lsitdw452MQYlzhSiPnmkAjU+HyccrySbcMouU/SJCN6KQOK\r\ncN8eNo9mPL/vLT/rwDvhiEJ6nuOtE694rafejq65C0fTAkITZy/yGBSO8jWa\r\nXuKBUucGhnFTzrIuABWBehSlQ64EVpzodneUXQMVLMsR7vmPSEIqT77bom04\r\nrKeJgrErKofx+OXJIL7jz1NQNkmHqt5U7Y9a0wUHdQpO4venn9D7+1aC5vLs\r\n/knfJL52aXkKvlUFwJzwtIeODrHZSoUf+xELmXbPFuHVuFJW+Skf0HAFUDjy\r\nb6zaqqCqnS+ZtglalsgtHzgJ3AEgX4x2+K0wLqDzUDWmEpOzTiekeu8NBSkU\r\ngiIWV06ATlF5Bnef6PUtUgegr3+Iqhme4f0Yngy96qcUVSJUljTzxCwN+pv/\r\ndgwrBsEnBnNBmFJjnk13KiWdV9spBHu8Ay7L9HsFVJowJkMxcNolP57r1+1Y\r\n+95y42S4+Mm3j/riHkLm/YK0UPtLEzy2MPdCAfNQavqBoQEwENt9l3fRZ2ck\r\nOZd06py0S+AwZb0WcgmEDJK53IjDeVEwc5XWSArpOoRVQoC/cIm5Z8XqL3/4\r\n8JOGvdytHltEGYRLXP9WPiYda0Bqj73GP15blOqnMmi9t9IIfRfPBlrRR9KV\r\nKySpywv1G5rr3BQaYtKFlsAh2t/S6TJqaAM=\r\n=5UFt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBN09Udq3eXf/HpKI0GazTMKlAQhI4ma/sTFs56gG32dAiB9wyOQc8YeEGAuA1X0VrdiUnxagSCdYn8XdgAG0tqgRg=="}]},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_1.2.7-alpha.0_1646692042144_0.8185414526530481"},"_hasShrinkwrap":false},"2.0.0":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"2.0.0","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"02453064cb3ae22257d96b6d5cf6c03426b5ace5","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md","_id":"refinerdb@2.0.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-Bv4jnYuM1CZhJUBh/WjTwjfzdCoMS9gAtkSw2d1+aPtAjip5M0HPp12ziC59T1HLsVyi5VdHxEN2PU4LCtDkGw==","shasum":"1f0efe309541c6a354bb35ea95efd5037675c6db","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-2.0.0.tgz","fileCount":103,"unpackedSize":874398,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqvOPVOwRyErYSytkI4BMauj1/HvxtizFPwX38ANGy1AIgVtEZa8OFqfW/2xW/N41fVhS/yhLcBmwdHBvu3bzRYa4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJihTc6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo7xw//dLrZGvWKWrUQe9LO2IIQETvXC7HBdkcW2hCS8unIRsuAY0jd\r\nTTEkvyv0irABU7GBfuBte+hBGeQGOu69AkBBt4PI1MQAbePlfsHcnJXMBH/3\r\ngCX9VopqHowgBJ18g2zW5FclmXV1sC/5eB8aFHXQvHix77QkP4qy9H2R3EeL\r\nHyTVmHvzZeUAdO5YQL9dffCe6jkBm8ieMAQAzxnMId45UD2m51uaXOqJP8Zd\r\nA9+YbatVnioQgzGs1z9S6Z4ns8p0he8rixzT3uh7lvN0UoxcS2eLk/oyJ4I5\r\nRYgzICdpzqMiecGbwJkj1pg9pw3VrqgUHCS6fy9A5px/p0TCkMa0E3Eryd+W\r\nLb5R7UISm72Vsx4WMzrEblVf9vHX3Ka2lY+Q84nugd45TdHb8U7/bQEn1bIP\r\no2o0itdnIr23DvdUCbV4TPemS43w9DRMPy6K8BHOVJl2b7teAo3NmwEuRLG+\r\nFSrkp/seXh0QVeQ/M9dTwi081KHWOKUPdnFpska++w2qNyOAq4aZbJ03FrQv\r\nqwa3szx2yj/56ONs+6+22IdZjrUTqof0m6Qxdj3xlIq4jYEfuaRDmnpNsIOE\r\nqhShSS+wooO1gDOFkeI9bFys3AkCV2wHq8auwVlDCXZxZyPw3ykTr2qXyV+w\r\nbiXBnsb18gn49YvyH5F/2t4gwYPWXFOD6A4=\r\n=4RMx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_2.0.0_1652897594286_0.7972493053399032"},"_hasShrinkwrap":false},"2.0.1":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"2.0.1","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"dc50d8521ffedddff8cf2218d75e6e3a285b9135","_id":"refinerdb@2.0.1","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-/DYrL7n5MWOgBDL6pgAedgBsUFJtcLgOJiFkpuM+2h8sFznL2FeLanDlR0C4dL/8xPif9T6K6B4Oo3CRZ0pSKA==","shasum":"fedefe81c195c27d3cadf8ff31c00f0517a27347","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-2.0.1.tgz","fileCount":103,"unpackedSize":875525,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHAhdCvAz3cWX9Icrfd6QRqOIsSiez7Bu04sp3I2cXmJAiEAufv4AYL1Db9FCX1YXG901AQdDqiN2DyLoi13/GPUdtg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJihU0cACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrdzA//fGKyPDdPPdCBiSgO8yNnCnXdqe9cbX+U0rTJdXpj7xpijVUn\r\n/dQAJCxI6985ve8BjSFInpkzkfB/pW6/qrwcrqVLTGOaSmwxu1qJamFPVfji\r\nHTjE0Z3j8V1Ib5PUrsgLPWINfEKFdonUkRNYlQK2ccpoxfen5egOL1/NM/FH\r\nKY/gZirO3w8T6hGtJGEHp4HzZMaF6cP9aPXBPPbSY6pNx69X/HXWuY+Gcdbp\r\n4jo6FvVh/zIC0bdQLE8cJnCgQk5Ui2Sv19p8RwjrwhxyikpmYoPxsoE3P6Db\r\nFujeWph9KNNw37vvaY28NDu4xq5s+jUAxtv8qWRWHDG4ZgDnYMh0gk/xEr/Z\r\nFvNoZy2osivvB1ROgY1Y3B8WWUxGJHGo3CtksXBupKknZl4AAIy18qdE/jsR\r\nf4sj53405iQQtHaXtesty0NhcFf6BrkNmECEkLQUov7iBOz366dXpJd4+d4G\r\nlgw+Z2nSkXzzm0uwOuPVE0qaDmIXNtWoweo11dQp9gM4yo2NwsQRLoipp8vS\r\nRRN4A+gNW+KA7005RTvcP08flpTypFFT/obasmK6fYQDT8/5vW4nwPp0qWfv\r\nT7a8/VeZFwXEoO4VqyV7PuvMmiqDMLJEVSBrfHGzXXPDYGZLown1mJJBR6ZD\r\n2CGBMKX8Zf9ymiTgw/WaWNx10Cc47A6nD08=\r\n=7rus\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_2.0.1_1652903196381_0.25176600063406807"},"_hasShrinkwrap":false},"2.0.2":{"name":"refinerdb","description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","version":"2.0.2","main":"./lib/cjs/index.js","module":"./lib/esm/index.js","scripts":{"start":"npm run tsc:watch","test":"jest","test:watch":"jest --watch","test:ui":"majestic","tsc:watch":"tsc -p tsconfig.json --watch","build":"npm run build:esm && npm run build:cjs && npm run build:worker","build:esm":"tsc -p tsconfig.json","build:cjs":"tsc -p tsconfig.cjs.json","build:worker":"esbuild src/stores/localStorage/refinerdb.localStorage.worker.ts --bundle --outfile=lib/refinerdb.localStorage.worker.js","clean":"rimraf lib","prerelease":"npm run build","release":"np --any-branch --tag=beta"},"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"homepage":"https://github.com/DroopyTersen/refinerdb#readme","dependencies":{"comlink":"^4.3.1","idb-keyval":"^6.1.0","just-flatten-it":"^4.2.1","just-omit":"^1.4.1","just-safe-get":"^3.1.1","just-unique":"^3.4.1","robot3":"^0.2.21"},"devDependencies":{"@documentalist/compiler":"^3.0.0","@types/jest":"^27.0.2","@types/node":"^16.11.6","esbuild":"^0.13.12","fake-indexeddb":"^3.1.7","jest":"^27.3.1","majestic":"^1.8.1","np":"^7.5.0","rimraf":"^3.0.2","ts-jest":"^27.0.7","typescript":"4.4.4"},"license":"MIT","keywords":["indexeddb","refiners","search"],"gitHead":"bed5d534d959cf80b345db64670c01acf54b9bd1","_id":"refinerdb@2.0.2","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+arm64 (darwin)","dist":{"integrity":"sha512-zv1EC4/Jb86E7E+AIxnxz8XjUdoQPLojjkmjWavjLVuv3BgOSvXz/9NkOFK5gZf+KduYTDCwTGHaCEASUPFroQ==","shasum":"7c59287c645fb343e1ad90e4ac400687063126d0","tarball":"https://registry.npmjs.org/refinerdb/-/refinerdb-2.0.2.tgz","fileCount":103,"unpackedSize":877083,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEZ6LVqDpFE5xoWEK9NUb4WmxaaejBhKLZ2UgRNAQmGGAiB8zVqhoL139KzAAoR6l0LmmLgT23/yB/fMrOYBTuH5ug=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiir3vACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp3uw/+Pj6glDq2tTRcqU3md/kGLNUC7nXvGYpiLPiM8TWoaw9s6HUb\r\nVnlXxl/cC8k/HkeKNvmQ4UOw1JPcOzLE8fOy1jCOyfPslzxj7QrAkoiDc2Iy\r\nGiopwFWzuOvhPCsEX8+33BhU1JJKEV8B8SN7nwAYnl18zEHYXStMzysaKiLW\r\nW6P71ZAfrXcImUJIXnMuDoO3bmF8ZGV+4M8xKAT0sB8vCV0i56Py/J8OtV6+\r\nyFjPhDaAhvb5Pcj5IaM24xNSJMt2c8dRjxXhxKzTnZbN3rULcxxzM3tUfcjH\r\n/15DK6FZsRZznEDH9fNZXRF0eaDhX4okARb+GwzGkUeRFzaimWpEF2Tw3Sva\r\nzGWWX+GyFClPLBOANew3OmP83QD33kpnTPn1UmbpzVPSLUB1iNHtBjNfBRbC\r\nlXTJYvwjclGsuOke/KkLYrKfZnuBroto4jJfKOvWIQn8CwjsrPDkH+cuL+rT\r\nKXZVvqaw8mka7+dmdL7j4SJvZLKQs9KqL552mGpDF3RmFtlEpq/shZCQZuxH\r\ne5TFwtdxl4b6esGfA4w0Ezkt14JyGnirUJtt3WjTqmEDPMPU2fMrj9pKz2qD\r\n3dP0tCNxgZ7s7G8xYChtdq/St10fs7f4b8i4/npkV8vLT8fChmls6tp1shF0\r\n5gOAFQDsT/PLlvkL7monM5xlzctqg95J0hs=\r\n=dgOJ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"droopytersen","email":"andrew.petersen15@gmail.com"},"directories":{},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refinerdb_2.0.2_1653259759431_0.3829835872604348"},"_hasShrinkwrap":false}},"time":{"created":"2020-01-17T20:35:36.076Z","0.0.2-0":"2020-01-17T20:35:36.259Z","modified":"2022-05-22T22:49:19.743Z","0.0.2-2":"2020-01-17T20:41:40.779Z","0.1.0":"2020-01-18T17:45:51.909Z","0.2.1":"2020-01-21T22:16:55.168Z","1.0.1-2":"2021-11-04T16:59:19.921Z","1.1.0-0":"2021-11-06T19:03:37.913Z","1.1.1-alpha.0":"2021-11-06T21:37:25.769Z","1.1.3-alpha.0":"2021-11-07T00:07:42.278Z","1.1.4-alpha.0":"2021-11-07T23:04:10.317Z","1.1.5-alpha.0":"2021-11-12T01:41:48.521Z","1.1.6-alpha.0":"2021-11-12T03:55:42.261Z","1.1.7-alpha.0":"2021-11-13T00:45:07.722Z","1.1.8-alpha.0":"2021-11-25T07:27:43.022Z","1.1.9-alpha.0":"2021-11-28T17:35:01.662Z","1.1.10-alpha.0":"2021-12-09T19:14:15.767Z","1.1.13-alpha.0":"2021-12-13T21:38:54.348Z","1.1.14-alpha.0":"2021-12-13T23:17:41.338Z","1.1.15-alpha.0":"2021-12-16T17:56:51.174Z","1.2.1-alpha.0":"2022-02-25T20:09:23.238Z","1.2.2-alpha.0":"2022-03-04T22:21:25.452Z","1.2.4-alpha.0":"2022-03-04T23:12:13.923Z","1.2.5-alpha.0":"2022-03-05T19:03:37.532Z","1.2.6-alpha.0":"2022-03-07T18:31:06.056Z","1.2.7-alpha.0":"2022-03-07T22:27:22.353Z","2.0.0":"2022-05-18T18:13:14.615Z","2.0.1":"2022-05-18T19:46:36.650Z","2.0.2":"2022-05-22T22:49:19.668Z"},"maintainers":[{"name":"droopytersen","email":"andrew.petersen15@gmail.com"}],"description":"A browser database (indexeddb wrapper) used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.","homepage":"https://github.com/DroopyTersen/refinerdb#readme","keywords":["indexeddb","refiners","search"],"repository":{"type":"git","url":"git+https://github.com/DroopyTersen/refinerdb.git"},"author":{"name":"Andrew Petersen"},"bugs":{"url":"https://github.com/DroopyTersen/refinerdb/issues"},"license":"MIT","readme":"# RefinerDB\n\nA browser database used to support advanced search scenarios. An engine that could power an Amazon Refiner-like search experience.\n\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Create a database](#create-a-database)\n- [Add items to the database](#add-items-to-the-database)\n- [Creating indexes](#creating-indexes)\n- [Querying the database](#querying-the-database)\n  - [Exact Equals](#exact-equals)\n  - [String contains](#string-contains)\n  - [Min Max](#min-max)\n  - [Sorting](#sorting)\n  - [Paging](#paging)\n- [Displaying query results](#displaying-query-results)\n- [Further Docs](#further-docs)\n\n## Install\n\n```sh\nnpm install refinerdb\n```\n\n## Quick Start\n\n[![Edit refinerdb-vanilla](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/refinerdb-vanilla-9vijf?fontsize=14&hidenavigation=1&theme=dark)\n\n```javascript id:core-quick-start\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\n// Create an instance of RefinerDB and register the indexes\nlet refinerDB = new RefinerDB(\"movies-db\");\nrefinerDB.setIndexes([\n  { key: \"title\", type: IndexType.String },\n  // An index where the key doesn't match the property name on the item\n  { key: \"genre\", type: IndexType.String, path: \"genres\" },\n  // A date index\n  { key: \"released\", type: IndexType.Date, path: \"released_date\" },\n  // A number index\n  { key: \"score\", type: IndexType.Number, path: \"vote_average\" },\n  // A nested 'path' is supported as well\n  { key: \"director\", type: IndexType.String, path: \"director.name\" },\n]);\n\n// Add data\nlet movies = await fetchMovies();\nrefinerDB.setItems(movies);\n\n// Query Data\n// A 7+ rated 'Action' or 'Comedy' with 'day' in the title\nlet filter = {\n  title: \"day*\",\n  genre: [\"Action\", \"Comedy\"],\n  score: { min: 7 },\n};\nlet { items, refiners, totalCount } = await refinerDB.query({\n  filter,\n  sort: \"released\",\n  sortDir: \"desc\",\n});\n\n// items will be an array of movies matching the criteria\n// refiners will be an object of like\n// {\n//     \"genre\": [\n//         { key: \"Action\", count: 13 },\n//         { key: \"Comedy\", count: 21 },\n//         { key: \"Drama\", count: 42 }\n//     ],\n//     ...\n// }\n```\n\n## Create a database\n\n```javascript\nimport { RefinerDB } from \"refinerdb\";\n\n// OPTION 1: Just pass a database name\nlet refinerDB = new RefinerDB(\"my-db\");\n\n// OPTION 2: Pass a config with any or all of the following options\nlet dbConfig = {\n    // How long to wait to reindex after data has changed\n    indexDelay: 500,\n    // A handler to fire when the State Machine transitions state\n    onTransition: (newState) => console.log(\"Refiner DB State: \" + newState);\n}\nlet refinerDB = new RefinerDB(\"my-db\", dbConfig);\n```\n\n## Add items to the database\n\nOnce you have a database instance you can seed it with an array of items.\n\n```ts\nlet refinerDB = new RefinerDB(\"movies\");\nlet movies = await getMovies();\nrefinerDB.setItems(movies);\n```\n\n- The items can be in any shape. But each item needs to have a property that represents the primary key.\n  - The primary key can be an `string` or a `number`\n- By default RefinerDB assumes that property is `id`\n- When creating a database, you can explicitely tell RefinerDB what the primary key is using the `idProperty` setting.\n\n```ts\nlet refinerDB = new RefinerDB(\"bookmarks\", { idProperty: \"__id\" });\n```\n\n## Creating indexes\n\nWhat is the shape of your data? For any properties you want to filter/refine, you need to define an Index.\n\nImagine we had data that looked like this:\n\n```javascript\nlet items = [\n  { title: \"Watch the new Matrix\", id: 1, tags: [\"fun\"] },\n  { title: \"Cut the grass\", id: 2, [\"chore\", \"lawn\"] },\n  { title: \"Buy fetilizer\", id: 4, tags: [\"lawn\", \"shopping\"] },\n  { title: \"Build RefinerDB\", id: 3, [\"fun\", \"code] },\n  { title: \"Document RefinerDB\", id: 11, [\"chore\", \"code\"] },\n];\n```\n\nWe would create a `RefinerDB` instance then define two indexes, one for `title`, and one for `tags`. We won't need to filter or sort by `id`, so we dont' need an Index for it.\n\n```javascript\nimport { RefinerDB, IndexType } from \"refinerdb\";\n\nlet refinerDB = new RefinerDB(\"my-db\");\nlet indexDefinitions = [\n  { key: \"tags\", type: IndexType.String },\n  // Because all of the titles are generally unique, generating a list of\n  // refiner options and their counts is not that useful. We can improve\n  // performance by skipping that step.\n  { key: \"title\", type: IndexType.String, skipRefinerOptions: true },\n];\nrefinerDB.setIndexes(indexDefinitions);\n```\n\nHere are the available `IndexType` options, as well as the full type definition of `IndexConfig`.\n\n```typescript\nenum IndexType {\n  String = \"string\",\n  Number = \"number\",\n  Date = \"Date\",\n}\n\ninterface IndexConfig {\n  /**\n   * Unique identifier for the index.\n   * If no \"path\" is provided, it is assumed the \"key\" matches the\n   * property name on the item.\n   */\n  key: string;\n\n  /**\n   * String, Number, Date, etc...\n   */\n  type: IndexType;\n\n  /**\n   * If the key doesn't match the item's property name, use path.\n   * Allows nested paths like \"author.name\"\n   */\n  path?: string;\n\n  /**\n   * For things like dates with timestamps, or really long strings,\n   * do you really need to calculate refiner option?\n   */\n  skipRefinerOptions?: boolean;\n\n  /**\n   * A convenience property so you can build dynammic controls like\n   * a \"Sort Dropwdown\"\n   */\n  label?: string;\n}\n```\n\n## Querying the database\n\nTo query, create a `filter` object, where each each property on the object maps to a registered Index key.\n\nIn the following example, we are looking for movies where:\n\n- `genre` is \"Action\" or \"Comedy\"\n- `title` includes \"day\"\n- `score` is greater or equal to 6\n\n```javascript\n// Each property on the filter should match a registered index key\nlet filter = {\n  genre: [\"Action\", \"Comedy\"],\n  title: \"day*\",\n  score: { min: 6 },\n};\n\n// Pass the filter to the `query(criteria)` method\nlet { items, refiners } = await refinerDB.query({ filter });\n```\n\n### Exact Equals\n\n```javascript\n// Find Action movies\nlet filter = { genre: \"Action\" };\n```\n\nPass multiple values and they will be `OR`'d together.\n\n```javascript\n// Find movies with a genre of Action or Comedy\nlet filter = { genre: [\"Action\", \"Comedy\"] };\n```\n\nIf you add multiple indexes to the filter, they will be `AND`'d together.\n\n```javascript\n// Find all Action or Horror movies rated PG-13\nlet filter = { genre: [\"Action\", \"Horror\"], mpaa: \"PG-13\" };\n```\n\nNumber Indexes work the same way\n\n```javascript\n// Find anything with a score of exactly 7.1\nlet filter = { score: 7.1 };\n```\n\n_See below for the min/max filter that may be more useful for Number indexes_\n\n### String contains\n\nYou can query `IndexType.String` indexes using a 'contains' by including an `*` (asterisk) in your filter value.\n\n```javascript\n// Put an asterisk at the end to do a \"contains\" query\n\n// Find any movies with 'day' anywhere in the title\nlet filter = { title: \"day*\" };\n\n// Find any movies with 'day' or 'night' anywhere in the title\nlet filter = { title: [\"day*\", \"night*\"] };\n```\n\n### Min Max\n\nYou can query `IndexType.Number` and `IndexType.Date` indexes using a min/max range.\n\n```javascript\n// Find all movies with a score greater or equal to 7\nlet filter = {\n  score: { min: 7 },\n};\n\n// Find all movies released in 2012 with score less than 5\nlet filter = {\n  released: {\n    min: new Date(\"1/1/2012\"),\n    max: new Date(\"12/31/2012\"),\n  },\n  score: { max: 5 },\n};\n```\n\n### Sorting\n\nTODO: describe `sort` and `sortDir`\n\n### Paging\n\nTODO: describe `limit` and `skip`\n\n## Displaying query results\n\nTODO: describe shape of `QueryResult`\n\n## Further Docs\n\n- [Persisted Stores](docs/persisted-stores.md)\n","readmeFilename":"README.md"}