{"_id":"pouchdb-entity-fabric","_rev":"38-20207765535344bedaf96709c6172003","name":"pouchdb-entity-fabric","dist-tags":{"latest":"2.1.1","beta":"2.1.1-beta.0"},"versions":{"1.0.0":{"name":"pouchdb-entity-fabric","version":"1.0.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","babel-jest":"^28.1.0","cross-env":"^7.0.3","jest":"^28.1.0","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.6.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-find":"^7.2.2"},"gitHead":"32ab1c72c9d40fdb064f4b048bcda70605d29304","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.0.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-txwaS9ZM2/E7FUBdXPqFSUkPs/SYIaKNRaw0k18R5+f0Gz3bS7I3LC30Z8UwObh4Om/mrJO+zoVDyac5yitwOQ==","shasum":"26439228c563ab0740cd648085ecaf91c56ab0dc","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.0.0.tgz","fileCount":15,"unpackedSize":53673,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCS+FshhPm91EpOFTbzhUHb6LHab9NOvXUmBoQkPQbpuAIhAI3nAS0FRM5U50IvjE4E1PHEiP6cS0r4Ih+y2vaQAfcP"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijtEhACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqF7w//RvK9onXDSMgzG62bAJGfIH1HgYU4MBFye4kiOg1Ew7u0iKU0\r\nTxkePwOrbd/kuQn3oRAxkMyyrsCgYiW+jHOrcdbKrt0pbebYXJH4yjN6UU4y\r\naGwwKjf27XHiO7bVxJWO5EG40JEh7oXwvJK60Kz0SlUqpwgCf9Hfu4f3tJWS\r\nUqR/VrGQSbgeYWkh5PEzFSy0rxWVnkLNPU4L/8Vi57J902aH+l9qJrvokkuI\r\n0ViFHtFly9s1qpxhrbl2jHmdDIKYUsaEBxETIjGfxk9xcRf58bEQOD8PEktU\r\nx2kJ87/w0OyF+lXjnn4uKvCgNIJ9gXhg0XPp2D4ETYwW8UJDaLCBssPK+S2P\r\nyOkGQxFkuyjeHk5ANo7RHq4ovZDKidM1wSb/mnED5Z7JznDzgnuX9CiWKQom\r\nAsl8LoC9xrl1u0Ev2GlAnUiyj7HdLOgUydh/Ha7RZID/ZlrpoIVAIsvpDsrc\r\nDMnHqM7p01UFO+nJW7GoVVPliJtg6SCBrXJ4P+lZwn3z8mgid7BsK+Dq57eB\r\nOSNsQVjPqjUy1cNYEeu0MrxBrsI7FdSr5I/ezmvKvWrVY3PlYnHwH4G25h0m\r\nwazVfntHH8gdAUa5iRmKZteFk44tSlaLZl9ZVj1/Jvh15AnuqODEmnVCraqw\r\nG/pLU4ktk8sHJl1SvTzzbihlwTwpyBQm+BE=\r\n=iJop\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.0.0_1653526817207_0.5202831795707694"},"_hasShrinkwrap":false},"1.1.0":{"name":"pouchdb-entity-fabric","version":"1.1.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","babel-jest":"^28.1.0","cross-env":"^7.0.3","jest":"^28.1.0","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.6.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-find":"^7.2.2"},"gitHead":"d96ef28edad1903cb73370fab68d574ea5ccdd97","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.1.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-6WEBDTNB4TKibtNuL/n1jk6ILOfMvicHqTpCZC7l1+3SDhq5MfRy6gHEkrPiBotjcUAveY3RMLBovVHXCMV4fA==","shasum":"5ef386d7b02ef2943a2930d5a99266df9cbfb72f","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.1.0.tgz","fileCount":18,"unpackedSize":75347,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIeu3qMIXwBrcJ5HSrdsnwJ0oFZhNlQZQTFD/3LqeZsgIgDCTpdC0hg6nC+KS84KZAC4drdhyjhyj7py5lAuxaQZQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJimi47ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqdwg//V29D1bC4aN800r3nedTlLHypL1zaZv1z0b6HWOG2yL/PQTEp\r\nKDA0JnH7HLyKQaWbb5UFIUF8DHrl0UHHFwoUL9DBaxrN9ZsVvakMzX4UujUm\r\nWm47hPoI0zPg026kqSCKUlyE7wH+lRvhe70dxcLytz7Th/PhaR+JX6L6Sc1m\r\nFFR4Bf6Ymdcw7d64J7vmZXLjXfUlZQvFEGnfkcAKP1dyTdsi3DBDgDXlNPPE\r\n2RPhxChsz/dpwoMtth6tq6go2UAoyhjQZDrObUoo1hLAbWKJ5o8yNhj7lX2g\r\nlyJRdGxKWvPb8q0SBm+867NJoBVEbof9YS4XG/n9nGs93bbBId/BRjlCA+qL\r\nejPSgQl8gQXqLIsVFjzCGr/DZlzdQdFigZ8l5sYCKQtwuaZPPpen0ge5x1TS\r\ncxVizhM0RzYa1ZE437Ce+QiKb8lbG3Pr6dv3qCPxQ4ok9ZKMXai4w/HfNRDb\r\nzAEIrZLklqi/lIPgjwdOSQV33paLi4zOSUeOhux42SQVtEqIaePrHPY9qJKf\r\nQ3XNsWoNvI1VvUxGMzlGu/11MPaRxXwOduTUrl+whU38y34d6zCydtiygPwf\r\nRHDvBwy2JtYj6pLa0Y6ecG+iDMuMPff9KEIP942MYM9LTTR5SV9QA99Of9U/\r\ng6n//QbdlrSyw7HnJoIF7bTeX4GbVGvCSNM=\r\n=7AzY\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.1.0_1654271547326_0.9380900246466684"},"_hasShrinkwrap":false},"1.2.0":{"name":"pouchdb-entity-fabric","version":"1.2.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.6.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"0abaf4605ea72124e680ef0a563ba0b331a0a884","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.2.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-EbLJ6+Hiv4IdDcqyqRz3UTwZpyT7zHDHHOVxoS36EZuBT2PAK30Qe6aotxmt+dRSAX99X5CTDFM1A9F/EzB75g==","shasum":"5266f4850bf1b6982a9fac3ccc0effaa4b99fb42","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.2.0.tgz","fileCount":18,"unpackedSize":75202,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDqtGuaqmAv1whvblcEjCg6BMqbbaal3xByB6jcuR7B/AIhAKkKdlh2KNVL/rXa3olRyVhxVFQbSBYFUji8f5ablV2K"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJip1VNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpGtg//fvjlG2ObxCgXP6vINtorct4BXteP8MNi8Uos5kWAPv7aojas\r\nNNoLiI49q1FGwcJRJ1x+zKFvovMjHHG4Axxnjm1wJIRS+3Y7VXRzBCa5aTKj\r\nW5sfVPnyP+ptQbNGzq5RAXhbX9Gz2CrynIUAYZUiW3B5spKAwCkSa1gCrq4C\r\n/L76PHDbEe3Ek/YFc9i1VDYWvL2DfHAAlpso+xoSXNeEqBXeA0dCMv8icCBg\r\nNdp57/WYmb5U4P5ai4n5MpL5o1QRR3p3JFR12rfSjvEY/jl8MUQpFWImBLLI\r\nP39iSX6J0HwZ/Zfywgd92I27d/8t/+PhTp4l1G3yRA0gbIPd02eQsDd6yozp\r\nl0T7n3Y0qcailHgxnA/3zic4Z1iyUvQYxs3JdndVRkV6Ym/nHz9wsumePcmL\r\nzx1cFmgapYqtKJiUb5aNGApWbcglvSiiiLqryS0aK6wPOOfhV1doajk7K+Vt\r\nMEsR8mKWNBkpt+OOygxWFMDh56Lzbhq3+jmBT6O7sVfIptElqTO00e5KJ6R9\r\nlbv9PMrpd3alE215Me/IwPhOWmtodGd/Vqj7h5/R/tPBmbdUqAlHcTH1KVO0\r\nuefW5nUBziuhK1VZrE+iTdesjN7TQ4JWuOBBt3HBGL+d+hRDer3Z/jiLxjLJ\r\nu/T/U8vgCMGQFXauVYIZMHzFl7/BN0NcSPM=\r\n=ZXa7\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.2.0_1655133516967_0.06806344172439949"},"_hasShrinkwrap":false},"1.3.0":{"name":"pouchdb-entity-fabric","version":"1.3.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.6.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"230439fb111accd184e08f71a14ec15af19a468e","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.3.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-DYdly2jmIG91ZzoyKTmFZrRAOvkXIAoa5M1ncfyWho/+FyCa6fiTfsKpaPi1Wi5eTpNok3fOu24LFb9+RAiaGg==","shasum":"453d967424095b13b8e821614b6fb2ab16ddd375","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.3.0.tgz","fileCount":24,"unpackedSize":116033,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1GUlqIzrUcmpL1EEs27CdatRAvbLN5cXiB4dfU+RRVAIhAJw6pURtm7Bd18D+EB7wuzuQK83AZzezZIcBIX25lWVN"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJivhFrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq7pxAAjkaqgbcaHXi9DlDrQxJY+1qn/ZKqAVdgftvIiHXpgSGjoc2G\r\naBKs8wzDDk9dP4BTU0h4+C5x0sFemX1YBHZjqr4VBPwxeSbPjPdNcl95uHi5\r\nCbbbg5uOV+q2jNOPdOUCkwXhl4KUYzyhU3K4oI8+dSUjLJLdh4gFnlKTkuD/\r\nt6J0TeRLyHShUt1ApgEsycs+Ro34mATx2bBSl2iYvXM9ZzBROhSJz7cMuNml\r\nP3uzYXsK6ltjupUmFRZmEm8V5bUYdwRMnlNHmxcCkVC4xgYOdsyMjsKo3ZNs\r\nsiBNOA88zUlBD/sPnDQTGd4LfegkyMFHjHfxUxskDl+UElKG1mhw9+bs9ZUH\r\nZMhS5X2iX+XY9Ii7WGOr2EXbvlRSkUMMRGfGabd4Z8Q/b2X9KxJCN3YtdKvx\r\nTBG+L84fcv/oDN5dlvnVNxIRVqUsuRc2LNfyqGjwRvtWaZeaW//59/yaWi2E\r\ngxG7C4lkT9Qd+217a1f2Qktv3L9kcswol3n0+O4faQH0kKiLv/vQ+vxsG6VU\r\nHaphRt/hmjvAt7JKicRcagX1GhrsVq5WZSWHa4sPYKKJs99TLHUv73BV7rin\r\nQoYZN3RPboaZKCUmHLRapoV3UzFiiCtvBO9hE9IEbejFkl5x1YpoyY3DcSFD\r\noj34PbPuuf9q0YZh69iPNmEJo8FkvtcSR0g=\r\n=npHh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.3.0_1656623467192_0.8190560481657572"},"_hasShrinkwrap":false},"1.4.0":{"name":"pouchdb-entity-fabric","version":"1.4.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"52077402224ba9469b11ebbf55836f86579311e3","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-dlubGlsu1JtUSGcvQ9qrI5Z4Ysq8+TB0gR3drkOzB12jfNItyu2xuyvmBmwrSaXGl6n7/ZZfeyK++Ec06hZB5A==","shasum":"0acaf03197be5b3b1bb37db15f48b9a0a1db6235","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.0.tgz","fileCount":27,"unpackedSize":129516,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7K7jDRpZkvNi00BZhc/d0eHuxLUziE3vfxyxN4oAm+QIhAOShHT6diUIfuLZJXDXRBPgU2I/H7VO9pY0ygu/cXNzL"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi8SCTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmplCw//VOGVwA1KYG55MrZgT1yyMKzw5A89raBywJwssxBGlBiUQifM\r\njrIhGtAe55vUUOn8H1rDIMRGykgyjH0DDvMZqDoRgfw9JMJIwy7iCMliW436\r\nquW+zZvAAfuHf9/+DLKOYLAUmud7+GcF5+q6dzh0tMOIJHqLNYrygY6N+3qE\r\nRbgCUeqR5SLQM/ZZlpV6oCSxbzyZJpMo7LSJV+x3axf/K1WkDk3K/IdxKpir\r\nF0I2eHA6Uuj7kokssRpxhqruzgDPMb3LVo5X1dyw4zU2K/esVNtUg8gwmcBC\r\nB1JYRSH9ETL0BW7fB8nRsReWQO+4OKcjjN2lErvDDoP6L0tcd59y3sPUie4B\r\neGkQtKPC7PVr5TtvlXdjlMHVwIhM1fYDPu2W27xDm6CZKfHs0QNn74LoO8vi\r\nOU2KL39QB0tp6jGQM+jkrTKo3xN72g6GGuZXoKN110MnVPNfrbFxJRtJWntL\r\nGBbBTKv1zQdTjp1ElAeS4YBvJC7K9ZjZtcqMVVQseXZH2Bv0iOW+xgPb71Ez\r\nFby6CAPx+QjmVVltfPnPWShk73nwR3KJiMfndL7O087tl39ilxVfV31wlkQq\r\nZzEw/MWdo833MAeF/q+7lgdof5uyMnKl9acjgfQ6w12T7n5g/SoOWsjAt1k1\r\n1nKUujKD5pUzgo4HByzldgogGPBTDFVNkOM=\r\n=KSgf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.0_1659969682920_0.24904983910160228"},"_hasShrinkwrap":false},"1.4.1":{"name":"pouchdb-entity-fabric","version":"1.4.1","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"aaba8f66d21799e5d34bf17aefc4b1d38c79bf57","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.1","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-zLqiNf/k6RJjCJ3DT1sY5YbUTtA0gWwMSu7IiGmWcB8uQzosfF8IzSoUjJR78auiM5212u6fqvz305zbNRvkew==","shasum":"69ab56b229c8fe3999a6cf9727c07b0fa2103765","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.1.tgz","fileCount":27,"unpackedSize":130877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMZe8kvoRF4jvRYxxOtrc009r8PD+LYCneW45+arNj/AiB5SbS2KI9aqU9ZKApbtVju5pPRrZUx2+SBEy3gj15RPQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi8oQMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo+wA//Xyg+bUANu1ou0RD777i0fD8I/XlzGQ7xebsW5YleqFHo92E9\r\nVgdbL1AOKNRTZtP+wAwNujZuZi+0KzuBMHV/30+o5SzZkC8gBgm2efI2ZHZh\r\n1byr2JxmeLrKudLRmF9drsNOmQw2Z9crpugm2aFjQjODdvzh97u8+1//hQL9\r\nQBJ2gs4iBIpiY5IzwBInX69M2sa8Bc7XNxrsAtQC4Hy0D442CqQVyLAxlY9i\r\nPzxytB1G8MNcnjM2qoiIAqNPahS3cuEYelHfMMSX80Lx25iakZn299PG9qj+\r\n3+1Ck28iEEZrfgXM9qwTt2jNtDzM9ZOiWYVeX3sMAP8sO35DSlzvCgGS3Rxt\r\nLeOnn6VC8mESYVTvgAgmcXOJtQj3VIEegY3JUfyQYgxC11tMlZKmLOZjNMYf\r\nUvWuZBIOXeSmCHZgkHtuD5QSc43fN67dCIOYAL7a+BWES2BRvgI3gOjdAjIj\r\nyKHstywJs44m+lKABq/zcMi6XmxQhNJrAXaJjq0FQn+6/7+mM/V5l5EhGAUW\r\n+0sPna5Iil1HuoOrnzOU64NWnXGfIR4CJO+7stS0Q/9frEPECNu8DAS8lQR4\r\nyzRVQjghTREmSs5L5klgZ8sFFVUWgPVkQf3mqLHZJjRTR8Ue8BBzbK733PzH\r\n7JxD/RgdbfLDGpS6rpWPk5m94yRItnFb22U=\r\n=QyCJ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.1_1660060684669_0.3332296982675784"},"_hasShrinkwrap":false},"1.4.2":{"name":"pouchdb-entity-fabric","version":"1.4.2","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"f975810d4ee986bafedf4091692857051669b7ef","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.2","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-QpiRDkDDwRZhFAl0aypJTM0D8gYcAEIZaw70bfJWiE2mANm58l4SJ1vnNgcMQNgOQ3lsvWlG2LNc0Auti5vv8Q==","shasum":"01a7c5b30339cb2167460e758b50d14f738fbafa","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.2.tgz","fileCount":27,"unpackedSize":145561,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFUcLF8GZOZ/aIg6TOpgG393O5zP59QrvBlHrIZnvU/JAiEAufDZpDMgRI0PHM6bp1qI8E8md2Yc/LaD7vdcdSAPYtw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi/S/gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAyw/+PsKAi5BcIM6MY2ytwkVdGsKvwJcuTxQaQesURAc2Mv0SajFO\r\nSABJ8W9Vl+llt44+12HbDV7m0X322s6QYepCqLfQTG0G5ajYC3ok4NSTxl3G\r\ns71Sn/v+gxvWcOrewBQXw5eRozexH7UK2EuiEDqj40DoWnz3oZUkWUnUSXCG\r\nS3Lq6xN91Fd4sZK8D0RmV0ljHW4RwXmpyvKdtij6AGmG1phNa5kfzCBgqru8\r\nU6rqPCLcVSvwBVWFnpnqKEOJFUtbFX4ocCp7OuuJKAxb4KBh9M5gVL3iY6SQ\r\nJFZhgU7uNH66kzRgBwdkyip0VkpcaGWLB3ctp4JpzUl1gSHPgTo7MWRB2RKC\r\nMwcYjHW25tvxSoNe0qsBSWyAZ26pWWVwmXfBJfW62xUCyvDKYF4EcCZD897t\r\n2Hx3yxAkjF5BNbJHYXBWBIbcWA3LRuJZinqlF/AI1Qn8+FMvWqoGJupMp+nU\r\n+zcQctL4oE7DJy3/RAux1b404miL2FyoDF9SPmiCLkMPDiD0VcqAKgyFeihB\r\noyp0kNELa7a9JjDeQnKe+NeRf0W5kZNKYaRAUnrM5pnNNGsvcyx0gu1JHDDN\r\n6OHeuLzUH2hGSIyNEyFnzx3jZHocLNxd12c+BC330JrtUctQRtG0bcdkPkLC\r\nsWynXSRRW99ZJfB7Ue3znnjUleCdnMMGKsA=\r\n=UUdz\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.2_1660760032104_0.9278852740908947"},"_hasShrinkwrap":false},"1.4.3":{"name":"pouchdb-entity-fabric","version":"1.4.3","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"05b18d3cf516cd7d47485e1e1f299b6074791638","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.3","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-+54bPvQp2384EGfcNIOo+bzpXEex9w+ANA6ZkSoByS9HQUit1d55coH9cYKFHLnyE9Yz3kSEoRrr209HsgXxug==","shasum":"03fcbf558ec9efba63ff71e3a4ee7a54e45a9d92","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.3.tgz","fileCount":27,"unpackedSize":148775,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBkTLyReBxtKbYgA5MJu7dypPrM6T7wxIdFSxCF/Z5wrAiB1E2HtIS55liJSpOxPE7kDCPAW2DqweeyukTYP+Z3/5g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjDLtvACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo5shAAn4trXPkBwl4SldVQ2aeJA5/nCiNaf/6GkG9m7Z9wNxLKJ5td\r\nOyyqHmGEhuI2isS0GEId6GhtBcn2fZ0bvqbuJ2zELDU+XKc6Zdk1fQkr4FrD\r\neCRcmu2UyWL7p7PesPdAmCAKtPciR1XbiEvrjwR4A6XnJaTTTrpTS6v919sl\r\nOCNdKhuU8tXmy+eLCbqOXjS2lydAD6RgYokLqILE/gkukCoccgU6Z22CStV2\r\n6ma9Ai0bGisBHgt3TV9u9d0mp3MlgAZu7CT9jOFRWDRHSyGN63HbTDE0NOlH\r\nwJlq9SMlGjJCsVF8raSxahO7cYXqzDCrFIo8oTqiydKEhs4wF0P//BK5l0cI\r\nbv0dRPFh5E028ZmpTQeqDbscmgH1wT0tcmcTVNv+Cf2Ublv9w3FSrfPhsaLO\r\nAmHLQaBXAX4jbOUCYH0jNt/T/PFYB8VTWmSVmqekqoM++1DaTItJ9mrsGl6v\r\npIspYoFfNkQNcYMlcfAQQ+4TITn8z9109sm39FmdHQaVzRQIUsUtxDQGUGXc\r\nedopYnm7Y4mP6tXiCCVdVIl4fmQSeFFe91MJe/lM5QnTKuIpsee5t+qE9cZT\r\nRW7pPpMgHHaEcibTkWgjlThEKDGWfl717sjauUnQnPxyc+t3pRShRH2cOoZD\r\ndb4sqNxOc7GV4l0ToYuKeMje6VXMxCwxFl4=\r\n=DV4d\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.3_1661778799741_0.033424398430354385"},"_hasShrinkwrap":false},"1.4.4":{"name":"pouchdb-entity-fabric","version":"1.4.4","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"74e87e2f54f0fb88fd22d3fec3d6b2c783ad52ec","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.4","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-RG3tHajXKKcCSjwomO7HVa7l+r/0j+hdpP/2svd4PrSU0ZLQe0KOkdH4Hp34QwT++ZOIO3+uqQyQQjd8OwBFmQ==","shasum":"f70bfd2ff3a33d9d8cb7987dd99bb471c4ef557b","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.4.tgz","fileCount":27,"unpackedSize":157002,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICYPK21lo1BUTJ8EePDO5Ocf9/4WYQ/aF06+S5VncEi2AiAvqqbCeuY6RnYU5Os+gUOm0tb69g0V1L2jfhDZLNKbBA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjEmOrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrIYRAAlHDKOApHSSVEu1RkhUrhQlF2j/vSmGAx9lLWb2lUIP0Aky8b\r\n+Af4wANiVRamOUNtHWvu14mqmvcaaMetz3Zz/oXqo24Ys1WhHS0ST+WBwqVU\r\nk8LDtVCgNghHhD2rKKmlYStqJU/Ailqr+IGGeQGoptx/PGj2sVNzKIaW2SKT\r\nAP70nOM5BrzZOOeD9XiRVa15GyZCmB3566zYn2KFOWqZuoiMjUe+B68dIhKr\r\nQvhsKXXbcZJCB5dZr2nUV1pS6PrkN/K/p7dkU1Y8RmsS0PBQ1T/tQ1UHVUB9\r\nWHR2k7niiiP2gcZcsa+pZFcUIhsEwu7Qin6KeGtJN/OnUcaM1a+WYrKzW6gr\r\nxK64whqSmVyQxD+WT99qbii39EGYdLDcT91Eq6d/SVUThK1HwNKGHyM7uwiG\r\nMdwH4FTzKX7s0Y8xKSLYvtFDxn3DijwemFOuB68s7l239U3SYKiGAg7VxviF\r\nl0575HWX2WbQZ7uZoaVcNxS5YFm5rSMIqvAiX7CFim1CaAixW1ZIpPRXCO6L\r\n+0joqsOQARKhyyk2PXPCS6FWa4bjHcgQAjN0oThkepsEzKHHXyT+bgtKDXFE\r\n4kRBWSeFz+55D0xkF8ziQDQHOHgx/0eeSKP1nk3z9o+yZ88JLMgZyxPvYLya\r\ntBtMSZ5jLKdqkfhEEsrrXZl+CkiG1o5KxZA=\r\n=pdkF\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.4_1662149546844_0.219508005299482"},"_hasShrinkwrap":false},"1.4.5":{"name":"pouchdb-entity-fabric","version":"1.4.5","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"gitHead":"bdbb882c07d7f336d3d1ab3f72b648b609896e7a","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@1.4.5","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-6U6ThTpN7tz22zfFSWZ4V5nKnKRAmp5lOJb4BHXoH7h3Mpw/z+Vp521SU9xlNPK1FosxcpL1cOtlM2Lv9GoKQQ==","shasum":"ffd95a33801cf9ae56f1e25be3635f56e10e22d3","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-1.4.5.tgz","fileCount":27,"unpackedSize":160121,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH3c4jlnWbRDL+CZ+3kqGwi0ZbuZr8Ffm447Ol0oDG4bAiEA7FWYW8uUXGeK7o0+f9S0jv4PtLpGBYh5bLGdbwXm5Yk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjGf4xACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpzdg/+O9LHiv2kUiUmgkFq/079o531MsRXc6CBEGc8zZtrQPMTpDjn\r\nv92O5ToXGbR+E/JyhPr5xFrk9hoWIpy7LdGr6XFCuvCkOti0qiabKNOgFr8u\r\nBuWQ7IBkyPT0iQ9Q9y5FNorlEM5sPg6Up9oPWn5nEbHv0o94FoOHcysXU3IO\r\nUIin7JdLIWnRk9m/NUPDs13owUcYJLHYSUDSrREmufLNAIrh5hm5hPFy/3zx\r\ngGgbs4lEnUr7Tr4nsHL1SL4pAv6gA4UA0ed+7rfdbLudYwZSTwf+RXz6942A\r\nPhC4PpRQQ27wSQXcPuI2PE5DchdaOi1r8OCcZRf9Vn0KmRb0AhooStDkvjQK\r\nd+WJdh/H1NZlGX9iJ3eVfLHnlKgDQqrxtP9JeDvdWsa12SNMsgX5v1ZKLPLD\r\n8U/XnlZxX0eqJbEBAF5XcvCuh9kAcUsA118lKa/iihf0JToD7zl48Mvcgd12\r\nKCJowDGF8Ye2z0VqTQCFIV9WUK5TiRz+/1cT8iRdhO4LCiBwhbHm7DyvJYd7\r\n6nWvcE9SOneplcI+H66v+xjASi5Yk6aWZ6w6FustiVxT3sGiugQxXD2EOjAw\r\nGHuyoDxSCB9Ohc5yBmu01CMcmyxyS4cZFyNwvhbLnh8NOd13k+e7cybbF+5R\r\no6HNtoB8pN2pTs6K8dka0UY6bi0YSqyHlm4=\r\n=XrXl\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_1.4.5_1662647857289_0.12180081927426412"},"_hasShrinkwrap":false},"2.0.0-beta.0":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"peerDependencies":{"pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n\r\n\r\n## Changes\r\n### 1.4.5 -> 2.0.0-beta.0 \r\n- Added `purge()` to `DbSet`.  Allows users to permantently destroy a document\r\n- `pouchdb`, `pouchdb-adapter-memory`, `pouchdb-find` moved to peer dependencies\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"231f042afd3d774bc1efb60f7582edcd2e52e2b8","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-s411+gfCvLERMSYlA4obEuSYkOaS3zy62LgKesW1g764CQgT8UH579bfrdQcddpEberCmRDLGbwjgdXt1gLNbw==","shasum":"be7ff0c4293c4e5d089fb0a1a1648e0b3f3447a7","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.0.tgz","fileCount":27,"unpackedSize":163601,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDHyqsBm3RLqURZLfmF/zcrRjjbgu4ARygLGYQyK0BpjAIhALEZ6bZCT1DIkZvoEJb9ZK8aZh2/9QGzO0xtTvtTS/09"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGeJjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp+Ug/+Mfc6QIgwBNLgikpX+x6acITq6lK5zHKOT5YViMfgZz9AFfgw\r\n/RwK3oxFUm7aAoTkd316YlxhE5wUXucw0cKUlMKwa0HftO3YESe0t2udrheW\r\n+i7dzdse2Rn3tNf4FM3pwKegWnwRtRp4Z7xTIX7nRO882Uo5M/4udn2pbr6E\r\nJPeL1mDfu0LiY1eNET0R0iF0eS8CAtN2NODQNa35ov1sFCQdZT80NrzAycNB\r\nXGL4Q3kskOGshG4ujw8nSqVr3hEZeziDOXInOB38977u4pSG/I3lLZpvbz0q\r\nmZt8sG5NzTbREuWB4dpjjKBo1MKG+lYCK1R3Xgo4evLxXsczDzdso0p0YOyv\r\nEjHzkvEM2Vmlgu2Mda0Duc0s4EO9zoBZB+w1wUMOLpAKQzrzPP9q1zaZzErO\r\nGSOvrFp3AnHbwppKc2uKqYRZ/yG1pcP8k7KTkzxxMuGHX2uXxlTLcLZFJLsr\r\n5c/bBcyuy7rkq/tWyPqZtzSZkeWSY7FNdBZIQz0xfPmytzMCw8qAssKzWJjd\r\nf6B5qIkkI2fjl8wAhZRs7sE/pC7I3zqJnp2idzwMz//rMmy/zdp7pWisEKlm\r\ne2zNfqPzl0Ihget0zhDyMecz+IOZJz9E0qxzwrg/W2unbyeyiWfkXhH/25zi\r\nh7m98Di6QxSXWTy455dbvpOGAKXArYCkObo=\r\n=H839\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.0_1679417955538_0.5794562532900653"},"_hasShrinkwrap":false},"2.0.0-beta.1":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.1","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bdbb882c07d7f336d3d1ab3f72b648b609896e7a","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.1","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-PI+wNMFj/mQdJpdFtBwP+hELiJbhe0aSOIkKnAZ/oy3XTiRSQW5kl5/fwJ8Yd5ROTr/A9f2A05jl8rhFBdKNpQ==","shasum":"885545f0f260d0e9828ea34cc416ecdc5edca441","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.1.tgz","fileCount":27,"unpackedSize":160224,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWAZQmL+DUSdETHT7mqHxwLTz20WCtwgw9IZm+671BwQIgFFZlE/i/8wCczEUgtIWEfgNOkMxvDwWKs+3hkLmjJ2E="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGfPHACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqp3Q/9GGde7ITtAFEHdNITx+N91nJMDcTVIxDSuUyPtq9fb1yAS9Qh\r\nXWMGJ/AODJ6lg7eLYp09sY86WQIEVbfq12kMJKUtm6Ntajm6YDDweTET8GCX\r\nHeXMEnjprQEzkQSK30BB2e/cOMuAjF8Nq1FquDtEzVlm4xsjmg8zlkH5tP1P\r\ns6tBV4Ob7R7rPdaOFdulPop058nCqaxiIuuKKzh8xBnjMyN0lE9ReJdtYvjW\r\nkVM01s6xXh5pQBygkGC7pm/tQSAZPBUaByhI9mLHiBiKx6opWSHmCP49rYRV\r\n3FI3PF03jlTg9HvlIpDirGrm5E0mhcJf7arkRLbmklNBXNyTnf2eAWlfRZyj\r\n9lwGtqjstl8qs/4kudQBTQpedJCJFhwXZQkXKxLJvThBufmQyCW4g2lYiQSm\r\nvg6UXDDS8IKL5/fh0KVO02zdccwxewbGgjphNzorbtEDYaPSYRBvlqtr5kMN\r\nlHssNpq9/CzZrgwS7CFgW88YBRw9WbT3fcEPLoT+oya23d5MIcSLJg27KjPH\r\nL7Kr2rn2umrs83poO3J+iEzgregMpnqjHkpscblkdArLB3DixTKs5fJFnr3y\r\nMavr9clfHwsPJ7GKSiwmEc4srwDrUF1J7FN3vUOrO/QbLDpMVDNt5X55Pzs/\r\nIglHUXZWR1tfDlxuxn1PZtFbahLIRdYoTvo=\r\n=Eqrd\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.1_1679422407391_0.46164561512824887"},"_hasShrinkwrap":false},"2.0.0-beta.2":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.2","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^4.7.4"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bdbb882c07d7f336d3d1ab3f72b648b609896e7a","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.2","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-TQ6vOQ5CaUJdJ2s/eloB6OF/67SoIQl/YWKuRMDF9qAIHYu8zWlj0KZg3lUipw+/YEmh5T7nXPHKRGRyRWKGWg==","shasum":"df4921746c134c9444e30a3e937367c788b8b444","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.2.tgz","fileCount":27,"unpackedSize":160326,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGgyen2E0GwROBeuY7x2IQmUHSB/wu0vq4G52b6h9j8GAiBSZm2W7Srx6y4sY4beY67fWJ9o5AFv08PsvnYHagEa2Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGfYuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp3uRAAmviyJXbTNNKVCl+6VapEzZ8r2vQduq5YaEOj8axkGz1vJby7\r\nf4q1YRyoJe3oW+Ti550hbEAFeefm5Ux92ecET7stgtqZvYMUYU4O1uwUTMkI\r\nVw4mk3IR3+yw69ZgXI+XbBWQ8uhJaRa5rPtekDYXezirkJB+J9NLhW6sc4a/\r\nOMpDk54Qej2/q6TmkiUhvEtaMg/RMyEGevcjONwXYOu3ck4ilCmnlquozxr9\r\nsr8NmDufvqrexBKv9qIIwhT4Ef2oGbTJThbwZkYMB2FRmVbhHJjdKglxuZ3f\r\nBGdE6DJzH3bFVX8jrry5VqbavMc+bF9vRZbHs0JjHyP97Zf3gh5XhqtKEyeD\r\noLYJWR5IhWY+tpFcwTUr3jqMiweemSD7nWfX9xmyPo6SDifqY27gQsyessY5\r\nidh1VoNQbHZkVqAP+AHn/2qLbt58JyndtUQy6zJAcfijZ4+KFoVhlc5o4hEY\r\nJ2i2H631X0uM2pAOW9miypxRuOs2fJf6AHMd371Q4lOlqN6+CBiF+l7fuRYj\r\nwdxBH+nmDUYBWNXlxl7AlFWlruh1MuYkt4jrgzodvGKpjNUg8rDyQzAfuMUA\r\n0u8Jj/HOyj6f1nRrG+0JH7nhVM7d/LVOkokItLeWuoGXPFOmkkYDuvDq7UYA\r\nxYm/YJT+CVIDY0foFDHwH0Cd84JD6OMp9IE=\r\n=VdyF\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.2_1679423022506_0.4196703576588283"},"_hasShrinkwrap":false},"2.0.0-beta.3":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.3","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"dependencies":{"pouchdb":"^7.2.2","pouchdb-adapter-memory":"^7.2.2","pouchdb-find":"^7.2.2","uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"8064f7e879b874e4f589c87a8f55a94ba161c0e5","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.3","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-sQcCXNz5tkk+10v7M7ZdrWTDboEUDjvB1lh/dC41ca+hCoLXsunK3PvdBN2/8Ft0xmCix2UdvVvHuBp28avUPA==","shasum":"c85bea929b685de9a318350489c4b73eb893d6c8","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.3.tgz","fileCount":84,"unpackedSize":219238,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfBbBdRrpr0ksqX5nBkna7jqAn23yLABZa24RsEjtCLAIgGALsGmteQrcG4RJ8WaOPZODCXswlNLOyafdpHmvCuP0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIfKfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoCNA/+JdceIjyW1VFWZptJn1AL0ul1peoKSshKAmlA4ikyHHRer67I\r\nnpUosGifIGSmyEWD3h6F6RtoQWpWXLzJ50mj+Uvyl56qbNJ9pn24CSGjhPQl\r\nnteFlKcJhWnB9+24A+6R/rTNhD07XdRKP+jT+jvNA1Yqbw4FPMAZgKxbIG9Z\r\nU7ay6J9QMigf5uvgYSzgsQJ63HMBxujvbgG5/dIKAoG9sNrNNP4XOa4Tekw0\r\ngl9ddB5PRacBNzSx+whDC3uPGsZn1z7TyzCmfvIVNHazUGRaHWKYNqmJsnsH\r\nRgtjHgf5GzrnnUvp62OKDYuJ9G+RCcwrJP4YsgTlG+IaVRoDzbLjwYaxYaMF\r\nZODifMg3t5MrH0hWHaVB3UILjQnowcasXRQaPLJyR4NXLYzlm3bhuCYoon5q\r\nzMoAYZBdUxHYT/4KxgH/3RBbCvujGxVB3smZZkwi8/XvlAC73ScsjVlQXmtx\r\na/tFdWuw5SI4ioKMEFanzctwzeIMjpgFE44bxX9SShC0LI/0+4rpiqxXS/bI\r\nQm+fFBpEHJyFnjYVo+qk5lFLECQXmFENbcK6xloDjJ0y781lo5LOb+Crkfht\r\nANfGxuRwgjQ0RZr23c4F5UZ8baKvA69nSYc1pooHCPm0ClXI6wLf0+KyxJGi\r\nNhcI9DCbXnhXXspVGHPv/nh5QOtKpub4xTs=\r\n=z3dV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.3_1679946399147_0.39044539103241305"},"_hasShrinkwrap":false},"2.0.0-beta.4":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.4","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"db6befac816658512489bf22dc83c009ecfbe009","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.4","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-AFF34uoSVdENn4KkGSiHPlvdRFzkgS7/T1lcD79Y+SkB/cXQVOu2tm7iApJt6WinYFcB/nrepKD9/XFuh0xHlA==","shasum":"ee1ce85a62ca2012933f12dffd175fbc23398720","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.4.tgz","fileCount":90,"unpackedSize":227317,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJl6N6GaqSstt58BFKrWsJNvDRjnFVHAXC/XUqu1zHogIgCl2IZTPvX0I3rG5w+IifVltI9wPL3YT14cLhSHDKlrs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkIxslACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoKWw//XvSbY56F2um3Xh0WqCg4Z9JzzmRiufu9/JJoDqAQ/8aNRnZ/\r\nKqpbzKXqK7QLxP3fM7AFZJz7itrMOjXmbyIjcNNHoqokaRwIbwglSigrErAy\r\nZhQ1qAiZA+xB468vdmmOblTdFBf/mvcloo0w4PuUc/mkFNjZhJynHl3q6ER1\r\n+mixVJlmKL14CWs6onlJiyjPPKmGG3pbYVaq5B4Isgo6UUWxMCiJS1Iy141c\r\nqa5iq+tDVA2Ok7pdB3ax3g5Yb98nGma/z7hj+6VbQB8+vgc7nEN3JS0zNWIL\r\ne9SFfHYGzGJn4pj/0dr8M0PELrxpavr/un82uOxVvvk6IIqEyg2ePycP2rZN\r\n3a2YcyBtj3zLXCFxPNRnl5z6aQullKh/UEmLViwyP3v3A9uqAqBDJ9m+ytj0\r\nZHQ64qrhRIiZu8x8w5Gzr2uTjR/H3br0q9zjhWqP4TmlPHUuEIj+EFdyFTXL\r\nx1WjXyikrnvZxidI/fM0hiY/He4P+ytqnRpAD4mSUWoM6fY61Hlrjj1nOM7r\r\n4HbnO9D+3VAAUnRLyLujgNmsUYcGJ6vXi79BUc+gkmQu6JbCx8AUpMDHCXef\r\nWpfYeMYBQ19TLRxtuBlGjVzpkLic+EpTktRRhg98AGt8vHE+7JAytYdaGoXE\r\nERByy5sQ4FHxoG4ljpHqyZi8YnR4RG9TkFY=\r\n=wzyN\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.4_1680022309089_0.7405975590009206"},"_hasShrinkwrap":false},"2.0.0-beta.5":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.5","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"7c33249ba32d155f125ae829c78a3048947fd31a","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.5","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-gAlVgmkcHVjlui71Kb+xMaPnALqYZfLNoour451RCnFtjXtbwYI+PmkMhEUiAqXiTLkgiEXO89O6VVdYHfIkJw==","shasum":"be4ac831d87d21141652054f16e55ddb87441cb4","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.5.tgz","fileCount":96,"unpackedSize":230253,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEDBqha5RBOd+e8r0Ex/SArkLNJ2CkBF2OhdUopi+2a2AiBSZEqqyNg84a6SIvKDIG2HCGm0/o5QkEZKVJT3NBUyKA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLbiwACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoPlQ//TCU06fIGYceDY06N6W0hxZbktFvXdYV4bDLbrpnKix2uGuyr\r\n58uQcb+OB6+Zt4iKJVdSeBwCLV4Y8NqhlMli8KMfRU/gdKFkJXR7RuCUyqxR\r\nF5HPeyfCq8DVay3o2mFyJZ0UoAEdhNplB3Bxo5hmyIFfz24RF3l1Lb0w7DxV\r\nPsIyfOG06lJpuNBDWEMWUHt6pJCtu5ZCSHY3o8X8ci21ACpIFRhU1FImg6f2\r\nY9AYEEBGrAWYdV8QQyHF85oopmiuUtpbG1qRK+pDmHCCpHUBPJlCN2Vmjsqz\r\nDDJE/sdXnZ6BN33AfCJTa0AGJmC0srfOfky5cYx5bBlO2wG9v5iZX1O46pBB\r\nEMHyXUdGOR7Ck0om1+c7UaMOHmP2sn4fpBQh2tIR4KkKjOUtIcwfXZ05uf0T\r\na3BkfIRkvs/uoKKSgKEQZZBg+rHNfxplLYqo5qjXm1ZwIFR0pBFnahawv+72\r\nZlI5fC2ugIhj1VPu2HpgTx/P3WjEP1U+mbLjUDNW/+lgtMHjR+1mt26XdhwH\r\nsCQMscvIW2+3pe9EqzTXlb3MMWX1E6lR9Rjsu0b7wuZ+n8nTG76Nm1vZEon9\r\nHEnw2k58dzYnSCAWO4NBAz7imFY9P6iIu95L3vMTv3TaJwfBg5tmfkNARh/F\r\ntqhCJ5LhyYweiBvDSCrKUlc087eHQauJzC4=\r\n=+dcx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.5_1680718000224_0.5064449239102682"},"_hasShrinkwrap":false},"2.0.0-beta.6":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.6","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"c7d8d96881593fd8799141ff3df8eaaad9062f0c","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.6","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-mDhJM83cq4g/HcNHv45j0D3Os9iC9Ra2gIv0bTYGHQR42JUKv5wFV4mcioxlgTM3N6ZjFEaozqOMhs2lS8OFIQ==","shasum":"0885bb0818ea568dceb43b56b28ef8b49a6367d6","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.6.tgz","fileCount":96,"unpackedSize":240698,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIKWgGaKIAjrjAIAXo6sRjdS+/CX2NDN5/FRdYCVyWFQIgCMbJswVm6guxL1bFnI7BMOK0mBSr6OUTvKF/0XTn9/4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLirtACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrORA//f8wP7TVOcS2xQzm5FnKk3DqH7ExiL6+45TRoYFtKtpPmoLqj\r\n3UUKCHxqJ0gHdRHTwAqcEKN7chHSIBmgfCy4XMW8dG/wfsC2DhTaWYOIaSeP\r\n5EXqwjkpQFN0D4YYSUWHeBVeFg+jjKKThbqYIh8AL0TZ1CAGQMO70qfZtFKd\r\nkzWeAHDndMKY+sq+IL2lKC7TaChDTdagiDeYuW3zxb0WwDWHrCCJtV1lwHwN\r\nUcfrsx/p+LYkwUgSSM0hcHygzHaX8gCCWTmXNdbGRbZDsIeEpmyDvOvKcL4d\r\n56/yITHjc492eei028MmT9hkh9UkoHS6pulv6Vk+7Q573HRIkRyPa4B8gyBd\r\nJr1/GXNjM4k9PNLrOtQjyDpfOfEXQ+sJSo33Iu6KRdabs7pyTsah+PSFqh6y\r\nd4O2GEFgiIBXhKaNu/ld2hGcLpeDANtadySZwwcxzVuMt0Vx60E0mlIt+bVJ\r\nQizRAkP1rTF1UDo/GJi7rDiFFPUaQxkPnA3TVtbXJWnhgDkmpS/qHekI8ejh\r\nZb94JuNwU1zhxaIfBnTLQkjZCH4phKt74SBcVkLlDKqs9H1hxojbjn/gQLEb\r\nBy4+dkKLamOCi2dSexYMIxy+Y5ofr7JdMNxV17023AaYnkUDLmT3Oogy0ge4\r\n/L46kVDokmIO81+hohKVBq65M/XN5HsT2zc=\r\n=sjTg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.6_1680747245648_0.6485300547909321"},"_hasShrinkwrap":false},"2.0.0-beta.7":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.7","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.7","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-bOz4Muu6rxjWk9gmEu9KoMYCwXJxZ61taF33bbHUjjHLPKcxjtgEcxgRbJ8vOxXvdKYB4AjgPuL9m9qojIrbVw==","shasum":"16af92843870c11837cc23cde1314b3a1a5780f3","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.7.tgz","fileCount":96,"unpackedSize":243410,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDnfVFlWuaMU2DxALqnrSfFfSDwW5QkxXl017EDWC413AIgII9y3/lKg+GbYfUlVa9LenBzZqQkUQqF0YygxTR8+cg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL4NaACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo0ixAAh3IYc4Yx0QC5n8NFUZVRwFeUMKDU/BLEBZxH6Oer1p51rqpY\r\nYoYkyHEQc/rvtXFeOJXO8OWsA750kUL7Wir18iUevkiqzb4+CApjVpZ80/sy\r\nzG0u2dNwSpFPQ0P8z/CkNxtjf/JBKgjC3AmbubzyYKQiImiJFQFM25pA19k6\r\nRAujcNU50wPT2pAUqGyAeAkbPU8+JBWmY4O8Xcxvf1WaHtc/mPZM2ps2yoLZ\r\niv1+oTvS5/aLJ+pQasoLS4kydG1HCNJhL1HGbr+nNUImCuq9YiWT0PUFOUfE\r\nOKr7exsJYxiQQ/cKvOI7yN7XYA9s77nip9CgBhH1U0VfMq1PR8Co622vdh80\r\nHdeer2A7m0h1ZkWhSw/g1miLGZaKuAovc22BWON5+xnukRgAN4q3Q4l4MGY5\r\nbCqLuY2tBtGdIIP96hzCGg+Ud8Vjw0eq6JqDjNTrsfY+LM0GYqTOEP8M6sLp\r\nS4g77wUHF+8D6GE2XPh6YgzPFrr1TJ+eNJJbfNRg7iXj6vRM4znCiEqF3801\r\n6apkyKL5PMnxtWngr35lYOO7ffYkDsfIgwZorwNwTKFL8bwZeRfDQD+wY5YR\r\nYxT/GLTwa+XCR2GVAxDaCvkpgCadQFoPOdMIl4IG36kh1FXIHHMaJqV5aNhX\r\noyfD7P7rizu7fic8cX+wz3oMmoyBZRr7dfI=\r\n=NIi5\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.7_1680835418408_0.03047418141027136"},"_hasShrinkwrap":false},"2.0.0-beta.8":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.8","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.8","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-ddizaMXJ9HDLcRxZbvIlljocFp0ngwyXesblB+W/st/5RPCmM2flVDZDGyNQcaF1plJTvHt7FMzlUtSgW8vTtA==","shasum":"ef2af4f547d61d989451902749bdbacfdb2b84e7","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.8.tgz","fileCount":96,"unpackedSize":243879,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG7cU3RHaJXvSOabdNRyxPyt2qmQXl8X8NzmqIWdvao1AiB0kNBSYT9QxA8/LqqByrvhavESAjoN4EX173YOoM7w7w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNrBCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo8Gg/+OaqjQOy/sv/ejyiUi78DIhtDi+u3X6Pf5jyB2zML1OR6jgbB\r\nlzaw7uvPQ3yrGpNfq8TkMZ8yLAHpaUS2iyPlp8kxufiKF7auuWs1ibiPIWJ6\r\nlOtmIf69y8E1qcqoD8Q63O/6k5XAdQbgc8Znk8SnD2dbnPGmxV3OFlYgNEbw\r\n9bo8OeIf96SMwycWvpAue9LR6xzsqci1Dt+xVBfhsmiC0by4ONX/bTRj37mj\r\nRDlszPLREWKN7USCwjAAv9kC8nfl4PizXIfPhYVOCmm8ivSKXa3ka4qjzmmJ\r\nZxnM0XTdnS8SYBmedV1N0EgzNI2jxV6AqbaVq1OpqeajJ8mBs2G+iqrw6QYf\r\nGbfhOKvQCB6jBOL+OgF4/F2UcsbXLK//htBExgpTMAv6X0NbykC5KvsDDOjp\r\nO4rNrHgdfXz8dt6eMSSbpoQn/BeDe7gJoRki3QaRN08Slz+QXodwPyll+jps\r\nylnH0TkasZfJjJzBfklOwIpE5n25/CnAdr/5GMJdKfPFoISY5grGSVh807oF\r\nFq+czCROeZJcsYOVoRkaxWE/UR82DypLyhY8WQYpoZS8BmGmj5tzE81FOhys\r\nSOxVzZQFC3ZsGKcrJPUd5cjgSlO/y9CwkY8pWmEQ7ZIiXo1GCCfVM1dfIGoO\r\noAvizD4J44XBdRdxvti+7DLG7FRTRFVGH9g=\r\n=jSQV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.8_1681305666120_0.2515700401062011"},"_hasShrinkwrap":false},"2.0.0-beta.9":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.9","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.9","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-Xs7RqLypw7RW9SqGyqZGVoKaOnbY18bweNKU8CxhWciDnTAMekG85tTFjQrz3MaHiFPyy/BImpl/DcidnKlDmw==","shasum":"fe54905f3d2f0135e4a74d9a086adf88ddf6fe40","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.9.tgz","fileCount":96,"unpackedSize":243914,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHZXRN9gBM6Da8ZmbsVIJZ1Zwxr8f/1m9OLKUuZK26HkAiB/QLY5UiY3B9fR9kvmTKnceBUBCuqg+Zx25OLNPccmcg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNsAjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqm9A/9GYsyK0ZhXy2jOIsl6APPWmyG+5owFkruzVKjme9YCgqCpBsc\r\nvhhNvnmzqp4+c2+LGzIlQuC9m0fkkXSR8U0kdg+HcPARz2I+llmIwzhyKynQ\r\n4umZMo5bDEiVV2i5AQ1QSnRCoz2Ztv0pv3JXgYYZWAtifxTy5sGKVgQjMyXu\r\nNTe6vESMXiCtMDKJuLBFYI4f8z+QBywehPkj1FHMMTORkSfa26EMJrlZqeHc\r\nKxy06BjTPC3myaxYon3/SL7LnIMDws6nNlqu1W9gOifSJzy40v+dHM4ALV5G\r\niDW2014BLLI0PH0gevD2fRrcE8hUuu8gTsg5qln7/5JRvwCuR3B8Y+iUF6vf\r\nVUKoA1uI1fUM2MqGl+WeSs40fTbvxyLdvzNCmjBjy5wmSxVwWU6mEsu/jwJF\r\nad7xlMjFjOOkyU/5yEa3TAaMBjC+SijcZpknclEVz+IuvGkw2HjpdHFzobBl\r\nmeysJznSu8ThsfbEERnyjAXMEaTWCZku0M9ylnMGQdTrzgDtsuuBvDxDv8b+\r\nGIeNRi779Vp0Sq8hWvApXL2x8cRK1THQOr0pvBhQPRzdREnVqcYSX3mRYALg\r\nSzjvqDnWRrYKytcaiKXnsAiei43u0+lk0AfUH+0xdBQTXxcYtWZlvpE1AjKa\r\nliTHSCnPuaSApg0Oo+a5CDA7aC/2MuxsXrU=\r\n=Y2Vm\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.9_1681309731127_0.7992190552054985"},"_hasShrinkwrap":false},"2.0.0-beta.10":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.10","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.10","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-LFSYdo62oSRXDJRp78kJxVEt/Fx+RxS2sB4q2qfjrJ7VEu0/9xhWcgfn1URfPiOSYbtfH+TVmQAVOkOmvWHcTQ==","shasum":"cf962ebcb8000e0ea0ec25e5523b56a2747de4bb","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.10.tgz","fileCount":96,"unpackedSize":246562,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICiIQSyAc3qbrqhba5bAePO4UWdF/bH5rhSbYA9IUOHJAiEAvkgtgJ3fKZR0oecEJlTJXmpAmSrAVZVnaQWmtQZuKKM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNtHkACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqBcw/7B85RO7+xaZQPTMPZ0VFntEddbro37xaM9eFL1BQNBji6pS+w\r\nJIcWR95QigyKupmJsgyAEs04RU7RfepDJdjpEPTOBdUAcYP9ZRazr1roD8lV\r\nEcbXRf6aydiH7+WwN9+WrAmD/Ph+imitlpa1xmFGfr+E3HVApKnWcCUEz/SG\r\nozwuLjPra/kq6jsG33E99/klQbJ9SFIFo1uAkBG1B9MUm7RVfLT3P0Ats3kn\r\nRBPy0Ij0p1Lv127bmFkbeAvSbBc0iOCN7pN+ApgklS2pTNDX+xG+dX9FtB1m\r\niJ7x6mpiYJb04votZWu86Lakt34PG1TemZGMPRAFRed7+9nCjcHJ0Mf0Y2H/\r\ngb+vG35ovgrOIp2fqRUQyuiMporLOf4NrC9YlWw6n0A36dlnUmxMPW3Xroys\r\nubTMm151wqPT6zvsBmOqs9YMc+0kOykYnLeDH69UCJpdrJpvLj2HIk0KtIed\r\no7fH4zy2TofqPUO7usfOlZV2taEFP/V5D4ZZN6j6Z5oNjV1gb+KpYyOzeqST\r\nmfADX4PY7W0O1gTgsq/Z3fIuFVmeui95Iz0vnNtkwhjGg/FcAlNUdvgDcZHs\r\nLi/CudfRsgH4mbdMiMRTKqZT+KOXgVBRE9quCCC6uI0h12nq0krwQ5TfGsni\r\n6CwDQWHPbGZoNU/HhhAlGVsmN7BwPD16oLg=\r\n=8QzO\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.10_1681314276308_0.6783823884086688"},"_hasShrinkwrap":false},"2.0.0-beta.11":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.11","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.11","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-dxPfX+Bt1/qSvhM1xZ0vodI/LAqArHLGkYmYSMytfGBGXyhog9b4+/fFuITY9lG2GfquBrrHwn5tQ/wDJxcOIQ==","shasum":"6794f93843205627d3991e2b0ec2bddb95732f3f","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.11.tgz","fileCount":96,"unpackedSize":247326,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCazEdgHFGp3ELVDU7gozTIcPGPpKSECVzO7jgfvGV0VgIgSrRa/kD0nVv10yHW13TjLetEFfFKV7+dKpVjHD5HjOE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNuH8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoLog//VoKSncV5lBlZ4BJwQupfXydrL4vdZMSOWOIGPm5S85f3znIL\r\n9gUpqudrHN4uK/r9ohY/KDquR4HH2C1S2+ptqJ4BnQEqCmVc+g0SEgf97A7v\r\ntmvl7TEzvgdtgE88H4oLauELMcs4XqeHmS/rJiBSHdOUJ1QLQEf0VF2v/Bp2\r\n/asY3GxuqGKneCVn7N2RMfhiKIO3totuc/PHHTQ6m8Fz+EbPilrXIQz/abZH\r\nh5lanXAXMou/J1mb2hg75HKarlPahnrPZ4FrL0L3DYRkc9U3+LRc/dhMw6sv\r\nOfTsu4zXtQyo7V0hRWAiDIuYKTRdCo7E3cb+bnGpoKqxp78HV9LvFjSWBWBG\r\nSPTzzjEgP2s0GHEfhKcUR8rRwMprMPsp5bBugACNa2XRi3jvC0qSiflmktO7\r\n29vS7x3Dro00y+LPGwDsU0WotJsKp6Myjtbl7ML5+SveilKO0hKL2bY8GkMm\r\nXnpC72vdGPeq+ovuKDSv71OLXs8aySr55mbR6t09D0N1+WnRMhRZIr9VXvPY\r\nij7Sv06me4Rz5+xsqRidpiyUQU+pFiQ2i/aZPYN8+6emf1naXL0f6MTru8a6\r\nWDc3GQSe0UTPsfEI1+eJ0nCzYH5Jt/jJ+JSNN4WcjcLRS0Nb9zC/+EM8nSc6\r\nnHJV6ds2mKJcP57RHi0ltCq3MeIqHCAXcCw=\r\n=CKt6\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.11_1681318396466_0.1774333853020038"},"_hasShrinkwrap":false},"2.0.0-beta.12":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.12","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.12","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-jlMzX3wlJS1KriNzlhP3TuqU0kJHjPx9AlNDYA6p++dWCoWVHgdBUBg7BKlejeAKWG55oloJwGMTv2N0uBc3BA==","shasum":"b267c9e2a51e51576752bf38179bd23937ddbed7","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.12.tgz","fileCount":96,"unpackedSize":248880,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFWtR7ajc3qAhg8Z7hA61g0j0F+moyb5RUusGZJ3sYOvAiEAvIT1vzgywLN30/8rR3H6S/ox8VQdbD7OCxfAJU7rfD0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkOLiYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq5IQ/+JIi7UBYw5quAXS/Dt1RNZbkZABvIxe+CIPpfNEdFIrsgATvK\r\n0aehrD99y2/Q5NTUD5bvwuqYtbHjBsYDRq29o9KdMLzpjb9spHXfuAQjPYRI\r\nlZHXoBsf7rTDvo893DDQEyP/qoFHKQmgtJ0QcTcU4t8Cg4mspCq351lG2DnA\r\ny+I9qxI03hJuDtedVk3FViS702cBUOR+Rma/oAl1RlDpvCSDGXMascWKW4fi\r\nw8A6M99RVS+zjo7+8ylS+y+RPzK6K6i5VU0kZvF3/bFp/sA2hLmZV0ssNJ5B\r\nM9K0OD3w6qZFjcS6s7a4rGq1aCjESVvQUaKvvbP8tlolHSmsrUJoZdZBwCuv\r\nw1cYzJLJpYRHeqLiAbKlc5ayUnSm5f1o0aUg6lvVd0r74CcZjfTu1zPVgMQ1\r\nje2bxF+SgQZkptZ2j2AsRw/2U7fItyIwC1XGiJlKiDJoam3z33PQqCOX7ot2\r\nTZA3B85WPfzcMJFQCg7GbAraTccVlDegXgNAjLtfskPbQhVjLGBFTyWFwGfC\r\nw8sxGi2eFISpXJKU6GrXnF8hw4e/AGx87kLvInKu3JZNkbp6dVGeMgEiKyw2\r\neZFyBn0t9k5fOXJ0XA9zlw3HnJ0+YVw1B5wL7eDvkOHkpwa9iV/G1YdAmmst\r\nmTs1pb3hcmu+eH1j41fuAFOwf2T2ScR5gdw=\r\n=N1fI\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.12_1681438871850_0.2333962301593664"},"_hasShrinkwrap":false},"2.0.0-beta.13":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.13","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.13","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-4FzvoyiHBEZgz+IAZbq566deOuAmFZb/ui92ZFmfDVWiBKwwNsrxyCl5QmNKRzRg4pQ7K7G8GbtkYeeepBZE6Q==","shasum":"d6c5ce09b2738a37d42c3d27dd8d94b80eb337a5","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.13.tgz","fileCount":96,"unpackedSize":253456,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGsMwOU47vMcCRcibRwMFtxffEb5bdNbu16/z3N8pVjZAiEA4Pu7s9XKaQEh3TFlJHkaDMNK9zMcaWusXMdCav0ltLA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkPrsAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpYHQ//T2vUvrSitLAuBSM7CGLLUwZ00cLkk1iJOGGx1y3Q5aoj+hvy\r\neelkuOui2T5oJsvwf9kbjYlM6SoOSK49tOlRhC0DvGceniQYO7LwnOnv9z1w\r\nd9nwN1b40OU6e1TBtQ436O1Q6TEb/TIX2QihzEPojl5vksHpcBQoV2u/E8tq\r\nuii5YcKggPpeLdjki36bgjosWLw7i8yQfYVHTd/T/4uZ4yaj6MYS3ecgsf+D\r\nbxTTtMlGPMJ4uK6c7DMRcpSTS/A0un3qurbS/qat9jTBlm30AC71js5OoYw9\r\nPwfH7qwM1hWEuD/AxYoXuTzE87B2BeTv0V+80lsDO2nCO61H1enIb8+Q9/6X\r\nn2HNPvnrsTd5p1GLpvSkuG8weDM8rR01+JODZ2G9awaqWmmX5/oYiZI9fvkC\r\nAQT+W/9lV8i+AMf5B+5MMPn2tw1qoLxwUAAkg735rgIVYP0WeUZeqvOA3Cr+\r\ncQNrphLwXCXoit3oA+ZbYlMjC7H5ObdsEMxCgHYqSJMu9eAaIs6iS1IPZmGE\r\nKhM/rtopMEZMd/pk91v3j4+VQWoL+433VGF8lEDAdsTa3oPJpBmxsQ1wG2D+\r\nfVqxSbI8ui+66r9i7vIvEnG/boqMsmF005E+YYEEqVszeyPncUEM7nctBXE2\r\nKxLxi9hXDzsGfcsDbuXZ+Hvw3eKx/RtVqF8=\r\n=pcpl\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.13_1681832704574_0.1200100983242014"},"_hasShrinkwrap":false},"2.0.0-beta.14":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.14","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.14","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-s4tRUX4M36mzWUyQp6KH9bT2LSSJf5daktDdDEkpBCwxq9D8xksqm20yw94RumzxJfX5btiuRcFryvXhmlZYyA==","shasum":"547e60b1d71f5a3aeba567e184d07dd0fd29743c","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.14.tgz","fileCount":96,"unpackedSize":255070,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC9yrFU2YycHgHSce6a2+KURk5BoPI/Huyk9pC11IB2XgIhAOEXZ/KsF50Swdy7wJygaNKx2dc8NEcT6bKGc+lOehWX"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkPtmlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAjw//fwUROgwEFZw4JsxPUwS+Pq7PtLiDp3YtGzNebc4aUQScV7MM\r\nAZbyA9rDO/3nFSiEEcQTaEMGrqE8fAjmbAezKW8z1rq4sKmXc88jOWLTn043\r\ngnKJGJwyrUaKv2W41g9W3Qj5JuccL6Qq2vNVHp7FPsfMVHRcCrK3WknJGDNT\r\nG28IJ2PML6ApUXr+g2On7EJlaltmzb9ch7vaUGve/siy5bjYtaNAYS9g2TpO\r\nDuVGmRnMiV40UPN3530GpjcyIav6Jl8R8A7MRUBQl+NE9YJyLkvP5p0ORk4r\r\nbAaaLuG2nvEtPU+J8lpGHOBHqhFOZmO+xFxjtlR6noDL/ZFr/CmzbAsuMtDM\r\nObvYOlVVB79f52j7E0f+oPM4fqWvOLhjFqfRer5rGWbSOU/Ne6gC1hvh6LP4\r\nsS7YYB3th9zJmn1LUcIX5L7ydg3n02Ko0pAM5yQAQXvcMLw6fMMxW+Fh1WfD\r\n6LJT10PCoN45li714O5hTm+g5+ePo777TBs9HYBuWOM2ebbhAjGtTlhwQEqs\r\nXWy0Ly4ussGPa06pzW6PNQbw/LOeAsJXHlQUTfzog5XI4jUB+3qImaUSubb5\r\nRCUyBaK81rVtJxRp9EzcNQs+kS8P1N0W3r/G0vHSGeklHU3ZEoFYstFTbSgr\r\nmf0euYOHgA/q2nGF5xDRn4J77vKbBDwN3S8=\r\n=sD+M\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.14_1681840549056_0.18388184569927768"},"_hasShrinkwrap":false},"2.0.0-beta.15":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.15","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.15","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-8BcA2CGMnP+X3YaHjBGHQqMbOmXKEgF4g0JhMCEhpYi6H/QvQrRg6GKgnr3oBJvUZ/IO3pdSKbM0TOq4a1bUvg==","shasum":"a9cb9068af770a472059b23fba6038f497b11de3","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.15.tgz","fileCount":102,"unpackedSize":261247,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDPjBK2j6vFCyvILLyevFNAfM3Z6fjWLN3OroAHPglQuAiEAyb8tHiIlKM7c1QBgrNEId+L1iY0Ke8/edE/HaJtDM2I="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQYIiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp53g//Zx89VRNCxJ6gJ1WXjrITw97VzblkYWqxQrEsE2fyHy3iejBI\r\njKnwEhqAfh9SIOpMzRd5ZieEvro7OyGeEbFD4VzoOYGvtLHJMagTxtPd0ntg\r\nboIiUL+hthXAtz0gB/wQeCuobE7SCZsQ5jLS8WyyQ6YfEpeU2AtbjmsL95Jw\r\njnlizoMCBBOvVsMjOB7DkQNUOjXaCWBloaxCe//3TFjRdBEi2EH3FnNOVb0/\r\n98ybH6pZ62Bp7e96ncdA7zUPtdsBovvhXfEAQR88ZD3NCSwz90E94XMxZdUh\r\npbQ17JS8REqclIFBtItnvMxQOtRPuKuaO2c5dakpkAEp3b1Lq0siH1+5Yp00\r\nGiFxVADTzDo0ERSReBy/txGVMcbn6pYuwTTRRj0xAk5eTTNCFTyVKNTbzFc1\r\nNFw44f0Xtjc7PI2RFv62Af7SFKoKxDsmc5T0MN7cqP2/xc06/53q0eDoNBqL\r\nEvv0d6cn/cw3e4wX+SKNvu59VdVnUJvMR91iRJXiUNUmlN5Xh50fx+aiQLAy\r\nIVsABlKJqK9RjPZiDUfgzo1n3vKgzcGhP4IAJ51z8Avjv8z9xPuwWuCekPbT\r\n5RtaM56PObDWnvB8qd7xA1N69gexaUHfUUkd4Vt2FTTgzQEk5BgnR11P7MFN\r\nrr5z3bc+L7hld9YxXxgaK0zpLGDjPpGYvs0=\r\n=Jl3h\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.15_1682014754592_0.5219453970604699"},"_hasShrinkwrap":false},"2.0.0-beta.16":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.16","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.16","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-BWkJ11e322p+sBwr0KwrJP1d43E99kqNs3eYlUOwUJE6hfCPCwwlPWfYtnZwLCU3hoNL0g6T4oZBX0zTMeJ3Yg==","shasum":"960817b1c86bb00c7039afdacd52ccb07e14afdc","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.16.tgz","fileCount":102,"unpackedSize":261214,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAEZENvPAmoeR9T9RmOyO8UfyIiYM8er38HCpxjkcxbAIhALemZcBje73woXPF/L1QygAgTcmBO/BnyvKauq3od8L5"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQYaGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrDlQ/+KaD/9qgv3Ho193QmPeftBBOYQb6LooVubTB66rRFxDOKa/SW\r\ndrV4kRnWxPaxnTylHRr3TkQtdylkU4/snIjgzIEevAUumLubnxloxyaAmhID\r\nQcxs6s2UQJsfnP2i1CMpdCRdNDT/T9lqsBrMGMqUxj68WVXixSS8a8dMG8ao\r\nRpyAjOPd6MqIkM2O7ijw3IyPg8yTUGw12NEOj/rEspYW6rnRRlgL6EyjJv+s\r\nakc3N1vmVG2sewtDW3hi6sS1e2233BGgOypbe5qFnrPlDkASRDnlZ62rocXI\r\nF3tCvqveQed3v96MFiuloVr/mh4Mme3D38G8ymylo0g9YRw9dRclR/dp/T00\r\n7lLCCXq4eXi/Xp6A+A1f2Op6S1gEuSl/ltkwncRobMcM7XLdTj+al6i08McR\r\nmXPURl7L8JqWE05aynYVc4fnmx9yHeP9z0FXkFOoret44XGN5HoA0S+NrtGY\r\n1ID8qHVrEV1r0dNe9CC9tI2VP7IK7JP4ME5FgVRN98iFlbEu/ghFOkC9Dwvo\r\n7HTjLQSp4Sf3Mr1O8LAQJduqq+sZrh3FMZnzyZ2RKe1poY2+A53zMw+fu422\r\n++AUBfUl0H40F50frXSG8gEduHZY5LPJPB+fJN/KXmCAkZ9FLX1yj+9pb+A3\r\n9iaHC7la/Ee3WXmmdrzec4+bG+xb6Ko8hGo=\r\n=6jQv\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.16_1682015877897_0.2391539126009401"},"_hasShrinkwrap":false},"2.0.0-beta.17":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.17","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.17","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-bMfwU8+XxcYL2uSqPgCgcEqACSLMruYHEGrZK5P/U3DXJqZVaJzI3ynoWlfruldj7m6/WTuNAMw4RtB/9DSqsw==","shasum":"7aedc2931238e09f46e9363cc121e67e08a542e5","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.17.tgz","fileCount":117,"unpackedSize":270738,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFn9u9OSFiK5XmR6xUoKhHZIE5MDZm6fhbOijt+IFRNlAiEAwnCwdqiAFU6p/JqCMEJ0ABEmStHNRajz5Bt3TAj+/EY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQZ95ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrYDQ//evWGJ8ILaUUR3loRduAk2C5aNY+IDrLbVIW2qyZu+cIMz7NB\r\nFCUJMb/iGNRRtaY/TKrVH1j2XQPSHXvV9gkQ4rFnmHZBoE+pBDCEKBpB5H65\r\nfFkNFBpAtkIS8KgMspvZfEx468X3Nwy0N8bWB9dxcnKZjsK2OWCyDGIrFBwe\r\ne50gtpOf+BbT+dfF9ikZQnEscNSPf+aWOfVxYvMvEtdpE6IZL489crXUU0MX\r\niVTSXyvyvZ/03L+BgI9Bmg6gG+DRmGjQ51iwySEgQy1IK/U/aopMkMjwJvAU\r\nXn50v1/O/LRc+Anr4kJUdVONXqrdNk8NR0bLTCqKVe/klf8T1Dnd5piT0Joi\r\nfGbsXlxfdqBrPmXfEdiNBmZv+sJmzPxkkZx1X65SxJgrMxeXncR51F/M9zIV\r\n7//DK0g3DN997Va1mH353j7N8zFZ3qB46jK69TD9+9rGcesdF+mYhmDwRYs9\r\nQgu1/7vclb8hG+wcapKM/J+usPZvppMl4fbr9QhPio/vZvpofxRcD7kpTTgZ\r\nuoOqTaSSpRJ+IeLktjymU44s0HMCANnky0WeRu3jQvVfIlbHwfukgDSMR5fA\r\nWjJdLU4DDGhG7UUeOwHqyaQAQk68Niie5kSN4g5AdeTx5ypuo16D14+YTe3Q\r\nKw+PfzVtJZPnmicV7w1CdzKNtLVuQGzVCno=\r\n=kMz2\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.17_1682022265197_0.6476219771075218"},"_hasShrinkwrap":false},"2.0.0-beta.18":{"name":"pouchdb-entity-fabric","version":"2.0.0-beta.18","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb-adapter-memory":"^7.2.2","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=7.2.2","pouchdb-adapter-memory":">=7.2.2","pouchdb-find":">=7.2.2"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Changes\r\n### 1.4.4 -> 1.4.5 \r\n- Fixed bug with `.upsert()` when spreading two objects with optional property\r\n- Added `markDirty()` to `DbSet`.  Allows users to force an object to be marked as dirty so it can be saved\r\n\r\n## Installation\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\n## Getting Started\r\nTo get started with PouchDB Entity Fabric, create a new data context class by inheriting from `DataContext<>`, create a document type enum, create interface for the entities, and declare your dbset's as properties.  Full example below:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Context Usage\r\nOnce your context is created, simply create a new context to:\r\n\r\n- Create\r\n- Remove\r\n- Update\r\n- Delete\r\n- Advanced Functions\r\n\r\n#### Creating Data\r\nTo add data to our underlying database, we must add an entity to the context and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem] = await context.myFirstDbSet.add({ propertyOne: \"some value\", propertyTwo: \"some value\" });\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\nWe can also create many entites with the same `add()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem, myThirdItem] = await context.myFirstDbSet.add(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" },\r\n    { propertyOne: \"some value 3\", propertyTwo: \"some value 3\" });\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem, mySecondItem, myThirdItem will have the _rev, _id, DocumentType properties added to the entity returned from add().  Those id's will be populated accordingly, _rev will always be populated after saveChanges() is called.  In this case the _id property will be set after add() is called\r\n```\r\n\r\n#### Reading Data\r\nTo read data from the underlying database, there are several methods available:\r\n - `all()` - Read all the data in the dbset\r\n - `filter()` - Filter and return data in the dbset that matches the filter selector\r\n - `find()` - Find and return one entity in the dbset that matches the filter selector\r\n - `get()` - Get one or more entities by their id\r\n - `first()` - Get the first entity in the dbset\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst all = await context.myFirstDbSet.all();\r\nconst filter = await context.myFirstDbSet.filter(w => w.propertyOne == \"some value\");\r\nconst find = await context.myFirstDbSet.find(w => w.propertyOne == \"some value\");\r\nconst get = await context.myFirstDbSet.get(\"some id\"); \r\nconst first = await context.myFirstDbSet.first(); \r\n```\r\n\r\n#### Updating Data\r\nTo update data from our underlying database, we must retrieve and entity or entities first and them update them.  Once updates are made, save changes needs to be called.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\n\r\nfirst.propertyTwo = \"some updated value\";\r\n\r\nawait context.saveChanges();\r\n```\r\n\r\n#### Deleting Data\r\nTo remove data from our underlying database, we must remove an entity by passing in the id or entire entity and save it.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst first = await context.myFirstDbSet.first()\r\nawait context.myFirstDbSet.remove(first);\r\nawait context.saveChanges();\r\n```\r\n\r\nWe can also removing many entites using the same `remove()` function.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n// remove all entites from the dbset\r\nconst all = await context.myFirstDbSet.all()\r\nawait context.myFirstDbSet.remove(...all);\r\nawait context.saveChanges();\r\n```\r\n\r\n### Upserting Data\r\nEntites can be added or updated depending on if they are found in the database or not.  If an id is supplied and it is found\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [myFirstItem, mySecondItem] = await context.myFirstDbSet.upsert(\r\n    { propertyOne: \"some value 1\", propertyTwo: \"some value 1\" },\r\n    { propertyOne: \"some value 2\", propertyTwo: \"some value 2\" , _id: \"my-existing-id\", _rev: \"my-existing-rev\"});\r\n\r\nawait context.saveChanges();\r\n\r\n// myFirstItem will be inserted and mySecondItem will be updated\r\n```\r\n\r\n### Entity Declaration\r\nEntites can be declared a few different ways.  Two of the main ways are to create an interface and inherit from `IDbRecord<TDocumentType>` or add the properties from `IDbRecord<TDocumentType>` to your entity.\r\n\r\n```typescript\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\n// OR\r\n\r\ninterface IMyFirstEntity {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    readonly _id: string;\r\n    readonly _rev: string;\r\n    readonly DocumentType: DocumentTypes;\r\n}\r\n```\r\n\r\n## Concepts\r\nBelow are the main concepts in pouchdb-entity-fabric\r\n\r\n### Creating a DatabaseContext\r\nA database context allows interaction with pouchdb.  Dev's can create as many context's as they wish, if the database names are the same, each context will act on the same database even though one or more context's exist.  Keep in mind, when adding/removing/updating data, all changes are stored in memory in the corresponding context until `saveChanges()` is called. \r\n\r\nTo create a data context, dev's must create an enum of document types add pass that in as a generic parameter. Below is an example of creating a data context with one dbset:\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n```\r\n\r\n### Creating a DbSet\r\nThe DbSet concept is derrived from .NET's entity framework and works the same way.  Items must be changed in the DbSet, once all changes are made, `saveChanges()` must be called on the context to persist all changes from the DbSet.\r\n\r\nDbSet's are very powerful and are developed to adapt to the evolution of the software.  The DbSet Fluent API contains many different options for creating a `DbSet<>`.  See advanced Concepts below for all the different dbset options and what they do\r\n\r\nTo get started, declare your entities and document types like we did below.  Next, give your `DbSet<>` any name you wish.  Last, supply the correct parameters for `dbset()`.\r\n\r\n#### Auto Id Generation\r\nIf dev's do not specify any parameters to the dbset on how to create an id for each document, an id will be auto generated instead.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n// _____ OR ______ //\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.auto()).create();\r\n}\r\n```\r\n\r\n#### Manual Id Generation\r\nWhen using manual id's for entities, the id format will be `DocumentType/params`.  Notice, the id will always start with the document type followed by the keys supplied to the dbset.\r\n\r\nIn the below example, we are using propertyOne and propertyTwo to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\")).create();\r\n}\r\n```\r\n\r\nWith the fluent dbset API, dev's can also format the values when building an id for an entity.  For example, if we want a date to be part of the id and want to format it differently, we can pass a function into they key builder of the dbset fluent API.\r\n\r\nIn the below example, we are using propertyOne,  propertyTwo, and dateProperty to build our unique id.  The resulting id will be `MyFirstDocument/${propertyOne}/${propertyTwo}/${dateProperty.toISOString()}`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(\"propertyTwo\").add(w => w.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### Single Entity Db Set\r\nSometimes we only want a dbset to have only one entity and never any more.  This is very useful for things like configurations.\r\n\r\nIn the below example, we are marking the keys as none.  The resulting id will be `MyFirstDocument`.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.none()).create();\r\n}\r\n```\r\n\r\n## Advanced Concepts\r\nPouchDb Entity Fabric has many different advanced options for dev's to fit an scenario.  \r\n\r\n### Data Purging\r\nWhen documents are removed from pouchdb, they are still kept in the database, only they have a `_deleted` property on them marking them as deleted.  When fetching data, they will not show, but will still take up valuable space.  To combat this, there is a purge method modeled after this [post](https://github.com/pouchdb/pouchdb/issues/802).  Purging the database will remove all deleted documents and keep the original data.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst result = await context.purge();\r\n```\r\n\r\n### DbSet Fluent API\r\nThe DbSet Fluent API is a very powerful mechanism to create a dbset that will fit the software's needs.  With the Fluent API, a DbSet can exclude properties when adding them, have defaults to either retroactively add new columns or to set values for excluded properties.  There is also advanced entity key building, adding events, and extending the functionality of the dbset.\r\n\r\n#### DbSet Fluent API - Key Builder\r\nThe key builder in the Fluent API can be used to build a custom key for each entity that is added to the dbset.  With the fluent key builder, the id will be created in the order the properties are specified.\r\n\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).keys(w => w.add(\"propertyOne\").add(x => x.dateProperty.toISOString())).create();\r\n}\r\n```\r\n\r\n#### DbSet Fluent API - Exclusions\r\nExclusions exist for developers to specify properties that need to be omitted when an entity is added to the dbset via the `add()` method.  When exclusions are specified, it is implied these properties will be set later in the `add` event or using defaults, below\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// PLEASE MAKE SURE dateProperty is set before calling save changes\r\n```\r\n\r\n#### DbSet Fluent API - Defaults\r\nDefaults are handy with exclusions because the value will be the same every time we add an entity or retroactively adding properties that are not nullable.  There are two defaults, `add` and `retrieve`.  `add` defaults will be set when `add()` is called on the dbset. `retrieve` defaults will be set when retrieving data from the dbset using one of `all()`, `filter()`, `find()`, `get()`, `first()`, `getAllDocs()`.  \r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).exclude(\"dateProperty\").defaults({ dateProperty: new Date() }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\n// dateProperty will be set to a new date on add and will be set when the document is retrieved if it does not exist\r\n\r\n// result\r\n{\r\n    _id: \"SomeDocument/some value/some value\",\r\n    _rev: \"<generated>\",\r\n    dateProperty: new Date(),\r\n    DocumentType: \"MyFirstDocument\",\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n}\r\n```\r\n\r\nConversely, we can set defaults for `add` and `retrieve` if we need.\r\n\r\n#### DbSet Fluent API - Extending the DbSet\r\nDev's can add more functionality to a dbset if needed by extending the existing dbset that gets created\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).extend((Instance, props) => {\r\n        return new class extends Instance {\r\n                constructor() {\r\n                    super(props)\r\n                }\r\n        \r\n                someNewMethod() {\r\n                    throw new Error('Implement me')\r\n                }\r\n            }\r\n    }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst value = context.myFirstDbSet.someNewMethod();\r\n```\r\n\r\n#### DbSet Fluent API - Readonly DbSet\r\nDev's can also mark a dbset as readonly, only allowing dev's to add/remove from the dbset.  Updates are not allowed\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).readonly().create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\n```\r\n\r\n#### DbSet Fluent API - Mapping Data (Dates)\r\nMapping data returned from PouchDB can be very useful, especially for dates.  When a date is returned from PouchDB, it is a string even though it was sent in as a type of Date.  To turn the string back to a date, we can instruct the DbSet to map back to a date.  If a date is being mapped, the map function will show the parameter as a string not a date.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).map({ property: \"dateProperty\", map: w => new Date(w) }).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst [item] = await context.myFirstDbSet.add({\r\n    propertyOne: \"some value\",\r\n    propertyTwo: \"some value\"\r\n});\r\n\r\nawait context.saveChanges();\r\n\r\nconst found = await context.myFirstDbSet.first();\r\n\r\n// found.dateProperty will now be a date\r\n```\r\n\r\n#### DbSet Fluent API - Using an index\r\nWe can direct a DbSet to use an index for all queries using the below syntax.  The index must exist, it will not be created.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n    dateProperty: Date\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).useIndex('my-index').create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\n\r\nconst items = await context.myFirstDbSet.filter(w => w.propertyOne === \"some value\");\r\n\r\n// my-index will be used for all queries with this DbSet\r\n```\r\n\r\n## Linking/Unlinking Entities\r\nLinking entities is useful for transferring entites from one context to another.  For example, if dev's want to pass an entity from one context to one or many child functions and do not want to pass the context with it.  We can pass the entity and create a new context, link, and save changes.  When an entity is linked, the dbset will update the _rev with the newest in the database.\r\n\r\nUnlinking entities is useful to make changes to the entity that will not be persisted to the underlying data store after saveChanges() is called.\r\n\r\n### Linking\r\nAlways ensure we use the linked resulting entity, not the one we passed in\r\n```typescript\r\n\r\nconst someNewContext = new PouchDbDataContext();\r\n\r\nconst [myLinkedEntity] = await someNewContext.myFirstDbSet.link(someEntity); // NOTE: Ensure changes are made to the entity after its attached\r\n\r\nmyLinkedEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // Changes will be persisted\r\n```\r\n\r\n### Unlinking\r\n```typescript\r\ncontext.myFirstDbSet.unlink(someEntity);\r\n\r\nsomeEntity.propertyOne = \"some changed value\"\r\n\r\nawait context.saveChanges(); // No Changes will be peristed\r\n```\r\n\r\n## Get All Documents\r\nIf dev's want to get all documents in the database and filter that down by dbset, we can use `getAllDocs()` with `match()` to speed up this process.  `getAllDocs()` will be faster than fetching data on each dbset.\r\n\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n    mySecondDbSet = this.dbset<IMySecondEntity>(DocumentTypes.MySecondDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst all = await context.getAllDocs();\r\nconst myFirstDocuments = await context.myFirstDbSet.match(...all);\r\nconst mySecondDocuments = await context.mySecondDbSet.match(...all);\r\n\r\n```\r\n\r\n## DataContext Index Fluent API \r\nThe data context now has a fluent api for dealing with indexes in PouchDB.  This makes it easier to create, find, and remove indexes.\r\n\r\n### Creating an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.create(w => w.name(\"some-name\").fields(x => x.add(\"myProperty\")));\r\n\r\n```\r\n\r\n### Finding an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.$indexes.find(w => w.name === \"some-name\");\r\nconst filtered = await context.$indexes.filter(w => w.name === \"some-name\");\r\n\r\n```\r\n\r\n### Removing an index\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nawait context.$indexes.remove({\r\n    name: \"some-name\",\r\n    ddoc: \"some-ddoc\"\r\n});\r\n\r\n```\r\n\r\n### Querying an index - one time\r\n```typescript\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\nexport enum DocumentTypes {\r\n    MyFirstDocument = \"MyFirstDocument\",\r\n    MySecondDocument = \"MySecondDocument\"\r\n}\r\n\r\ninterface IMyFirstEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\ninterface IMySecondEntity extends IDbRecord<DocumentTypes> {\r\n    propertyOne: string;\r\n    propertyTwo: string;\r\n}\r\n\r\nexport class PouchDbDataContext extends DataContext<DocumentTypes> {\r\n    myFirstDbSet = this.dbset<IMyFirstEntity>(DocumentTypes.MyFirstDocument).create();\r\n}\r\n\r\nconst context = new PouchDbDataContext();\r\nconst found = await context.myFirstDbSet.useIndex('some-index').find(w => w.propertyOne === \"some value\");\r\nconst otherFound = await context.myFirstDbSet.find(w => w.propertyOne === \"some value\");\r\n\r\n// the first find will use the index as directed, but then second find will not use an index when searching for data\r\n\r\n```\r\n\r\n## DbSet Events\r\nDbSet's have two available event that can be subscribed to, `\"add\"`, `\"remove\"`.  \r\n- `\"add\"` event is called after the entity is queued for addition.\r\n- `\"remove\"` event is called after the entity is queued for removal.\r\n\r\n## DataContext Events\r\nThe DataContext has three available events that can be subscribed to, `\"entity-created\"`, `\"entity-updated\"`, `\"entity-removed\"`.  \r\n- `\"entity-created\"` event is called after the entity is created in the underlying data store.\r\n- `\"entity-updated\"` event is called after the entity is updated in the underlying data store.\r\n- `\"entity-removed\"` event is called after the entity is removed in the underlying data store.\r\n\r\n## API\r\n### DbSet Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `add(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): Promise<TEntity[]>` | Add one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `upsert(...entities: (OmittedEntity<TEntity, TExtraExclusions> | Omit<TEntity, \"DocumentType\">)[]): Promise<TEntity[]>` |Add or update one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `instance(...entities: OmittedEntity<TEntity, TExtraExclusions>[]): TEntity[]` | Create one or more entities and do not add it to the underlying data context.  This is useful for creating entities and passing them to other functions. Call add to add the entity to a context for persistance |\r\n| `isMatch(first: TEntity, second: TEntity): boolean` | Check for equality between two entities |\r\n| `remove(...ids: string[]): Promise<void>` | Remove one or more entities by id from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `remove(...entities: TEntity[]): Promise<void>` | Remove one or more entities from the underlying data context, saveChanges must be called to persist these items to the store |\r\n| `empty(): Promise<void>` | Remove all entities from the DbSet, save changes must be called to persist changes |\r\n| `all(): Promise<TEntity[]>` | Return all items in the underlying data store for the document type |\r\n| `get(...ids: string[]): Promise<TEntity[]>` | Find entity by an id or ids |\r\n| `markDirty(...entities: TEntity[]): Promise<TEntity[]>` | Mark an entity as dirty, will be saved even if there are no changes detected |\r\n| `filter(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity[]>` | Filter items in the underlying data store and return the results |\r\n| `match(...items: IDbRecordBase[]): TEntity[]` | Matches items with the same document type.  Useful for retrieving all docs and calling match() to find the ones that belong in the db set |\r\n| `find(selector: (entity: TEntity, index?: number, array?: TEntity[]) => boolean): Promise<TEntity \\| undefined>` | Find an entity for the underlying document type |\r\n| `unlink(...entities: TEntity[]): void` | Unlinks an entity or entities from the context so they can be modified and changes will not be persisted to the underlying data store |\r\n| `link(...entites: TEntity[]): Promise<void>` | Link an existing entitiy or entities to the underlying Data Context from another Data Context, saveChanges must be called to persist these items to the store |\r\n| `first(): Promise<TEntity | undefined>` | Get first item in the DbSet |  \r\n| `on(event: \"add\", callback: DbSetEventCallback<TDocumentType, TEntity>): void` | Called when an item is queued for creation in the underlying data context |\r\n| `on(event: \"remove\", callback: DbSetEventCallback<TDocumentType, TEntity> \\| DbSetIdOnlyEventCallback): void` | Called when an item is queued for removal in the underlying data context |\r\n| `info(): IDbSetInfo<TDocumentType, TEntity>` | Get DbSet info |\r\n\r\n### DataContext Methods\r\n| Method | Description |\r\n| ----- | --- |\r\n| `saveChanges(): Promise<number>` | Persist all changes to PouchDB, returns a count of all documents modified |\r\n| `getAllDocs(): Promise<IDbRecordBase[]>` | Get all documents regardless of document type |\r\n| `protected dbset<TEntity extends IDbRecord<TDocumentType>>(documentType: TDocumentType): IDbSet<TDocumentType, TEntity, TExtraExclusions>` | Starts the dbset fluent API.  Only required function call is create(), all others are optional |\r\n| `on(event: DataContextEvent, callback: DataContextEventCallback<TDocumentType>): void` | Subscribe to events on the data context |\r\n| `hasPendingChanges(): boolean` | Check whether or not the context has any pending changes |\r\n| `query<TEntity extends IDbRecord<TDocumentType>>(callback: (provider: PouchDB.Database) => Promise<TEntity[]>): Promise<TEntity[]>` | Invoke a query on PouchDB and return the result |\r\n| `empty(): Promise<void>` | Remove all entities from all DbSets in the data context, saveChanges must be called to persist these changes to the store |\r\n| `destroyDatabase(): Promise<void>` | Destroy Pouch Database |\r\n| `optimize(): Promise<void>` | Add optimizations to increase performance of PouchDB |\r\n| `protected createDb():PouchDB.Database<{}> ` | Can override and create a new instance of PouchDB |\r\n| `previewChanges(): Promise<IPreviewChanges>` | Will list changes that will be persisted.  Changes are add, remove, update.  NOTE:  This is a copy of the changes, changes made will not be persisted |\r\n\r\n## Issues\r\n\r\n### Web Workers\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - override structuredClone and clone the proxy properly by called `DataContext.asUntracked()`\r\n\r\n### Comlink\r\nWhen pushing Proxy classes (entities) to a WebWorker, structuredCloning will fail because Proxy classes cannot be deeply cloned\r\n\r\nWork Around - Create a wrapper for comlink and provide the proper cloning mechanism\r\n```typescript\r\nimport { transferHandlers, wrap, TransferHandler, expose } from 'comlink';\r\nimport { DataContext } from 'pouchdb-entity-fabric';\r\n\r\n// handle cloning of proxy object\r\nconst proxyTransferhandler: TransferHandler<{ data: any }, any> = {\r\n\tcanHandle: ((e: any) => {\r\n        // we assume or proxy is e.data\r\n\t\ttry {\r\n\t\t\tconst canHandle = e != null && 'data' in e && DataContext.isProxy(e.data ?? {})\r\n\r\n\t\t\treturn canHandle;\r\n\t\t} catch {\r\n\t\t\treturn false\r\n\t\t}\r\n\t}) as any,\r\n\tserialize: (value) => {\r\n\t\tconst clone = { ...value, data: { ...value.data } };\r\n\t\treturn [clone, []]\r\n\t},\r\n\tdeserialize: (value) => {\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\ntransferHandlers.set(\"EVENT\", proxyTransferhandler);\r\n\r\nexport { transferHandlers, wrap, expose };\r\n```\r\n\r\n\r\n","readmeFilename":"README.md","gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0-beta.18","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-9J5lLZsZlvlAVsFYrZAZOXrpRnTmixL5wWcKElIwxlIFOHVH3oKio08Tqu8jnfmeL5QlS0HPdFaRlDn/I567TA==","shasum":"b33df695cdf4ebed9338af91c7e488d2aeccbb95","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0-beta.18.tgz","fileCount":117,"unpackedSize":270736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLPXPC3QMQ7B0fe9igVZDirImHxmkmtZnfRZwiHl4SHAIgeh1sfzDmcFB3Nv46/HTKVlDkILE3cjy0dxg2rygLZCs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQaTAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq+zQ//b3s0Ojzk66CQVtlqR7UT2Swf0y6OmAzxyx/enId7CKNJVnHS\r\nnZr0cUy2lw2degNykKm0w8vtptxm9rySxSvF6viF2nYKpDJqUD/lw+i22vo0\r\nGjJCJeflkngtKk2NMZGeE0N7pQV6KtptXwabzHC+D7vqRoAIKcKQ9gPSKlHU\r\nL/PAQYrbA3OSRGx9m+wrGvoF5nKRDYBHizksAw+wPb5/fuRhGPfr2o5hhJqY\r\n1hwP/yUViztuKaXCKAkVjk49yhYRP8NeKwW0sENEff7e+4iFh2xo7CBUyOs/\r\nbUQytCqsgfL5xETcSbbpzGgoTk53Zget2ppAPuafRN/P/0K71ysAew1DvH+7\r\nh+R7oapqvPGnPOipuNXWJ+MS4EIPKyhg2IA8VFcvgwphASOiSvk/c/pF7qkj\r\nq0b9qx6Oedjoo0UOMcPu+2gTUyHQrQKNe2gZ8zW0td6SQZmjLxethQbWoUha\r\nd8Zqn4wWqqus7mXS1/Qn/WSm+ce50Wxeuo2bqvXFaOFLUXoMAP27lxi0n0uX\r\nWLL2gCuE7TieLxnNm1ViqJNoRPumbcF4SRN+iKpuUZrAo0urhA8jjUW4wYws\r\nUfM0BSrmyijVVdEDQmBWNhpUsh3OKir2mwTJl25VaLdVrNGCzytLC+nFOBau\r\n9aZzgjFSMRWvvqF5rxwU3tLjlKjfTddBQyI=\r\n=0ono\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0-beta.18_1682023616703_0.2430085529699264"},"_hasShrinkwrap":false},"2.0.0":{"name":"pouchdb-entity-fabric","version":"2.0.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"bb954af580438914e018db23f7d04df1d8548e60","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-pjWbI2VqrN1GYmUpzaFppIMWK8DXKZAC5CQ7FU1t4LLVqlPlg+8Wt/YRwQnwR3WD4hK6Ps3Yyy6Vp2AyXLppHQ==","shasum":"c02bee3d5d97c67e505c7e5e69fe65d1b332d111","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.0.tgz","fileCount":117,"unpackedSize":235989,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEWKSr98qK9bpz9+25RluKCdZUAuEFWYw2HuWQAvc5AhAiEAjGPF5NchpXjzHsYTpeq4UauZCsKlkJk2HUTcnXcmZU0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQuJeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrcDhAAhfMpT0hiUxi58w3PzJNr5/A9G8as2zt8lg3MHmkK46++aAIh\r\n3GegKW2jGpDwEaMa0VMVV6Z0AMnXfv3veoQ31apuWCZ8C/aF1yu/Vl0zRYZV\r\nxr6NZ4NVs1nzP4oUDR5zEFq4Eo/ccKUMdsxatusrRvwFis6LvGOF6VpjxTV4\r\nIQ0p0ojlmCHq6wZIESJmRlHV4mLO9peeGgAU3U4D5Lak5O3R23BZOJyjeioU\r\nb0bsb4avvh0igcMUf3092r92MUgalSUayOR0TXRlall996Ky6LscfklyMIEe\r\nXclKLQ9SbeB28ZqukBEg4gWGMwPYTZhEVdLsg5cDTs2/OXE9lsfwstbLgx8D\r\nY0XkIBjU+w12nUXfBa3N6gl1K3lBTddDEwimTGWPcqJRUNteVyRrIySeX0HN\r\nwUweKHqc5C1UIcZ+cZdHk0N+AKza9Ac2bihbasuk9o4+L/F701AI78X6iIzb\r\nYo5hhLpVRtUsmIbwacmY4Bw4qZ8ZlEGhHE+9rrrWFA/tMw+JUh/1efIWpDB9\r\neTB93kDzufdV2l4eHSkHKSCm4VvOMBupJDLYfecjzvk+4M9DUAhVSwgeAK8Z\r\nssCghkGurYtI9d3XjGhZgBuQQr3lHyOL331LXHiBSRNtFhTw5EyLkGKHhvOR\r\nH0ldEjQwRjJMqZA13193WsMkeLLJSMcEJsc=\r\n=jml8\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.0_1682104926470_0.43555525560897346"},"_hasShrinkwrap":false},"2.0.1":{"name":"pouchdb-entity-fabric","version":"2.0.1","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"63589286f5490eb06d1ca7c1c13f4d88cad2ad93","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.1","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-8zhHed3/V+kvmyqVXMO+rb9EB5NJihrSv7hS06NbVglsXBa96m0/dRXqBSNxoeRhFUHjn38gUWE37PhDGCsTBg==","shasum":"b534c9cf4b9b57d8af5cfddb1ba17233907813a2","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.1.tgz","fileCount":117,"unpackedSize":237249,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFZRGQevlJoYhn97n77M7w0q4l6TnI/tC67UQ+JUeCTzAiEA4C7PjanPRgO5hQMym4WqRYK3qSvA1RMoqnkW3UrqAew="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkSX+tACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqByxAAk4AzqRw/DjkCZh05zgVJsPbns1EZNWfWDntd+4EpltWMq21G\r\nAjlXHtdYXMYHtC8Bq91TfthQQ7jF45drxFhL1UZrp1bcCWpdnbR1RmStYpT+\r\n9HP1cRbj18WB/ClCrPL5uTTRjr/4k4Tg4gGUggOoVcKe6AYmlgFjXT3EP3Sc\r\nholrg+Nq2+mfsy0g9iLP6owVqJFvrAnxtB34aKYKrIAhJLK/XNl0eXOwmo0b\r\nX5OMsVjPBRbvUw29LWhQ6Tdkd1vXe8qx2Pq3pDRetpU+H8sYeMv0E16M5a0r\r\n5SstdC540Sqdk19NV15ceOnhXfSqnHxSWA749uoW56zeQt1PzRBK7V3XDyrT\r\n4HnZEPa72e7A45krKY9uQfajGWjj9T14LRYBR4vyvXPNsT9Llf1hdw1cRuTF\r\nDlbk30xuCDPCQO1c5eAomrqAtWo5o2HdZAlODJUq9ZgMhhb0GU1Icz9vassg\r\nvOufba/u2fDqOwQzm90rLO+RRwOxmQQYjlBeRXk6tF0LFd6+1Xogpcv1mouA\r\n6fiFcTBMQIpElD92JIrlvRRcAPM3BCgdkbisj92YaeRxFHqopvUQdiXLGSzM\r\nLrNKyJ8wLYlxLMS6sZKgozFW518Z/DvS7m8eDQLgIAfaonqJfRJTEZkT7+0A\r\n2OqUg6JY/A/v6EiuUr8Bcz+NrG7GE9mPOtI=\r\n=LVHD\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.1_1682538412989_0.418429179656701"},"_hasShrinkwrap":false},"2.0.2":{"name":"pouchdb-entity-fabric","version":"2.0.2","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"ed616e998f29a5dda4b3718a0d56acf367065302","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.2","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-iIlNNf3sz4OpnuGq98POmznwbePElv/+VQQ2RVb+U+j6p4OSoKLP0FL5RYHu7VCd833Soki2rugM/ilnsCBADQ==","shasum":"80f471bf0c7d3eb53195e357675018c0696b9788","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.2.tgz","fileCount":117,"unpackedSize":236961,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICXRDueaGqmqxfkTF29RmX/o7vPpzyvzS5Ap4YyMB2gXAiAFDuch0TBZ06NRWQmd6lfMDSvaamWstOcAUTdagio5zA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkSnm1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo3EA//dlxF0mO9u0PnnL+SQj7jbhwDXZwgMKD9Xbw3aZ43a44dmhds\r\nz8jVZCsdyBSl/sO0paNtUTBp4BDu+tiCHzHKDSscxigUjppItemydGFOV1+m\r\nnW1Er/XkdAajMlqE+MO/1n7gn4VTjXnpHzAlC5v2SSGANvH3+GZVPWSntjZ0\r\nMRr+WVmmF11ctRoPL5ClccbJKVl2SjErJlHV7FZmv5c3kFJvp8AVJ8zmQhnf\r\nbFCglHPqeuo34zlIksuj0ISoKUFfsQq7+SpOwiCGLFKlL52RRZOUG6bQWzEF\r\ngJ6OBjpwccGzjJ4HSOBhrZ35c/M41ufHwHzdVSSU6g/HyJuP9waZx1kA6Ofa\r\nWbZ1CvdNbXIW3dM588FJHw85QRYRuRwBceTNs8eE4vRKWeM8XnkTfB31yCG5\r\naTbEXowYQXdfVuenqKyRkxa6Gfde6KIL2v6Ui60tLTHIiUMrNtHw9HXyk78p\r\nfRFurhP/rf2Kh/u0UYIMUAFvNxRkdfbJCMhF2uXTn2mH0QWEeVCfK3IcqiGK\r\nJP6XyscPDJ5SdFl87Zy18w5bAtIZ3oD+lwP0dygIRx5aPHr5R1BSjx1in5h1\r\n6Gyl0z8i5gQp65EXcDNzx7vs1K2iQaNWf5hxvihpUwP420L2/31A+BFo2jqL\r\nsIoyXlAETmFVEpWUGU248hJ1KloOE2tXJvY=\r\n=yV+G\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.2_1682602421699_0.5549773212170646"},"_hasShrinkwrap":false},"2.0.3":{"name":"pouchdb-entity-fabric","version":"2.0.3","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"0e18d6db458faf8b50d4fbadb7ab7cc0dc9aba27","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.3","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-WIkifUjDy5GtNtnkwsUuI+yymYT0SXtXHn4Eo2gzZdEnULpOA0VDuOCuvw62RcmY4kodfFNG/B+XgCkxKtOQIg==","shasum":"752a95dd11d5f5179e10ce11581d37a1e929ee93","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.3.tgz","fileCount":117,"unpackedSize":241111,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEErlrKxHS6CWIXS58hL8jGLw0Gx1MDlLrem8rNsuDrAIgQ6uamJaIVJuddW1RpLJoWEZe58ORcTrTGlxkctUAeco="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.3_1685049532902_0.8146503640317313"},"_hasShrinkwrap":false},"2.0.4":{"name":"pouchdb-entity-fabric","version":"2.0.4","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"211198f409d6f8428a78c3346058e6087cd49653","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.4","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-WaseLq/2hQ2CPA0XUiBs04zGf0uIDaDjNGnlKaJiHZGrbCPKkZLenXTO7wFmaF9U/LLvVJ+IUe0Tmg2U3YN+MQ==","shasum":"bfe44d2ab3d28d2edb072d23ebaf6ced7ce057ae","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.4.tgz","fileCount":117,"unpackedSize":236714,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyHIc6O39QT6FltjRZioC/x5tu/CNujjFIKdIb7zyeEQIgZ4rhpTs4u+jn9APTUDfuYKOYCNXJ3Eoyb9hWfFiHn+g="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.4_1685736380945_0.1485157859174253"},"_hasShrinkwrap":false},"2.0.5":{"name":"pouchdb-entity-fabric","version":"2.0.5","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"^5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"d49a514e5f3c11ebfaf094a1d9fed7edf00f7731","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.0.5","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-/K5OlB5By0ys+uSGcxlsEJWKUpa3cAXEveL/Uc9QEcFjjtGCY3aUf3nR/2oFNVly6lVnSiCqCIDMrZlfBVQZaQ==","shasum":"e1e3a800958fa48cc259f1a6f97a512b2aa7ab45","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.0.5.tgz","fileCount":117,"unpackedSize":241510,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHfEOFKnp2wsDcjmtDZ/txmPQ6v0cOeO6fXb1LXPf0uAIgW0z+qH9gS4ByZRcciEavZQyyOtoQVnyztuTgtcajclo="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.0.5_1689886689490_0.8414431295872264"},"_hasShrinkwrap":false},"2.1.0":{"name":"pouchdb-entity-fabric","version":"2.1.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"6ab4415038309023d92e45863ac791f9dc3198d4","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.1.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-6skHYaD01CBHEjF5tO58n7hNhFiYN856qq+GT0SsMv8tjJ/r7H9gDXqBWftC6swlAJ8Izsyvj3g7yRz3pPox8g==","shasum":"1bb5a9232aa7e451cf7d2770a4bb5856425bb32d","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.1.0.tgz","fileCount":117,"unpackedSize":247744,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCjxcdxmVY8CtwSqPOvEDk5BbYR100HJ8ePi+nP8f1+TgIgSmEweZC+5NSphypSOUoaY8VacU9BT1TDUZ/k4n9WqiQ="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.1.0_1694444917662_0.2999446049673402"},"_hasShrinkwrap":false},"2.1.1":{"name":"pouchdb-entity-fabric","version":"2.1.1","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"gitHead":"c2a911d21e6fc74646394e8de09b44332fa92043","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.1.1","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-WNTkXBFwnRcFItCDf5ZYgbB1FZierjU1+MLcfD5vR7fTE31j6iACwC0AexEilqizK7GdInp+8EbvaGf902MODQ==","shasum":"b3709058142177af4f879c2da0ef3017a08a9407","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.1.1.tgz","fileCount":117,"unpackedSize":249528,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1soENsGWFgXlVNrAeZ0EhXO4VLGMKO08ZQycldXamGgIhAP7lU0hnNZcX1mdDQJpG8kxB3JIV8BoSFi9we5Ze3AiV"}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.1.1_1694546294582_0.9660457723118798"},"_hasShrinkwrap":false},"2.1.2-beta.0":{"name":"pouchdb-entity-fabric","version":"2.1.2-beta.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Documentation\r\nhttps://github.com/Agrejus/pouchdb-entity-fabric/wiki\r\n\r\n## Releases\r\n2.0.5\r\n- Changed call order of data reinitialization and onSaveChanges in case SaveChanges is called within onSaveChanges\r\n- Added documentType and map to types on a DbSet.  Can be used to get the document type that is mapped to the document\r\n\r\n2.1.0\r\n- Added ability to tag entities with meta data.  Tags can be retrieved in onSaveChanges and onBeforeSaveChanges to detect different scenarios.  \r\n    - Use Case: Developers want to know if an entity was removed by a user action or programatic action.  A Tag can be added before the `.remove()` call to indicate which part of code initiated the action\r\n- onBeforeSaveChanges and onAfterSaveChanges calls were altered to include tags\r\n\r\n2.1.1\r\n- Fixed onBeforeSaveChanges, meta -> tag\r\n- Allowed for add/remove of items inside of onBeforeSaveChanges.  Previously any add/remove would be thrown away\r\n- Allowed for tags to be added inside of onBeforeSaveChanges","readmeFilename":"README.md","gitHead":"1fd53ec1fea112b578d46bc4c5534faa8b374c9c","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.1.2-beta.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-fMDJUQFb+1IP4fbrUbakeY+ASRA4wu7iPZ+cQ8zYbH2suUfyxXuDJadkF67Y3ArjehKkoXpDzushE1Fh3EJiXA==","shasum":"72aac412ba8ec5f76f46c75a3cf432c37f482fe5","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.1.2-beta.0.tgz","fileCount":117,"unpackedSize":249762,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCd6eiaBy4QEMO/3DrBpfKTrbU1tsgj6DP/Xugg/WhrwwIgbxj7y9+K54xTZ2w1HMPkCB5jw86u7OUW6iFWwlNjv8c="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.1.2-beta.0_1694716485320_0.186932996115744"},"_hasShrinkwrap":false},"2.1.1-beta.0":{"name":"pouchdb-entity-fabric","version":"2.1.1-beta.0","description":"PouchDB abstraction layer modeled after .net's Entity Framework","main":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts","scripts":{"test":"jest --runInBand --silent --no-cache","build":"npm run clean && tsc","clean":"rimraf ./dist/*","performance":"ts-node ./performance/tests/performance.ts","test-grounds":"ts-node ./performance/tests/testing-grounds.ts"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"devDependencies":{"@babel/preset-env":"^7.18.0","@babel/preset-typescript":"^7.17.12","@faker-js/faker":"^7.1.0","@jest/types":"^28.1.0","@types/jest":"^27.5.1","@types/lodash":"^4.14.182","@types/node":"^17.0.35","@types/pouchdb":"^6.4.0","@types/semver":"^7.3.10","@types/uuid":"^8.3.4","babel-jest":"^28.1.0","cross-env":"^7.0.3","directory-tree":"^3.3.0","jest":"^28.1.0","lodash":"^4.17.21","pouchdb":"^8.0.1","pouchdb-adapter-memory":"^8.0.1","pouchdb-find":"^8.0.1","rimraf":"^3.0.2","semver":"^7.3.7","ts-jest":"^28.0.2","ts-node":"^10.8.0","typescript":"5.0.2"},"peerDependencies":{"pouchdb":">=8.0.1","pouchdb-adapter-memory":">=8.0.1","pouchdb-find":">=8.0.1"},"dependencies":{"uuid":"^8.3.2"},"readme":"# pouchdb-entity-fabric\r\nPouchDB abstraction layer modeled after .net's Entity Framework\r\n\r\n```\r\nnpm install pouchdb-entity-fabric\r\n```\r\n\r\nPouchDB Entity Fabric is an abstraction layer that wraps [PouchDB](https://pouchdb.com/) and makes creating repeatable processes in PouchDB easier.  Often times using PouchDB, a repository layer needs to be created and adding new document types requires a new repository.  PouchDB Entity Fabric removes the need for these repository layers all together.  Let's get to the code:\r\n\r\n## Documentation\r\nhttps://github.com/Agrejus/pouchdb-entity-fabric/wiki\r\n\r\n## Releases\r\n2.0.5\r\n- Changed call order of data reinitialization and onSaveChanges in case SaveChanges is called within onSaveChanges\r\n- Added documentType and map to types on a DbSet.  Can be used to get the document type that is mapped to the document\r\n\r\n2.1.0\r\n- Added ability to tag entities with meta data.  Tags can be retrieved in onSaveChanges and onBeforeSaveChanges to detect different scenarios.  \r\n    - Use Case: Developers want to know if an entity was removed by a user action or programatic action.  A Tag can be added before the `.remove()` call to indicate which part of code initiated the action\r\n- onBeforeSaveChanges and onAfterSaveChanges calls were altered to include tags\r\n\r\n2.1.1\r\n- Fixed onBeforeSaveChanges, meta -> tag\r\n- Allowed for add/remove of items inside of onBeforeSaveChanges.  Previously any add/remove would be thrown away\r\n- Allowed for tags to be added inside of onBeforeSaveChanges","readmeFilename":"README.md","gitHead":"1fd53ec1fea112b578d46bc4c5534faa8b374c9c","bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","_id":"pouchdb-entity-fabric@2.1.1-beta.0","_nodeVersion":"14.19.1","_npmVersion":"6.14.16","dist":{"integrity":"sha512-Q6X/L6TMB2ClJoCtomr+NWnKE1SWJD2dlNXXRfpjIvr5KDbNYnIFi+UaVygtv7mxpxOX64heFZg+R7/5pfPwEQ==","shasum":"23d2674c80179f9f9f418b4d5c1e2875f18845cb","tarball":"https://registry.npmjs.org/pouchdb-entity-fabric/-/pouchdb-entity-fabric-2.1.1-beta.0.tgz","fileCount":117,"unpackedSize":249851,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFt+v1AqzEgcSx4qjMJWMeUEGGkga0A+wLUkUiI1Y9FJAiEAmCSWt9oCmsQON8coW6eLusozrhJFyPHKP1wRB00RIsY="}]},"_npmUser":{"name":"agrejus","email":"james.demeuse@gmail.com"},"directories":{},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/pouchdb-entity-fabric_2.1.1-beta.0_1695403047599_0.8786483530934293"},"_hasShrinkwrap":false}},"time":{"created":"2022-05-26T01:00:17.206Z","1.0.0":"2022-05-26T01:00:17.326Z","modified":"2023-09-22T17:17:28.052Z","1.1.0":"2022-06-03T15:52:27.454Z","1.2.0":"2022-06-13T15:18:37.158Z","1.3.0":"2022-06-30T21:11:07.439Z","1.4.0":"2022-08-08T14:41:23.087Z","1.4.1":"2022-08-09T15:58:04.815Z","1.4.2":"2022-08-17T18:13:52.550Z","1.4.3":"2022-08-29T13:13:19.921Z","1.4.4":"2022-09-02T20:12:27.040Z","1.4.5":"2022-09-08T14:37:37.451Z","2.0.0-beta.0":"2023-03-21T16:59:15.723Z","2.0.0-beta.1":"2023-03-21T18:13:27.618Z","2.0.0-beta.2":"2023-03-21T18:23:42.657Z","2.0.0-beta.3":"2023-03-27T19:46:39.301Z","2.0.0-beta.4":"2023-03-28T16:51:49.371Z","2.0.0-beta.5":"2023-04-05T18:06:40.392Z","2.0.0-beta.6":"2023-04-06T02:14:05.858Z","2.0.0-beta.7":"2023-04-07T02:43:38.593Z","2.0.0-beta.8":"2023-04-12T13:21:06.327Z","2.0.0-beta.9":"2023-04-12T14:28:51.325Z","2.0.0-beta.10":"2023-04-12T15:44:36.467Z","2.0.0-beta.11":"2023-04-12T16:53:16.730Z","2.0.0-beta.12":"2023-04-14T02:21:12.029Z","2.0.0-beta.13":"2023-04-18T15:45:04.780Z","2.0.0-beta.14":"2023-04-18T17:55:49.321Z","2.0.0-beta.15":"2023-04-20T18:19:14.915Z","2.0.0-beta.16":"2023-04-20T18:37:58.153Z","2.0.0-beta.17":"2023-04-20T20:24:25.422Z","2.0.0-beta.18":"2023-04-20T20:46:56.886Z","2.0.0":"2023-04-21T19:22:06.663Z","2.0.1":"2023-04-26T19:46:53.273Z","2.0.2":"2023-04-27T13:33:41.889Z","2.0.3":"2023-05-25T21:18:53.118Z","2.0.4":"2023-06-02T20:06:21.139Z","2.0.5":"2023-07-20T20:58:09.687Z","2.1.0":"2023-09-11T15:08:37.828Z","2.1.1":"2023-09-12T19:18:14.820Z","2.1.2-beta.0":"2023-09-14T18:34:45.584Z","2.1.1-beta.0":"2023-09-22T17:17:27.880Z"},"maintainers":[{"name":"agrejus","email":"james.demeuse@gmail.com"}],"description":"PouchDB abstraction layer modeled after .net's Entity Framework","homepage":"https://github.com/Agrejus/pouchdb-entity-fabric#readme","keywords":["pouchdb","orm","typescript","web","indexeddb","electron"],"repository":{"type":"git","url":"git+https://github.com/Agrejus/pouchdb-entity-fabric.git"},"author":{"name":"James DeMeuse","email":"james.demeuse@gmail.com"},"bugs":{"url":"https://github.com/Agrejus/pouchdb-entity-fabric/issues"},"license":"MIT","readme":"","readmeFilename":""}