{"_id":"miniplex","_rev":"88-dc0a0c220410179c433bfb5a7730716d","name":"miniplex","dist-tags":{"latest":"2.0.0","next":"2.0.0-next.20","canary":"0.0.0-canary-20221029092412","beta":"2.0.0-beta.6"},"versions":{"0.3.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.0","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"yarn clean && tsc --watch","build":"yarn clean && tsc","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.0","dist":{"shasum":"642cfd1219db6984557dddb740ed969555851629","integrity":"sha512-W8o2Z4+4vQR4OfJdGqZ0kOPO2EzBP4vSgDaVB2skMgpGtN7M+0iQ7Yz93QLZejjQz3vuJSJU1ZgOaglZaOxhQQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.0.tgz","fileCount":26,"unpackedSize":15306,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiB2RbCRA9TVsSAnZWagAAti4P/iJYuSsXcAwC+H+pbaCe\nv5b2E7eD+uKcIY9FeEsSZleb2c/tZoerhUACdNF7GcfJljwtXAK7pC9sfG4F\nW0GqwbHgUTmyAKq/5p9D4I6fc+GPWKZ/mviaPh6yJ9QEOjeI+1GJtk8noBlB\nSVCSweHQ88phUlb6nzBd7qP+gJXD32Sk9o/LRwhxXD+wvPttsk3VxKWOcnaF\npiS1xS8M9dnzOXLT7/DUn3O2/U3k+JFFbcnhJ7UNVEjP6F9V4sNdnLDbEqCR\nZZjxNzzECFDk1eEG21KWnPUD7t466uRARqudcc4tiAn1uUzlJCxevJJOK9z/\nt3AoKyI242g7jm+TF71qPsP32jaJcebwC5gk7v+g7Z5tDOcelJvehyQHX0er\nMKGsW/39glxNbez+82qy3A7t+hz+eUtpg6dKwEVFgZyqNrEtwksQ8Ilui7X7\nRk5h5Nbf3t/ndGqwL8dhBNC6Q4J+G4dBUJriGtBLP5+jXfZxXVSMksEhafFf\nhb8L6PXhxFMjaY3zI/BGinpFb1msEbk++E2oNp7hBH8IeoPRHLF70RNlXzpY\nXZf4sxYSbiDOLRTJ4Z8ikjZ7fsDSAwmTTmzgejyTG0F6zF+3OrgSOdn4CavK\noN0Byor7sMDxObXTg7v4CqeFvHBvyLwCuUCmFLXqOs6d1QTReZfhO1gIEiF0\n/L+H\r\n=C175\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDin5654KzPHP3BPWb7nZoG5WpnhGvxxj0f2k8WUk3ybAIhALROrEqR+3PO58Rbt3wUKhl8m3W4WDfg8inOlxHhvE2z"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.0_1644651611243_0.7296616505323847"},"_hasShrinkwrap":false},"0.3.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.1","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"yarn clean && tsc --watch","build":"yarn clean && tsc","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.1","dist":{"shasum":"d7a6b9822a01c6c4e8b20527e61e568ae10b55c4","integrity":"sha512-Lx83WZe7VDW9EJjx55sCe1NakCWV0Hku3Qg4jOFz7NbEXUKqFdRn/Z+g44rEPoaNwLy/wWUuVjevcuFdsdYLFA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.1.tgz","fileCount":26,"unpackedSize":17068,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiB7QHCRA9TVsSAnZWagAAk9wP/ilnARZHGr4eYZGl5p4s\nqmEMey+whIWJ6SzKjWJyjrxwz7m7cVmklWZKtmfMSuf6zSCU3havwKd5vgch\nhYQiHfu7U6J0GbvGwk7olty7oOMAwujFWWiJ8/WlZdig5PxDDqVNoPwzEifg\nij0OgLl1cnZZ8mh8oZTikYMThsQMEEzFXjK8OMCRIpdSEFG4X+1AajiF82IM\nfhDHMuA1ZzvMzYYlyXuuzM3rujpKZVfMFfSRrB2EkQRvJv3qgA1oLHUFlpeL\nm5aAuQoFhl8SGN0r+MqPkCcB17b2Z2stFbJu3IIo3mx39OpCtL2Jicdw8/tT\nMrF8sLosaLv7hlujTi1WGW2uyMzrj+aplz8xxR1rT2cG+KEClRnmVcGWr4uQ\nkDpgBRK6iV/Y/Lo4T/FM17I6zFAGC4GiR/6NAntOGvsH3COBn7RWPM2uazev\n5ncPs5d7aO/xeFvmL/17FwQ31g0+82B7ILSkw2OBZqCi7Klo2TEvsl9Tnt5E\n7Wcgr4Is/lFItzut3GGQwZ8FQ9++tjV8lGmeysm8+67bHxUhwWVFL6hdT4pk\ntpXxNcUbnwIQ5lCw8k0TrDZS22qChRb6sLx7toWnUabYiwNmQjt5HLJyBGKx\nzy4/LzBZuxFAuH72N14Xpkixta66pi+dxQ4/VPMTb9UwnoM/fS7pjRlKbGts\nXWmG\r\n=m4yL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCrcSLLafYsfKgTGsu8QzhbYWoC7ZXkzEAX6xPzZ6qslAIhAIeXJPg5aov0zzBZ/6cv+3uU8YIcA0WzBJrN3T8G/+0D"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.1_1644672007417_0.11330539128098538"},"_hasShrinkwrap":false},"0.3.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.2","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"*":["dist/index.d.ts"],"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"yarn clean && tsc --watch","build":"yarn clean && tsc","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.2","dist":{"shasum":"321ee315078619287eb6db538f82e941513f6ae1","integrity":"sha512-yCTtFThhlbuWCR/f3ZJdQJLegdAM92R1UVVnP7XBa7F9r3qwt2hDLWeQ18Pxb+QQwDzcxdALJkpt7qJdvi52jA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.2.tgz","fileCount":26,"unpackedSize":21811,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiB8gWCRA9TVsSAnZWagAAFZ0P/3+ndtIW1dYdCNa1E6dn\nyb56Dhql2+xEDegbDlvyBeYDncoEaYk2UBGEJKAHRflYdUAG4Cqh1UYmySkE\nnTdRE3vvWRxB9hdxSM8/+TpbyZ16+dCa+7wWKxnSJI2UKFluWk5XbYhOVY4W\nXNHFsEavHeH7g0yzb+ET+yvEzjCRSZi7G7GTiwJg9lhMX1dec45DpY4piR+U\nOfIod8xA2ywzVbJMWtk1RUC15Zrh7MLGljCcuLAsP8Sq4oddZsZybxB1zhA9\n0vEhqx5y4JQmCs+11sqKROaunjPFPYjbSCH0Rs2zCHjwGgERhIUaDIqFb+Fa\nMwHF5w8DQYpbJPTCziehilOtXJB4ms03VOp7NrMmRVMN9P3LLZX/oYL9SAq3\nnipkfjrHz4SYdmVRWcuso7oQJEnc7O+GWNOrt7koaHm8PJhWiBS8w0m9sHX7\nnHBaxvSw+slnfTIsYKiQAraG46ponS9D/4LxwcS8Cc0Bp/khZRX83cMklhRg\nx0YnAURL76c9j6DhquYYml696XUQ3DKEwI0OGuAj3ctbKpgVbkcjzUoR7UC9\nwQHSq7dpMVX9WZRkKHoZVbWUZCDX2kHWX1MsyxiTR4uIym0Vs8Rcxq94Ev95\nR0FwLOhKviY5eA+voz85wANC0Yo3F0wc/e864Hcai9i/wDiQQsxjJIakyzHM\nCXsD\r\n=dAvr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrLpV347iJ7VVYEKbsTmdypvplvMTxbPEROeub+q5+qgIgZ1a6viC91/bNOx9c4y+PmcW4+HzJcZ2aD4gF3V6D3nY="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.2_1644677142089_0.6520944898944079"},"_hasShrinkwrap":false},"0.3.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.3","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{".":{".":["dist/index.d.ts"],"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"yarn clean && tsc --watch","build":"yarn clean && tsc","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.3","dist":{"shasum":"ccb000e0b2535dff4a49cae5a07ad3282f439fca","integrity":"sha512-R8omR0aYp+XMyZ/sjYdsAqJoswgQxP2PC8tk3gNXgqjL1uGfqlKxHC170XeWEFZsEGkJR1tYx6GUZhQ86EpBwA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.3.tgz","fileCount":26,"unpackedSize":20980,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiB9OOCRA9TVsSAnZWagAA+FYP/15qfbxokMYHxcgGxg0F\nhtTWgbA5iYdHdAGvnxkwRTBOyd6MZFy3SPWgncwyFMjJANF2eCZoJcR0Zpqx\nRD8rNBgIHH38sb6Qy3zK5tmd4Y+eqzKasBTPBDGAbDJzj2AtA1CY9H87aOwV\nhUP/yQOzojxQrkFw1LrjCP7FEkS85c2xjP+8yubXFEJ4Qbwr//OcI+6JgvCs\nA6iJ4lHoBPyqmU1SLIiWbWI1HgqhRElJRSeq6PSw9ehOTgQrgdFCQYAFHTTG\nUFBPk3gkZf4MS0AkoIXoHA/0FCpbomx6ZcVVEXOgthpygl+Jl4i8es9KAmf5\ny0B2ksHZrGaV6W2hoVczlxCTji8Y9Mn/NRUBvJaB73jZZFDfRRzDZLMfPcVv\nGZtXk058M64tliR74M1exaxemi81/1mJikkyBrpjXBW7Lfv2hvreu33bS3Bn\nSI3MfupZedIU03XxXI5tSnb5Mt26pLK4/zhhixPnDh0kApeg3dZY+qYLXzI2\nr6a012/OosaCfAsjO18+iQTZS98mEGjtQWGROhxHsCfuHQCJFYyRrEXWnQuo\nJWT2sRIYmSHSOhB0gjkMefTJvubswI4CUBEgVLlIOk3q5fw8zXK558DyWKX8\nQBy9HBmOblt3V1ugsPaG3M1or8a/ZVyeXXYUxd+5UfOYc58vpGNVKHOXy5D8\nnzgv\r\n=vwoZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB9N+dqL0mGDPvtLd+ilbZaosZoEkfKAEfMTG4iHGPWyAiB+Taj7QxsPZ40Qn5/2nWw8Y/LdeZBdY/sWMJMpjycb1w=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.3_1644680078423_0.4030149357784032"},"_hasShrinkwrap":false},"0.3.4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.4","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.4","dist":{"shasum":"5dd2dba4bf122809ea574badb49480d302c386a3","integrity":"sha512-j5tkOYHMJ75h5gGVEsBnCnfLTaCkAAcVz1LtIUHYo4IWHinX7Bpu1AHfoOH/gQ97Vyo/ySzMR5RRfaS4lNRXwg==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.4.tgz","fileCount":26,"unpackedSize":20963,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiB9SECRA9TVsSAnZWagAANmgP/AxIRVzL1jhl5hPbQC5z\nzfWxjXYWAdJn5pgPyJwaPMcURInq71rdVQU3P67DSOQYCMF++1M05HHNrqe3\nBWFBgBPjOvjyob4pxkcEFOXVxR+oQF0J3KPYJ17Ky80XvPjTjYRVWARTTdnw\njxcNQEYrIm/tCORrSls3vhNyI/wpRcKwBcjzPNhXBaOs8eGxPulz8at0/3Gk\n9fbS8aL72MP1gnTs8HL7nBnrGWQJGSnrz8o9fJDpG8Q9dZF0GtvP+luinIAI\nJE12dToe8IZJY3ZYfqxbL01CnaIRjtiCRsHBbFZ0lCOwbcPYPSjwkk2Kg3x2\naiJVIpukBIYGkJhjP9IHpBduQSlW+27RyAMxnQtejVC8F2iqLJbRyR4ezqo/\nRi06o/Nmcmu/FuUtAF2ROGzjEr+LmoLu0Hvw7wtE/fpelgnSR7j36CJruDnb\nkw7ZiflFp5m/Vt2YECGA9vw2vfE00gvOb/blMWPIAb8uUU4PwbUS/odlkeYy\nSMIp34kPvFpppy0mxSrezEnZNiC6/ic5OCv8I0hZi6B/JnTyvgl69dNwHFVt\nFU02JnmzjAWvV0hYYQ8zTSLs9vCFNX3cuu/2ASD3HFN/lYDDXa9U6aCT1aFY\nr/WSdzwMlfPByjneaNhYs0rV9115mctCj/rsjioFeth46DqR03saPXX42AVg\nOR1t\r\n=6iRd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDUUS/xunWgrW30eqJu/eiS2evQRkvvWSXK25Fan/0GWAiEA3hK9B7fP/5wNTC+KZblSosXVgX6ay1BuVkEvRyaNCvQ="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.4_1644680323985_0.06023502230547906"},"_hasShrinkwrap":false},"0.3.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.5","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.5","dist":{"shasum":"d110fa2626c6607e27e25ddab4c5557de812adaa","integrity":"sha512-pr8oYFrQG2X15LdWYDCk/LLCJUNhJMw9Z0UFogiFifCnIv2UKq2gePfyyan+/gN1/AGwahQkY/hCTlybY9aQGQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.5.tgz","fileCount":26,"unpackedSize":20703,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCAGFCRA9TVsSAnZWagAAjIcP/jDCURnD4eTtWACkM43d\ndWx2UHGXYyl18fH0nzgL0xrdQDzkLgrpwu2ozKovMrInMsqusjoBjqD/nnO6\nPaEsA4SSgc1GpagZHZq69tSEsZgjZa9Hi0bA94Z1RZoB0RPa0qlAvLN8yxrZ\nDh0NRW0PEwDg3y3FK1BDAMbuXkUZ0PLazIJkHmfDGQmV4BDJ50zMVc00wAt4\nk43rVAjOmWnutMOARsW0lrQsWHwJUNo4p8/xXruapWYqrbPSNWVHsWXE+Faf\naH1J3qkRDaBRENZfe9Hxj+Bm/H6wFonGnC5IbEVPNwNaGMnQ2zEg6q3QHmBq\nSKEF+sKiAygc8MwFIINQ8ddmwIhYfZt7EBGdGYeBD/tZJhstiUq0VA9mPP2C\nG9G+mpdtNpZ7BRQWyMOZyyJZiYdfC+8O0h+LATJlfPhlRUpi3l9KxhUBG8Iu\n2hWauoszsWe+BEyDhDsjFNjRVUVl8Kl0dRT166/AdaeGH7ba5sjJwOD3JyIP\nUHOrdPCUt2zjf7yneF31hhLp8FUsKId8d3VoNGIwI6iE6iAhoh+nGriL1VlI\nDu8EwZdMstipxlVyKYVwoyyfhfNWoK13nS5Y8c79OAOnZCvEbyiq9Y3jndLt\nlxb5EIE4wyTdX8Lu+mG8rNoCOneUCkuSL9cKEk2/o4ZGBYZVZKtZCpRfve5C\nlCAF\r\n=CGjv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICn8bTOTIRTHIxdWojY5B99JpFqqY2NcB7t2Jsl7UkwiAiEA65sQXN72g2wfaImUVuJCNoNDIGpnbES6360UVPTdtrM="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.5_1644691845342_0.16337826768229147"},"_hasShrinkwrap":false},"0.3.6":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.6","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.6","dist":{"shasum":"33b7eb45c89b69f72f9b4d19c9cfd556c2c0b021","integrity":"sha512-8f2Gj3t9au28KhkIj0wpaOlqmWY7fnnTt+ymsXzkAJAogqRfsX3mhwLsdGOEUlJu9ZS+a9I730/iiw28Ox1MdA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.6.tgz","fileCount":26,"unpackedSize":20955,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCP0dCRA9TVsSAnZWagAAEvMP/2t+QrP8nfCQnA6MGHbm\nEWhUh2r/ydxcu3o2XO31lAlXXdPEM6+1K0JCKj8wTOsjvjc4R4TQO1fznqm+\nCh84Pes8WuhZN1EGoV5vXPRS64edIsshC4BLUGVXf0cXuIRjs0frAanIqU3l\nVUBJgiX3WLzmydkYTkZ2+t5FbF7Ap1oxQJMFQtbzu8S8nEqUHtSRJrZImpf7\nAATD9PmRYrFNDmpvON14o1Oc7KjUTel6qf15XKjZyCz1SNVzkoJbsYVsEci+\nV4+xtFjVsfvs9SYQJoABstSeU19M1+Jz/iQknrqFwsyzAqayRNAxt8f98qd3\nZ3r4mFEcPQSo0N7JCRfaqCC9w5rV9X9rzjm5Quu9qC5uCNrTIPeTgmoIMmFI\nyXdUXBtyVzr/s+X/UVn7mJEqAmFSlxt4HSl+VnhUOlP+0LuutpwDPU10WvVX\n4ToJ5eBWdbPgPsaVcbZ4OzubfSH/FcmTY7Ap/SRvJGWvFgxZx9wc/+plJpj0\n4dBpl8zalvfbELMM8m//085nHSDVq/T4EN6D4GVOqwZLi4vxmPGb4bmVv2PD\nJtuqX+Yctc8uhrQQgbDcemDN0Afq61ZtCG+EW3pzZdwFrTbMJTlxkdq+MALv\nPk3LqELhJebQ5gkEVgfJEDzuiS9c0EE0oWpEdMts2G1fdFUw7GkWer4v2Kmm\nXvuM\r\n=4Gol\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPbvEF0hHwtGKiMbb219zgAyy7sZaJQyvYs1lNX261/AIhAMNhHpPFA1jaYL0AMTaiU/0wZ+hHs3ecITHMLNwhtp2G"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.6_1644756252885_0.39322947968558375"},"_hasShrinkwrap":false},"0.3.7":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.7","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.7","dist":{"shasum":"89e5543cb4206a560e2eadf251dca0185681111e","integrity":"sha512-m3CaqRamMBi3viZoiJQCeiVO91dMD2BxOKKLZLGJv4VaYqTc1ajF2MsaCfhotokAR5BjEMF4Edk/M7uwtFHV7g==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.7.tgz","fileCount":26,"unpackedSize":20995,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCRO1CRA9TVsSAnZWagAAxowP/i5P6rDlthW/+AhOuEOe\nTSyXfFw4nku+urz/rG/ef1R293xG8JW1DJgP2XkcQTwcn195ghyzlNNGee1A\nY2zNUkxv5oA2l3VBuhLA563vNuHKRF314bmtlcPe47XpOuWpuiaeaMwlJn4t\nf+G2zUiq8ZafkUBkYCEKJTxnI4Ol8B9xkYMOWAzEpouRAWE4oSRLzeO5rr5k\nAxMBs8w0iZLFSMr6NvWPge7D0pJdGZ0C4SYs9I965l+CZbKyQ7mnigZx06le\n9Oz5t/NWTd+kUnrXAa9aqh2gx3IozjKZIKJwQj2rvCeaEV42RaVMmHAMBear\nYLsptOQYzFfHJ4COFCKgHYO5d4j62vuyXTG+V5KysD9mDbac/kjQbsa6Z3Wj\nhk2Vru/ireeUeQLJDwrPIuAhdJBxXNYSCqBaTNaQl6X06y/Ugd6hlhY1BL4W\nFoOTI3r+N0Ido+QvqPPxKobbwz38U942pcHSxMtASx08HZ1YmseQh7tNYN+i\nVW9JK1tDGPjdw09fS9+62p/wzUDvG+MvIW2sKqRP0L5WqglrmWGUu0d79Dpu\nB+1NR/r4pIYGxLnVvRO4x/Xr+UsjltzgH2NKhCmiYwqiK07NepwZzA/i4gbO\nxyC2umQX+bE8r+RQ7RSHzDFCm3AdnuuTdg9dfrEcjxXoXVb8jp7tRDaXuXrj\nqzG4\r\n=Jrd0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICkU7ww1L9ezIkjphEznCzpag2vRQNagNJvg0TzxKb4kAiBri2PYrFHnAqKNTbnrdp3cCl+xlpwP5sr0vBzFx/xoEA=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.7_1644762037136_0.36194608560381125"},"_hasShrinkwrap":false},"0.3.8":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.8","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.8","dist":{"shasum":"4655d3be0b913e153ce6d49ad420caed95abaccd","integrity":"sha512-ZVFgtUmGQO34gbMUwLOLHSGsT+zWG24OAt8gvOe5HQ6HLZQiBzDJPTKlOLXv9R/2RvCe8FM6xpSENHFhprJqjA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.8.tgz","fileCount":26,"unpackedSize":21043,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCTEMCRA9TVsSAnZWagAABnYQAKIqhCJt4CHFXmkZrwQo\nGTCJSgx9K4MncF3aUFtVtM6J0UITvn3qDxDTYGPLRJjafhlnsMNJJrvXT/a9\nUdr+hmh09VaHSv6EQCLqCwW6R4PS6OFTbqSW7mfEIfG7n0EEsK8iafAA+w5b\nQNLUn+97oVHt33K1VuU1ETxybCpRng0w5Fu280h92TUhoHMJ+76ALfvUsMvF\n1p7kawaufOh9XPVnqL5pPR7JkL6z4/e3LBDYZ+lfuT1y0NwBbGbLJuZvyDIi\nQ663INVM/mzBhX7aC2VWmqfsY7FsxBY3+gUhv8bg37ARQR2VBdadKUFn7+J+\nerK7PHxVi3Uf7bSzJzVrHVh2Y9QVsWZZiTJigmzCItuSj1xh0tL52pEev/yR\nCNxfoH7/dcSLkxCaMCf/0p+CKkfb2/aWgCYqAsolTp9cwW+BvEgxG6dK0qd9\ntwSBVuF7kDGA18vQUJLcOvj0QQg5loSSELF7p7is77GqnURH2/gAakYaAJVo\nCfIW+xgmFrhueBkDjPCx6yJXu+bepp8iTzee//0twj9yycoiHIdoY7uA125P\nShcIA2CauCgKby3YYI4OZMt/lSvBbU0RIUDqePKaI1nXW131KlwYgcuBlpMP\nxK4s6UW81jlvP9c31bLT4Gy0ZKL3ig9CH/qTAeeAKKP4AaUtqRZuB+S1vFD/\nD3pr\r\n=34V6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAHPn83DVqFsm1hyU+YwaEMhudhrK40ALSkdc1Ycjv9VAiBnAsF3OQVqcbjNdTwxxRzQCJ/wbJp4YCVPQi3yzA/eHw=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.8_1644769547942_0.5994251491285365"},"_hasShrinkwrap":false},"0.3.9":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.9","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.9","dist":{"shasum":"89da39f71cdf0a789e75d181ce9faf064409b2ad","integrity":"sha512-LM+BqtRnFp0LmIRMr+rYxTYJ0wSXybBJCF/sRMERK/CEVLtc4cqT+Cw21JTpCtmoFJg+rqfZMK5xVzvJSllAdQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.9.tgz","fileCount":26,"unpackedSize":21088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCqBNCRA9TVsSAnZWagAAJZgP+wa07NlGLImug3E7JUqx\nxv6SzIz0MXRYT21298/y9hzZMGV+BEWxdDm+9BECkVrHiLqtOTZZpzWfPDaZ\nBLh1E4l6F5bIXxfTS7JFB2C8TI3msKuyNzlZliCIZlzfSVrCzc9nWKE7qzzR\nEStmMxO8+RZ6EBwihjxHUJkm4gI0Ez5Sc8LPy5x1/xx09s5XPnwaLGgHgw7r\noMj4ZWiYHAhDW8WL5ut/NK2ZmpXPfCfIC3jrANjlRcFem8OpHE7NWgsUmHul\n7LfX5rcsAxg42b6GuMy9g3f8vLCEQKkhVhdHWYumtAiOibdsZPdP30yyljW+\nYYq1oAtjRiakql9raOYA179J7df0wXqvj8Uo3RDz8iEvjGF1eaoKYhQXFdO7\nc6S/DtQiSGI8JKOn/3leSUTm7glbvr3Bl0JawvfwFeUeTWtm4lf4tQSsT9Pt\nRN7rDTtpLbnGt88LxjK6W+4VJAnDy5+m42CRdmO6qkU2cPFV9kD7JT9y7m5k\nwUWH2EMteicfjfX7TQFgtqmtKn7DL0jtv2xDPw6ZIjeyOrL9G7euvt2nqd7s\nvo+gYljPMdmDkMIJCq1s4Lfg3lCf5XOHQ8DxA0TSnYP0bcctG7ctTG6bdDPx\nWQMndBKc0YrWx3fBzX4WCDoTq86XL7Od/Ol5Rvmub9DUV6Yk9bZptZqW2qWv\naWW7\r\n=cwpp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFdysVXJwLNhqdvVcDkA9zQDh/SP77yD3eqwlTebJp4SAiAZH0rlEvNSaTVqB4W48JD3QGSZzRW2TiRXXKWt0AxjXQ=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.9_1644863565241_0.9189128723874722"},"_hasShrinkwrap":false},"0.3.11":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.3.11","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.3.11","dist":{"shasum":"788a760173276160933a9e9e352538f05563b1c9","integrity":"sha512-IL4xxRPuVCAROny8FHFDUqQDnDl6ioeu+WpcJ9zqdjo4+NdWGH4/WhVX3RvdvhePooLdnliUjeikx1Gj70KKSA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.3.11.tgz","fileCount":26,"unpackedSize":21839,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCzAmCRA9TVsSAnZWagAAW40QAJt/6R0+0fRJuhKU/udz\nz8MRXuuW5V+WVHt/f2fTO1VXIXTbuqxlMweXwW/NC2b1d3qPXDXa1WEEYIUR\ntsie9AI3XcCmEIEec5q4NjJk+47vVTeau3Tr8A1L0w6tbK4ZLOiR10dyTX1t\n12CMVMZwvwe2tK3Zx24KRwQyJDwXGaYxkNmyudSUXYGvyBv7UixGwqolP3+u\njg5RyOgSrV521qXUvJ2YYAfig4wV3NtJQEPsg99a5SgOTC2fCmWRzijQPx0w\nxhJroYCf+Avtx3/8QByCAxePZQ2ZLaV3Jan0t2/tv71XMB79Ed/+hTzx135O\nyXTEhlyaFFEJc2B5xDjSYu2vNXV9vjXU+Z1yNoU4gtrVqrmgmGjEkYSbWn2B\nbSSJR+BPibhfSvim36mHczDsBC5+jSMD3StMRPHp3OA1eBZrHilfJzFgnx+S\nV5lILb/auNSzmzojmSpNDVqYlYUxW8yGNkvPuHYojDfk3dwDc5q3TuJGh6av\nGRJ3H81jVvmYIBx1M6w7hl0m+tX9oOy2iDfavLLmI5Hg7cpNYh7sZxcOMd9P\nPEjMmx0HTQjPSvZAsxEm/DmxQ8PM19kHOZMrg5cFLi+6pzj4+d5lVCPsAj4/\ntBBjxLpi/H7hT+A8z3LHk/SmhMXy0tJnCVUMmzgoh/REwN+/01oo5wN6N/Lv\n/aU2\r\n=Nx5V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDepmf6ihU6IDEmpMYgUJqcYeS9BtpOvCrFWMRDn6ObmgIhAMYbYIIMrSapAeAhxyZ35ao69XFS+M5UalsFs4TMuQz6"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.3.11_1644900389909_0.3930057339152031"},"_hasShrinkwrap":false},"0.4.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.4.0","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.4.0","dist":{"shasum":"bd2bf8d0bfa7c41e0ae2c76174796a2b66e5f4ad","integrity":"sha512-n+rzuVK49xmQ9IQrSpIQ10kFApwndHHidtIFMx+o6qQ8kaaeoXw6PzMOBWv/9+8ctrI/DrikOFWYJUTyJR8qCw==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.4.0.tgz","fileCount":26,"unpackedSize":21517,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiDRxQCRA9TVsSAnZWagAAj1sP/RFiyrAEMhnguEtoHZD7\nr3moNzZVFtPMb+mT3JxW3ssXe9Lq24MWAvIJ+pAFdwVTVoD+VN8KBt2MIaQ/\nBsUKNYUQWN/XlcwNnk7lq6BcRsAXvNAsHQBn1UzaZ9/LtjAdQDFR7jE8Txdk\nExpItf3Ogz0zI6XRH4FxaNeP14U9rjoMX3aqkQS3xcdKb53eL80fyPV4qGGz\n6WWD61WxhdjCXLOh9wcS0t8GOqSb7rCf21NiHcuWkm2hCdOWgi1Oo95rFJV9\nLtfzAv9u3JSwV4jCxMTnYyZ5JAFoXP0N4LY0wZTL6kCpUF/BkccTPAC9QeOm\nwQUw9wD34DjJfYg63PGQEIeXPxRUBVAODnSnbjBnNsw27UceX1Fds1CfksJP\ne2mRmd7Zwm03/kQMr9QppxV7ZqJgB2sN6rZZDfGyDZz4avgbKd1TsIc4u0QR\nBB7jl7Z/gIdZaDF5riQt3eD3gxMv/IfLKa8LV+J8f+CKEYDFdvy2k0ehoOdX\nja1QyrvOueXB5VZOXbKV0UrXPs76IfBib/Mxbvu8Ir2gskdcNxoQIougRo3P\n5KPgXqABzSrWA+cM5OVGWGd3f4jSZNHzzv4zKzNEMrKWhtcxkojuMqgLmd9+\nQxGRNLYsMXDxWjQltvPqEQhbro/LLLsdwD6syENzKyhNzyaFD+wQtLeK2Kbi\nVLCo\r\n=IGlC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIHd/TyGu0TxLE9txAPoS4gQvu3Jemhs94ETbKaTIRLgIgJeHM5rhDDVD1T61uvgK9vT60DuKTi8sf7WOhKeGCS18="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.4.0_1645026384753_0.025854625737730563"},"_hasShrinkwrap":false},"0.5.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.0","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.0","dist":{"shasum":"5d6475573dec877f31420088d1c4d34f3dacddba","integrity":"sha512-MpBXyB1/EEZQZ/Nm55107lPonSSDW5T/z8+M+p/moM32TuvDpvEYFewh2+/yuJ8wX440sbf7IG7rVhbenzE/Ig==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.0.tgz","fileCount":28,"unpackedSize":21603,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiDkrEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpfTRAAhUSbFY7N4hpt5BfUaiF+wefFz+lNHobxQh5+mnYelHbfASHI\r\n0iAJOHtyYhchfiGdJvQ0nm0d0lGM/q+Isy1TG4WA+uAcIW6KYk94YKBZkeZP\r\n/DBPSQgNY50w3hkOo5yfwD7zsN1lOMHUof3wuBtQ+8DPwhhA4cOcSCReHy05\r\nk6B2R0CBBBCIAO5bSOX6//rX0KcYxHSnVUb3V+BWbM4B0wV5xYVHcQH8d7X6\r\ndq02tT5naHSd3YcPs+c6gI6WOTyIbLBskl6E5B+w3yw4A0cbhxKj/rHk2Zbq\r\nxXmjlwkqO0icIdksQ6h+F0Bkm+SYgzKl83jU67uIBkDTySpRFxVg3BGySm2h\r\nwQSmUF44wCaBz2zWkr7HjBfPRRQqtbZ6eiR38uQ0yGCmNjA9dq5adezGqJE/\r\n7imjtVSosous+zU/KEDL786b3nhLAhVXox0GzVCCXIC0YbFSmBNvJbrfYX4w\r\n9xRXE6xSZzT5oJc4ZWl5BpecCWZpUDCbPWojEsaPvO/QhvMnKR7nsQ6EEbaj\r\nve0n8ZJJZ4d4JPWld5o07ZWArC95wYBBxW/6Mv7p+Dve0fzie0O2Le5qK0uF\r\nVuscgM/iyBe6PWAYFWMdI5TBaoLE4a5yo5EZxVm9TVaPw+DlfL9RehuTj+OG\r\nN1yO66ldjoV4DkGBvoN3GbPpsNTwHhiZYtE=\r\n=o0g5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIELpz6CFWDu5R42BoZnRqDxX3s3zT9YvOoevEa3wTfuSAiEA80LGZXUAM0qyidIkZk9trArTFbdEOX21gmI15fIkpL8="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.0_1645103812148_0.7040652910143679"},"_hasShrinkwrap":false},"0.5.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.1","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.1","dist":{"shasum":"27a48ef32ffc201e89f6f621d559cfad2d807184","integrity":"sha512-zxCmFDAgvAyLOLt5E8aNhz2zuHLFBe6Wc/6IVtzGsxzeS3tmQIeooVtUPCIo4rQUmipEYTT0Hjr+FALsCze3wQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.1.tgz","fileCount":28,"unpackedSize":21849,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiD7tLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbdhAAgTAzi/v1gScnoysdyZp2VcTP4eD+nrgnWyx34gwPAxgKavpB\r\nMTqL1w2m/gZXUdT+zGsTZPCal884oJUuCRGYIplyBqx3r85hY+yfz22F+8sc\r\nXDQq0xGyyUP9lQAhG0NsYgCVKHW5hkua2prckfUJpenW9X+vE8lZf6KNehQv\r\nbkbFd79aXEwY4nK+MIgYL7O3yA4bwjoxcmTPLEeMJ4WJYLQBui9ZDeqXt4zZ\r\nRDiB4D+e4mZJZOAYQr65iKPfyvQjqountdr69D2QzXmD6OB69aFAjbW7xriO\r\nR4o68qpdtgasM1g0daqlCmvtlT7Kpf0/7c+w0cA1TTD4uOMb9i+BNkk9gyZM\r\njDmybFKOvAskr01x1pjTvvY2LS0kPBp/YvPUeJkCIed4GfHl0/7JWXPtSQ0c\r\nOcy3Ab6PCI2SEtSylbLWOQyU+c3sj1tLt+dwZcejxztrX90c8zcM9/VSuKEV\r\n9eiTQV2z8QLtt2U+/9RudklcYs6sYPxFst9DW5PVUX3mITExXDpvqfR8AVJ1\r\n1epixPtGZtyfGnexuhHfYd+TItagPEbFXbT4AYRcox0fzLstXX9oqWCGn4Qk\r\nJGlLkIeqdQVKduP//JQ1HibSLmKkGn0G9DBfuZc2pvNqSoKCoYGXgA4sIO6h\r\n7Zxufw8FC0Aymu/d2329V7HmZgj736q+84M=\r\n=Hoyn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICVJUEj2MSdyPjlX5E4kiHSaf/QR+MYAoYk2iUNmjg3CAiEAtVyZsYyUMjCgFqe2vaHMvO3uDov5zyk1ofYoQ9tVsw8="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.1_1645198155621_0.4233420167090256"},"_hasShrinkwrap":false},"0.5.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.2","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.2","dist":{"shasum":"0b08f8599a4ee86f9d207450731198c5d80cde2c","integrity":"sha512-KsI1cjR1LgUZF8ZHY0WxMn5QidXBkrXAJsyd+ss10EYIoYj5mCpFaeeaC+yh7hpI+xf/j55mw4iVzWIILuxgqg==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.2.tgz","fileCount":28,"unpackedSize":22041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiD9ueACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpv4w/+M8EnXUDOma6JUeXktyU1lm7XcOqFKVnfuzZ0rW60We6qXbEf\r\nNwDQ1YMi+qOgr4jN3oDq+09bNIwm3+rwFxb81QlMuCncbkBupVJ2GAv+1Ikz\r\nkZkf1A7GjIH5jVyX4zX98LgviDindh5skI9ebGcjs8Nj3e/xzRQ0C0wzSW1h\r\neR1w9NKr25LFa7sTajKztajzJ75v4r0iPlPBq4opxSxslQ/bPgPtv6AiwyP9\r\n8noOBHXYPDXpRzmToIFkirLt9N9VKs6rWT401LG2oG5PWOg/M2r3MzMkfirJ\r\nIxpC4zVX6twrMpytDdT7K6As0xK7kR3XXRWT3rEN0jfMz90jjhOUgKQJxrx3\r\nzh7L6Q/TBMvgyMc8IwDTQp64KU0GFSGjjR2tRdudUDLbZLKvmefWmYzGAeAH\r\nM0rlGmlUA7h/akCSg1nm++PzN1/Fms6uVu+9ueghaD1NA4R7WMXYxHC2wkKf\r\nTaEIutrH7y6LULm0KR7dK8Cs4KjbwzzGRJx2KagH6s+I2v1u812py+u0p+KI\r\nDzQqGpg3Zf2eJQ55GdnKPaik92KHgrF9IkoJ7aIKY77GcShj83HKQGjn6Ec6\r\nmeEnw2aXwKlZrY/wZkRzalkUCg6ag2qDlFlzU+gYYDDH+kEmKjjT1t4V9gCK\r\nZQChNK10lja9LfhPcEtbDMW95poXVcZLRAA=\r\n=But4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGgjmWUloFlkeb+QeYC37olyxbx+VehKK8th7Jxyu/NbAiEA1DPmzDjaKCRh5ogrqxFuSg2Sb6BLIQBGQsW1rB6rWpk="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.2_1645206430408_0.8485195408362955"},"_hasShrinkwrap":false},"0.5.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.3","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.3","dist":{"shasum":"f6818ea524adbca3b8ebbb6ea51fa426d15b0fba","integrity":"sha512-ogzmUItgyvxUO9e+2o2nl1/4P1mVT9KVGqJWo29FFXIPZ2VrsvCNXleFQ/1qvue5fI4oIkhrsKrbQbQuBlk/9A==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.3.tgz","fileCount":28,"unpackedSize":23206,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiERqLACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr4HRAAnwE90fqFY5VoFvrRUfHnKOQ1plZbwJMnKCEoy++0N1uYc/Iu\r\nVX7syKMTF6T9hzvzhyxtQkV9dnCLWH0q4mMSZBGe2MjozWr3IswYm6CiDu2Q\r\npqJGPHZ4RCYmb1o5ZdguIIoPdBt6046C9V7/xPBmq9sDCCnoaM4/4CDzTKsU\r\nbggzMz2f4Fp4Pv7rIK+xStFtd0fRK6oyhRz9mcLd09qdc+eT6fWldOcbRPDh\r\n/dmngTJ7ozDmC7/q1ORXP5M7aQpMLzdkpL9XLSMPUETEPzonqW39Knkjf9M2\r\nTIJE1h68slo5NMcZmKboQP5LAQ0lFcZdJyqzTKf9We3qOAZUaXcGuAhcjBzl\r\ngCaZXdugq+AxA//9tTzQjlnzvctqugHseQFLIO7NtTlJKHyNUSNsD2knMQos\r\n8XAxVm1f66V/COcOClYgwHsRuPjDH3dxdLjHTlZr2n8BplaMCypNjts92f/f\r\nhJ2unshwvJpgljDZTgVvbjD2SimxKLS8Ewu1CJSYuhOzts77m8Pq6tdd8AKq\r\n7oJZP3Fu0yA8M10zCsSTHTqIB3fn/M2BGKKFNN2C3aq28Ji7oT7tJQtKnWpX\r\nfuSBMFwlg6oNOd7TC9d1hqDMsb7Bwqurc5RxdenBTjQN38bsuo3W8L5RF1J+\r\nfGzYYq/cagQW4KuWLvVkc2PQvh9U8Z2zTWY=\r\n=ucQN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDIevN5bC/A62aPd8sPY0ZAWc8zQ25rtV8HdNwJMQeKegIgK1iT2CDzhZy/fMkRJ+KZQgUkQLvW+JGaS31ACgJ7kqI="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.3_1645288075700_0.8558587772439779"},"_hasShrinkwrap":false},"0.5.4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.4","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.4","dist":{"shasum":"45ba5c36f56aa8183bc6cb74f2b18f9c9e71e2ba","integrity":"sha512-Bd4lWOxP3K7cg+mdcL6DqwbI4UVJaiqScH546nMKhRvKRIZrHmHx1KYcLbg7Pf9G88W7V3kFfBZyX5M+al/z+A==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.4.tgz","fileCount":28,"unpackedSize":30347,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiEkK6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqkgQ//UZQcjmziXLpQEkU3jIgAT2gNM1MRxpdV7AYLIfrl1wBxQEVQ\r\nm1vAmi6ComW/+fxNqvWjbljT/9pSxGOL+OyhrpYJK7PTugSnmRIFkDghihh8\r\naJ5hluFC77GaEKypo1l6lmWMVL5AAbJz3jzJvgI6x1/j3k507ISY8aqhX1X5\r\nNfhr2VQLcwxUR7GoSdes4ClJ2h4+Ufgji9gwCRhkMx559xz4v6MSxpA8SCDv\r\n8tUfIrdA0qlFPqvk6XK+XeSsEkH1MPUQUO5JfB9UldPZyrSoKp6gUxAlsIb1\r\nNRTBMVPp4o4zY8R82jSUS7BjRL7zUSStCHIpqn7YdIxHWmsRTZ4YHd1bsqCA\r\nz0EOSOOMjcKaekXWGpOE237bXV3wFbHLkB/36V8uctMTbHZgIjkNABd6yhrD\r\n+Be6cppZa8g0ur5EBw0GV8ZSq/oRjz+XdbzReASbEJpH808psHqShL+OMBID\r\nNYhMlUkJtyVM8dyGG94qcyvF/pPENdV/+6rRuflvpihhAxFxnY0AUsamYH/g\r\nuH0hVe9/jJW9okWMFNJF7aiqAWyavyE1Va/1n0FHLTXC8zZWvhMejRQUGp9I\r\nef8nDARaFvCDUStGla+bOt+XqCOpG0e/NIPi2cpdiLnH2TgZFNEIk0Xv0znq\r\nyHnPmVZIIbcAJEj/b+Q1/xYPpA7tgUPFt+k=\r\n=KG+J\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAcnQhms7pNo21XmRyWWhZRMLTVC+yreSCEoWdq3hoHXAiA+hSacTWNxb8TxxkiTRKQh/hXvbIYAy1sA5InYUP48fw=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.4_1645363898644_0.9909167554622227"},"_hasShrinkwrap":false},"0.5.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.5","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.5","dist":{"shasum":"f85f4201b9507cca16beeed606d3f21639e15626","integrity":"sha512-7LfF6rZN690tiKLkM6VStaDi3fly89BXqaS+QVJLtQ/vgmY/J9SWBDfhaR9EX+BGRo1A47aoNClx7OTXRcwMQg==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.5.tgz","fileCount":28,"unpackedSize":30590,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiE9SlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrr/w//eG8lHeI23KnowA8UbIoD83/eb2lKfosL564PZLMjfWIfuOwY\r\n2UupIQGVSvNKKPRik8xH/bOAJFehO1wHne3mpE1PyFzQpjmCnRHFmWfcl9O8\r\nFvB0li1i14pvT0IixW/qk3Z2SFgUdmG+lFpcw/EG8yXbCa9Y5iSRVkYSporb\r\nQEQLdjZ7YFltGhMqTYDHlaXq0FpkAG+vCWm6IgvTrga3AoPODVeN/rpb6AGf\r\nDfWEmfI2XmVEgZAljKKTXqunjy6m1cmMtJWK+WjY1Oo65gp4qHsgQfsewy1r\r\noMO/8jrWSGarx7EXegjhS0R4FBWX5tBkuYEf4nvG5R5BOYIMHeavrCFmeh2K\r\nweoaq1PsFr20wzIhCG/wSp7T/Ww/C14SrozkhZ6uDAzpN5kIIZSCtm9EHobi\r\ngs+e5ScHQZ0vJ5TTshtyPP8Wr6dHpXFyVOEGV6NYRprWpAAIMfEcDCFKt6ZZ\r\n9ZEd5IGGXepRDf3tUVdXuIGtxLvUaJM0of7uE4f8JvFsg29iq5Aq9RKPIW7u\r\nTAPn9o8jwHBqrXqEdJyqVaLZkpNuGktHyuET9XS6wCK9UCNyNA0tfKgfBlbp\r\nRwXOZf12XyK9LhvaryQWpsSDzdF+cKytEsYLsUaS9IyfsYqYTIJSkXBSKB5d\r\np4v2ZXZRZvngOnAsQbE2tWaa5OIYWHwmcmE=\r\n=4Syi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIASJXfOOazn3m5mMS+ghPXDwSEYN62nyEJEQfZL3vWPhAiEApJ8XgupCJ21bvRYg4bSSHnp+l75Ktn5hwQumJyJmy7U="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.5_1645466789633_0.11763157397011192"},"_hasShrinkwrap":false},"0.5.6":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.6","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.6","dist":{"shasum":"d8cf1286d15ebc973383da33dec722f38eee945d","integrity":"sha512-ipiR302SJ5ZOpstqN0SaShFFFvin9PaVz+IR56vm6wTpvyghahml6xMMQIE6knZYY56exzKlF86wfZFmYlfgXw==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.6.tgz","fileCount":28,"unpackedSize":31170,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiE9ayACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr7og//Uait1V1MeOqgRsG8UeHEi3PCwZApURrDFDvtwlelNkAHoqyk\r\nIuxSgmVhxKmy3KCChf6koww1CQwBeS7SDcl6EnQC4kx+r7+Gqzn/Wq6TLXEN\r\ndzmzwdck89eH94ttwu3Oxtwf3dxEGaf4X9x4vZgT9gwQhHMy7pju15CTpf2P\r\n2lxuwCHPj37zSxQwVpVEw2o118U/iH9j4A/HK3ns5E56hmBxZQAhmzCWKAtE\r\neZkELwOUgEuJusB6vYvTOCTCpYSeGO7VcdcL8H6ncuvRjOqm7iecJruxjFRN\r\nE/5cxJUPWnYr2lx70eRzqSUFU1idcHX2BzNCXJiGD92bu3yroRod+9uiPfmj\r\nCmuw8nP8ZZbyKEFWIracVnLnJGIsmlrW+56u5UXa80RIN7TNlwmQ2Yz4aBoe\r\nWN7HbSNNVfgCOngEvO2Rgma0VvDGbtOO78ii1F5tTa8jd5XZBI0bivL00MIz\r\nkCcRetvqAIw7nqwHFSFkWFR9kPpTMF6JTsnfXN+aDu3Uj65TXUnj83SXQDgu\r\nZ4jocXGM0171PA6p7PJA1QQVN82U/dNb9t4NHWTJuEhVHZJ2jdmV+29Mb7kC\r\nHVz/cgCRlgNFIk8hMD8E9MaG1i7MrQBt5fgkNwPIVIBdmWTum7fIiVwCTwoF\r\njlM9hZVJR5wZZ7UwnTJRFPvEsm7BIV58Hv0=\r\n=jfL6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC269a8q+IWQtLCJHsiY4WL6BbRu1cAhTPzrrpE/Fr+YQIhAId4+jbA+n5feaLcdQoXh+O3GzwLCpSRsLvOynDUL58a"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.6_1645467314507_0.456591263674585"},"_hasShrinkwrap":false},"0.5.7":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"Joyfully minimal ECS with a focus on Developer Experience.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.7","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.7","dist":{"shasum":"85769dffb7744f1020ad3fbd88d48b96a052e427","integrity":"sha512-p/eNhSwrRaJeSsnq4C4fCaiKiLcTZU80OSmO8u+tZZiWKkzjTRWJZ10a0ZRvZAA+6HWA+gF6anKEnpVBLhi+YA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.7.tgz","fileCount":30,"unpackedSize":31453,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiE9leACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrtLA/9HFCI0NTyBqyICcWrLRzMFwY4BQCIagIDWKucK8miryofV7Wu\r\n2jzFtmuy4MIdDldg5Rhdsv0D4t0UKtiBfXe7RAYmXJNQpYBZbfUVto6myBZy\r\nnIkCE14OcTptkaafuY6fVOySR6qjY1wCvf5zsqesD4tHk6HLmNHzpvTKvjKc\r\ngFDoNlonhdA8X8pT8To7DRGPxZpkZWMFX6GPz2BoRRds5YGGQRTLeAD5NyqZ\r\nQb9Fikutk+PhAFhMepxwo4s4XOqG49EB2S08Nlj0vVg5dGJKwy+LNLMXxDTN\r\nJXYYBNDBhr0YAJsiQHlSPAvC05wEDulfSgjCptAyW8XpWaQe7+1koqN9bQL7\r\nmnh+sSHKoYsd8U4umkynuUSRI2C2V5aY5gCrUHlyg2ATANEZ1w3PtEIZzS0o\r\naxb1TVtSCXHo5YtXh77UbhLdej1U73VEhJcBg+kngpFhu/uWst1vZc2hFSCT\r\nDx/YFY4FpG2caV0Nba7Z2FajrqV1Q4fH/VYn/jtQk7rEdAQsshIdoJWYMccW\r\nOWFkahyaZCWjYT/bvgkRNhJaU/Ecko4PQx5oQH/j1h+ZeMS1HLa9zs3htzSX\r\nfBdHBkAqYQ5KvYVu9JDAOK+RSss5ZCVn1sRZVL/FuifT6gXeTCBNkOIxOccy\r\nwP7hL79U1WYa5hRs6ZXMazN4rtxfFam1TDk=\r\n=K8I/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICbw8pa3iEbSvdJ+6CD50hUdIOJ/8fM2a5Ft07I3pz4HAiEA2/sG69qreVW+H2zbePlMxr5mqt4sOFvXwDCPJEDAJhw="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.7_1645467998547_0.76878947998796"},"_hasShrinkwrap":false},"0.5.8":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.5.8","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.0","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.11","typescript":"^4.5.5"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.5.8","dist":{"shasum":"369869ae7c790ece8baf96b9f5b9d174f4ed7c03","integrity":"sha512-rMR9ciOjI3o4mVeOoYsTSo0OVGHkTNEZS6vb18leKfDqGS5vmXwK+7f8QWu7SgfPf/DnMGsnNwh8NFWqBdKq7A==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.5.8.tgz","fileCount":30,"unpackedSize":31578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiE9ttACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrR+BAAljGgbyvOk6S4Gh+uEqYFaYZsgpUxoPueQHozl0ayq5hO1Jmt\r\n1Ab1DuGIvEDjecxqt3aX5xBx+1mqNQZUMul67w6J7Vmxqp/odIlVjaSn92X+\r\naYkjTPYoJgl/JkZSYD0Boh7p7MfmPq3XnaI75P09VxoIj3Fu3W2JIFElaYXx\r\nMJZfFnVKoC8afqNylEwgenv5IDQFmGKx5K/zEwhIvhfIyLxX55QEom68KLUl\r\nw8bfIb8ZgVyNsvmr2SnVDeragHOM5o8pbhw61fs4vJfGZR5J0Wox3dbYhgoz\r\nVGis2icFfm27QPyd2Ss6x/NVinWBkfXK+XMx5Kfo0s4nNzMTQMIbfIECt7Aj\r\nB0djaYvMVmwb+j8huL0qViBRh/cmycFFKEnnjnha6JgVkBvqX5LQIpFX2dvX\r\n7p8ko/SxXYf0LAbgD3Rd3ik7vSLohrXm9eEarTwzDIYgF9yrCLM5ypCZ2RUv\r\nGHBBGPpCZgCkPyTeysh+o7yJpmey7Fi04lcgA87J17bIYe63TTpVkMvZxjCU\r\ntZoqyvPbrMBlpFfXSPRNxhGHSAipVWxEZ9J+8OGr8W00xYSDQPS+Wz7rFQDg\r\nqhyVn4XJTPuflGC5FMb5xdz5CFR45tN3B9CxGhw9IHcBcz2m3IotJpd0RQhJ\r\nAwVEd5qEQHCNV4NVsDbEJAEFV/mKnj0UHqg=\r\n=2gY5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDaIAOdpf2ZS+8xjSjhvlLGEPvq2zv+5I92ZktEe6kkSQIgAwI6c8N8zwXdwhLsKpuFDi7cPq9QHwvERbA+tttc05o="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.5.8_1645468525089_0.49042038784003705"},"_hasShrinkwrap":false},"0.6.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.6.0","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.6.0","dist":{"shasum":"ec231764b5a77128b1b43076727eb9e64a76ec6e","integrity":"sha512-6Ya93uhgH+lSsvOpTggD1X8R61bT37dC5adzGGAAl6t/SDSIoes9LvMvJNlj0GQglNuzMOpwMT3ujLtZChkYtQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.6.0.tgz","fileCount":31,"unpackedSize":35263,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiKPesACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqUeQ/+JMEieqS2pW8uV5+cPC12xUNmG99WkdJFP3n11WOg52SnFpCO\r\nU4iea3eUAEf4Oq1c0GPbmE3MJZoeRJ07GDU56acxxBOAkCjpmE/4QRSpt3o+\r\nvSH5j0PFA8qldJYrOgBPeHg14vvXhr3/HI9/yfh3moEwL2QK3NckdNKjiRB6\r\nhEJsGFLdyc/xNvTncOngK06CazzCoxKQlH2GuSoB9A2KT8sIBqmig+2VHPVd\r\nXKh26AVcGUNjPAKFivZFektQdntYhdZPwheEzfEqTRPlpDvjWr5Ge5sqGYL3\r\n/cQTwIWMtIuFs8TygCOorg5zIHLkbhxLBiT5OBhojLzooOjcmYsNIbmh7dOY\r\nVH8RV16N6GscEttMj1Ddw7AE4ZWBaoODyOwk9JLDbiHLOx8aocsUupRdA45+\r\nNOb97rAO+oV6s9Ijnc2c84/iHMSPdZ1hd6nYc6iaOEXcH9esSDnkdkwU8/kc\r\nHHf6Xi6kBwOGE2PNu2cj8AEy9XY205X7sB3tnqCkDZa3ggJcZ39ARF22oO4U\r\nxdiORflsIMeu1A3XhPMNPXC2tG1Fij5ggvCXApY2aTzvCECfT9Eh0LkSacYX\r\ngbsZb4kHAHZSfhk1GfNV8cFx1OmFwDMFgClrKqeKt+Je7bpfnZitXXcf6pDp\r\nGBaSbCCUBIwLXNtwBWyCvtF+09joHmRrEZI=\r\n=s5dK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrFkeGZqSOP+CMSKKDZ2tiRMfIytaNZgMGD7dyfb3AxAIgKuhOBVzO9+Wy0tVfISUuqcpvGawJQiftaCSJSp0YGPM="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.6.0_1646852012193_0.9929584661310913"},"_hasShrinkwrap":false},"0.6.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.6.1","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.6.1","dist":{"shasum":"aa68d915cd8173f9afb02a5d367739a063444a1a","integrity":"sha512-Po/gkJGPSkGLMsyizLYFh2QDZi70dVMNIWamX4KqvonMjKUJnuF6LiRNLPAGbU6GhpVX/EuoohqnxSnkmX8eWA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.6.1.tgz","fileCount":31,"unpackedSize":35321,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiKilRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrQDg/+Ok/sPHuqf9vnQz5oEdB+6LR/NBI6w1q6roRjJCcR2XmzpA4y\r\n7msLQ39uSqsamnoWgasUsMsAS1KakIo49DqoEMjSonBpaSEiwjC8GqM44Wx7\r\nl85gfqeq7eajflWMTbil+cTXwWYVemOUqGKn6/OqQh0UaaG4VffRYqd5Y+di\r\n/o9zIbd4HxmUZSlWTxGD0uovexgRVQK2DvM6+sE7OwZml848gsL0FwvU2Q7n\r\n1Uq7W8ARyFfohjMPHQzI+gcjpLtZMpgemMj20YUW21yRVeMCqa33eiFytwhv\r\naNOI0Q4VDdOM2xGKgY7GQTjhX9yhLnw2YzDRuh292yiePICJJuYH+OrGPHPO\r\n7g7aG1roluWOSl0vy342dJqHuo1iAo3PMtMIk+K9X1x0vkW3W4jOwe4l0XbZ\r\nn+DDRcrAEtgdcqKrEXRJ/RSZwRLCBJK+DJh/J4Ofw+pNbbRSLVblvCu9Pb6l\r\nf1nibwQcW7fOVBTQML78sczO04XpztohyNen7bRnfjLDcW1+z38p7THhDCwq\r\nWD4Y8Ys8yE2FP5b6n6Ki0gaSsN/P6DsH6UB3BZYK2yY3oOZ4HtPSRB2OW/OP\r\nPtYYsclOnid0Ux06nhiB9O6LCCSWic7Ox2n3Lu1v9UJc7FO79zYIg0mgi+Bd\r\ntsavYfs8VGVrj2rF3QZ/016IPW7VgnlKNvk=\r\n=9aN4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwIflyywUTbpyVMoza/xZXdpp5zHZOC4Q2dYAB71wZqwIhALbL0HW+8dnvGZ8Sc2opfLXW1FUusw6e8zbCLn6Bh5DH"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.6.1_1646930256805_0.9164150282222585"},"_hasShrinkwrap":false},"0.6.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.6.2","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.6.2","dist":{"shasum":"26838ad6a6cf32c4ab976c8476da8edc638d873f","integrity":"sha512-c5c1AuBkpNmyQSEviZRmiwOClY7C6lYvBI44qzKJnpbx0T4iypXunhq3wtCsDlJXFhZT0wbh3wOmzjV6So6Ldg==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.6.2.tgz","fileCount":31,"unpackedSize":35531,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiKz/yACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrb7Q/+LwF7SwQqLQxHtC7JovwsS/WNhBHxlkVXNTyGAp1P771mrWyD\r\n5SBqpntZwxLzQDvT3HldYA8sugzuCO4QF//Gcp7zJ88N1dr1PXTII+4P/vqg\r\ncMmIw1jaAsoV0wLy6B869QtSO4LgRrJQpd59r3brihZX9cI2sNbOG8dL+V5C\r\nI1TWdlEybIXx8clAUYfpJruQVW8Ih9cVXnmHMl4LU+dM13cFhvRGZpyRlDgk\r\n4JiyRproobztmBDeq40Z5+zf1Ebzm5t2XqpbJlYW8LjW1UxWHL8qh4ggo+4f\r\nuCM5CQ7vTWCZT6SF/ihmBkTJ4/rmR6sAJeNtwdtCKcy0bc+EkhrY4PN0oQYH\r\nxRR75v0CLt1X7g00SkoDT4N08ROpJvNcWnbhY9OarkZPgdJRYJ3p56RlqBMY\r\n5C39TIRHNu2O10St5fchp7TT05+6faU1Q0PZ78kWIk+JvLRuAWJbGTNNy0On\r\nZNJLAF2uNxA0d48OiFdy9XNg7AFMEyPgwXQP263RuO4JYv/jJTUn/sasvuyQ\r\nbHvVyJwkczmLjA8IlYfVbYD5fGkVLOFYYn8xyi3qiHl1qYQ7zXCPMZ+CQ/+F\r\nzwocXjN+8eELVdJKFcdWMTs9KjMNoAP+pqLFYj/ppqK1HoeHWmbDioFOB6wn\r\n9p9jbmW5inbiwUw3E2XC7v6M81wH2cSuOfg=\r\n=/mZS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICi0NYqa0yAF6Eu2uiHh710Cc5DBz7FBfqYH+fn8d1OfAiEAmMXODTHqPPZwJjC6tlU61aPrSqae5ZMtP3UKARrWktg="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.6.2_1647001586389_0.13795983666783362"},"_hasShrinkwrap":false},"0.6.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.6.3","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.6.3","dist":{"shasum":"80fa844938b83df1ef176b379a1e4111bfc41220","integrity":"sha512-Jr/c/NkLMXh6lSp79u/DxMhuRk2OmcrVHA4bB4+3kshxRjJe57N8OWl8cXxEI3v2ZLnHUItal5Hx78Cvi0CGSw==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.6.3.tgz","fileCount":31,"unpackedSize":36428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiK26yACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoJuA//Q8UgGCZTLh08uEw0lltuJiH9zcfT2DxlwhG2h1dYICHlqzkt\r\nwTXXrUHT9ItANcCywhxUfr18kWwY3ArpZRQztOowBdK+P4Y7rcSh+21FCYgC\r\nBPfeNEmUPU7H8Ja1QhfXh2uHlXLWtri9RvprQSnT/IEeLloWli2BZWZI6IQV\r\nmJoxe2GcOR7BCXhO1RCzrVpyxZmptBpmuIPMiBbfNAHxzic2TN5Fctm04Bne\r\nWv0yqlZK+AN0Bmi94bxvuTIVZuLiJHoBGH0bbXzFNr6Nnulcp2cexcGNzHSZ\r\nnjr3nKwICBQewAaPP5uIYBpwOVekrkY4AOHiXXeln8/b4sU4l2a8OkzffuoE\r\n+mchvYHQyjpLPgGHVUcZ9svU2re+fDSJ3RwA8Ar05UtztAxVFhSDBa9C3lZw\r\ntiPIWcG4vlRoWgK5QehXtemM/7Oq7QoPfPnsh1Ts1l3GzoWVgIxFHyzhfg1z\r\nSM2SjBXDIzMtwob7Spwv0YvLjqZC9IZ1oFj0YnOBnxj3/KG0NZHQB6and+xy\r\n+N4VMx8CTtVojVPZREN4Zc6hKdYVcg1HjkU85DEAXf72dH5lc0YwnwBCRBGB\r\nA6FyEnsrXVqRtAv0OOCz4vKiON4me9olxq27c1Ww4/DU0xVSy7QLqzUyf3jL\r\n3uYx6frfIMTi5eaUloGSskVjOAa0XC9xG4s=\r\n=lyrf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDBm4juY6vQKZTZ9Ll0CAhCg0XdiHlTz8hxZBVb7m78DQIhAICxbrMZkxTMSJxX9abt93mBPnxGPRnJo3SbwvMbAsWZ"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.6.3_1647013554719_0.6547325233860424"},"_hasShrinkwrap":false},"0.7.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.7.0","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"type":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"type":"./dist/react.d.ts","import":"./dist/react.js"}},"typesVersions":{"*":{"react":["./dist/react.d.ts"]}},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"tsc --watch","build":"tsc","release":"yarn test && yarn clean && yarn build && yarn publish","test":"jest","ci":"yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.7.0","dist":{"shasum":"64d9c9888b5a17afb49c967ae4a456aaa0d28955","integrity":"sha512-LuzPsrMwWzdMIpbg2V22nif45ZePs5FxkotKMOExx2keoFAgLQW7bHxhI5waVGWl5HRvUd2yqJrTo+Y5ueDCqQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.7.0.tgz","fileCount":33,"unpackedSize":36704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiL2VlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAvg/6A4OBeYBRN351ZPXjKyczE7FstdCSh056q2xiqOgkYJmcdylj\r\nH86/bE9NfPLOeqOS6yPqaPG8+Z+EXsbaF0qcEq5/7S0NXpkHJLqd7+IWz39p\r\nDn5LLlUXYFd+JXu5IAi5a5GjXNVNAJ83Q5ak0BEbn2Evea5Vtz5SKlozzDTV\r\n/l8xIj9O5dYuZNvlNsxsUUcSNwj8K8PWuk9kOiLCxGfv/eEgObBUS2v8RBYL\r\nsNYNH+0KnqYya8flr+1dj33QUrmtbU9YrtlzmKpCKZ0H1BVP+JJXlqLGqrJ4\r\nyaMY7FQsBvsEnWp5y4/sjGRJBQE4jKfE9M5xbjcM+8Q6UIi1WmrA7KNZ9pQC\r\nAea7Qy9Lbb0KPmqgT7zkykuLN/t5p1+fNuVdWfTcWxgtHvIZJG27GmR4cXWZ\r\nOvDwrN6nINKQPlMtE0xhwMOw1uQkEwcsRKi1YcVUNqR0GGiIDTQDl7JlFyDt\r\nzkiT0p0BbwiF8uO3N0CxgtaLUsSmlyzlc2zmVW1KezaPl0jVxYT3n+lmfRWd\r\nJ9X4LPcG2JLE7G7uu4RPIgUULMg6ImQmR9y+dIgL/Fqr51V6DgYMf2qES6fQ\r\nLBAW68pCAXY/iytKJADxRUjobXIysF1uWtTmK4gSYQwnrRVXNb+E4C/nXDSl\r\n3YHN/hktbfUjEwTUSfIIbiHtFR1N5DeAqBk=\r\n=kt5B\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDg65CL/QHVCsjH/BGY1S0YKOPaTbEM+8D1n3MfoXI7owIgBz+fBRaszGsGI19WQV+4w7816BgkZvgbPucZC2jgkgQ="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.7.0_1647273317665_0.6500204646550025"},"_hasShrinkwrap":false},"0.7.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.7.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.tsx"]},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/preset-env":"^7.16.11","@babel/preset-react":"^7.16.7","@babel/preset-typescript":"^7.16.7","@preconstruct/cli":"^2.1.5","@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"babel":{"presets":["@babel/preset-env","@babel/preset-react",["@babel/preset-typescript",{"isTSX":true,"allExtensions":true}]]},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.7.1","dist":{"shasum":"0cb9bb334af9f3c999af0879ae16872ea0aff0ae","integrity":"sha512-kHYlII9qsiOiMTgSGSWLuReKWmAI5ZAnK/ehpax8jefmtcPSCvFl0TfKTj1IZXBgL/eTlNYHd+r6gNtfHRITPA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.7.1.tgz","fileCount":38,"unpackedSize":86579,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiL3OcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmryeA//ZB5N7DrMGEZwnRU+g+6BFVP7yyqyDrTUTVli2qj92a6dkhzR\r\n3E/7i08QCcfiUnIPqsz4Ax32JedjLZjgpdX6m3/+p+fiPoQEtbG28CxKzvA7\r\nu0l4HS4jpCAJcrE2lsb0rB9NEWI836UDARBBhhmhk/zfZzQuEIrpt0pc9wdk\r\nqhmgdGmeDT8qSigflU269DNCjdKS/41rqCR2tKVUX/bOJwmkljuNSpjpjCCU\r\nTNLCmJ2bFVc/qiYQHgD/qBe8YHcRS68fMffbixuLSBlpOBoK0V+z2j+2xje9\r\npwOlBKx0J7YnSE3x+Kw+4QRcP34Fiyrp+Zf0rMwL/WPpzufrTwC7lQOFnthz\r\nV9Fzs7tJYsL42WcfjEvcAQkvLf8a43T9wyi/kzjzHcR8BeTdTTE0gp0BlJbH\r\nvD8c8MXv7E2aeTUN6B7J12N4QKfxZ5neycqDyI/X+yWNlAql1q38hSShbDaN\r\nrbqPSgGhpJpxLiL+8ybr0Pl/46K+K3xjNRzMkdJEzeRd8u1HBfEtbDFuECaC\r\nYgjojuQnPEOg4NWVQ+lyr3aawrBH8ifEptDqrQz2CO8a+op6mHbA+AWCgoQM\r\naY1klTlWFCIq9vTNc5ItdbWOziAbncbCAn8TPnB7RhYuGwy80nFpTHWZnIco\r\n9Pz4iiUdcPDwjGaeoVxB2EMYkPYUd5NT1+0=\r\n=S91o\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGqNP3kOwqPz9Q7rdDuVhL7IRqOuTZeEwHqE3r3qydbjAiBgLfgaldgEHZTGqxXzYYyHiFRM5LCu8lD4RMVcHgREuQ=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.7.1_1647276956494_0.32663518083324283"},"_hasShrinkwrap":false},"0.7.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","react","entity-component-system","state","state-management","hooks"],"sideEffects":false,"version":"0.7.2","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.tsx"]},"license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/preset-env":"^7.16.11","@babel/preset-react":"^7.16.7","@babel/preset-typescript":"^7.16.7","@preconstruct/cli":"^2.1.5","@testing-library/jest-dom":"^5.16.2","@testing-library/react":"^12.1.2","@types/jest":"^27.4.0","@types/react":"^17.0.0","@types/react-dom":"^17.0.13","jest":"^27.5.1","react":"^17.0.1","react-dom":"^17.0.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"peerDependencies":{"react":">=16.8"},"babel":{"presets":["@babel/preset-env","@babel/preset-react",["@babel/preset-typescript",{"isTSX":true,"allExtensions":true}]]},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.7.2","dist":{"shasum":"c0b759b21459de397006c47a072aa63dca469f07","integrity":"sha512-xewG/5wleeA4rJzNqHCRuOAoQm24gNALPYAIpt+GlTT/jaDOZM2QJCOCXRE37dCWkTSE3tMGQJrGJqaQQfJTsA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.7.2.tgz","fileCount":38,"unpackedSize":86759,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiO258ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAng//diSGx3Hq5EaeiiAtRHOZcKwgVPdIXLKEbYm6SorAY29xr9wj\r\n91qv9Rpq23eyEw65vWn3SwhT62fNOFwfmvicjSnn0FATvU9Klsy0/NfOSyIU\r\nViOKA8FaSuBPGQxgSKPKoutfQmZvv0mKYozKlCTNoGZEvxNiEqwyZgHhwef1\r\ncM9LzqPO81avS5IMNxTJ/uKi9TcwkRwoGvNxDkOUoev5eW36HApMgBE1PnxB\r\noGqH59x3Be//3+GqW/M2tUeV5MU32LFckKF7XWtLrUHAiyYH6Ms5vfbAjChe\r\nGER59VnLHWC7hnSlvHvmQ5wHw5E3/cVt8A4tDfppebYT8F4h0FixNraCDwg0\r\nGCvqVEX3wfDWASAG0T1YFi7hCisxvkbAO2V8NnqL2pQ9wimiEmpOku6JtvXv\r\nXY+e9uQJCOu+304rBsxG0L1QYcPDjH415iGMLQRDxaiRfPv/zXTY5JuBIAzF\r\naiI3XukfymtbednM3TGy0aIW0BJqQxGqg659NpY0OcjmsLGO5oc2PhBqiXk+\r\n8aTVTzZ8rD67009m5uBspIJQBSaxtKaPFvLlzbA7eDw25OhdTswEEGu1W52J\r\nIclbHjrRaqMWRZSADOGYE0oeQRRkSHlHgFCHPgXwJO82XZSl+XxQ77hYiBdS\r\ncIkGMT9Foht9su6GUafTtc6WXbkmMhNA1lA=\r\n=C9we\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGlb28/ecFQW44CjMcyYLYSm52BrFUD73Kft08vb5Ea7AiEAhuxx4f6ggYMBK8y4Ucv3uv9mfGXqatopA6x3DrkC12Y="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.7.2_1648062076471_0.1205063206532162"},"_hasShrinkwrap":false},"0.8.0-0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.0-0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"readmeFilename":"README.md","readme":"[![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n**🚨 WORK IN PROGRESS!** Miniplex is mostly feature complete, but parts of the API are still being fine-tuned. Feel free to poke around, but please be ready for breaking changes!\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, it may sound counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **zero dependencies**. (Yay!)\n- **Comes with React glue**, but works with any framework, and of course vanilla JavScript.\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS implementations\n\nIf you've used other Entity Component System implementations before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike most other ECS implementations, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Some React glue is provided out of the box, but let's talk about framework-less usage first.\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities:\n\n```ts\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n} & IEntity\n```\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n**Note for TypeScript users:** When you provide a type like we do here, every interaction with the world will provide full type hints:\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that flushing the queue is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage with React\n\n**🚨 Warning: the React glue provided by this package is still incomplete and should be considered unstable. (It works, but there will be breaking changes!)**\n\nEven though Miniplex can be used without React (it is entirely framework agnostic), it does ship with some useful React glue, available in the `miniplex/react` module.\n\n```ts\nimport { createECS } from \"miniplex/react\"\n```\n\nThis will create an object containing a newly created Miniplex world as well as a collection of useful React components and hooks. It is recommended that you invoke this function from a module in your application that exports the generated object, and then have the rest of your project import that module.\n\n```ts\nexport default createECS()\n```\n\n### world\n\n`createECS` returns a `world` property containing the actual ECS world. You can interact with it like you would usually do to imperatively create, modify and destroy entities (see the chapters above.)\n\n### useArchetype\n\nThe `useArchetype` hook lets you get the entities of the specified archetype (similar to the `world.get` above) from within a React component. More importantly, this hook will make the component _re-render_ every time entities are added to or removed from the archetype. This is useful for implementing systems as React components, or writing React components that render entities:\n\n```ts\nconst MovementSystem = () => {\n  const { entities } = useArchetype(movingEntities)\n\n  useFrame(() => {\n    for (const { position, velocity } of entities) {\n      position.x += velocity.x\n      position.y += velocity.y\n      position.z += velocity.z\n    }\n  })\n\n  return null\n}\n```\n\n`createECS` also provides `Entity` and `Component` React components that you can use to declaratively create (or add components to) entities:\n\n```jsx\nconst Car = () => (\n  <Entity>\n    <Component name=\"position\" data=\"{ x: 0, y: 0, z: 0 }\" />\n    <Component name=\"position\" data=\"{ x: 10, y: 0, z: 0 }\" />\n    <Component name=\"sprite\" data=\"/images/car.png\" />\n  <Entity>\n)\n```\n\n## Performance Hints\n\n### Use for instead of forEach\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis might incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (let i = 0; i < movingEntities.entities.length; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i >= 0; i--) {\n    const entity = withHealth.entities[i]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same categories of entities, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.8.0-0","dist":{"shasum":"cde84f23808b2e878aff5709d0d402a2cc6e7d5e","integrity":"sha512-awnMA9v3kM9h9Gtuj6kjPplZ+isMQfi9kj6j7wvKtGBKE9jl+q3TTs615gSnhvhdq+rYXbnQoej7VVupxKoDeQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.0-0.tgz","fileCount":24,"unpackedSize":61439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiPbRlACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo7EhAAiJFLQ04r92NHOhkrrv2EEvTgsllmiZyZD5tGSWkK+F/XBVp4\r\nNl7WVsRFgXOWuQdi8e1bMu49Y7TdrC5viKM2DlJa/DgxDi/BJZvq5inyzMSn\r\n1ctaIhsk5nOHLhPxqWB3qI7V1LzMDiHUkgSR17ossyHHRboYrK/F5VJ/ozek\r\n52gRNUgGEof22M4AHikpC6GcCUwqukQWGQexWZSNadID5PqrSem8jhWZuY71\r\nG1xSCYp6qGugQNA1dtXM8QkjJ/4AZq41ZkmAV37muCA0E4+anIxdNP/w1MPd\r\nE4ng2hyOw9i9cu+K3+pnIVbi+xSBTyVVpZ5C+bjvaoKRARfosmLs8+M4UZvS\r\ntLSiwkk1vY8+yMFp7HonOQhZqPpJYr3zSQz4LY0ba6ifK0J2nv0NAnXmKx2H\r\nEDCpso1uAiJe2MxBNu99ULg1du3GWNAgNkqmlY4rrfIfWvKeNOhNBBLTVj+F\r\n5K/UemP6PF5YQuPT4MJdljtkr+A3SlIwoSkLxxU9H1uT+bAXEUterIHAFzBx\r\nPmEKBIQyLhEMPFw08u38sewwW4x1CLRotwVYCbY1lyYwcqE8c27XH5kyTuGq\r\nAICANZx53hV4tHGeokbm5imFuWLbkK6xXafmEqz1+aI9wCIdphRmctQBUNMQ\r\nQS0lG5RjI3tKScYA/+t0kZI8wx1T5THd2N0=\r\n=8NCG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAMFWCgNrVD92n6aqlNuAkeayxhAxADkqSdW2/T6R1kfAiEAnQXFIdq9QxrwBeBlebzXIQVDTVMiIGEbi10cTkEX8Y8="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.0-0_1648211045126_0.9961803458136758"},"_hasShrinkwrap":false},"0.8.0-1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.0-1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"readmeFilename":"README.md","readme":"[![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [miniplex](https://github.com/hmans/miniplex)\n- [miniplex-react](https://github.com/hmans/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **zero dependencies**. (Yay!)\n- React glue available through [miniplex-react](https://github.com/hmans/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n} & IEntity\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\nThe returned object will be a normal JavaScript object that equals the object passed to `createEntity`, but with an additional `id` property containing a unique numerical identifier.\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has three components: `id`, `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i >= 0; i--) {\n    const entity = withHealth.entities[i]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.8.0-1","dist":{"shasum":"2c3a7cfd8dab9bcbad81081f7ef2ac8dbb054c8b","integrity":"sha512-dVnUoA2nJss05K6lP0+f4lv6HSJJlMZxquKGGZ01pQ2BQ04BMxfvfolyjceBeY6eMuElaDr8WaHNUjgBD3Df0A==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.0-1.tgz","fileCount":24,"unpackedSize":59736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiPgqdACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp7eBAAkXVf+i2WcGhG5VEwqCynk/U4Ao+AC2KbZnxqg6184t6Z+/rw\r\nPdsS5+0tLxLR8XweKolgMkIV+CyjCNJDPSDUOKSkVRYMSJoWRoDDPsFP/cEk\r\nbCEJSzdVWt0oXx5a/5CyWIbm9COygJHq9soPyibMuHkEPwO9xvHpuQVIvXlc\r\n2trrmPFV9VMGbSeNTGR5t1KpYidFtjs1wY3ZgRjBxmGX4LxzvdmOeD6Gsa1i\r\n/o7gX9bJhQltHewvBJqNvIptRgN150aEVZYuFggW29qD3mb8ZQzlWAsjD2IF\r\nzoRZl2PmNmIhriAYF6cCg4xbw+KNEso/gd9wvVaKluiR4VzFrNUfEXqSoSvy\r\naH+IEnQCDq658yJs3EC7GzRK6lX2nT8MM0v7yQ/sh0fFO2g/GIObfLQcHpv9\r\nB7vtREV6hQK32xvxkXkP8QPL5HvqeEpthln0Xc0/ExEcTIWoC7fS19/5+TlU\r\ncu4G+WPjcc6fQl9yGw3AJiObth5qjYo/L8Zn9ti9p/L5m4SLBirJtO6kWgTR\r\nF5bzYck8pk1iSSDzmkKGhopvobiPWztEohm1FbK3YnOBZg9bDLd5W8pMGsJv\r\noT1p1uni3zZfbXFeMMHaRbpKlxI5eVUQX0oaSskBumbFIplknl87QeKjUbcU\r\nVUPuIaLWqcT8E9RFUbmzoXY9+plU8BhVhxE=\r\n=37ep\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQCgyG//XaY/nulSd+pgjdwcpDns7wFKnJ3nHDtvOYmAIhANEdc8jeonpmmEgyfSWnFPf+iZ5zH5yLbSH9R+uD1rev"}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.0-1_1648233117562_0.4375813487798965"},"_hasShrinkwrap":false},"0.8.0-2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.0-2","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"dependencies":{"@hmans/signal":"^0.1.7"},"readmeFilename":"README.md","readme":"[![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [miniplex](https://github.com/hmans/miniplex)\n- [miniplex-react](https://github.com/hmans/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://github.com/hmans/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n} & IEntity\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\nThe returned object will be a normal JavaScript object that equals the object passed to `createEntity`, but with an additional `id` property containing a unique numerical identifier.\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has three components: `id`, `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i >= 0; i--) {\n    const entity = withHealth.entities[i]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.8.0-2","dist":{"shasum":"86ccef1cf4dfffdd8c560beab19d6f3fb6fa6860","integrity":"sha512-+kXYV1DATjQiL8a74Kc64rHc5LBou5+8Kje4VJYeUUu4O8Q9A/w4HVB+fH7sItndOfzkotX10JTwqOB/hgtzNA==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.0-2.tgz","fileCount":23,"unpackedSize":57596,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiQH81ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrgvA/9FNqC6MKwLkmsSHuBIYH9yP8B6b0hj1IvgxcpjtR0kBun7aj8\r\np6qC6KXqQqgZGR0ote1UWJAdJZu7DcuN5bTbp1R+qp2lFURNg3nYkDxVU8L3\r\nWxPVeseT0m8r4RsdQovjwH1g+g+UFrsHZx48E7WPt8l5WVChfxjzff4+3gQF\r\noHLEJ5tCmNiShc7wVtuK6UYD9zX54g1hPsugzjfWhMRoPwtYuij8IYUsqg5v\r\nf1/Yv9vKn5IuuN2U9JoKlryDwwmWtcuq44b9+FhZo31khphOdtLc7LJKNSW1\r\n89zaXEKlX6fP/qS70/jk9ahzVuG/ra/WwN16je6feVDA8VQsG5CxC4PY+1v+\r\n7C02W6Y+Ns+mDcjVnJ+1MVBu92bdPpscU9HYpqBgngMqgUQolFlBuBZcPwdt\r\nevMO4URQmeV4V00rptDDtpJIcu7y9YA8ouyFzjYyV6CKx3hHyyViGk/DMNXm\r\naAHt84NNuc6cm0KlOxavjWlGrcHIDsCClHvggqwMpLHZkzSsxKv3eEY3VKWR\r\ng6K1H3SxplzC5RhcmQD1Oys0PuLcVRgelxAGl7fhl8qHmgYll89nbGQgPLWm\r\n53nh4uAC232GFUEspEFCJHVpl77F/yFVpUau32H/QraECQTkQ/NDR+gWzDhv\r\njE51QkGTisVETJnQxUBXNf/gteXuanc/6Xo=\r\n=8vdu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1olw+driTa9Rs+7SnLHjRV/P/WzWS2yPbZ0KLgJWjRQIgR4yLvWRaWTtvj964C4hHpofzyeteC7unQwLPbkZdVBA="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.0-2_1648394037301_0.21105402325986833"},"_hasShrinkwrap":false},"0.8.0-4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.0-4","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"dependencies":{"@hmans/signal":"^0.1.7"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.8.0-4","dist":{"shasum":"37b31207c0ff9475737222738a91e533dea38535","integrity":"sha512-JOgXS0Mci1utKO97GNHPBnpxlYDJf8HR0dpOxyxNB1qTzTgvvHQcOzGDlZ2aqOtouYu0AouA5JTKYvDbV1iHIQ==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.0-4.tgz","fileCount":22,"unpackedSize":57747,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFNmpArBWIe3N1+oDWywGTZgGc+5gMDZ9l8KqSkcfPL5AiEAjvGYWSciJmG9Zhk+usttKxlw+S5S3zIFbPxiE+F8Q/8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiRbkvACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmptjA//bIENvQSYXSVByNTQ8Jy+UqZ8tA4PjwrM/jpuPjARBr0wEq+b\r\ntOpt8TimKKhPVIDDIQ+p6ZA6ghiIAfjdMCnI4ZjuluRfVEC3uOL0HQZUWTFs\r\nGHVZnON+xGI9I3PcuQiOgnU/qJrKCa2LyCMt+SMl/P6FazmxbtAnTO4Ufzao\r\nbK6FKrS4DNehcceyspYhbsobwMd1P1blECZmraw/nM3daeMujGbfe0qsxmZu\r\nUtLLmfne7I+uoloP2uE1HHhvGyiamVZH+eHxizhb8q2XuKPDT1iCZIBjZLDA\r\nlXlzbzoGshpQcokLfqtt85ok8qcb8QSvncRdKqb6ngqF16zijUyv5NzmfuZu\r\n0UAPpP2q6yQp9FsXvsqQPYFdWMpv3eK9ttZz7MSoxedKHiRdZTXv0byiYg6y\r\nAqEsKccZhtV+5dIpMxZNCUwfzoedGqAwg41wbPjXVyoHWtnuQy/6EhIwOnx3\r\nXgrerc4nC7HAtgzwPr/6Qk2yf75FTdXPuG4AqxSCreab3wDvTENMig0cn7m7\r\nNro+57gY4MXRl7oRDBYoHtNglfH5eQMGqLVSSsOkbFFiALxZN0TrNs00az99\r\nHm/0K3v9y65qpQKiIltlH2qBrQTNS04c6yvDZ6o4mb5bHq46B9SpWGdrU02T\r\nMf/hByoxdH8HuL5jfr69nPg59pXVsn9eGrM=\r\n=9umQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.0-4_1648736558788_0.5318530999413025"},"_hasShrinkwrap":false},"0.8.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"dependencies":{"@hmans/signal":"^0.1.7"},"licenseText":"Copyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","_id":"miniplex@0.8.0","dist":{"shasum":"01dbfcda0836eed42ba3f2c442b2cac8cd299b3c","integrity":"sha512-cE+OtLydvrtMObDlcXiCeB1KylI8iNG3JwwqgiNW/gszek99hn7/wNqmIkwL5WthsJOLfP8PbYhvIiTqOye2ug==","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.0.tgz","fileCount":22,"unpackedSize":57745,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH0I2ffTx2vcAD79E09wUN8j5vSjePJMOdECVDGTQaJbAiEA6628u1jeeFOE3l0TfGyti5GwB5iHZP0jsMQhiXxM8fo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiRbmPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp5OA/+OP1Qe0HTnKVwGq58DUSeqkTBZRutKM5AVjFwgsxxmTIUje1S\r\n9/WDbtb8RsTq9Fm9vLfBXZsTkD7BOJl1tJmnBTDjwn3Stt0jn48vckdHat4m\r\nJZaI7Y+0BswPMnHA1JPtUqUk6Ci/2JDiCoH7CyorZln9MbzhRnECDLuu/z6K\r\nAQxndH6EsZMGS1W8bKwBXwNbZn9QlMozP/HPadu8Ty6lBMdVA3jdgah68R3x\r\n9UsaadLOOtro0AKxTFtiNKVMojxX8iAFYQrYB0XEM6nNgF1bZH0vteg+3yse\r\nu/ddYLaet/9O7QcNaW7eCU8iGdruQmco269I3ozbHG1ShUnHYTD/eCpI1vXG\r\nntAV1R8Yt17IHenfikHp3nQrzoaYuHu1pRLPDblqfZFTtbaw0JH15C8pfwGs\r\nTtZ7pY8zRKKAxNkAVHBY5yWaU6bSsHdrMR6hW3sQJ47GYQpmgnOfl4FM4YGj\r\n00dw9ePk/6rmWOB20WEuqnILdryN9xQkmU6Thu8P9osEW8Nr3mt45kWhSyjq\r\n9m/xcTEAwJHD2uQdIcAU7GqEHaX+ILyvvn1j1axVVJwYm1N0AKtzYPOXO6pa\r\n16YiPI1nrcWp4TLCm/I2XLS7eWBSemh3iOH2UGdsozV4oiHDIHVVQnW3cjKE\r\npBHqluD2kQ4Rf/2dMDMEkSjaSYOGfMledR8=\r\n=Wjj0\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.0_1648736655228_0.2441190876591648"},"_hasShrinkwrap":false},"0.8.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.8.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2"},"dependencies":{"@hmans/signal":"^0.1.7"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"gitHead":"e00b2cb4034156f3f16b137b49e0bdb3642ef780","_id":"miniplex@0.8.1","_nodeVersion":"17.6.0","_npmVersion":"8.5.1","dist":{"integrity":"sha512-AdTV5AihrtTVd1KJCjPA2BTvPIkX7rpCVaopG+PAuHUSVMuyjFcWG0wYQPNlEGsssINqea0FhzI7WIlJ0xZXMQ==","shasum":"74912a3d8400d9f5e90ecafd515dc3cbceeb03ec","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.8.1.tgz","fileCount":17,"unpackedSize":57760,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDw4nxBmLGMo31XyclarXgeyP83nz66FwybvH4uWeAYRAIgVBMGM50JXuaZudR9/Is4o0IFR1Za2TqVq95tlBZUv+I="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiRb6XACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmocUBAAhI35h2gcNdGWmce4qZ04vzzkJe84EKUdvdhBIyUNcSntQDys\r\nBt25Y7dIFyfgm62oyG3+MEavrNObki98xG1IXNxfIvXo0EFsDeGoc4ajSEnl\r\nz7R9YJS5toF+WuOflyq2GngJH3c0+bGtn9fL1wVlh91d2j5t7vZ8Mq4QADXX\r\nYJHgvkvKogrRl5WJbFMmI/hXvsE/MAt/kDvn3eDwLbhZuuF9cq3cOzhgtTSv\r\nfeXXKXjj80Ra151TFgFTqkIRROdDxQL+iIZ3kPTj3spSm6ckkqr8s9y0+EoI\r\nXG226mP6e7hR3EygBbZG9Zqjs+6eaL+rAlEHClEPT9ZBiTHSegMaK0ScyNDV\r\nQxBLvnGkkGsPjf3mx5dvSeMt2gJUL+zNK305smGMYKgk9H/jEOqqfaX2WlKK\r\naOugS5oi+I00YWev93bJCzA9BMzuXO3qvarCpiq/kRSRyQon7cf3vskzf0Kn\r\nzqbegsYhS8LW5lzYfJ+/yAzfASqTdeiunp+2fywyoI2acPZV+nu0Oh1yp2S2\r\naGFRCUVpReKXJikFjFeRVgw1c7dh96lCLY8iOmB4tUaCugpoCKQmKghF8nNa\r\nu4xPkH7ssy/Tx80J3pE8MmI6DPf2lLBfQD7MNdifqqWOT64mSe6mfzawJIoK\r\nfnC489E6yh2DRRYbeUcRkytpov7F874bqcM=\r\n=PhSc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.8.1_1648737943101_0.4665050244725806"},"_hasShrinkwrap":false},"0.9.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.9.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.13","typescript":"^4.6.2","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.1.7"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.9.0","_nodeVersion":"12.22.10","_npmVersion":"6.14.16","dist":{"integrity":"sha512-mBmESBX2ZsuKo6DFxjw2OINRqEMKt1KtMr67Rb8QE0kFJbkuhbzkcjfdTqH2sDdOWvSs7vcmAsTfWOhdair/gQ==","shasum":"e7ce7a7a7a36c62adaff7b6568082d2a8c0dcde7","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.9.0.tgz","fileCount":18,"unpackedSize":68252,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEYM0Gzqtve0sU3oVzXru53jGQYnaBVzaBTeGsutVRgVAiA3i9yQRgXalxvHYuB26EQ431/6DedPATS6DAgVxT4s3Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiRwTYACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpEeA//YsQIB9N4Xye+T9Ex+j4G9lqQag5DZoVIVauBPHaJ3cok44N6\r\nMDpjBixrCJqJxRP7m2z4+RazMXUYfMZcn9TSTLwio7SMoAzZp+/b5JJUjagF\r\nzKutqXTo52uN1UMrCDEXmB0FWCJTDSz2Cu9j9fJ6IySKKCgnwlqe+cVSqQzq\r\nTbJUxRmauwGERgxUiU0fzELhZ8M/ipgEUkg/CFoBg6SFZxpKavE9fQrGnsFg\r\nZgxIg6w84e4OZKF4C9iFSFRcjFPVk7ZYXaJBKEs2w/O87ML3Ov+7nNhrtHo9\r\nIui2/e15Mypf9kZH/tlA1h8GtCsctq6pDu47aLjs+UeF2kiAKgeb28zhKwWS\r\nHI8m9bkRtvi3he+RLsDkoOID0Cw4gxhwjd4Wc6EgSR5pZes6eJXx0hXjcsAQ\r\nJWVGMTxn/n+fWnui+MNiHTqYveEmHDE6Z6N9ejeCMliAGJc7xRdt61PMEX4p\r\ns5c32pzO4BBWDcBQdwwYtiaqd1iZX01OicIb5Sdn3Na5I+Xx+jmqTCKXCOUn\r\nKSekGMxo5Et4R1QPOSBKNMq9FM2d/oGmtseVTZUXlvUjuEIoSnb61BAG1m9y\r\n9ioki1c47UEnc1yQxQ6ucEq1Dul+J1rQ/VgQBbF/UDzVTlLF3YDEG9g8N0sj\r\nbCrmh7/+OK0mRL7lsWYQJFBJIt8P5rlPmvU=\r\n=AQ50\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.9.0_1648821464003_0.8968443166987226"},"_hasShrinkwrap":false},"0.9.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.9.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.15","typescript":"^4.6.2","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.1.7"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"gitHead":"aaff0498da1e89e26e2f9293fb32e8d0e201cad7","_id":"miniplex@0.9.1","_nodeVersion":"17.9.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-ivHUvcVdnTSJbVWmbi2plyH4GZM7ezSxEJfVwS5NAMmU8uk8XnTJ9LkDe9WSe8t52BJ1jHHe5P8q/6YDmtDNLg==","shasum":"73a1d21fb63f765adc6f107768315e58eeaaf6ad","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.9.1.tgz","fileCount":17,"unpackedSize":65987,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCQ54eJ/CDKQJBw78hNW1DcZg95fYjrEQzyGZWVvD2HzAIhAM0W8b2IztspiQ+MLHqDLanDENNMK0D2NMzjBfYB69SX"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiYF38ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrPlA//bX2FJZlUZGgUHpY9XNXE+wTOaPwHrOuyEWsSf16Ma+GUVzNe\r\n/6AYFn7PaCGFNwleV/8L9pamAzL3u8OC6LpG0acg33qKwtU2iHXZO3WeHx7V\r\n/bG4Lv6R2fMhdVEYFSHAHEDMjMmJ/F7yG5HtKJuKwhD7pgmCR3yhcV2Lp/u4\r\nO35ob/9wnmRwKg2lA/eUgc6U7pPMCX74hfElMJgwP1KpaPE9/NLUuJwhuffA\r\n9yGBiC0u0DqpwEN3ChDcAHu6zn5XyM4yrxSVe0/RnbyrcNqMdlOaGx2o0ADL\r\nV8s0ywl5NhdavPmDdqOTnzdCqFAMW1J98T9Bj8qNA4iZVE9yMDsVtzQVLWMY\r\nL9wLxd3SZDTDnDxQCKzOWOA5rQX5QEImUMuuXNf/jRtIZy3lBnfrKvn+SEYr\r\n1js5HAdOKD3OKH26zKYMmZrkQzoyRS9fkb+hoEUTirV+u9mQcsCO1g8YiDfI\r\nqr+bEg9WnS4gaFvOUIHNyJ5R8j29rq+YPaya1EGRa0jNUPBEPvv3fWsG1C7u\r\nRRJFr98hFeCoI8beLNsmlTs/Ma6it2ofDXf+dJnKvLnaD3F14BcWbAjc03wy\r\n4touAFNpQ2ihn15zavfh5rCNzjN85De02KwL2W1jedNejTrC2nAjcYMgT1YZ\r\nY+DNgb3BvQBRqJjvwaASbYQBHnUS2g7vWcU=\r\n=ft9Z\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.9.1_1650482683961_0.9975145136296051"},"_hasShrinkwrap":false},"0.9.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.9.2","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.0.3","typedoc":"^0.22.15","typescript":"^4.6.2","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.1.7"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"gitHead":"ab0188d1b66678414fe3ed0bf52900f3bc0683fc","_id":"miniplex@0.9.2","_nodeVersion":"17.9.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-38ZjpnGXrMjEd07IqHr03PrbIj8kjEV+3ma9phUvwRLW7u0AJywvnHcdz8rU+vqIpDVD9I1l7lbwwT03xCM5IA==","shasum":"8b3a7e77c4fb531cac76de4d4dd6ec80f2f59ddf","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.9.2.tgz","fileCount":17,"unpackedSize":66383,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQQSWctwHSpgrSTTiixyVnRCLnXNV8WQsGd40UHq5NawIgHzx3H0S5EbAkyC8mpoUgf8qTgDyD9sOA/D+gZ36Ppks="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiZFZBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqhaA//Yk1p8L2KGK8Ikp9C6uqwL9jkeII6xVQF+pa5EML0rZFlnJaC\r\nZ0D9gSWK7ydKghLF+ESa1fMICOXw2OtBv4ipC9crvi1MGPGCkO0no1KEiLKR\r\nAPn4JA4huaPtSMUHD/XcY4MmBLlkbY/oqQEox3NozJrfrPv/3X5mmHOn7DAu\r\nFBdHT4K6YEr2u36DNMO8mtDhBxvjvaXU+8wt7jGFhVkLPqPxPi6UVYow0chr\r\njQXmh0P6Z5oUYdQFZiRAUoxUJANgC6TtZpcwc+KMdIGzkOyJ2CYs07vJyR/7\r\nnT5ok9Eyx2jKF2vjN0MatDsvcigZDP+6o2Dx9EIAdbuD8bfwvQ9fHXh4eOv3\r\nfmOgN11jgbrBMU8wKhhxcIMJn9OISIwDNbs6YZ8wm4y32V7E4XcufoOctrAd\r\nSXAqthf42WO1q2Y7VUaiaRGKVUalyoT3YC2g8OaY1BPCoLbm/i0U2FARpqhm\r\n0EQiRHmlFb4Jfp5ys2VGlDu8ZRCrQzSHSm+mKVQjOdWymQZO/+VDfpcN38UJ\r\nHaHJ3xsbvrzl/zKbQp4uRaAmichVIua1SbX1UbtuIE3R5nDJde+4KJqWN2R0\r\nJkXbd0wMSBXS6jPqB4uaeZWfHZ8DOFDb2A+MfSvvBghw/EZehuA1G+VyJMl/\r\ngOv5at+JQRmu6hqRRNv1yKZzgoNfPpwnb+k=\r\n=HFvn\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.9.2_1650742848735_0.46073746874060406"},"_hasShrinkwrap":false},"0.10.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.4.0","typedoc":"^0.22.15","typescript":"^4.6.2","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.1.7"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.0","_nodeVersion":"12.22.12","_npmVersion":"6.14.16","dist":{"integrity":"sha512-7k7NL69e2C2O/CkaleEHMcS8oSxFpJg+pCrMy3Z7s7Qgv7uO0E+whRjLqi9RHTha3bvhwZFDCum/TNnFz1OVFQ==","shasum":"3ea611c4f27cb0719c479115df2411fb819b19be","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.0.tgz","fileCount":17,"unpackedSize":67254,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDuuVxzsTzrij8h6vd2u7uEH+N/iKDv7wYT7lE+Ldg3jQIhAM5QuSzCxvn0k6WNixk+yzznLhGAjYWBqGSnJ1thPy8x"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJia/8AACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpmxA/+J4AHieDKkrd7b6NrXzZbDDSmPsdX3DRaPe7issRDgSqY2/TG\r\n5BfrWVeYRLHAyo74k3Ui1cFLwtR+niCaLJRVSB2KCKSYVNJVE0kX3EZ2zYRj\r\nmOsB5FfK6fKw1KBp2YILl6zl/vDdI82AL7M3c3sj5HOPfkYw/OeQgaiZoMDi\r\n9I/xUrUrC0UD8plntIdqoxmv23yxFPAwdlz/0ySxLFoQ0YVyJMRpWzVMrCvh\r\nCJiomQwxuEdGyygqoHBUEyfEvIceV0b/llQNolX2tGXh8N7XbILuuUDlRBUN\r\nx8zRFId4BFL6OS1x9o2/gnGNljnGokiI47YEm/v0fgZMjmDoCRgpXrZ4biYN\r\n0CvClw0lzIUzMgIwNl7C3irqvqXo1hj4V8Tq+Cayxp/4BOdtV00Vj7b36ite\r\n1EHbydiDv11ti/gqyjcjzCngtDz7CcHUxf0OYTFvgQtboor0XHbrJAwmyip1\r\nN/R1SD7SeWJ2uWZAWRu8SnGnaAhAM4z0aYQMQlu/rzvdH+Ot3n19tCdeK1t4\r\nuhGxJjENOxhK7EO4wc2h9bOF57KOdfe1gW1Vx8kDucbALX2sVJ98v/rIqrP5\r\nM0sXZ70KxLYgBbtlY/c5qugavllAmuDX+WgE+pUhKNTTpbfdmJenyxflRpPc\r\nij7uKDJSIfIiaGgFgDU08z3c/bDpJrIly0E=\r\n=0BUo\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.0_1651244800506_0.3856706666844043"},"_hasShrinkwrap":false},"0.10.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.4.0","typedoc":"^0.22.15","typescript":"^4.6.2","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.2.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.1","_nodeVersion":"12.22.12","_npmVersion":"6.14.16","dist":{"integrity":"sha512-3ahZ0/k7qJqI7NAYJnEqbbV/1haua1YLPdBtFxMDbSA0ZYXc6YyGuXP57u34dzm14+9IxXWDw1PliGQdZIZYoQ==","shasum":"890355fc9f77b29aa1cdf126149f20c2673a3f84","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.1.tgz","fileCount":17,"unpackedSize":67885,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHF8hsOs9ar7z9HFQBLTvV9CdaBDDf3WgjL3+P9KfjP3AiEA0H/vxDSNhdd74+kpDPA8F1tcxvtJP3CXaEbK1v8PJLY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJidW7gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp2Rw//cJTENUq1AfV3UZA7XXWUDP1mSI7bXYyfyIEjWKWFLG8pdyXk\r\nPf2I34T0hYrkaYbyBu4vyOcdmB4jFGNRf4fbNCoQqK8QU3w2RGFI7TtD8QVg\r\nGWOw2Iv4/WWgBV9AFxTkbu9HicC0K0VKGDV1vRCARNiFjYMn6/exRz/jTosl\r\n+pnebeOxes1QY5H+F2U5nzoorfOPj0GmShnOWVP8JlMkk61Bj1ur0qUmdov9\r\nbTl5utDhBu/T5d+6JjYfxZx3fLwKEBQ8KI5vFWp0D8IkTWi3qk4PWHld3qQ1\r\nFeHwRDW0CaWybSDAFCt3H3qrnD3eRa1djL3Mrz6JrmjV0snft7p8KksXvvI4\r\n/tKP9Cx0pul3wrcXCu1MLN+KGxN0CS8Eeg3zkgMDgoG3i6hGUSBf0ZOFBsQW\r\nnAdMHZFVFmNiSwOws4tmrZLj93URF1orH7MV6Q1OksrM5GBeymzP3Hdr/s7u\r\nf8JHekLcwynRaajKVb8b7ANzX6F8R3WnqIoteGT0GmTMAfoLZhDfmJUhREnT\r\nuWXsQS8pcLAIOaWU6wpVBqmrLBq7H5siUPcaqlg8EajFpEgdWdpEOtlfeb1K\r\nQ8hjMlszvSKp+zm455W8C0o48Njs7BcKAr2lD40bmHhEL43pMjv9u/UPPb2T\r\n9xUIE7Jx5KtGPJjq8s5lC3tb6Z7R8uQWaZg=\r\n=3tZn\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.1_1651863264575_0.01736393893139576"},"_hasShrinkwrap":false},"0.10.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.2","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.4.0","typedoc":"^0.22.17","typescript":"^4.7.3","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.2.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.2","_nodeVersion":"12.22.12","_npmVersion":"6.14.16","dist":{"integrity":"sha512-8WQJNpIQLIZfDLB118m2Cn5nypSnXtn/J2SWTz/4c6Q1yxM8Sghoa8aDNCYzTOi12EPpDCwVACqG8mWsmOdjGg==","shasum":"439f36549e3375a1cc1c09d96ba1fbccc00edd76","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.2.tgz","fileCount":17,"unpackedSize":69207,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEF8z4+gjKSLpFB2YAJS8H1SoxyaciT8bW7PjPMYZh69AiEAvH1vYUsERHA88O1dY9WcDbJOrhXF/apGrxnZobq7dIk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiwJr8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoReg//bS204bdUKseioQjMzZfDigm61dkDNsiPdEYYYR+s+V50tmES\r\nCPJKMRuAZYwqqEInCMfnPO9sJD1XBpHpnBO3/IaDGfB3z5KSE6d++zPlQAqf\r\nivoPzNVVfpb/zCI6cXUAdJZnZqy3GV1q/SaU2CpE+fiaM6/Q5FxA+aNm24e1\r\nvqagLvIHVLcJTnwxE0xjubO7elE+W6Mlcwi5Qvn2DwuJ2knPPwWQKbzlXMlX\r\np3iqFwXKQSAaFSr6rjEIC5lSBXJI2objw/55eSTynSJ23zfb9EaoD5N15xKR\r\nR1Z7rB0wKLEWr3Ks+OSF+Ismx8lvOOQv2yd+geeUJSxjtNLLf1RkhGumycGe\r\nsg822BKh/83Uppc2pfWeHPwXWIJGmgQ+7ia+1Dhxc5Xo3ITo140vCSsB5u6S\r\nwiLUW0AhH5eCKL3gOiyxvuVBxOcZJymsu59ji/Hn/ooCtj8IU+N04OG2+7zw\r\nk9zqPWDn+mi04LplgaO1x8xC0obN60MNanVvrYgDmY1kjWJwYAB80g1EJmgo\r\nYBeKk2/Zt+qI/Z6kKL8qAO7YTK1LQEQfQQy0V2imjilVqYzgCEg5VMn710SB\r\nbgNGj/6wHxDr1Y2+lo/6nLsRdtAwn/VmiSvnYu7+dZ2Ni4Rys5t4uOpkq/k9\r\nabHqBLTtXRfi84jn3W8iqio/SQAerUvF3bo=\r\n=/D22\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.2_1656789756030_0.07871436009914623"},"_hasShrinkwrap":false},"0.10.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.3","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.17.9","@babel/preset-env":"^7.16.11","@babel/preset-typescript":"^7.16.7","@changesets/cli":"^2.22.0","@preconstruct/cli":"^2.1.5","@types/jest":"^27.4.0","@types/uuid":"^8.3.4","jest":"^27.5.1","rimraf":"^3.0.2","ts-jest":"^27.1.3","tslib":"^2.4.0","typedoc":"^0.22.17","typescript":"^4.7.3","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.2.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.3","_nodeVersion":"12.22.12","_npmVersion":"6.14.16","dist":{"integrity":"sha512-M0bgzl1D6Rr5ML+4lhkGQTV/JvXJLF3rDMbdrgEZuCW67ZNmak8uPMMQXJDAbuuKDR7tNaub+WgOKmmTzFkTvw==","shasum":"9265cebd532384ec452eb4279d060bc8df6c20b1","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.3.tgz","fileCount":17,"unpackedSize":70459,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDvfycZCWp3B0ybQaFl/2C6/y/upD8WdLH8YpAHfBhjnAIhAKdZt7/eBE0+8CB5ok8vAkAM4Ztf5OeRJJgHyoe3iHGG"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi6Tk1ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpZbA//bzWdPsEAfD8zbHfLG67MiCm4Z36W4JG/ympC9LeYrMjnN2Y7\r\nQsl0zmbfb3+zFxXm/exKVnmQjR/HBZ641tuTFFldLBGQ1AplRwPtDgS0pSaO\r\nUcYoRLPvUl3aoIO9a1HLNzFA+Gn/KglV3hedcjsj6Sumkih0BvlhmtjciSP1\r\nzXnFPJH3b18YMRYy12UUuQqM9SgaJSq4LbtTrYMpoDQVow2XfpNhn1dd2EZD\r\nc++8kqZFJwHRCB/j3JZc4mwe+XmGoIKRqFaoE+biMc+9fxuzfe/+xoFKL1VD\r\n7JMlDJvCgu9Hc1373u1ktpkEFLI42d1y6HDLqC9yPcKwJFgK5OgvCAK7YX5t\r\ny6JPTmmGeBTZmCeHQpthB1UYOyCjSEbFOWyUr9jFpfIEmLSKG7IvaWFj7PGA\r\nQJrebTvwFVvaU6tfM+HZVjpM6PZHSB07J89em3BQuG7j/yu9e3hiu3IvGlKz\r\nolRvi2VAPTJrRaDjBYIdgr6xI/Q7MSx0LRgPU6WwnCWQ4kqR1zSBn9rLurQJ\r\nQUqACqwfGBpfao5o9FFP89vMGF8ijkT9awiOiXPY+WpGeLD8WOyr5/MQtCss\r\nzZ4NXxG21smhfe+EFIYgX3jzOn+H0Re8/dqmbysuArKwFbX+BeNJq96JgyMv\r\nyEgWLQso19tbeRlYHM+FWdAzmTHOXv3ESgw=\r\n=jxxK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.3_1659451701122_0.9992853654453961"},"_hasShrinkwrap":false},"0.10.4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.4","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.18.10","@babel/preset-env":"^7.18.10","@babel/preset-typescript":"^7.18.6","@changesets/cli":"^2.24.2","@preconstruct/cli":"^2.2.1","@types/jest":"^28.1.6","@types/uuid":"^8.3.4","jest":"^28.1.3","rimraf":"^3.0.2","ts-jest":"^28.0.7","tslib":"^2.4.0","typedoc":"^0.23.10","typescript":"^4.7.4","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.2.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.4","_nodeVersion":"14.20.0","_npmVersion":"6.14.17","dist":{"integrity":"sha512-9QE2dIqSmjOS/JABDxkC5TK9DOmLFRUYF1CSSiVB47uMS1kQEGt5D+2h8c0nraZgI8hQbcMpjp65XfksClyxHQ==","shasum":"6e42f8eaa422003a5156b41588b38b7a61c4aa07","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.4.tgz","fileCount":17,"unpackedSize":70597,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUt3GJ45QqFFcUHy8yustcx4NNDxKd9wAZ0j+uAk0wQQIgKVjs3ByixnNx7YfNfRiAS5/SdsMsbjUWQu60D5tfKts="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi93OCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoV+Q//TU0FvfCWBq4zLKLgVZJYj+gGq3DsFNGhRy46nAH1GJL/hlyQ\r\nhuD9UtcwUzAtAnA0xRF9muFWkgaAiGYCFDkpv0nWcGXIp6jOjoqfM2usMmKD\r\nNAt4oYKhNzTovdFl+j+DYy8abfehfVKu6EW7cVjvjYRdqEd0AzxPawqGUOBi\r\nYma0EfVBSX1dHj3WDsSXkl3lKMuU9K5HYiy8KEv2IjHE9e46TY/bmNr9xgvn\r\nj1OQGf2JNthJ2wcJBEG9Ryj3qP0jYy5zt02sr4J1yFTMqpl6M6BcHHxlscpm\r\nioR/OqG8N7t9/lxR5aTTxDf4sGaRunjloRnawOsKuGpehlA6CFSqTDvGrUBr\r\nDbqOm75woxSSFnP2ZPCqc+bb6u/aWvlGrYTL3nf6MVGwp0rRLrbymgM1Tw+R\r\nUhFer3IyxTWuIsoic8kznlWUKW23C9n5nv20rgb88GZfF4KU8K6beO4ROWgh\r\nV5yn0CjbqqPPXZyw0qC+6ET/DCa7FLD3WiK4O6dasJwPD7dScykP8XaQWr2q\r\n4cXGMsDjfL2NHkLAZxbC1eBtPSXa3LegUtVj94NH8HuAiUaqZVlvVdBCZSa/\r\nOmqhzW62yWgh7k+uFdj3Vck3B+N0Y+xYP+vZkYOGTI1WOWejqVmtqDuEn8W/\r\n0THN7ppx9VnTuGN7hVGaWLEfT3LG1MhYIV8=\r\n=iVhu\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.4_1660384130650_0.09350583765161602"},"_hasShrinkwrap":false},"0.10.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.10.5","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","scripts":{"clean":"rimraf dist","dev":"preconstruct watch","build":"preconstruct build","release":"yarn ci && yarn publish","test":"jest","ci":"yarn clean & yarn build && yarn test","docs":"typedoc src/index.ts"},"devDependencies":{"@babel/core":"^7.18.10","@babel/preset-env":"^7.18.10","@babel/preset-typescript":"^7.18.6","@changesets/cli":"^2.24.2","@preconstruct/cli":"^2.2.1","@types/jest":"^28.1.6","@types/uuid":"^8.3.4","jest":"^28.1.3","rimraf":"^3.0.2","ts-jest":"^28.0.7","tslib":"^2.4.0","typedoc":"^0.23.10","typescript":"^4.7.4","uuid":"^8.3.2"},"dependencies":{"@hmans/signal":"^0.2.2"},"babel":{"presets":["@babel/preset-env","@babel/preset-typescript"]},"_id":"miniplex@0.10.5","_nodeVersion":"14.20.0","_npmVersion":"6.14.17","dist":{"integrity":"sha512-ldfZHviVJ9uJfp0UriVXlO+6iv4u+j5oQPltLKpAjuQK0xShssRG14JEoDJRz4CV+st7rw6krc2lvY4m3452Cg==","shasum":"a15aafa75d96c26bb0777570dd10f5a45cd53715","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.10.5.tgz","fileCount":17,"unpackedSize":70349,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAUHr3UkyLrkQShiLdJBc4xzjXSatGsi3qbYs5gommRPAiA8CuArSrSWEkP1dDVrN6jR/JGC17lm6BiSSSEO6qP51Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi93Y6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpCXw/8Cmf4lPEwup0BNmdA7QP/AF2hGXusXmeqEOeoaKHjQHShzrB/\r\nf+od7uvPdvRrifebUWTZjQgzRUr04eb7gt3LaqD1gbXr2gtea/L7IBb9JxXp\r\nKVnnyFLgZU1APlPozXPP6nSCQETYQE/FGkxQ59mSv0A0qbZ7F6fQ5InvNs4y\r\nODg6IqA4Hpadkp2Z+nQ2ZZ9+Ry5zkvn/dg6JfBMUUCsFbV89uzfuNqFNsvJ5\r\nKcIxlSQyDdUVyUq6rqaZ7+hfpQ1sNqcMHWAfstOiG2w29SImqrPZcWvi2r1M\r\nN7Qkih8X5S45U0XtsflfbOnbFYEn7NImfeMnjKQpDwKdcfmU5j/mQQ+X3y2Z\r\nE49lbuOZsUUSjs3K4xfIw1c7vSLtIZBzl/7e//nKpLy8VCfVW2NaIycF3ky9\r\nDAoa0QLLho8RUcXEAcNVXsoH9UpWyMavqFKuDGjYIJD6fd0YBKWTKqXFjtIH\r\nrnIi64vkBwrmeXs8AnIvGMTMMrjjWAqxCq7TxJeszX3+VE7EJY/KnaUK7nis\r\niR5yKDrrLhmkXowp41hCsCbB9gX59oIgLG9NsNnjbbbJqp7cy1zGqKUR7dCn\r\nCP6ExRuJSJZHpms9Qe8GSvWa0f5+n0LVKOywBnk1zFndY2ECrOZ/2ANs+Qdo\r\nLkSohGLwIqKTfhBLvVtLJyXCFTYAuXU0A2k=\r\n=/iv3\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.10.5_1660384826649_0.452947055671584"},"_hasShrinkwrap":false},"0.0.0-canary-20220924150908":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220924150908","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, { velocity: { x: 10, y: 0, z: 0 } })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n**Note:** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220924150908","_integrity":"sha512-s6xlDAaKuXpbolBhxtu2IdAawsY+R+O4x2vEe3RJ/fQktZb5VleYApCBe9LgRraSvgslZHvZQqKEIt/AVDaHjA==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/e70a8eedb249d8e58c36d5422cb46cb1/miniplex-0.0.0-canary-20220924150908.tgz","_from":"file:miniplex-0.0.0-canary-20220924150908.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-s6xlDAaKuXpbolBhxtu2IdAawsY+R+O4x2vEe3RJ/fQktZb5VleYApCBe9LgRraSvgslZHvZQqKEIt/AVDaHjA==","shasum":"15a252bea9b6bb77ba6eec8849319947221faa95","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220924150908.tgz","fileCount":17,"unpackedSize":61829,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC52l2IfTvh8tqaYZgAQtM9hCeyjXqBL4Vtwx3wm6TGPQIhAKI26eiu1kOJDAuZqmmOSdIV5WD5yyTzk80zAmrwmQrU"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjLx2gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqOPBAApHSzxzQfbyFkoKHUK/btJFKie8pObS2CklZQQHDa8dUO4VKO\r\nS4FkNmoCJYGmcTQXkzQRJMl1krN2/U8l6STEPsTab8mU49vD11qqbkihere+\r\n+bovRXwBteuo/uCQwNP14IbU3lBD0ozN19HumNJQ37VAfd02g4HfVR8WhAJE\r\n/Vyzd6uJ98wvwBS1FmVwaVXV7lGz5ycLT6tbulkOIaPX8MVJFiSGgOie4zd0\r\nTL4CPIkj1DpN3Gh80MgJKgvELv9K5YNUnvNqzENxhD5xIBt91a4EwbYgePKF\r\nX1/P7ax3P26705J3CaQEbCd7BvMTvxA+N6jZLWDREilhQiMaLGf02A753eTk\r\neGKuzCnmYz4KyEj2m2rNk1/Gy/XS2glVTBAfEFmEe7ZWk9Mb1WbgM9GEQoOJ\r\n8QJrI1A6inh2Nnt/fjk7hz8o3K2X9SKHW4s3UFoHK15hMcGcLqAEeEAyiClu\r\nEknXfzjCgq7pTFU/naU+RBSHt6kjF4gxv+TKnKz4fLC6kzSCs1+rd3N3GxtX\r\nzMvZju4kkdcfx1+thqq7WaidPg6HBosKTmKz3H+FiFSim3rEeNICR/rlfBgb\r\n592t+I/5By9nVLwJ0C43wCmGMmgsCTJk46ZCKpzO5dCOGmY+V1mVNyY+f+Lj\r\nL0S6MQBKzk8q3oOFoHdSjlw/kHVfTjp1CKU=\r\n=nh4n\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220924150908_1664032160414_0.9210607776409419"},"_hasShrinkwrap":false},"0.0.0-canary-20220925113205":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220925113205","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220925113205","_integrity":"sha512-w+to+/jPT7nh021cJTg/V8/dV94KDn0OfiTPLsvsP822AbalMj9mSqeCRfeQYtFHT7jI0E/Ks+e7dKbPKxTq4Q==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/33f957815ee89e6186d37491253145c0/miniplex-0.0.0-canary-20220925113205.tgz","_from":"file:miniplex-0.0.0-canary-20220925113205.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-w+to+/jPT7nh021cJTg/V8/dV94KDn0OfiTPLsvsP822AbalMj9mSqeCRfeQYtFHT7jI0E/Ks+e7dKbPKxTq4Q==","shasum":"eb187f8c12ae19584b15e2de2f1415833d7cc7ed","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220925113205.tgz","fileCount":17,"unpackedSize":65276,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICjtRwMKAv+CXqQ08AQEnDxlugUkUX6rOXFGYOYPNiSyAiEAuKFvhokmtQd5U+43Pp2S8qZIL1v8dQn3XvicPPxo/zU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMDw9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpP1A//XICittV/aTgWjGuFS3N9x48PG6HA4oUTKh+/MZrNvcaJJTDL\r\nJC5ZRZSYKk3pYBMoKFw1cI+Ab4qWe3z4ixp7UjaWpDu9yZKkpvE4nkFX48OE\r\n1sP0dmmC1IobBE0rRByONkYadkHNvOdgxGVpFC9QsRExoiccGSdvRYBe8Ju5\r\nxqsTXfxxKDpfdJI1uWDlcGd2bUwurw4YsxWinH757L+0QWPovRXfOFdFmG3a\r\n11oIYTEsMdM3n3cGNn9vF/t1Wpu0VzPNumvCBftpS36D+8a2hhqgJktgJ75S\r\nzX5CkT35zgKYl0/wqTMkLfwVoN1RnM2qXw9diSKIPpjq40m9B9WpFfucEPss\r\nwEGE4dTsiPvPDELS5udAiUPcTomeOKxj3PRSRE2sqo4MBrE1i5jBUb4lzqvN\r\nXtr+KGqJSgbwOcXqwhu4f53cRU1ev2R5qvm6N1My2CMnBZUT6UtBleyQiKeC\r\nsD8YnSLRpQ6eHuUO0wFJa1L8r81KEeFfhAZ2pc0lIMtaYFvof8ZA45LFC7TJ\r\nI1b+fydOgnEXf68qIG+ludfKydwXN10igWaX/Et6lgn57RypovzVntT5P61R\r\nFfNx0A6GYEV2U3i9G6+wQ5wWo5YLh3F0KwbLr/QGrK7wR+tnZRnNt40rhsGI\r\nYyEg4WVPTidQ36cW2+CZ0FH0WPRMnfy3hvk=\r\n=Yfa9\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220925113205_1664105533433_0.059283280341096534"},"_hasShrinkwrap":false},"0.0.0-canary-20220925113423":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220925113423","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220925113423","_integrity":"sha512-PWhMi5hPmN18u9OHZZCFExBgVyQMtrF6ashc06LzWMXAmLhCOM7siBcjj7dmsnKtsYxym3eLW+o8FmnA2w0mHQ==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/1a351c6bbee2483bae8b0106536be24f/miniplex-0.0.0-canary-20220925113423.tgz","_from":"file:miniplex-0.0.0-canary-20220925113423.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-PWhMi5hPmN18u9OHZZCFExBgVyQMtrF6ashc06LzWMXAmLhCOM7siBcjj7dmsnKtsYxym3eLW+o8FmnA2w0mHQ==","shasum":"a257da513b052ff09a620d80fe1a673b8357490c","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220925113423.tgz","fileCount":17,"unpackedSize":65276,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHLPbzxfYkoTDcv9PqlyFgHzCq9Blx2j3szvhmJ+lJGgIgEyoWtICwNLir8sVw3amJrbCcP15CQLT4HglySxZN4AE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMDzjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp2WQ/7BVNs/hUB0hzTraRILYp/4+6QFeyrSYHm4+Uyfxa+HIxtLXOG\r\nydoCIHVI6n27s1HHvXg47njDDFGS11/7OXNk3y2N2DoevKcx+hZPMaT0G6EC\r\n2+dyjZjqS5c4nVPd7b1YRyBJteGQT3PzBmnzsbE2Xol8B+LTEP7sCnVi945f\r\nGnJM785NdDoDKDI28gH8UW4aiSTnc7g5Rx0UGfbgDf1wqSA9FrtvZR82swH7\r\n04nisVBHz4BIuFnFD/PoJVhy07Fnq2bNV25quHbgBzD2ui/b5EBF6hmCPMPK\r\n5knSthvncZRBnFSYnQSGrDZVxvUdBxphFj8+1Enx1xAuxE6QnDpTLT4vlQMp\r\nJFZvra6a5kme+2iYkUOxGLPC52q0Q7C053bvX/S9gRAWHJDfqyKCgKL7gvn6\r\nJgR1icVGmIL4rM9evSeYyegVynB6K20lu0bUaaOpEb2GFNEkIY7FuOQRq8iG\r\nHdWYWL/k/XfpFwFolLYV7S2PitJ0F/KwG6YOnBMFxdKxypvphGQWikNfnxQU\r\nRoG4gm5HKGRX4LoACg55vDy9B3T6pEaBSzZG9yjcosZ7CX5eDXiOyB/+cBFt\r\nz9n7qFXLKICrC6dFlLgMKJPU7QmyXVMwYrI2bncuN/aDwDgLPa9tf4X1PSm7\r\n8rNrSXrzwGNc3i9qM8bZIrPfdoaRbqfbaSk=\r\n=frL9\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220925113423_1664105699728_0.9268839958143975"},"_hasShrinkwrap":false},"0.11.0-next.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.11.0-next.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in addComponent */\nconst other = world.createEntity(position(0, 0))\nworld.addComponent(other, velocity(-10, 0), health(500))\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction healthSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction healthSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.11.0-next.0","_integrity":"sha512-HszGzfYt5/N8MnxsXK9wIJt1oi+fSvCkWeyL3a1RwxH4wrfnAFamK0Y7zbCEq3snyvR5qPYfNcbsXujCbYgp/Q==","_resolved":"/tmp/d300504e4fff61b6934c84f6afb46125/miniplex-0.11.0-next.0.tgz","_from":"file:miniplex-0.11.0-next.0.tgz","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-HszGzfYt5/N8MnxsXK9wIJt1oi+fSvCkWeyL3a1RwxH4wrfnAFamK0Y7zbCEq3snyvR5qPYfNcbsXujCbYgp/Q==","shasum":"91dd07c3c9d6c927c573bb787e8254f9886d7dbc","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.11.0-next.0.tgz","fileCount":17,"unpackedSize":65262,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/4h4Jf5MukL6GzEEpMdijWwGMsfy5GS4bDgJuobXa+AIgCA4foBWM93GpRmia2K4IaLBnleRat2lmw1pHDB9V54k="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMEjEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrLiA//XMnwyrIJ9nGIcRPd7OVszI/HljQcWAekOHNqt12Tkk2+nu84\r\n95BXtgfeprvk+7dZCkp1H0cHuW/a9WMGTG52Xud1Nz5qmVGqxgio/p2lQWvw\r\nJWylFVbFJ+VC3yrYmP4E02QmaEIQ0hBbIHuJI41nn/IN2gH4nQawi/d4TD8n\r\nK7LTTlf4p9RaQbdD/Aa3nYQKGb45LZIcFCkiNb/M2qzslqTYyU8skIelpnHP\r\n0zKX7mm1Sy7VUvNmyRXpK6ByVGN/mHOpvrc3i5a+X5aeBtXzjnTBcow7K8Sc\r\nzXc9iB3gU9AoEd6c+qz8TkyzWL5ADL5miba0QlcZXlBNdsjHe5/i1XRMZRG8\r\ndjkOaM6biSWadPda1ZMBx/bM0nrg1pN9Br+fOBhbzM7TulpOxRY/nzmXoF/O\r\nl1KS5vOdLGQUfzpR3zOE4G0Ju7T9R+4PmrkSJVC8MSY6t6kepLYaMgUNp4+Q\r\nxc+FWnWaa2UEhL1IiDE7pm7MwN58NHvv0axkHPCW1YR8fuCLvPQP3Cuwll28\r\nRvmNx6Ff9hPBXkESWVc+wDVPOdkb2x1r2Mp5QWL+XxbzuxBUj+06dM/xfbCL\r\n+2Crr611s/hp0GKEZWwIV3kUGGXgtDVpGv0YpWwCZ8+yqzs6bCRm5oBJc2S6\r\n0gVcFjbQxOj1GqjqK9awahOI0VhOz666bv0=\r\n=Nizz\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.11.0-next.0_1664108739774_0.6827402033820171"},"_hasShrinkwrap":false},"1.0.0-next.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"1.0.0-next.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@1.0.0-next.1","_integrity":"sha512-t2Jvdj5xCCWc7dh4rSIUcajaeKt4O90ULSA7smPNUXvcXS5IT9eopfDI0OtE/1a7/cRLQLHzTfNP+3QC4WQ5lw==","_resolved":"/tmp/a9e97a9182d350504b8de78785adb3f1/miniplex-1.0.0-next.1.tgz","_from":"file:miniplex-1.0.0-next.1.tgz","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-t2Jvdj5xCCWc7dh4rSIUcajaeKt4O90ULSA7smPNUXvcXS5IT9eopfDI0OtE/1a7/cRLQLHzTfNP+3QC4WQ5lw==","shasum":"e1ed8a427a984c89614f381f138b472b03196107","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-1.0.0-next.1.tgz","fileCount":17,"unpackedSize":65608,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEtq+p/27YydNZTmeAslQzu6Mzg8BuD97aF1pDgO+Gr6AiBClYQEpUHTRdHcY6F/pE57OcIPY7RspXZzN9d96eDvyg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMVIiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqfoQ/+Ky0W5DnZphAOJqqpQq7dCkTrCCLv/GfeNyUbcPZatadfLqf8\r\nh4aG8TbPADyUUdVchvg/oCn172NE+SgdmUOvPqk+WFkRfSUl0FCwTGDjSvtm\r\naodAxt5EeFvxRoLxHxgumgQ4viTgDv+7ZAGNqNBYmBnjzSmGAg/BiMyi9dMv\r\nrssRtVHVj7Q/NCCzSMn0D3t5O/UwiPtaopJTrO2BnKkc++5UFG4P07u/r4db\r\nTSyK/dYCIFexKoVFAHPtkHXXjX22dGYqqMgpgYNgETxuadZMLIt/vxTwqrof\r\noQ/4ZaafFFTe2do3qeYHqsJtVkLOSTBtpFuUVIbD8iosM2gnxhCgzWc6Q0IJ\r\nP3JvzkHHSZ55hEpmEQtaDxrgBcJZITNi7I31KMxiuFULhotVZXTbZS8Jcx6w\r\n/mZwPWjDn3NuN8RpA52eUo0VnNYZ03QiKHw1CLC0T11b14YT5n5/tV0VZ3Ab\r\n5F1rSQlxIbOPlBQg1lkM18EzS/elXa92ntJV1i9u3HmGOodA/FKCTMvyI+UL\r\n3j4Vx3a0hfk64A6V3KaZUOKPGl279hhSkw9qys5vofji00tdREDFTtbSEMDE\r\nABDxBnSWPmlrCU07ekOuMK2rElFDk9YzwMv2PpwVTOqePezON3/YJ0EfP4NB\r\nG4bKLVVC3viPoxbgoujcsPegiPHB2WLgZWM=\r\n=4wge\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_1.0.0-next.1_1664176674716_0.5140823339040035"},"_hasShrinkwrap":false},"0.0.0-canary-20220926080217":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220926080217","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220926080217","_integrity":"sha512-nu+hz6wAedvex28xNUb+4oWnSmqjaoIP77xHGR1SLYEN3qfNOyG6+cfX6QivaNzaMPW+ncdgl/bSa1CaGeWT9Q==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/5ab0dc1a18591197584db0c4837b52b8/miniplex-0.0.0-canary-20220926080217.tgz","_from":"file:miniplex-0.0.0-canary-20220926080217.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-nu+hz6wAedvex28xNUb+4oWnSmqjaoIP77xHGR1SLYEN3qfNOyG6+cfX6QivaNzaMPW+ncdgl/bSa1CaGeWT9Q==","shasum":"d916e613cfb31cf026dbd5da4d44bd9195263365","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220926080217.tgz","fileCount":17,"unpackedSize":65623,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDZbMPYVBY7DOxXQL2GLzuHlCo05rePsAdDMfQBvS4FgAiEAvofB2dRqjfb/5YG4eS9yAmK2BXv6GJJCOOnMxcZ0Y9Y="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMVySACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr4lQ/9F/qF36MZv87A4/5lZ0WwYgAub65h4QAXGAN83uLaq1bAmhtf\r\n5O+Cwjq7JcU0qWh/fBTerimVnhx3aUANvakJUbHWjTmCyuFh+97gFRAv03lP\r\nwKgUJBTmNG0g0cwdlFEtCRqIl8J7R8rMmrZMFuo4gT4wGPG3SYMuS/x19W3i\r\ntUCOeso/ylKLuns7hjjp+aNHjYH9UaWjAZnAyLlup0Q8ncDEfVR88qokDP/F\r\niw0H/K2vGNUJceAqJbW4EX+yGv5KGQ02A1YM9XggaQ32EWbBXFzxpH8XGaBn\r\nW5g9hojgRwUqjvh9rypsXRAeXp/qte71KNnSLTty4ts6NfeRBJYZEDUBt/pB\r\nx2B6yImdUvSoOclFId/MecvoHlrf2mNBINbNTFPTRb/TzWBATCEPHCUqTBz7\r\nYdiGRczi3t9+3LLw6NFXijbToVtD7qZkpdWJPzd/AW6XdPd/9Diwmi5cNLen\r\n4Q/w5odm/P2/4wEiMOWtR2zAvoukYcrPdre1CoWADjaIQvMIW8tjNig1FZdg\r\nY+JNTF9U6PrqJnUXm7W5buMZprTmBhy8HoROUUyRx+uUHXLibzRuKONK0BEH\r\nEpSrk1O7TANuRnlCYmTU2wTIS2G2FchOZe2g3Upg3aH+wSGAS9R0xx1kzesM\r\nLMZACMzSAy0jhRIwcNJMxQR6zoo/U/QrAOo=\r\n=szS3\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220926080217_1664179346103_0.08410541288010065"},"_hasShrinkwrap":false},"1.0.0-next.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"1.0.0-next.5","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@1.0.0-next.5","_integrity":"sha512-seBJ8+Aplm65JpB6DFC9hSbjK8OxcUexGobYRLMCb/3J8ohBzFnD+hLDIYjhhYzziVtMuBbmYOcdo2iyjjMQWA==","_resolved":"/tmp/ebc89a44e8174dc66dc42c9a425f6741/miniplex-1.0.0-next.5.tgz","_from":"file:miniplex-1.0.0-next.5.tgz","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-seBJ8+Aplm65JpB6DFC9hSbjK8OxcUexGobYRLMCb/3J8ohBzFnD+hLDIYjhhYzziVtMuBbmYOcdo2iyjjMQWA==","shasum":"12d2f9a823ae99d07f84cc5b0563e53c07dea4d7","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-1.0.0-next.5.tgz","fileCount":17,"unpackedSize":65591,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD8xHq13NdOnwypE6QBJ/MQYlvCtwAVTUb0hUbMApJn/gIgRopqZpyyPmr9XALbIPKrnNw2n321XfIMlEAop4W29/4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNWNoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpk6g/+IWpis/WzGVyqyYYT8JNTBW5fRRrZlmEZCRZ7HVdZv/+PwpHD\r\nO6/ODVYaB06elX2b0UZO6iKFYGsIgUF1Sb8iWmq8QrOMF3AWtwkLMFJyYLjs\r\nmp4/1AgltQyKzZQwYDbQ8JvV4GMwwFJpihtrhWgUkwJsg4is92itvtk39wW3\r\neWKY76Zqd+iF7xoxSIeEOkE/m93/k10+46lGEh8xmOXxFCyCtljvQaFC4/y1\r\neIy0GjSF2BL1ASxPYNhYwMYfSLKpX7bGs+o8yZFvSGEP+Q8trza5CMdJFAHi\r\nkkezl4agRdoLd7LTWt2bmSWmtBILr7YKLgQQuLm5puX4FT9DDGbj2FbCx2BU\r\ng68Jhy/ilMNPU29WOQhhCpPjXoO9fwYtpDiSsnerOTzTdHYfIz3J5Uvwy/er\r\n/yxLpTRQ7k2FIwVp8yKbb/MnX6iFFw8kjdMpkPkPW1+Wrql7cladJqyiofwE\r\nGD+rlSoQDZ6EjJ/Jis1uM6ARaGXLoXRE1KxyW5+DHDitqQBCxJ+GH8Fj8F9X\r\nWAURZJ0TP5rO0ddrCL5OlMElCha9qZYYnRmGlayAqa+oXPAzuSgjwlaSWsq/\r\n+XV/OB4QvUtHNpBDhBasf1HTYED4l1AomruXwbknKla0Iw6KAaRymJdgZZNT\r\n1QTvt262GbTaZybILlGhBb7dmH+tbioi1Do=\r\n=IULd\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_1.0.0-next.5_1664443240347_0.8675614248371653"},"_hasShrinkwrap":false},"1.0.0-next.6":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"1.0.0-next.6","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@1.0.0-next.6","_integrity":"sha512-HeRpwCyhGa3LQKztpWG63sYDG7fThqP7xDiGq+jg6GXMGdHJB0TXSWBxGIPRd96XIJioKuCFuMT9hVPr6ZsfeA==","_resolved":"/tmp/c17dd41c39e75c83b390703060f64890/miniplex-1.0.0-next.6.tgz","_from":"file:miniplex-1.0.0-next.6.tgz","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-HeRpwCyhGa3LQKztpWG63sYDG7fThqP7xDiGq+jg6GXMGdHJB0TXSWBxGIPRd96XIJioKuCFuMT9hVPr6ZsfeA==","shasum":"843ee57bd7a674e35db07704e56e9705be871058","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-1.0.0-next.6.tgz","fileCount":17,"unpackedSize":65591,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCIcSKdsCUhF90Up5YZa+D5+N0khML0b/G9aK8fZ6MfKQIhAJehHpyiqWHFJo0Adgzzt0g0EqYwLMfzipr5T93grqSe"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNXu+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmouChAAkzjEuYZcRQ6VDgUE4ngrETGPWoMaz3Yl/RL1fQqpISRG0Rmw\r\nHRHPPRimQU2y4tmQgv4XxHF2mttFo/25YA+2Z4nJ9acvcfNqOcUmjs+EOz3+\r\nC35MzliuxWQr61ZmuEcsNWnW+siPllwqQ3mTBJcpOFecd3Et7Ai90dZJhSH6\r\niKnEyLsW4dEWqpt9kMSEMHFQs9PLNUlhwXmXW6TksnYAUIQc7eMm2LlK+z6x\r\nCPL/Ou8YYoV6d/ItDLpw6yA7Bf2/2x+6ABGZQscaqeH5armC2Iua82zB8Few\r\nUYodK8/5iHkIQKq8Eh3Nfst23LNsNvqs76yFgM+bUXolrU24gGx5QGqkFz/h\r\noct/2wXv/7yd6KrWtsg4wcZZyGtD3CY4JgiekmQW1xcR7hSZhWuNXBOHH2mJ\r\n2hUOHeqm9CbNqeuJ9BiKeJNzM93GfiIjnnRy2vKVGUrPJF92Y168tEFOle9D\r\nUfQDUJ9G5lU5Zv5UITz2vgMnZohQgkNjfv6Td8bvKzoNsHIJmEsPVATduNX3\r\n9ETAE38Os7YcfbKcFbXsLxKtuz1mK5haszpp/dZa7CBEQIEEC2mp9OrJrLaF\r\nkOvRzqKwV+/WbT4U4qVoV/VgARHhGNEbCslHgq2mqPfktEMOKidDLvRqOdf8\r\ntXG5XZMF22ojXmr8dCxHtYZW2VJ8ekpIyeE=\r\n=0ic5\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_1.0.0-next.6_1664449470579_0.48378472454025334"},"_hasShrinkwrap":false},"0.0.0-canary-20220930161643":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220930161643","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220930161643","_integrity":"sha512-kRFIXxjwpmLMQlXx2XQfO9MrbxuW6liU4xrlOqe8mQRmUhPL22Z2FmR1pHSTrWKGDytC865GD6w1f44rUaaD5w==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/ab0dd627cdc9a30d645efd8a66e98b05/miniplex-0.0.0-canary-20220930161643.tgz","_from":"file:miniplex-0.0.0-canary-20220930161643.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-kRFIXxjwpmLMQlXx2XQfO9MrbxuW6liU4xrlOqe8mQRmUhPL22Z2FmR1pHSTrWKGDytC865GD6w1f44rUaaD5w==","shasum":"11312eaee6e814a1233e744b529ab360eea92bb0","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220930161643.tgz","fileCount":17,"unpackedSize":65606,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBct52J9AVF1mlF3I1EZj6nzV5Vs8h+Ggy/7atQNQJqQIhAJjinBbN1hP50ECrFUrEafeTjSJZg3uXbML2y0LeG8J9"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNxZ8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrmWQ/+Jvgbu85JyQBT/otPt9eNCk1NsyZ2qlnxn2N/z2jymza+Evb6\r\n95enAGN+dM3IFVvaHWUuoCrcRToY4+WoeDE66XignMvUme5zYPV6diJBGak0\r\nS12mgZGiyXEftQa1Vg3Z0pZgZd0bm3QTnbFOsYq7yegwfnY8ZqJd4uVcWOvP\r\nHgnsOxlD87ZaYM+uuLvZT+0qSXMuOuHCAwWP9n0RnumgbKBVHnFPYp4dCENu\r\nC1W9MdwQMD+rs2ZKZ6tbT/SMgjfppBrmrqOWP6AJg5JUhGU4b/8g749wV6rY\r\n/SZdyj63uo9goUO6vlMZrgs6c1OSOHF4SZAovHWAiqoP8BNw16Dsxas0v7WV\r\ncaexKdcnNWSvPbnRwPTGmdm1EMeB+l0p5wujRdCmkU+AY2TWemWMtlHoz57Q\r\nY2zzFesCBajFUUTiMxCYd4bhc+uMQwhyzziqIO5J5ob8btTjHmHIvuY/3+jI\r\ny8MnuODTfP160KctLLcItQ2G91e0FO2h20/q6JKJjpfFkfNbOlorYcDxopn9\r\n0RVy/CTbgxhhHqpc8+UKbe+txMZhD16/arb9vMf5ZKTLuCWt3v2gsnjqCRJ0\r\nxzHn1SWnG1vL1QtD2T4rhH9s0tCgHLjpMpr6rmV7gSW+apw7Vos5InP44LOT\r\n1l/wMsFu43ujE73TZGGaJPSDbMW6sE1AdIw=\r\n=8UzK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220930161643_1664554620310_0.08349778069091318"},"_hasShrinkwrap":false},"0.0.0-canary-20220930161815":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220930161815","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220930161815","_integrity":"sha512-U2dotXgmVJ/iaUyBScEAdixSHs+TVS4Fh6ja3kI26Mha/VMuj1viHnbRC5IMhgntBxRePCNbpbhMqU8niTQHqQ==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/729648e47f9ad889b6065d9030d86636/miniplex-0.0.0-canary-20220930161815.tgz","_from":"file:miniplex-0.0.0-canary-20220930161815.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-U2dotXgmVJ/iaUyBScEAdixSHs+TVS4Fh6ja3kI26Mha/VMuj1viHnbRC5IMhgntBxRePCNbpbhMqU8niTQHqQ==","shasum":"fdb2e1fc336a3e56504ed36ca5b2f126214ff68e","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220930161815.tgz","fileCount":17,"unpackedSize":65606,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/Edv+keLFQnDh830ywA02odZQ/6cqoCao2XYb5h5yfQIhAIQkE/ZSm+oLIzT1RlnplUR+YGobRaP8p9lCOi/+GJct"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNxbPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpBhg/+OOnVUyBjPxxeAsVzZTRCkQAT8eWFxOvv1fCDIoZsDuQSd9eK\r\nGzn/PeCCV3dY1mENxqX//ba8XG2oOdXrXFuY7VWVeZy4jHAi3tVOskjmbbwJ\r\nofxs07dcykOBLJezEQUtYkO0P7QhAdJM2mqeFWJf5zdg/nKIGK9QO3qpKWKt\r\nrXym58xZ+bMdYRv5/5lLmXgeIwqJtFVpa1qRhVPm+qRu74ylQgIafAz5G2sC\r\n2BvmRJhKuMgdgLH6ZFSRQPp5jKdNHQWm2xIY6DENcVEkOx9bibsmBAud4KHt\r\nqezGKs3Eh11YfAEmEbbJhZ4EkkjuhgyfbAu6UQ64G3Ljb7eNA37jpKtOwAg7\r\nIl6HmuMjv1CURNjObOFacrYlRLiJ5uccNfrHlCr2p8tlH8U8bA5CBl0Gyq0x\r\neR4/U85sbs9hDXXYPTW0lmvtc6S3DRBm6lFLc1P+N+qJwdDjtaR//bSSVypb\r\nMxyhUPqdZkTDz+ldPlKhEEaZV/7d9r0BT/Pgh8okNwZsUTM7lE5FFKkECywj\r\nFFSAC7VlzwlSKOnlR7R1ExpbYMt6MWC2mfT2NX8zjCPHnZwJPfh060DHK607\r\nepMOMyEZi0K6kYuNFK+AEkGuxIP/mZfa6vQAZW0se96vEKF3neyDAQBbGP/3\r\nwVcNe1VGiohTqPT2iE6Z0a9Q5z24C92E3hM=\r\n=s7l2\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220930161815_1664554702997_0.37713512651715164"},"_hasShrinkwrap":false},"0.0.0-canary-20220930162615":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20220930162615","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nIf your system code will under some circumstances immediately remove entities, you might even want to go the safest route of iterating through the collection in reversed order:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  const len = withHealth.entities.length\n\n  /* Note how we're going through the list in reverse order: */\n  for (let i = len; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20220930162615","_integrity":"sha512-ZatwXfpI+io4GDT2jpdu9HO3ehfio162zZ6ql7eGyvlpvLEksS+8Yj/J1TyYyLYFNmSUHLGv33fWCDy2k1/pTw==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/8cedd0e91aaae85f0d90a36cce8b3c12/miniplex-0.0.0-canary-20220930162615.tgz","_from":"file:miniplex-0.0.0-canary-20220930162615.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-ZatwXfpI+io4GDT2jpdu9HO3ehfio162zZ6ql7eGyvlpvLEksS+8Yj/J1TyYyLYFNmSUHLGv33fWCDy2k1/pTw==","shasum":"13822ab16964040cf0daed095800903666f944ca","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20220930162615.tgz","fileCount":17,"unpackedSize":65606,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDesbLmd38QJWUuEE5u1lxMYKryqVX3157JWcCcQ7wbqAiEA8VIsycIGCjq3trMg6/uUUrJteMLYkLKcWEgIFiP8arg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjNxiuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr5Qw/9HtAERxnzdESbayqQoQimTR7bv9pEd9QS0Tk5CltO1xy0tmEm\r\n2dMeNUnAVD/ixLSLUGqpmQNshgaAa/ZevxCHonvbT2mJjXE+NWrG06XsCVet\r\nL3M6Y6BtBpXGymLBgdi1mAoZ6l0PwwFkWqW9R+2QWzRHVrwKHEYfOgu6PD8j\r\n5Ol8LyrRl0iihVZLzKICgKWBDDmFDPOQLyLJs5TIs+9AEGE7UVXORO6QuyIh\r\nSpS0M9sjApZkIFaZ2D3Yf8wiDAsvy5F8tzIg5FoOrbDhXlwow72EuhuJQywx\r\nQvkjQCEdQkCwQXV8PHEPOUO5Cnek1Z72d3UmTFbqIgWAxQ5CxOAoc+aaR6+c\r\njlQcIsk1yYwN6jpMQCCNA8Ka+HpEYMIoe2Y/3lxhtjr4lRhlRv8pfPBb6sob\r\n9pH4zq24DhE5tQa8oqvKM8Yckmt7xJ38l9ZLXTyF0Bw3/fz14FArn1F9wYT4\r\nTk8zgYK3qN8a8MlK6IzYiK4UhjuEreqatdYb8uQX7ZWIOryz6q6Ok9njK3fY\r\n7GtqrbPAQnyw6Heup7yiJqsY8TADo03CbmX1SU3yTpXFAfYc64CUANOFJOfp\r\nUZrjlxEg9OG3pllyT9EPL8emMOVZFkVQt9mIFd+4rd5FEXUzbnJEzjzC8iFD\r\nKxZ6Aq7e4fFZnCJALtMzaGZobmeeZh3+Ik4=\r\n=xTFg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20220930162615_1664555181867_0.275301231903484"},"_hasShrinkwrap":false},"0.0.0-canary-20221003160633":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221003160633","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Deleting entities in a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221003160633","_integrity":"sha512-HwU9l947QiWHwqF5Dzv9t4DaN4P6v55sE1roHTvfvkzOs/TsC/0Fw7LTDhlHYGNR1NCfk559nO+u1ioTnuKMEw==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/45a17576b7c83798ebc4aa41df0f1c68/miniplex-0.0.0-canary-20221003160633.tgz","_from":"file:miniplex-0.0.0-canary-20221003160633.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-HwU9l947QiWHwqF5Dzv9t4DaN4P6v55sE1roHTvfvkzOs/TsC/0Fw7LTDhlHYGNR1NCfk559nO+u1ioTnuKMEw==","shasum":"9b5cf15c028a0ebfcbbc67fa40699a54460a002c","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221003160633.tgz","fileCount":17,"unpackedSize":65755,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCbNdh/QB0smoF3Qe3tFTD98WswojlgiNlPwDxnYK0tMAIgNwU2JOeRoly8vd6UaZOebuZGw6TjLJeeQfBlk5g2tvU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjOwiXACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrMFg//YsW7hDouMrxbUAm3LYXqhrr59uO+rNlynjNw0CsLcT1kx8Gt\r\nspLt2lT+q4j3icZLhYqiOoyPciLd5W8L70DujPnZgRY/Q4SadzkjHKS1wtqU\r\nOoI7LT1G5cEKr1XQzUtMpErqE+JQM8yEc8C8qJQCIUMdtdsvWGscF89KoiUO\r\ngG0a40qZq4J3W31ragQsn2fqNCzJg1pvDn3nQK08ThXe6aVJJzaFSJL9dwhk\r\nKKDxXn/8R5eVSWJ6cbBSyWCgcrbOTgfnevmbySMftt3rvwzouuuQ7cPaNGgH\r\nFFD3mcg9c6zR4u0czQCIv4wdH/3enk/68MuinvvtoKbsuct9IwkpnjP3aFnQ\r\nAq8vjWZl7oJPIHiq+E2/k+Xjui72FT6tiK7cLRLFZzIuiU7oJne6+oabc5Ai\r\ne1bBIC4zGZeuyDs03veaEC4q8+JTDTlLMz4PteycAwv11h522qdA8+xi4i16\r\nOe2KwTdACZtANgDOjmpwaX+t9T+OTkhCOJA7/8InGGBPmXdIbGuHuXoIvm2D\r\nn6zBkCkr4j7ZxCFWbza5xy3D+iP0lRe7ttA8kwbeo9FfehxCNaf/ThtFAvJh\r\n62WT+/yo7B/i0uG2ExEGcRPiz50bqmiWfj/J+RY0n5ACZHcJm2d5BkM4Ou1v\r\nCm7wkOAcPwI3t2HkXqg2pf9fVKjrg42JpMQ=\r\n=qNeK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221003160633_1664813207501_0.7191150933569561"},"_hasShrinkwrap":false},"0.0.0-canary-20221003172623":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221003172623","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221003172623","_integrity":"sha512-vT73nu7rOGLlzb1C5LA9g43pzqbJD0hvuR2OB5KliOuhJzy6UQkGxhQRcoNrBKXT9cIcy7zwP44Fo0651zjpNA==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/f6f91b8c56a038ce9a5def36e854a3ac/miniplex-0.0.0-canary-20221003172623.tgz","_from":"file:miniplex-0.0.0-canary-20221003172623.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-vT73nu7rOGLlzb1C5LA9g43pzqbJD0hvuR2OB5KliOuhJzy6UQkGxhQRcoNrBKXT9cIcy7zwP44Fo0651zjpNA==","shasum":"a43798306bbc8980ca4ae18a01e203fca93702c7","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221003172623.tgz","fileCount":17,"unpackedSize":65780,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEcL0t6ZX7Aw9jmrQEWD/hMfcxXAJ5NRZHHRSDQK2BMxAiBudugRbwLLU/uTIXmfusXoRxUQP+Psf40cRLCou2u7mQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjOxtJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmolGA//Zvwv89UT3GlUTC/KNztzew9zIyj8u40wAY+xDmC2DJQjktbL\r\nmMfMWAKDKnqmFqJf2KztIx0aWLemMbuqMMtdU7kRHQCEZJV0Mtwre9MPNyyT\r\n6jdJJoAnRrIkml5LlmRwlOsCGc4Vi3V7MxjXYQnGxvs66agEiA57xwCRiOJL\r\nblkJM5jH2MRXvdwJ+aihiAu4xAkTzM3CNRD4gcyv3GkUVnTwg70l1zTCh9U1\r\nf5oYt4F56JJIJd1SiMZ+2jAtOrQqIJ1kfkUEvneAz4sE0J+AFAz7fpcUHm1U\r\nydsk6/24vxWIIGMCuU2xAKqW8TATboHkw5N4EnFxy3z02FMqofAz/F7E/5Re\r\nn0GEQZLi2X1dNseSfnd/nw86hPzx/FBFKO+w06vybOGu+namSYwIPJ++RaC4\r\nzuv3e+44Ui3mH4s0/Em1L/3tkIAybh51YrHrt6cd0QDmvdYctVFYLofr+JES\r\nN04YrJe22G8JnoUEgqtTRvWlWbplqG//9HK8eM8nY7yhhO6bUloE+HJ6V+sY\r\nvCBg2TXsW0heY5ilETiSUNNVQCfDa38wQ61Z/m+OiA91FSABurGaWc7niqNH\r\nhW9ZN7eomNkwHiVnN4LF5s+WaEbtUyfA1gd3AJJlaaCuQ5Dkyd666M7PLn12\r\n1CuRevtT7AdSjZgl86UraYz2UWwJ0v6ucek=\r\n=LpmQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221003172623_1664817993593_0.5727055189875956"},"_hasShrinkwrap":false},"0.0.0-canary-20221003185021":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221003185021","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"[![Tests](https://github.com/hmans/miniplex/actions/workflows/tests.yml/badge.svg)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex\n\n## Ecosystem\n\n- [![Version](https://img.shields.io/npm/v/miniplex)](https://www.npmjs.com/package/miniplex) [miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)\n- [![Version](https://img.shields.io/npm/v/miniplex-react)](https://www.npmjs.com/package/miniplex-react) [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with Entity Component System architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation.\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [reactive stores](https://github.com/hmans/statery). Miniplex aims to put developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as a containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. It is typically recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities.entities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221003185021","_integrity":"sha512-INY/bLv8ik3LefceyvC8AeCbQx+uI+9rJ+48eX2jZY7izBu4XdpCfvDE1YRMijiSsqrE1tlLTSIjSPw6P//wDA==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/5575bebe97ec93e399224d6196f60d67/miniplex-0.0.0-canary-20221003185021.tgz","_from":"file:miniplex-0.0.0-canary-20221003185021.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-INY/bLv8ik3LefceyvC8AeCbQx+uI+9rJ+48eX2jZY7izBu4XdpCfvDE1YRMijiSsqrE1tlLTSIjSPw6P//wDA==","shasum":"df3a6101133f84867d0498c845d9402b951541cc","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221003185021.tgz","fileCount":17,"unpackedSize":65819,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJ8YzgSSbJyrCE1vxkTp3a3FzOA62KNc/yM1Ebtr9ywQIgUhxVVs0jMGEtnMkRNk/65ltrf31qexMG9S4BRhRdvx8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjOy75ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoUvQ/7BOeA/2e7TAtJztoGsY7fhAwhT+WBvN5v9KYmtzWoh1TktORR\r\nTQ0NlU3NV3HHmgw1xh2XfpPhUTXs6dhFel/xZGp8WROxFHHWoSCes3Flgrr3\r\nVtqCVZkY3pVVzXaHhTMWIuay2F952sLwi317fQir0YEcpWzosM+A45t8SeMK\r\nvJKmaA+QRmaaur3Bq8JKgshVPINI0uNOpGgL5uhR3Tji/qUp5HTA2C0jLR8a\r\n+jP+iNQVN76sZGDIaLuxE4bHcZuricdciEeBTRhZ4ywancOje9X8Tdrohk7R\r\nGKCBacFWZ8dIajWjp/1QYAjPNCTUsBVcc6dsjyMVFN8gVkPRJwVa6Znkz05i\r\nDLsgn1vDyqnlo2bViyNPiDD4DywDlNjFSMSV6rM0ue20jW0ObNbt0HRMR51v\r\nBVJJOe+GuYlIJeeuWV70nbOz3bKzRFIi13d5QZdQ26TjwX8/V4cYy/7lMtjD\r\n+gO7rWaXR8RTxRCxH6VWapzEjP5lFdY2NvvlHUaDBFj1eex+D9eXulUCSHkA\r\nx82/pZXquVwxA5F06scfQD0ebFQLDi2Xi1753+JxWM1MspZfQ8ASNm69MQ0d\r\napwM45k7EwEGkfkhmTfubKyqyNFamtFukqt3IAmUWJD7633jaORhM6p3DkLH\r\nfqtFuB8ltYjGL0fhXNfpE9pOHdrA7Ri9fL4=\r\n=0AVh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221003185021_1664823033050_0.17703218016133992"},"_hasShrinkwrap":false},"0.0.0-canary-20221004084019":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221004084019","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.addComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendComponent */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendComponent(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221004084019","_integrity":"sha512-8AJTd54Nq+Yf8kX2Ln7gWeYLHQkf2qA9Yp7Mjwi5dqJ47+85PtnFv0JiihuDsCj0go+H1Nd0MYMGRZvhuB8NGg==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/2b298789901c94ccbe5e0b96e9fc94c6/miniplex-0.0.0-canary-20221004084019.tgz","_from":"file:miniplex-0.0.0-canary-20221004084019.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-8AJTd54Nq+Yf8kX2Ln7gWeYLHQkf2qA9Yp7Mjwi5dqJ47+85PtnFv0JiihuDsCj0go+H1Nd0MYMGRZvhuB8NGg==","shasum":"86d1ed84dc33a933c6dd07671517c8d4e3835388","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221004084019.tgz","fileCount":17,"unpackedSize":67061,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFnQAjf0V+mtknVO3osn1VfYaWsDXdXHaO5+bh604CoIAiBTIzk94qxUNz1ykKyzXUC9pvsfLICv0f7TuPYeDlX/wg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjO/F7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqY9Q//T8Vzlnm/3XCSpEy51cZHbW1H0Js/9UjY35vfHunXhIYwfm1+\r\nSG/TFhqqq4OA201V3pmv4DdhnjT8j28xqwyJNZj07FeVrrabsU87ldyMuGzm\r\nqZvCYy/CLU4twKyKlIPLu01T3mE8X8i3nXxAKB3TqyWbIDmlpFeo23O4QFMe\r\narR4z2iSpyip0RzDLldK1PcnZkpmw+0R5v47RKBsUgBrxu+RVWSwpOZsfbXM\r\n9cI6z9h4WXmcfKGx7SVnWEjwQWmtn4V/MYLs269sD/U/T0tawMC5KqUYU+Xl\r\nvPCH4jt/gDQtYXtUUPefuTCX28OYNgYUY1cWAQGt7ui/TKcnG2jS2ZkZaFl7\r\nbv3o8IKcKk6XcZCVbMc2Q5Hv7xtm2P8bOZvli3298NCr9IlILkAyuxoSCFmQ\r\naQVLl1mfu9qXSoUS3NWzNw0l908x6F3qWy6eWP51Lc0uQz/T6vuToo1oGdd/\r\nCIKzD4D1+alc3YjgjxUU86hoz5g+Q0V5YclbVfVS1+tapvUbbp0AKtAMo0sM\r\nNp1U+G7+bJR2s/AGs5BjZjUsByUZV3DpHGvWVlywx/xojOYhPGDi32kCdON8\r\nfxXGSqYVdIyzAMyyp/OW6afzNIaEa4xRBa/5LQsjt1bGo2DE0BD5oncWNcfd\r\n4Cr/hh/StTA8HaZ5fAoJjUOFuw+Av5nJ3U0=\r\n=2mSW\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221004084019_1664872827323_0.5918968901634749"},"_hasShrinkwrap":false},"1.0.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"1.0.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/signal":"^0.2.2"},"_id":"miniplex@1.0.0","_integrity":"sha512-cGVpcR8BpPLn3cH3qE1yWOKo/Sll30777+c8jLBcyhvahNgauJ1pFDRxfDoWumnAYgmBZ0JE1HoQxXHSmO8lPQ==","_resolved":"/tmp/7c2a7fc6b3659a1823ed537cc01452a0/miniplex-1.0.0.tgz","_from":"file:miniplex-1.0.0.tgz","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-cGVpcR8BpPLn3cH3qE1yWOKo/Sll30777+c8jLBcyhvahNgauJ1pFDRxfDoWumnAYgmBZ0JE1HoQxXHSmO8lPQ==","shasum":"54865e54b8f0b5ed2956dcb5400e1f40c48af698","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-1.0.0.tgz","fileCount":17,"unpackedSize":67103,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG15PA/eG0nwIyiwQna6lIzb2Lb02vBRHle60Wzt2RzzAiBa0LN3UvbnhQXUhtcT3/UA8jCn1MGk0kO72Ctc2a5/cg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjO/ILACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrVLw/+NYQnWTKW6OgD6umuBLTR0/kZsGwqO2JkJZro9YCHx4dl1oTL\r\n9XLKhb6Mv0N36SIxfyntAG2bfPMYZBAX/BZFvCSOUgn7YZ0bTcTxKCUKLloV\r\nvKd7qi5JEVoyT1YuZY5V7MJzNo4aaUt1I6B0sC+vXk9A8gkf5MRvIqGAOJFH\r\nq8ZRCMBEPTi4+mu0SVmHPP45LRK98ZbnOUDgdordi27F8ctUq/8ndVGDOa70\r\nKLxJ6UpnRTonuDIpjjHMu64QK8LV8vBj2jxvAJEdv6U3Z/I9IJ9e1YjOKvL1\r\nWKzjLoic6Wbt5Z9CKcbKyA0mqcqc3D3Q2qjg7dHTC0fdIVltV2HSAXMI+7hc\r\nQOh0OG5bh31F7lPCFVEKuL/GCyEo/zVSWqYVEQfbVeTiN4N55WJPCcXOySvJ\r\nYDpU6/FhiGdGb1jNdy7cxg23kY3U5lXn8U8KMrvBSfpc/oV2IHT2Vos51BkK\r\nJhh9niM5GXkz244sDjHAEBHRn/uB7RbaGy3JfMjbmDY4CFwWpzONdFQN6yNF\r\nKBv9y9UwSnaomu9yAVmO2yiiiFwR+W6OruDyaY0LjhnyhsH1Jj++GSzY27QG\r\nysrp9cTiED3wvXfR7Dgkuq01pmKO35PSLToAPgBiU1vIdP2bHDGOTToMEFBb\r\niBK35nIXGJOLy1gesfO7/7MVjj/c3cpAUK4=\r\n=W7iC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_1.0.0_1664872971228_0.06875960084499377"},"_hasShrinkwrap":false},"2.0.0-next.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/event":"^0.0.1"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.0","_integrity":"sha512-24utqgpAupy5jBWquSsoWj1ITjvXtCybQrawmpK+lKZ4N4aADFTwN9zMZixLD7tr+ElwzCaJK8W6bFqJGCaxvg==","_resolved":"/tmp/a57719ebcc84a0d7728da7f07b6c80c8/miniplex-2.0.0-next.0.tgz","_from":"file:miniplex-2.0.0-next.0.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-24utqgpAupy5jBWquSsoWj1ITjvXtCybQrawmpK+lKZ4N4aADFTwN9zMZixLD7tr+ElwzCaJK8W6bFqJGCaxvg==","shasum":"f1c13f6dadee312fecbe9d41fca3d7e053fdeaed","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.0.tgz","fileCount":13,"unpackedSize":52503,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGDQKUTXkDBDGIDp2XILAB+QIHpQ7KZ9fyictyVF1/NJAiEAyn19eAI68ivjvCea1j/lUj0FtCF5hUnBb7Of5n6Y0EM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjR96fACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrT1A/9F2piFFj7k0zxjinQL7Pb2+vkQ2gEpzxQoPlN55o3AHi/zfur\r\nDdGQ8w4unrp3yr63OfXqb/lJ9zOcpmlya7gUn4T1UhW8Kmz3JEwRz7LfjMBy\r\nItwB2QhlZr9eodKZcPsYEpQNyC7tuwzWbg03C92aN1SXuAbycs40cxhLmMJd\r\nNeRXWdANpRdmgn/W+ZT+Oj7RTsQjUqNtX+izz05T0uwziOg6Cti+p1tqhNAa\r\nI5erUoAc2x9GPUs87d5gTIPETb9Y50eu7rbaz3xVfY7o5YeYZxEMqz63lFMU\r\nTIEetgtqCMxMC0FdQ3K2y18zp/HBe/9JBluKQrRnOruYqytZ9I7vcCKt/WrC\r\nrwubdOeynz+r6COVNVqxJ0In3l1r0BdiJM3ywGobA47RUPa3mXzeYJIExylX\r\n/58UcSyuOlwtp9cPgExKMFRHeJV42HngvtkB9/NeSqI+KJ5byZuPEtqs/DNl\r\nzSEaxD2Yy82XvEucWervFiVLqk4fWJzP6838ab/M2qA+X+V18nBfB5FexIWQ\r\nWLaFVw1ohPe0UI9835gEOypczyaP5JS0CjHCwgc1/ZZhYc5ekiOZs501sPCV\r\nXA33WRIr53vU+jjPjI0xgV17/52SOTE2bCEhyc4R1IeHQu8nRjGTS37mLdIg\r\nQsXsOTTvQ2BGoA6Ugw9Y7Am1r2zrJxivLlo=\r\n=l0p2\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.0_1665654430937_0.8459024635280488"},"_hasShrinkwrap":false},"2.0.0-next.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/event":"^0.0.1"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.1","_integrity":"sha512-cmozRANWYh2u/IXBEQG9x3mG5+8A1GtKGA6bsQuzDXnxJjGv22Q1h1MF2vFaHZVI15GW5/hCBBvSpmpO6trjkQ==","_resolved":"/tmp/f73eabf215ecea3b47205723c938fc60/miniplex-2.0.0-next.1.tgz","_from":"file:miniplex-2.0.0-next.1.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-cmozRANWYh2u/IXBEQG9x3mG5+8A1GtKGA6bsQuzDXnxJjGv22Q1h1MF2vFaHZVI15GW5/hCBBvSpmpO6trjkQ==","shasum":"a95b06a3ebaca6d8905b9a942e4c356e5d78d5ca","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.1.tgz","fileCount":13,"unpackedSize":52508,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDkoo2wPAHtYm4hFlld23vHIsH765clHnSFrHNeJszxNQIhANDRdGjtiBld4uHk4h+si3x85kS4wXu79VqvS3oWXKXK"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjR+fCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpEvBAAjLr7wORJs9IJ7r6Zvh150vxYDC+ZMaQfqee57e56hJaSfGxK\r\nAEtryGJqfr8Uo9rEi5mhby/4y2GWyjJ6iSG1aiKgTtAdBpup93ApuMP74JO9\r\nuW2d3c3DMh4UydZjiIxshMxdkl23HriK1LZbvUJXoxGQupwwclyVPhn99C3U\r\ntKTPY0d0UgQHHQCFLi9y3GcR1CxjGYi0vkK944CYngjf+s39DEM0LQp4Th7J\r\nU612OwG17kD5kZ62VeGvAxcQM466+sjp+HbtyUEmF3Z1dWg/AuqCMKevgkSM\r\nv3rC2sTQ1rAM8j0aJJgfVqyGYq2SNi1gTdHClwWrgmtCpZ15ONfaqlO575bA\r\nQRcXNC14Ius/gDHKqHzWiWsVkPLYvDZWwRxre+X03VOlVraDuLmoxgSWOt0U\r\nE7oROo/FvBHYQZs27iXoNRJWafZpmz58+XY9JPJKsAjE/O2BNETfHPrxrGjV\r\nldjNPg+9mRedExVXfOLRjsaDpUXW1Ks6cYREE3dVP3WrJ7wuV3HftqMXT2Et\r\nntDORRKa2WpKiwvGoQgFuJ8sz8n/KS4rnerCacGFpvE7HfQL8zZvqksdaouS\r\nfNmNEVutC5dhEyNfqLY/+CfTWPHfFCt49OfJqM3+4/q4a8DCLUFbxbcs3fLz\r\nDMSfESc6JCHFZq3W0sAda/Nz3wozAY9KbLI=\r\n=uBaE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.1_1665656770242_0.11822936629913561"},"_hasShrinkwrap":false},"2.0.0-next.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.3","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","dependencies":{"@hmans/event":"^0.0.1"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.3","_integrity":"sha512-lWIrN4BOwjyx1+PjwU0ABdgz4aJASngQrfZW3Ad21vQaw9lLfDkeiGd3fezrkXzZqc44naFzv1+jvRonePY+ng==","_resolved":"/tmp/cd5e35bb302488de384c7c85c2f6b1d6/miniplex-2.0.0-next.3.tgz","_from":"file:miniplex-2.0.0-next.3.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-lWIrN4BOwjyx1+PjwU0ABdgz4aJASngQrfZW3Ad21vQaw9lLfDkeiGd3fezrkXzZqc44naFzv1+jvRonePY+ng==","shasum":"b4065f989eb18673b93a5296aa3aaa1ca17bd912","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.3.tgz","fileCount":14,"unpackedSize":60174,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB9iFzA9Dr1YSmvHnNk7uiN+yFkZrBU6mavK5M2adXMDAiAMkqrmx2nh28nRtc8BLImyS7i1LRIjz8OxSddcNbWdCw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSSGOACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmon1hAAhegYmtG+uNbsgaL5bwyLLa/PhGxj3tArErs0wOdTHLgmYbaV\r\nr1+8QJoHMIrG8gp26XE4RAdEQte6ZVkdRFFVjudKDz3ylAI13R/A2OjrDOca\r\nE3J2GtrzCkSWdQzml9dZPhL3dBA4Q1zPero57r2MUbcANZ+oqTSvCZ/fhn2X\r\n42j4GSIuKN1R/ijTNr/E2GzhxjJnLMtuX5BAEwNV7ChmwE/HlflqIdmsb+Nm\r\nb4S89n3I1Z31mVBCIHfyDRlquZvNG2g1WioVg9atefEpVyMKvre9GJteitHW\r\nuHtPoJdGjFWSyjDoOb0fqnW2Xc7wr82KTeTTLfmylwZbQnBglaf8X1V1AY7I\r\nSmHGECnBqAFUmTcGls2z9y3x7SSH6kqfZw6yALUu4NJfud3oRwEg77+lHVZh\r\nIVdQsMuJHlBXK0q25hVsVFiORGeIKpnpC+nsz8YRxg2m/1Wj5pGcGj6gJQw4\r\ne5QFjAIYnTwU47q9I/MT9fkg6YC2NNBh8rwj9R/aOLusEck4z3kPIDteRDGS\r\nIzM4mQY84AWQjhnQImp1ad95OZVDfX4lrTq1unjft5kTlBeAS1lUL9ngkWyi\r\nkBbWZUJBU2LN9VhzGZdAb1liTt0HGV8z6OCPgA8+BGUQgzzsIIAFiv+S65AV\r\n1OpJ6C4QUYDTM9exhenrXq36v5AIR1sr6ss=\r\n=J/xf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.3_1665737102468_0.3968911092722791"},"_hasShrinkwrap":false},"2.0.0-next.4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.4","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.4","@miniplex/react":"2.0.0-next.4"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.4","_integrity":"sha512-DCIpuJKPVKXosB4QN7xXxs8K4N4hM1/Y39a5hijs7eHyrUKnupQR27o94+S/K7LLGiR1PSOFkRfJBcvXoRr+dg==","_resolved":"/tmp/859ec52029ef186971a96dd7fe11e52c/miniplex-2.0.0-next.4.tgz","_from":"file:miniplex-2.0.0-next.4.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-DCIpuJKPVKXosB4QN7xXxs8K4N4hM1/Y39a5hijs7eHyrUKnupQR27o94+S/K7LLGiR1PSOFkRfJBcvXoRr+dg==","shasum":"4eab621b6e19c1e92c60fb474831e3947bab3133","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.4.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICA+UHP51EbbvLKkImiJ3ZXrOfr55NtDZ05SgXyxnYaBAiEAtdW7eJdbd+pwxtlMwkwqMTHPlUv2oVivIjyaQ/F0ToY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSTjBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqhoA//drBp8XPYXrECKPit+LmFoRon6XhV3aPczDp9vaLlzSm4Cx1Y\r\nukYqGEBTMR+b+5dHsGSoZrX/K6yhbz1KpwgSL3d3/QNe3aOtTJLMs6Q6UnrC\r\n2fiZGEj9oB7Lsye7ecvaYx1t5usm/G+dOvWvTR+NeO1PqZjXd5bhg4LqmiT6\r\nKGVvjRlk/fcKpYEoO9etOuMvNddNN/KSxrkptU4vkYQ7nlTEtv5E4NDN4OO9\r\nvaY3AoQJysPZ79gVENb7CT0vs7yeR6ME5spZJppkxdznKHkmiuRuKHdnjFPU\r\num2n+P0+q3GAtss4hLEPRaaCLR4oGaAzAykSTYw/KYZZXpG3tYjvd3k2tqp8\r\n3dp54qbLFzoorZZ7QgyYj+ZL2ZNkE6cURoEvQEp1ugt3uLI/+KnojPPyt4uP\r\npcD9e/QCtZnQTG7y9o9vPpQiOIv8m/qzUA0qL7jueCLqai8U3y8kQ4QKrZ4Y\r\nB8P93y1kw84OpzwP7YTX+DVqxTxjWgta5MiXp7sAMYFG/Xlsz8+wNrND8bfg\r\nziGrecYzq1+gGysxP4Un1x4y6KzXky2ItTkFzG4HfGxsPKvsMXGVfgqBNmRR\r\npdIpKwGRat8qPdQDBtWU/W/Q6HPlLeV5OQZikrmIqXPxIYqU/zdX4qnjKbJp\r\nqQ+xHAZd30AqL2oisuHuLpFV9oTlLa5pSPw=\r\n=M0F0\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.4_1665743041421_0.0030711421743483402"},"_hasShrinkwrap":false},"2.0.0-next.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.5","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.5","@miniplex/react":"2.0.0-next.5"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.5","_integrity":"sha512-3CCOyYL2fk8kRK4u9mdfmh9ZPENaEF21PcK7/Yfb3fx5mKBU7mRf3rGgqAs3cgwFklPIoDv0nf3oaK1Fe3KOPQ==","_resolved":"/tmp/6e71bd70a205986c96c0fe209f62babe/miniplex-2.0.0-next.5.tgz","_from":"file:miniplex-2.0.0-next.5.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-3CCOyYL2fk8kRK4u9mdfmh9ZPENaEF21PcK7/Yfb3fx5mKBU7mRf3rGgqAs3cgwFklPIoDv0nf3oaK1Fe3KOPQ==","shasum":"026e26cf73b4d3d80ca97da0f2a0cd533f1844ea","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.5.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHG69mJmCHneCxJu3dRQJ3F6pQxViDXxK6SUb3EOkjIFAiAy7l2fMugaRb5rhLABBUcJ0seeZpgsDz6G6otsMTJ6Sw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSnc4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp/uQ//XNHXX38WxGCS5vipbAvCXfY+pPoCUNqENxaCluLeFvhMsBGR\r\nTl6rViSiLPwLpszJAhqOIe196xQ8CzDYWiIK5riCy0rSuuZKojrUPaj9RE4V\r\nYpo5vvr1TYbUtoWKgk5OhVMc6pg4zUu3E2kD/OuiUVKQTYvLO8QV3s7qsSI9\r\nXnHQO6we4fpDcgioU92kOhPE+AKkOMAAFrA8bMWKn9aB/2utQWMTKX2FUfgZ\r\nBxTR2Sk1ZtcdoXdgds1lC+8VCGvle6FUiBMrylJv4rUrJ4N9Ymh+ws3GMT8M\r\nEUfzz7dE0DgXLb/f57nhHhVSFb2mN2bdPINtgTChNs8q2GXtwS8sYJdSdSW9\r\n0tbcgG7oFkZ2CS47qooDOuxzRJPjRvNqZ8StmgZtRz9GxUt3rUTSWMXa+2b2\r\nEHW1Q4535QECuHjtEibnmK5Ij33k2exjwF+NyD0gprQVceUVPc5xa1g140ma\r\n8XRho4ifCTEj1HazrHEqy+bYXey5qLi+H7xz0pEgQeydcgFrCtSzagiEO3JD\r\n3LudzFzmrfZ9nB87xgINBKY6bb24pd6Fk4la4/ghM/QYXtyVpD0fz10flQva\r\nH/NUrFNEzqyGRYfZyC4sQHgg8XtNskhbyZcl9/QruIm3n/w/Uta0mqwSAo71\r\n5cJzvH9viv54KYiUuOwg0tLZbTiJ8cesKYw=\r\n=IcM/\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.5_1665824568705_0.8094907958040052"},"_hasShrinkwrap":false},"2.0.0-next.6":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.6","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.6","@miniplex/react":"2.0.0-next.6"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.6","_integrity":"sha512-FFaSqT4RfXjP1Vof8w6oMHXYsq1lAoKjkRvS8kXbxG76IVdD3rvEKgR/+XC59PX2NbPr0TVgQ7+G+nO3drY7KA==","_resolved":"/tmp/bc8a0ffe00ce5db9c7c855660d33b0c8/miniplex-2.0.0-next.6.tgz","_from":"file:miniplex-2.0.0-next.6.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-FFaSqT4RfXjP1Vof8w6oMHXYsq1lAoKjkRvS8kXbxG76IVdD3rvEKgR/+XC59PX2NbPr0TVgQ7+G+nO3drY7KA==","shasum":"aedd7863eef98dd055f52cdd4c1e0a7bf2418757","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.6.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC2RgVNE23molRtPwZ55A2oXr2lG+mEQaH1QuSe/fBmfAiEA1l4mHeRxA9RoHHJbrNhcR8m/l14Eh5dh01IaVwkozz4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSo7eACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmozGhAAj6cM49FfnqxMfqTip9BisuUWelOS/WpdBEqcaTzl+L04Os/R\r\n14SBkyRYtI6cGTgBDhO+GT7+yXP4JAF8OiNQ3N0NUjlgYn9dRJO9W8AH0pWg\r\nUfXY4Q1RSq1XLaWC9mU0GeIKB4IHYJyPhmBjWri4g9Lxk9BTZPL5qXPD+2MA\r\nzdG5aRxHV1RjWdE9R7s7721vRSNy8PQmZCZtygMWBPmsDpiYl5i5n+9xjBil\r\nfJhAeynhFqt+h5ZIud8U00GjB7sZgf3zDvS1EQC7gs7O6ZDnT/DnzP1wlIqI\r\nkU/WdNcDP5/bPZ6b/0QO51dzaIQuPWB4oo2srvVxeRrlvAYqHtIcgxrX7szX\r\n+POl4NZgfgHZAqXNCDUpV84aVKxG8wyedJhV4INII0qlZrKR41RQaMO1blSG\r\n88VgmNcHZdBd53VLoEyP6QTIQpYuzADLWKXxY9fptjY3w/MWvbyt7E4MrRvr\r\nuA9Ie9xsUOGVM01x5ZWxkpBI2LYMD7bsNPuyDwfUbSkvaXjmwRt9WrGVSup5\r\nQrsDjIDusRRNIwROtHXIdKvbdb9dPPM6L2Uq+SUzGt+sI0xyqKBZINp4kEDr\r\n7L7yFXHM8sx/ngT68sh2vIDj4jU9Lhk/nXfB+JTEuGuf2Wf3jOpLrnVPFMER\r\n8HVFm3Fv7ttmsFBE+XYDBIml+nCIN/sRi4E=\r\n=t6mH\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.6_1665830622130_0.5800852487302461"},"_hasShrinkwrap":false},"2.0.0-next.7":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.7","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.6","@miniplex/react":"2.0.0-next.7"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.7","_integrity":"sha512-RC1K7IXJHdZzxu73pAotjpogiJET9p5RQdUwQzbqGTJyzjwGJvZT2UXlzBsMVDq1Y7ALk7c/fg5jXDfleSz/sQ==","_resolved":"/tmp/2324c00bd1e5ea57fdb01c16b1cedca0/miniplex-2.0.0-next.7.tgz","_from":"file:miniplex-2.0.0-next.7.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-RC1K7IXJHdZzxu73pAotjpogiJET9p5RQdUwQzbqGTJyzjwGJvZT2UXlzBsMVDq1Y7ALk7c/fg5jXDfleSz/sQ==","shasum":"b7ba43d5e7e7d6ba6de8031ac2adc7a9b2c3eb5b","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.7.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID58kEcguB07Obs4fU9EK9I7VKE7Vjaotz7CAULhgPvaAiEAwS2En8v1VSPpIM/1rKw+cr+mb/23EfkGqljy21fbJkM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSpRCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmprjA/+NbarMpeEaR2UHZ+Kdv6zkJPeyARNYiuyiIUGllNTwDkRiIQh\r\nyv9tTQ9kQFWMMdafAjyVcNm8UfMQCw6X1Q4nECfq2fcgwcM7GKJoP3QNU0P1\r\nGi0YaR7jvbA821uabivcSy7VXpP4wGBkuMNePOME2MSoOWUq2JCwNyXRHZhl\r\nh2PnqE3Pvp/S8+MQS/bblsBxuo/5zzE5mdyqIjvzbQKEcOIGXdVpE7O5XmpI\r\nIkIYljFnc3Zjuu0ZzQGuEMuIz2sT4TRtq2gK7pL7wSvHZx5uZWv1ExtXTfAB\r\nTiFxmpscKJUnAX/k2TNak2uaHk/LzPbvUV7CS4Gy/cI37saZ+hyLYe4p0a+R\r\nGWBfAbfsXo8k6ZQ0Stp6RJr3w4z/Zh+1Os1BHhZ6gYMtMJVPo2taAjQnR39j\r\nL7eZLORPLdPz26vB2d2ApX2C7yvYFfv81yvc8S+JFpljEy3ywVaToS5TWM9X\r\nFPcF4D7O49ypeb9wB01kLNjavMHv0OJesIaQaAmM6rC9UmO6S0XzJdtQUx3I\r\nUZEsLNe6b9/bSBEtzNsvNJcSUk/aE8Qels3DF61CMvmwNzK1MHEjmoeA9u9w\r\nv0bJMO9t10bq5zaOe3YSywtkVxCXy0ggcMaKT6iG3qA7iBex/2DgD98MeGIO\r\no/Zsx8Y6rN0y9ambdoFh7wp39iN5fpbjQM4=\r\n=Jbq4\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.7_1665832001894_0.040603572116892694"},"_hasShrinkwrap":false},"2.0.0-next.8":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.8","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.8","@miniplex/react":"2.0.0-next.8"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.8","_integrity":"sha512-Sp2a6rGgutsDbEjwcK5bwh+a6Xj8Zwe8NyPyNmZk0b0AVUt3sa/cj1Wo2oQi8DMQEi4WAeGVYFvvjTqGK9ahxQ==","_resolved":"/tmp/d65c5e5017ee3a268d6102e2e52e59cd/miniplex-2.0.0-next.8.tgz","_from":"file:miniplex-2.0.0-next.8.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-Sp2a6rGgutsDbEjwcK5bwh+a6Xj8Zwe8NyPyNmZk0b0AVUt3sa/cj1Wo2oQi8DMQEi4WAeGVYFvvjTqGK9ahxQ==","shasum":"a314aa48845ce8a5b1d504b8824fa6f1a2858446","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.8.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCWMLOOmqhTd6wiAvAC5bLlv+JZlQptKruzTUFUXWNWqAIhAKzxaX6ahV2p8Po7CQvCxsGdmwiyPwzIWLQgqckRbgs/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjTWiZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoJWg/+Juh4/Xf6582gJZl0JEdrHideLzMNXrwjk7ZPFNdFlJ/VCmyG\r\nxFWNFOG2IBb8xQGM4xQHM+6GiVvsCQkdHLCnYPOLW46hUcVCPAOPkqsKsgxr\r\nK692LzFGxDCiBMrBwkBwYXysa4jSltc7uSqwg6jc4CjxnEqdbJtD9JYE2+YR\r\nq9mpmRmqTz4hvqjvKSq+9i7nAymMZVkw7q7pf/KbLWtz3B4TyZWxp5i0geVY\r\nZXu9k6seKkwNbEBINiQpMRrHLGpqml5QmxXCGHmzkrZ45ESvYsRPMRTvc5X/\r\nJxKx/jZTgGlNRCq8pDtM2q02IeSVyWbDzVb0xeoE9xjPFHXo0QbRKZA3bbuU\r\n10uQ2+6rya0gVykr1UE+d2G044Eoy5bK2jkqYco7AqK59GUizWT+dbe20tua\r\n4tbmp2AzTBQmujq47gPa1U390eQHNm70nMTO1BKyPkU+WLzA9ZF7pXtIaKEO\r\n3TldJfwFGpTkMf4KpYDqkEOK9CXDey9EL7LggJrcEaRVgwLOjkRUxSuLVxg+\r\nLz11N0ODA/eYJXqLJWJ2KtY2FP8wMCCzZ7bOiEZphWCPGX2sv6YUcSKHWxfS\r\nOxYmZaglYZClxyx0O2yGbKq/5pXLXFSVqxJsyJcJIftv/b9PM0PHRhU+UybK\r\nIjsIo/kOlBy6KD9eUAChyGkGb2HtFp00XdY=\r\n=ZqWt\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.8_1666017432878_0.3480081289562138"},"_hasShrinkwrap":false},"2.0.0-next.9":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.9","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.9","@miniplex/react":"2.0.0-next.8"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.9","_integrity":"sha512-dMx/fUBVLzXEYOfSJamRAZl0mnObxIn7C99HibXJOoPu50tg8JuC7mO7e5ft8YW+mGZ9eesgeT0wXNCD5ab58A==","_resolved":"/tmp/edc541af5f683caf3a00d35f7a97477a/miniplex-2.0.0-next.9.tgz","_from":"file:miniplex-2.0.0-next.9.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-dMx/fUBVLzXEYOfSJamRAZl0mnObxIn7C99HibXJOoPu50tg8JuC7mO7e5ft8YW+mGZ9eesgeT0wXNCD5ab58A==","shasum":"c3c006162319cabc4c14bc92e9b342131a5f1e32","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.9.tgz","fileCount":16,"unpackedSize":20722,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjdsmh4hwPwC5zzJNWP28isQP1kn1XR9F+Ts+jm3EZ8AIgJyQhvJbZcS+lhdf6hdDkD6KUP7cEu/SaNKS9ffkfeRo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjTYqAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmozFg//ZTJgM2znFD502jX0lpFBlbzbIHMmuh/gm9Se4scuUgwR2Fwa\r\nbUlkBn2aTYHhnruqeH6bkJrsK3vUHHITy+OW0YHKEBi+eum+ADNdyt9E324g\r\nB1MmA9ZZSJFwrYO7v7o1bEBDNhPQgnkt4HWCgpr9+3QTW8OAAmDIFiAUWEqb\r\n11+nDooQ19Hj5wnaK66HWoIVUGiPiqMCqChaZTgE04F0WXBaBmAcUcoYmqFg\r\nqaFPNHH7PhJwgwSPN/G6PduW0NGPaXJexYcHC8qupWF33btsAtGD35x9o9CQ\r\nidj2av1MSdi3ZdPq8ShGVcKMjxH6jZCdz3xTt0wcfJgOzT99fw3s7F4pA5Uw\r\nJ3Veetzq9B/ZR21oJVRbSFzSv1cptfpwYRn8midx9k+Hm2dlGgmELZKaPFnc\r\nl693VVw9lNiKXeLpgzyoCCDPqik2cS8HmIsgMg7V0K1PEjgjCNe1gjXVZcqW\r\nAIdTSvFnYAQA6uyL36XCuq+nIOVHYTdP6Hq8XNTbla4JpfJWurw5rU2K8ebK\r\niANp1+67EeervVxzApycVyHIc4DZzfFXFdRnziFTLEWPBTOfaq+01cwJeJvs\r\nDFk3qoci17Mw24Pj75vkoUkAS2PbjMlblNsXzNL2WgtnZnCO9D9+/420q5tn\r\n0fRDDtodLiTvDp4Ti9ywikRVQMGJgRyD9fI=\r\n=axvg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.9_1666026112055_0.00472104430904885"},"_hasShrinkwrap":false},"2.0.0-next.10":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.10","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.10","@miniplex/react":"2.0.0-next.10"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.10","_integrity":"sha512-o+EjFgTVLyI18yat8HsyMLt9xxSmisQTdk8V64odymxb6b9rgJad8FKqRoglHpmjwplKuwvja+X8Ctj0cGRZnw==","_resolved":"/tmp/2de8fb010cee071b98f219d6c8e1e8af/miniplex-2.0.0-next.10.tgz","_from":"file:miniplex-2.0.0-next.10.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-o+EjFgTVLyI18yat8HsyMLt9xxSmisQTdk8V64odymxb6b9rgJad8FKqRoglHpmjwplKuwvja+X8Ctj0cGRZnw==","shasum":"a4b6c93c671ffb1017fb469884a9e39fb7fa93c5","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.10.tgz","fileCount":16,"unpackedSize":20725,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHuTukX5AKMj0EDBsImVT0OccUS9BERBt2OSSOoyydnEAiBaUl2iviR44QjINS1n+ezwz2gO1ngWMTAHzFYQ0LjlEw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjT7rzACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrq7g//aJBHvN6IzrNrfar9cZbsVE1FnIJrXxhQuM6nuobwo1+aymog\r\ncKl+ThJZm/ZOzNgQi1nFWQUFeDknt8Or7kfwXDJ6urvs6v2t1mpOtUXlGX3+\r\nSuNgex2ZXjWl1flM2TnbcZ/M1NZdp+zA2ct6G8zGpPvebDx4FyKZ5JmouJVd\r\nhnGu6QuRDgUxagujkU6HnmC5U5fpjNl3iCXTFaxXW8dnaBFT+2Km3cgta3kh\r\npJbs3/hI/xNc6t8tsvdYCgfILt8XV0efr20HNBh7QP43YPKFlUPfWwOlQKHo\r\nu7GvB71LTqtF8BsPHfEzroGpq/dwXNDllYzUs/9fpyPzYeZrW9W8AeRl9gA3\r\nuPSGsM6Aa4t/v4BZjtVZ1v1Jg2nCtQoIwBPtMuxofjTwBNhDZrqTIp1VbPYw\r\nIMq/iz1JKduvmQ8MDnH6RvGxvOSc5i8V1QsCs0OEO2YHz+xD2zJ8k0JsttzK\r\n5giiUjmQvdH1riHYbEmchMAFNMKAscv8UDUGiop3ecOTSPQAMSsw3kWfPN+7\r\nh2N/dvVbtiB9YSv5lvNbXoXFMWlqTKKxA0CQFq/MO+1losmTXgusKDt+VXm4\r\nGAOc2raoRNJYnbjRFMIlFAzsJOBCAYMhyHIAxgwmIIjPFxVvdSu3i5C7mHds\r\njHvRrdCEbBgsK+7dfm16EQDC4cCJT0aKA8E=\r\n=5b4s\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.10_1666169586991_0.01068499666824163"},"_hasShrinkwrap":false},"0.0.0-canary-20221019154835":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221019154835","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"0.0.0-canary-20221019154835","@miniplex/react":"0.0.0-canary-20221019154835"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221019154835","_integrity":"sha512-7FVrw263DIulZ+1BZpHfQP5la/b4REq8TQE03Kg21gG0KAmVxZ01NHjDRcUUVXUhzQN0gP0nqR8Po27PpHWbew==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/600bd41b417a1b4daeb3f28c6f844791/miniplex-0.0.0-canary-20221019154835.tgz","_from":"file:miniplex-0.0.0-canary-20221019154835.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-7FVrw263DIulZ+1BZpHfQP5la/b4REq8TQE03Kg21gG0KAmVxZ01NHjDRcUUVXUhzQN0gP0nqR8Po27PpHWbew==","shasum":"26347df0fb4ed5f9922b38042e4beb9548855437","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221019154835.tgz","fileCount":16,"unpackedSize":21175,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID+nBH3a4mB20RV3PEmOXIDBCS1g8B5aO1XXre4VL7HLAiAG0mofiQWz/gIzyK3Llz/hQSywQd3lMJFZ6Xo/RzA10g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjUBxsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpDBg/+JG5sXsfc63yyXSXMq9v0mq9v7QrA+SLmehDGBUzw13vID47O\r\nxT6ZMjgYKOotDxCnXebM5NL4sF3FBP0U6oYphsbJt91Txz1jR1Dk7sKxiyZU\r\nnE9Q1a7XT6vePX2PkfEAlgC+IFscQJq5lkOOzNQnTbMEBajchtarTbaIrtTo\r\nFKsvzD7i2glf6y3wGJndmKvmw87Up+5qZNiAv9lTXMCbE7jvdpP2c1GbcOTj\r\nU43OrmcafpRVfN6fxoKsDk+kZGnJ8VlrkjpphJon7bz40Uaxs3cy3NlghOMm\r\nYt5EcAbvnV8LRequQNVyxHVzGCImUU4LnTD9ID6RilPhwXddzSYwQE8ArFaU\r\n0tXFiviRXu7tCDQrQHXZu3RKjwZf9ZNZ3gNhsQ5m6pdRvUy8IX6Cwj3iZL6/\r\nT1Xu3bXc69630qmgPiDoCsMKulaXtG0fewiFfNUWvnn4nk5G9BHPD1Vpoo3K\r\niHwMhNWaOMifDkWQx2ZxT1dV1VBt8p0NIzdmDNmwF4DDaiTZ4nEKWWULp/R8\r\ni1+lpmMehBlsfGb+/B7usI0LUGFhY4nlP8WC9iaY6cVSmZxewLs2YZE0Wggv\r\n/je/p6WEqAH1Ce2oW7oZkjujNEDORCpcJzO2sJ4GBZvetuAOUrL/iahQOK0b\r\n6zprUg79zjjgOI4l1h1YcsDnupgrcbk9bFA=\r\n=kEuF\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221019154835_1666194540507_0.2543788532146698"},"_hasShrinkwrap":false},"2.0.0-next.11":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.11","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.11","@miniplex/react":"2.0.0-next.11"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.11","_integrity":"sha512-EwklDjtMLSnynY56Ouwe3XDTYoM0DtXhlumNc60Dd7fhH6ZqKo/HUJweJLCgxPzfMc9z+ecT1LWgNCWDzNKwEA==","_resolved":"/tmp/c073a756ce27a3819d21ddd1c9ec6c74/miniplex-2.0.0-next.11.tgz","_from":"file:miniplex-2.0.0-next.11.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-EwklDjtMLSnynY56Ouwe3XDTYoM0DtXhlumNc60Dd7fhH6ZqKo/HUJweJLCgxPzfMc9z+ecT1LWgNCWDzNKwEA==","shasum":"7cca5fcc4e478fdafbe72278d0a4924513b1adb8","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.11.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG08zWr7+A8tQjOQcLDKg66D8qqMSOj/iou8msVM/oo7AiA2zCzrjiTV7IB0ZzKIsxdDDKP7pGXi3HlXtpdvdsfAKA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjWikbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrk8w/+I94xlRY7z43LaD0jo37YLeKW4UdZ1FceWKcFKYOvtuW2u1rm\r\n/jKmHscF+NnqQ2kMsewXwuWlOoqeFAY0NZFB29TB56WHVzEElEyz/GyPD/CI\r\nlgigf/Dt0lX5JII4IQ27sInh4wUZjjG2Xt9uzmQ/hwQnN5pe7DCF5cU7Z9OA\r\noKnxGCmnEjjvgm6EmTRqiPFvNcrmaQ3gRyhisUOpUlINrmvTujt96ZvgvWiL\r\nvWzLLXyzAbzozgC4KRtGdZHomadMavp8O8a6sABdY8fY1oPl8MWUDA4xShzM\r\n1p3FDnXGTD9DlLwo9WBwQq5X8bGWwwL61dQYJxHLLW1XOkYTtOUGdfhFbkvt\r\n9XEj+NKRAgucP7R2eIVQ9RpapBliPxehYSwfsODoGgZlufUOtbTg4Rdo7obo\r\nzCZ9AFIICIk2yYgseQZS6kp5FyUpg/vFQEEc0UU2rBx+ySRaekt8Z+lPmot3\r\nV+uUuIftQFzGBi6Y767QWNAdaRrooGeeQK3ytARr2nBiMYiN7+zofVGtsGRf\r\nSvPKp+E1j7J2jh/iXWoTR+aT1U4e/RpK/P+ecGBxlmBRVB/Nk0azaphryVzq\r\n05r0q0TklZneXrSv/gCIXAMUy420B+JK9XRlj8m+VwlnQ+pq6MUbMkp8eunk\r\ngzw3D1RzLyr7ck9Ux1mjiDuWZJDF5k+EV6o=\r\n=Tqev\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.11_1666853147423_0.22741824168215774"},"_hasShrinkwrap":false},"0.0.0-canary-20221029092412":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"0.0.0-canary-20221029092412","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"0.0.0-canary-20221029092412","@miniplex/react":"0.0.0-canary-20221029092412"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@0.0.0-canary-20221029092412","_integrity":"sha512-xdniMgt0SmvWsOhh2O/O0krTuxHkTnCfE1Y3B8bScilmfTq6a9NdxI8YguMJHMF29nA4mayW8RaR6CKZy0L1Aw==","_resolved":"/private/var/folders/j4/hnqh_70x7wnfnqz19p_s_mzh0000gn/T/427802ad45ab378d0e42fecf8f8228cf/miniplex-0.0.0-canary-20221029092412.tgz","_from":"file:miniplex-0.0.0-canary-20221029092412.tgz","_nodeVersion":"18.9.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-xdniMgt0SmvWsOhh2O/O0krTuxHkTnCfE1Y3B8bScilmfTq6a9NdxI8YguMJHMF29nA4mayW8RaR6CKZy0L1Aw==","shasum":"b76ed1ec5535dcea82bdfeb098c5b5b17d01dea7","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-0.0.0-canary-20221029092412.tgz","fileCount":16,"unpackedSize":21175,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBSpjDXE03ZJd+vlsQ3O9/qpAXXH/xcCYuERCEUD/ZMVAiBBaAAuu5jvXqd8/3iGSraoAaIDtkgf7SgyM4d31g/ECg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjXPFQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpW2Q//aTVqjgE5uXG5023V5wrVzuZsPPskccAH6NglVUUK8MEv8V/u\r\nF9SUuk9itI2qx3CIyF43hDtCdWatAhgF+2VQXNsEVI957yAfx1YzJl0rOn5Z\r\nDGS/8wk1xKvutwEQfBm5nNdwuY219G7O3cFasmzuhfG34Q3UpmWyPzHLhq3F\r\nfhSXFLpmjlijaKRny6LUB/7Uup/B6VsAAvJ6A3YptmfJLI1b3lRBuYZhTtyN\r\nFZ4+2/whbLxitTu3uv3IyxILgB47VsvJmCZgUPlkAJyfhvRFZztCgo7U99Rf\r\nOGymtMJt0G0JjLHtIxH9g1E/Qzh9vSe/J4qHB0X4VSliRZJG5rSymbsd1jFu\r\nsoWgUB9YMrgb18vIMqmvCYJC5FQMX/ts/Fs4oEMI3MTCKuM37Ydv6SSHMiWZ\r\nadfqKz4HiI1o3kxm2Yshn3Hb/pvJLBGULb2EmL9jg9IQDbter3ryvehbPJTi\r\n3dWNY7nEw/l55svv9VQTj3ybxQOhcsUxnvAdxyVOUtvL2Eb274+Crz8EpQ/7\r\n8zbmSft6NO22svougtOzV9fcY7/M1L/P8vSS4E+BT4HIJZpVjXrHAEJR5ik+\r\n6oeyCHjFDq02yZ3cAcNsQTkx8SR1geA/PZcFa+UVNGSHOSi5GQr0tXTZRUVS\r\nVttoAlin67H4qvaGrJagPwW8j70oG87zqZE=\r\n=A4Ja\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_0.0.0-canary-20221029092412_1667035472515_0.662120110066402"},"_hasShrinkwrap":false},"2.0.0-next.12":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.12","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.12","@miniplex/react":"2.0.0-next.11"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.12","_integrity":"sha512-b0lx3/reds8WjH38Jf7ahHQkh1cJ4i6eU2RwCbMVXB7rcI/wv6N/jNMbsiNeVz0DjB4uhiQAhpsgaDzAHZi5nw==","_resolved":"/tmp/b7e07d74f5c5222b0f81b35aef51329a/miniplex-2.0.0-next.12.tgz","_from":"file:miniplex-2.0.0-next.12.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-b0lx3/reds8WjH38Jf7ahHQkh1cJ4i6eU2RwCbMVXB7rcI/wv6N/jNMbsiNeVz0DjB4uhiQAhpsgaDzAHZi5nw==","shasum":"f295fda3ca71ebaf1c0d4ac10b1e556417f24f27","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.12.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBzjeGaaUi5+7EuWiZyFRUWrwbdTOMzigLRU9IZcmUCIAiBcBakt2GiVBTSOmlIR79zw2/PhYgEFzdkmr2DNJtZqDw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjXooxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqBow/+KC0bTZIVYxTwrQ2+p8lC60LmuQPdx94gDA1d8wa6VRtGQ1do\r\n/6eR1kOQELdIVn6aBsKLa8oEs82WHnejEFbJ7BP6O8dp1EypiId2k8OOyTVi\r\nANQEuSX5mfvV+PKBPpAbf9uozdI+VqsOpp6CnsFrZnN5UwhjVsfpFttXvjvm\r\nAgLWr/sr615H7ki4GewIL1XddIybxQWRhcIjXIpkQr1e6EITZF5i0TJuQp6U\r\nLMHdSe7s7IdrYCCbb6ElPnoAvHtO90J0Kl2T9x0O+LLTtBH6rSZ/5jjMC0kp\r\np+3lqsofzOAj1lln++JFtWR8R0N7a08UKpbgp+d81TsAFyNJdm9Sqx+9p2Wl\r\nR8w6h6mbU6Wuz8kni0FYcDbz75Vii4ue1UmvHFSeRQYQNj/vs81ruJlil3Vu\r\n/Pf+V4GDEK+MnUQYQ1IrmllsAo6QaDM3iZ0qnQMBpfZyAjUrToT7YPKZjXdH\r\nYrP4zQBYirGZw+/LWoOzHHy7zwIF2brPW/zwhEu1LmAvw7uJBf8f6tgiOGIo\r\n1Pka2KJi4lSPH3sOR1QN7zQoPcJPlqbInOl0Ie3xdVBaefAwLTYbetW9x76z\r\nxH8iaizSTJZvYwLWbeopD2Q2yEYwzwYzDj9pMC0gOU49Pulj7VcC49XRUNvg\r\nObuvyL9hJB/lZblug6bh+oHtXY059+7qZkI=\r\n=jEip\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.12_1667140145107_0.17113792312788645"},"_hasShrinkwrap":false},"2.0.0-next.13":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.13","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.12","@miniplex/react":"2.0.0-next.13"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.13","_integrity":"sha512-CZICuPDoNw7zyCb7GCQep87pF8iu6jn8Kp1lAkPsb35qFPamWQfgY6OlfnAz0DkDRDzCB6ItayrOymddSAMC8g==","_resolved":"/tmp/499d6402a26e1b4c12f132f2f42b67c7/miniplex-2.0.0-next.13.tgz","_from":"file:miniplex-2.0.0-next.13.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-CZICuPDoNw7zyCb7GCQep87pF8iu6jn8Kp1lAkPsb35qFPamWQfgY6OlfnAz0DkDRDzCB6ItayrOymddSAMC8g==","shasum":"9937a38a1085e18a1f8ef8821a5db9c213374e5d","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.13.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID1X2GycXDlMebjg6ciiHEnvLgN7WucPXDPyw8a57UocAiBTYKXTlFoRB49vpFG6QkTS5DN5cvYS7Dp5VPQF2tzozQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjXougACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrdDxAAh1zezVrTRQzV2s7QLB5opgRwyUeE5ZzarB4a+QlcVBGFWe/T\r\n5PnAb1mMreei6VuMC1OeNjgjMygsEx24TjO7t/TS1SNlJPmzsbL+WpPn8HoZ\r\nHRguwWS1qP6vRxqdDZ6ALOC6KEbVrOpX60yL9Cin5Uz4QHwc782hI97QVUoj\r\nWAeu0hkWd3l6PTZvJlrZ4xiOvDpIuZDdtu1PEdgNUOZeEknI9uBV+8BLuhMw\r\nquiDTiP9YJn6rPqFyIvyBJlTMwhOTTWQTuTzlmXm5v5r//K/0X9QBe5tXa69\r\ntObPvaUHgmW7dulsMgtNkknoR0nkfgJojmNzkJUu7iUiy/nVAiH3KnDoJBXX\r\nRQ5EtC79ASZZT/fgej+RRVRGF6Bx+i1osXha71rGiMEGNAgs7pnohN9f8Hal\r\nulooXRv7ZmW2/Lq1dTwcvyvrK7NspNnAJr6G+lV5DyVSFY2CLwTQm1+15hhF\r\nBYU+ltx5I/0wv1f4SbAiFdtP/LV6NjEY/mSP+c0/DMHVRSVPxi8SQgwr2evZ\r\n7pK4Id4mDdDKroGdNDDmt/p3EOmTeGp0ukemduNToMzjMURRl089K1yJz0zS\r\nyDNstUkkzZv8aNDDDa/RdnFqs1QDOw4DeIWA9WhPdQEvt2/zG69nOnYFITCa\r\njWjKExQmd8qYU+lWrOzHQl/diWa1B8ZS8Yo=\r\n=FPqw\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.13_1667140511850_0.45110561426040396"},"_hasShrinkwrap":false},"2.0.0-next.14":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.14","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.12","@miniplex/react":"2.0.0-next.14"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.14","_integrity":"sha512-89DdEngtIG4VWVFBQHPeQyW+9eZk5xfRo9ZHTK19Jrs8dMP23x+fSvvx0u1O2/Jc/REJtloY5K8K4EBGaU26OA==","_resolved":"/tmp/f72987eb8c7786da6a53cbbb6de948ac/miniplex-2.0.0-next.14.tgz","_from":"file:miniplex-2.0.0-next.14.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-89DdEngtIG4VWVFBQHPeQyW+9eZk5xfRo9ZHTK19Jrs8dMP23x+fSvvx0u1O2/Jc/REJtloY5K8K4EBGaU26OA==","shasum":"8e58d57890071ee44e79303549fbcb8af50dee79","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.14.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJreaCgfnBqBMQ5Iwpw+kiG4TNUk3N+Sf3oQiZXpHoNAiEA2Nu7UCkaWl1mJfqRw14gjxhcJq3I9elVCaXbBfu1duM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjXp9SACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqSJA/+NbG2IakkuasTc4eL+WIAmnCH3AzVABsM+mxM/Fle5f0+SiSE\r\nFbc76fWwvGh3hylYEhcoaZjSbpO31DRy2ipCQN9nOG+ZMDyRk3/YRyVNhMDR\r\nnjylN6NAFJTzp6dJ50GGM6bLAU/hDhfxz2ek2G6SjnO64f2NTX/owchSk5xg\r\noyS85XWUjc23sutXLac9pCGmYU7sMnMLbwIgoECf0O0FkPKLsDJCBFtb5T+v\r\nPzH49InCxhkcEEHIK41lPxEEhgoPlRB+yw9sVYttHNJDwc5EIKb/yE6qEM0Z\r\n0kZCpVo/wYIJr2bePGRgfmvcgLJ+c05Va21tX11AAJXqbdQRLIFk7LIIKSSY\r\nFvc3KfFVsfju8+/5aQOCuplCDxhBsfM2PEI8Zm9aR0OJy8WmlBSigm4Ovg/V\r\nigSd7FkZViyzDNhCZPWRhyw9yzBmC20TVD6jAqjpKMCr6NFKALQHRwq7aAzQ\r\n/uaLp0VbGTW6GVsTjSG4tNu6j0doxfb1e765+b2PcsV/B0FuWmO0IqiTuvSs\r\noXEtM9mdtRaC8v9t7GcX9XgE4yWPNPdfc6T2/qQwQ4+ePCQc1grqFDywwZWV\r\n30MGvDYTGgVJvGTKRNXLtNnVaDIzmfNu2LNTd/SEBY6Sxsi++/D02EuF3WVA\r\nQRcEUzUltX9AcCJcngpwzm5NJCn3WdvfF64=\r\n=z5Lx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.14_1667145554426_0.6445332208897046"},"_hasShrinkwrap":false},"2.0.0-next.15":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.15","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.15","@miniplex/react":"2.0.0-next.15"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.15","_integrity":"sha512-Wufdz/WL8Io4k4ed/d4zrzefVWgkdQikYXG9LfuKYrB23tj465Ik7A010ep8sEwHcxverWPXIKag8vAJ7due+g==","_resolved":"/tmp/6468a8dda0d27587becd1a96a19859f3/miniplex-2.0.0-next.15.tgz","_from":"file:miniplex-2.0.0-next.15.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-Wufdz/WL8Io4k4ed/d4zrzefVWgkdQikYXG9LfuKYrB23tj465Ik7A010ep8sEwHcxverWPXIKag8vAJ7due+g==","shasum":"76759eea6fd58ec816bc33b30a22654da4132347","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.15.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD311hSSCGXsvBlB0BJLas/YYjLg6KsUe2oQdQfFQaqlAIgGvyGql32tnm2QDRjQ5P7ZYtzrTuJRxjL4RNi3zzTyTw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjX6g9ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrbuA/+NQpCl80YZHm4YYELTQHJPE8SV8aCyFe5Y3knR3o0ESniqNgl\r\ndnmlxII618iamKK4siGBRqM8J3GuXKaszofCU6lwOtJqgKFp9sXDeBbefkvQ\r\nq6cC1EfDSn6rTMFoLKOrd3TQqQ4kdgn8GJlkzaulGsVYiQBKrITjLpvbI+9T\r\nGmRiWOAaMvhoQPsrkJb7w+LYQ0iTwW41KerHPmhXzYNLqgPzVy96hhhc6/WN\r\n91sJ8atscNcMlzT3JFpcZj8elp3a56vq3VeLYt7QVDWaGuAReOIVlZ9iKlM/\r\nGora2ORYiobYzCVjVo5zOybGZEnbDRrU6N9QcQiRHcaR3nVIlqURmIh5Ag6S\r\n30VZbf3XXb8GblZhg6h5DJvE0oEBWp+thZgrCVnPQaF2nYKo3OlDtGCIF5wu\r\nJkgNHb4Hu8aocVLpiQbVuovN6ya0tQTQ5DDO08q988yNqZPpcGknQXXuMbv/\r\nn3q8xavFVwIWUFj2TqeyKB9RDJtbGFJISHlA2o3AgrzWMBGwiLXhdlBy/AGq\r\n3P4I9KUXHQIvaT5dhn0//wKI3sbinUMyzWpjN6uStpmYg102UAS2CtoMPo+Q\r\nzp1/UnAcNKe/c2tpY4i2gyNBV7iOcogFgYeTuzI6NoAgSpMoxIOUDz8+44b2\r\nn1sZeo8n7EI6wNkD7CZV9V7kXshnkQiaEuw=\r\n=EiP1\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.15_1667213373807_0.04235010732241595"},"_hasShrinkwrap":false},"2.0.0-next.16":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.16","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@miniplex/core":"2.0.0-next.16","@miniplex/react":"2.0.0-next.15"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.16","_integrity":"sha512-KMZmLrSpEhhXgxt4h7BNbCiYjf2U34oKxjxC6hWNMelkDtslYivAFeBNUe+5YR6zUe6lhwQ1IseekXqOlQOGEA==","_resolved":"/tmp/72c2e3d72ecfdbbbfd3f3f8e3828f465/miniplex-2.0.0-next.16.tgz","_from":"file:miniplex-2.0.0-next.16.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-KMZmLrSpEhhXgxt4h7BNbCiYjf2U34oKxjxC6hWNMelkDtslYivAFeBNUe+5YR6zUe6lhwQ1IseekXqOlQOGEA==","shasum":"31d1d1137fefe6c8fe84a699e9c63f2aa4310a4b","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.16.tgz","fileCount":16,"unpackedSize":21133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCps1jzN9rYZ3ezcALYdTo5X2MvTg/Aj/DD7TMagApC8wIgaI39B6d6iWGXKYIbQtjb1ODKsInDLfXR9BaADHOdXcg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjX80eACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmob/Q/9FReEkod4O8+BRpIEhTdXsh1J0zwI9mNFDxriOAHTPm4+FdbF\r\nullrddsWUfBtZhJw5t8NgIWHUuvggo+rK8KDmJgBarfOR3Lvyyrrr72scUEG\r\nwxqyYD1PfDZrMgDKsXbTt3CukvNR3IDCGZe6E11LqBEYxWMXuGyLS8ohFUaj\r\nhjAF9G1xXeJ60duY7uBZu9QP/AQWP5fOSPpH+DmtAE11X0wsu/5/nal3mFyi\r\nM1s545n3B38e6OnTQbF1KyeH3E/w4N/DuuiqItxTinwX6Dxe/7Xl0RM5Nm31\r\nEqfKBSztcmVOkTAgdvJC43XAOGazB7JXc9c2l2X6dGNCB1/N1vfoNmq9AynN\r\nB2RcsSgIkf7B8v+w6o4f2vNM3fKxjiUN1lMaQ6RBimWQqusHM9xlDgh5NLRi\r\nPW429ExaEG3DP2bJbZ7adTXahRFUp2NRxx7gGaIjQ4WNNOctAqk5GPPRfrLY\r\nFjQaVpTOzQheDMBeaTffbLWX/GTnVCo7NU6/izh9A7RCWCATnTvatiPqTUSs\r\nrwnJpu+Wj0TezCcInwi7ZMBUdY6nNuujCQVW4/twra0xDBgs5zHqK7jm2irn\r\nqlyJP605U+HZKdl0MYvHyqoIW+lgYnpHzmOGdS48t7vIVgVn9A8USSn0Pfjy\r\nmC7P9mEIOPh42zQB87Ozz/tb8l7rrwEUjwI=\r\n=13L7\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.16_1667222813897_0.6144066277781568"},"_hasShrinkwrap":false},"2.0.0-next.17":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.17","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-next.16","@miniplex/react":"2.0.0-next.17"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.17","_integrity":"sha512-ueU3dLQRXD9RNK0ee4vPSQh8IgeBdNxv9vDz4za5U6TLpDjX+CIHgUWghPGlirjs6Kw2uXgUQrgpvB/v2dPKTw==","_resolved":"/tmp/091deaf66b60923b78d423f7fdee9abc/miniplex-2.0.0-next.17.tgz","_from":"file:miniplex-2.0.0-next.17.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-ueU3dLQRXD9RNK0ee4vPSQh8IgeBdNxv9vDz4za5U6TLpDjX+CIHgUWghPGlirjs6Kw2uXgUQrgpvB/v2dPKTw==","shasum":"96ec98fbaa29dd09cb658beb66e9873b0b17afae","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.17.tgz","fileCount":16,"unpackedSize":23003,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGWiN9Z4sJFIqkb10rC1wB7cQaz9aagjjDjhh8si6+XuAiAorE9DlU1EbPH8oC2W2iUQp/YN2e1xtNCJ17r3YLEeEw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjX+bSACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrNmQ//fdjZERKSc0Su79If469IdcQw9PqlneTgazrbyS1ThLy1PvNA\r\nS/sjSDHkU5aZf3mlXzFkaMFrYXXU4/08PKXduHaTeLzVoEbneznFzIfeJiyi\r\nJh9jnWmy1X0lD2D0O9ezCMslCTDYdspbZ5/GAltk0inOQ0Vfk5PBYeom/the\r\nqZYd9q76U1E8dJccFj9ixfZirq/gKUXrgOzpxjqiMcVodukz2QFCSr4l1t6y\r\nkrDEkpfWareDW0wEoiegqwHPlQ3o+PaRIgvgEuDthbenACGdfsRCYqTp3f3Q\r\ntYbELng95x0670MyMV+IiBjjcJgJEpmEXr0QLXkPAb4k00KcpQb/mCjp9OSL\r\nRMy6nDTlkR2x1vVG8UQzAqdKvz7KMX/iNxiHQU0sBdjV7wb+bdLfOYbaQR5P\r\nbCScw8J/e/ceBuPQ2vQGghtMs3lAfWJQIVyhAVRZ4M3m1btSYu2oo2LqUwOt\r\nJoxs5kgXPhp8EOKmlk3zAkguTslIG8YWXQi14Dp9Hb+BU6X8OcTHiEBNf1/g\r\nISxDARDPObPTbYB/uefFfNij8NNgYem6D1YXXz0FL8ZwJWs7WGs2Y+0PWEUA\r\nhKoXXDEumYpHbESdtb6VzZveRekcw0hYvUcHDUyuqROAKJPpqEWkHldAYoPZ\r\nIza/Vf5mIP/2zimA/iKjGSnVBAQYF1Dy8+w=\r\n=I3vq\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.17_1667229394752_0.811167969480685"},"_hasShrinkwrap":false},"2.0.0-next.18":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.18","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-next.18","@miniplex/react":"2.0.0-next.18"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.18","_integrity":"sha512-Ha++z+w4hn/yc9FbNFCnenHyNqqemSwPQ6l3E0os0pEt+BjQysRDS4AFE6QUtaXkyrwhJ3oXMzb/+xQS4FCvSw==","_resolved":"/tmp/b5f67e94eafd4862da2d01b54e639702/miniplex-2.0.0-next.18.tgz","_from":"file:miniplex-2.0.0-next.18.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-Ha++z+w4hn/yc9FbNFCnenHyNqqemSwPQ6l3E0os0pEt+BjQysRDS4AFE6QUtaXkyrwhJ3oXMzb/+xQS4FCvSw==","shasum":"4df3e586b8ac16f8fcdfd7c7a0a0a6630d012f8d","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.18.tgz","fileCount":16,"unpackedSize":23003,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAzQNqqxtM6TxxCowIHWuE5XYmQyZB4MBwZuY0jmdMDCAiARH3fJ0Mx4zY8UlWUGtAE6nrhx2fcIoM+Bajqz3PZj+g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjYjHIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmolBQ//V1n0PY3+Mkd2q6YCFFqxEiiE0srnpqeYHcT6oKw8dKp9N6l1\r\n/4Z5EqsrmgcicIbj0VlFH9IktZo7JfQ+REwivV5W+xF2KaIk95Y4/sy4lbVv\r\nkIbphJRSVwq6ngaKx3BtK5qIo1wbmPBtscg9B9pszqBQ0ochM8X+uHhuXWnK\r\nme7ZGoB4ichNyE3Xae7jG8yUBa2OY3pbFdRuUlazNDXnTlmf5gJLRSNeYWq7\r\nYAA2QBPeWmWTcJED5bxsVr7oDiYQnolDZYoCSKoYzKYb5oC1ePxKfIx48nOT\r\n9uRSK0hKYwfqM/h+A3dFhznE01AhE33WBVcw/68sqksUrPhXXTGFexgF450M\r\nBRKuTkdQhDS3Ozh2qROOhXpj+Kc6P/DsOFLFBK9umicDdR/jhmwUD4HYeqKQ\r\nI8tyWih1lrlx1GGzT7JX4gEeOdOTs0nzVFQ+GcmXpZegy/r5n1iVjbGTG6Bm\r\nC2smjk39/6vE5vg5KNVsrWKmrcERdIyXkSJrBwcN2CBtq1KYR3KzXxxWrfPk\r\nRa2kfZ15YGNw02JoAGKDY46IwQZylyCtzX19cV9l1NLXNpDkB0xM/nYOito8\r\nQw0ECrRxORHGc2ePINS+LfX5ITIYdUX2RAlr5U8Dfaf3RL6cQKiX3eTpuM35\r\nJjH+MgSyJ3SedWTfuL8Ll+7gyYG6h70ToXQ=\r\n=XdZU\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.18_1667379656556_0.21776301317447166"},"_hasShrinkwrap":false},"2.0.0-next.19":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.19","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-next.19","@miniplex/react":"2.0.0-next.19"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Ecosystem\n\n- **[miniplex](https://github.com/hmans/miniplex/tree/main/packages/miniplex)**  \n  The core package. Use it in any JavaScript or TypeScript project.\n- **[miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react)**  \n  React bindings. Create, extend and render entities declaratively.\n\n## Introduction\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n## Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react).\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n## Main differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript setting.\n\nMiniplex does not expect you to programmatically declare component types before using them, but if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have a specific set of components. More complex querying capabilities may be added at a later date.\n\n### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). However, entities do automatically get a **built-in `id` component** with an auto-incrementing numerical ID once they're added to the world; this is mostly meant as a convenience for situations where you _need_ to provide a unique scalar reference (eg. as the `key` prop when rendering a list of entities as React components.)\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Integrations with frameworks like React are provided as separate packages, so here we will only talk about framework-less usage.\n\nSpecifically, if you intend to use Miniplex in a React project, please don't miss the [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react) documentation!\n\n### Creating a World\n\nMiniplex manages entities in worlds, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities.\n\nLet's create an entity. Note how we're immediately giving it a `position` component:\n\n```ts\nconst entity = world.createEntity({ position: { x: 0, y: 0, z: 0 } })\n```\n\n### Adding Components\n\nNow let's add a `velocity` component to the entity. Note that we're passing the entity itself, not just its identifier:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n> **Note** Once added to the world, entities also automatically receive an internal `__miniplex` component. This component contains data that helps Miniplex track the entity's lifecycle, and optimize a lot of interactions with the world, and you can safely ignore it.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n```\n\n### Implementing Systems\n\nNow we can implement our system, which is really just a function -- or any other piece of code -- that uses the archetype to fetch the associated entities and then iterates over them:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player):\n\n```ts\nworld.destroyEntity(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n### Queued Commands\n\nAll functions that modify the world (`createEntity`, `destroyEntity`, `addComponent` and `removeComponent`) also provide an alternative function that will not perform the action immediately, but instead put it into a queue:\n\n```ts\nworld.queue.destroyEntity(bullet)\n```\n\nOnce you're ready to execute the queued operations, you can flush the queue likes this:\n\n```ts\nworld.queue.flush()\n```\n\n**Note:** Please remember that the queue is not flushed automatically, and doing this is left to you. You might, for example, do this in your game's main loop, after all systems have finished executing.\n\n## Usage Hints\n\n### Do not add or remove entity properties directly\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\n### Be careful when deleting entities from within a system\n\nIf your system code will under some circumstances remove entities (without queueing the deletion), it is recommended to iterate over the entities in reverse order, like this:\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\nfunction healthSystem(world) {\n  /* Note how we're going through the list in reverse order: */\n  for (let i = withHealth.entities.length; i > 0; i--) {\n    const entity = withHealth.entities[i - 1]\n\n    /* If health is depleted, destroy the entity */\n    if (entity.health <= 0) {\n      world.destroyEntity(entity)\n    }\n  }\n}\n```\n\nThis is because the `destroyEntity` function will remove the entity from the archetype's entity list, and if you're iterating over the list in normal order, you will end up skipping the next entity in the list.\n\n### Consider using Component Factories\n\n`createEntity` and `addComponent` accept plain Javascript objects, opening the door to some nice patterns for making entities and components nicely composable. For example, you could create a set of functions acting as component factories, like this:\n\n```js\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0) => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0) => ({ velocity: { x, y } })\nconst health = (initial) => ({ health: { max: initial, current: initial } })\n\nconst world = new World()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n```\n\nMiniplex offers the `extendEntity` function to add multiple components to an entity in one go, and you can make use of your factory components here:\n\n```js\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\nIf you're using Typescript, you may even add some per-component types on top like in the following example:\n\n```ts\n/* Define component types */\ntype Vector2 = { x: number; y: number }\ntype PositionComponent = { position: Vector2 }\ntype VelocityComponent = { velocity: Vector2 }\ntype HealthComponent = { health: { max: number; current: number } }\n\n/* Define an entity type composed of required and optional components */\ntype Entity = PositionComponent & Partial<VelocityComponent, HealthComponent>\n\n/* Provide a bunch of component factories */\nconst position = (x = 0, y = 0): PositionComponent => ({ position: { x, y } })\nconst velocity = (x = 0, y = 0): VelocityComponent => ({ velocity: { x, y } })\nconst health = (initial: number): HealthComponent => ({\n  health: { max: initial, current: initial }\n})\n\nconst world = new World<Entity>()\n\n/* Use these in createEntity */\nconst entity = world.createEntity({\n  ...position(0, 0),\n  ...velocity(5, 7),\n  ...health(1000)\n})\n\n/* Use these in extendEntity */\nconst other = world.createEntity(position(0, 0))\n\nworld.extendEntity(other, {\n  ...velocity(-10, 0),\n  ...health(500)\n})\n```\n\n## Performance Hints\n\n### Prefer `for` over `forEach`\n\nYou might be tempted to use `forEach` in your system implementations, like this:\n\n```ts\nfunction movementSystem(world) {\n  movingEntities.entities.forEach(({ position, velocity }) => {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  })\n}\n```\n\nThis will incur a modest, but noticeable performance penalty, since you would be calling and returning from a function for every entity in the archetype. If performance is a concern, it is recommended to use either a `for/of` loop:\n\n```ts\nfunction movementSystem(world) {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nOr a classic `for` loop with numerical index access:\n\n```ts\nfunction movementSystem(world) {\n  const len = movingEntities.entities.length\n\n  for (let i = 0; i < len; i++) {\n    const { position, velocity } = movingEntities.entities[i]\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function aims to be idempotent and will reuse existing archetypes for the same queries passed to it, so you will never risk accidentally creating multiple indices of the same archetypes. It is, however, a comparatively heavyweight function, and you are advised to, wherever possible, reuse previously created archetypes.\n\nFor example, creating your archetypes within a system function like this will work, but unnecessarily create additional overhead, and is thus not recommended:\n\n```ts\nfunction movementSystem(world) {\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\nInstead, create the archetype outside of your system:\n\n```ts\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.19","_integrity":"sha512-0o3cvV1F5F2pHmibM7sfibaPKfryJY/PhqtHhkBE489cxmxZxtj9tbe79Y6sz5Cq634PSOWHp14bGKH2FLDi+A==","_resolved":"/tmp/6d20327f07d1bce8ea87497db61b9cdb/miniplex-2.0.0-next.19.tgz","_from":"file:miniplex-2.0.0-next.19.tgz","_nodeVersion":"16.17.1","_npmVersion":"8.15.0","dist":{"integrity":"sha512-0o3cvV1F5F2pHmibM7sfibaPKfryJY/PhqtHhkBE489cxmxZxtj9tbe79Y6sz5Cq634PSOWHp14bGKH2FLDi+A==","shasum":"f5475c41b0ffc097d88022b48b03470627843961","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.19.tgz","fileCount":16,"unpackedSize":23003,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDoq+YAbOjCHTc2cf+tqlvUbWv6wVuVAn/52h0SARslSgIgRT40ttTs5+4X5tL9rPy5M2wkWZmtiNkobYo2AWW4kKw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjYonrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmofFA//VHavNbVLi1h1oLMH7hijmNH9rSG/uVpa5hvaDvWssec91MHP\r\nKNMN4P9UQHnUa1MZDfAdjUTk1ltvKr7fsNltQC4QmAMl0PcNgdObtVKZBPSY\r\nVcrLOFbN5clVImPywg807vikiBmWay6mxOKBY9J8DV/gNUvETnj+pymimXDP\r\nQ16NvSPTtsv/Bhm11OQdRlnh90FhvXollOEZtgQpr2f66KNyLrXCIaPDAq5g\r\niB2xqs7iTF0K5hcsGclRx8QcSGngG65I2TsDNkRnVIMxKbykE7Mb86qiSZwN\r\n3DFLCPTMGPREk+sVY6cID0WBwQJUHlE7RFSby9Oo//73lMwoKLnSOC9NNO1c\r\nrm5bdRXrUNOGvCM5Wxn7EmrsvrefSZ8EFE9QJ4p1ADAS3XYRHUT2CjXLYorR\r\nxvfeM8dI1mZ2gQbx5GZtUdg+o18hC/8tMVm7Gx2H9mRlrKKBm32rYpO5cFdQ\r\nBibCt0kiG3Gl4CXYMkpsEp7oy+6xHXWJoQ+AVVq/kNRuXnVqcgG3957TPE3S\r\nYPNHeGri8H2erhHj6SyE364j7RmKNUKZyXtTLt3/gPIgu699lnchKrBnLteO\r\nSL+hhKn5BM8lUgLRCPD4nmJz+KocvT9nULGhYGBwlDHECz9QREuMtaYXpfSW\r\n40MXtd/+5rmmrhClIQdt5qR8GGCVMr+xKco=\r\n=6srZ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.19_1667402219415_0.9332033824125174"},"_hasShrinkwrap":false},"2.0.0-next.20":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-next.20","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-next.20","@miniplex/react":"2.0.0-next.20"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n> **Warning** You are looking at the work-in-progress documentation for the upcoming **version 2.0** of Miniplex and its companion libraries. If you're looking for 1.0 documentation, [please go here](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some archetype queries: */\nconst archetypes = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: archetypes.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poison\">) {\n  world.addComponent(entity, \"poison\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of archetypes.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of archetypes.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of archetypes.health.where(\n    ({ health }) => health.current <= 0\n  )) {\n    world.removeEntity(entity)\n  }\n}\n\n/* React to entities appearing/disappearing in archetypes: */\narchetypes.poisoned.onEntityAdded((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [@miniplex/react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\n> **Warning** Since this is the documentation for the upcoming 2.0 version of Miniplex, we will be using the `next` tag for installation. If you'd rather use the stable release of the library, [please refer to the 1.0 documentation](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex@next\nyarn add miniplex@next\npnpm add miniplex@next\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Before we talk about using Miniplex in React, let's start with the basics!\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant archetypes, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n>\n> Please read the \"Advanced Usage\" chapter below for some important notes on these!\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` archetype we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Nested Archetypes\n\nArchetypes are the main way to query entities in Miniplex. They are created by calling the `with` method on a world, and can be thought of as something akin to database indices.\n\nNext to `with`, there is also `without`, which creates an archetype that matches entities that do _not_ have any of the specified components.\n\n`with` and `without` can be nested:\n\n```ts\nconst movable = world.with(\"position\", \"velocity\")\nconst movableAndActive = movable.without(\"paused\")\nconst movableAndDead = movable.with(\"dead\")\n```\n\nIt is very important to understand that this will create _three_ archetypes; one that matches entities that have both `position` and `velocity`, another that matches entities from the first archetype that also do not have the `paused` component, and a third that matches entities from the first archetype that also have the `dead` component.\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    B-->D[\"with('dead')\"];\n```\n\nEvery time an entity is added to the world or has a component added or removed, all relevant archetypes are updated and asked to re-evaluate the changed entity. This update trickles down to all archetypes, and stops with archetypes that reject the entity.\n\nIn larger projects, the structure of your archetype waterfall can have a significant impact on performance; in some cases, it can be beneficial to create a large number of small, nested archetypes, while in other cases it can be beneficial to create fewer, larger archetypes.\n\n### Combining `with` and `without` queries\n\nYou can create a combined query that looks for both the presence as well as the absence of specific components through the `archetype` function:\n\n```ts\nconst movableAndActive = world.archetype({\n  with: [\"position\", \"velocity\"],\n  without: [\"paused\"]\n})\n```\n\nThis will create a single archetype wrapping the two queries, matching entities that have both `position` and `velocity` components, but do not have the `paused` component.\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over archetypes using `for...of`\n\nThe world as well as all archetypes derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in an archetype, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function and its shorthand friends (`with`, `without`) aim to be idempotent and will reuse existing archetypes for the same queries passed to them. Checking if an archetype already exists for the given query is a comparatively heavyweight function, thought, and you are advised to, wherever possible, reuse previously created archetypes.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if an archetype for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Create nested archetypes with caution\n\nMiniplex does not optimize queries automatically, so the following code will create more archetypes than you probably need:\n\n```ts\nconst a = world.with(\"position\", \"velocity\").without(\"paused\")\nconst b = world.without(\"paused\").with(\"position\", \"velocity\")\n```\n\nNow `a` and `b` contain exactly the same entities, but they are in fact two completely separate branches of the archetype tree:\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    A-->D[\"without('paused')\"];\n    D-->E[\"with('position', 'velocity')\"];\n```\n\nEverything will still work fine, but now the system is unnecessarily doing work twice.\n\n> **Note** A future version of Miniplex will likely include a way to optimize cases like this automatically, but for now, you should be careful when creating nested archetypes.\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-next.20","_integrity":"sha512-Cf42smGxt2ORoIplvTotMgksfRThtyMeIXXBxtswACj2r6hBKv0xjzpvyz1qgcKUdzxOUpm3Yw3cNhxpUiLp6A==","_resolved":"/tmp/4120e8b89ef511b84de071c8d4399b85/miniplex-2.0.0-next.20.tgz","_from":"file:miniplex-2.0.0-next.20.tgz","_nodeVersion":"16.18.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Cf42smGxt2ORoIplvTotMgksfRThtyMeIXXBxtswACj2r6hBKv0xjzpvyz1qgcKUdzxOUpm3Yw3cNhxpUiLp6A==","shasum":"376c380423841c2ca601ef8e8faf44f679f15f51","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-next.20.tgz","fileCount":16,"unpackedSize":25501,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICkLBUIZuDXkL1vzdAYEiXIkPNXWT1b4uAgkDp6fdpBhAiA9pQEYNpnKxA0Vk1xjn4VtzHHHyl7ytcgM2knZujlotQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjaOmxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrw0g//SSALlmE1HA13M8sndO9QDuw7dzsM+AE3/B02U8M2CEYgM24X\r\nfAvthCPyc9U1QQ9BG+XtyKV5KBgTVFD2ed85Evv6YmyR8EgWb9mYxmbr7VoM\r\nZuPr3kPlbd3tJxI6JmBBDCJU10JDum8B3Qsy3oii0BmMZaVhbJzQSxpsLQ1i\r\nU9rpIsRwmJP77qdA4Et3om3PeFK+ADdB+s6kAK9c8bOov6hLcM2aXGMyGVLj\r\nQXFa7Cp263lfww1pZUPQuGaOD+KOSgM7SW7+/DMIpphWQONERjxL68LA0+CU\r\nQAGKNYZNjXZRoVl+4RSPDMSKC+/W1wV605IjmuOtf2i7ASNA2WjZdCxf0vDi\r\nQ/w07aV7ZyNrCBSZfXWGM+oF+twSZR1NRwLkctipRffl1XF9+fK37xFEKiEg\r\nwVYhefSjNOXbOB7LIC61u+f8yKNaq41txMCMzKMP4KDHd5o83HDBaP2FXy4G\r\nYI3M0g/70Rs7Tcnq8loeERuDJJ4FPwOXxggwxZJAyguy47nhp9kjF1fvhe+i\r\n9GLsr7g+SFXPtFy14lX7ZVjbNTAa9074wT9kPNbgpLppSq+JzjvTTZz81fwJ\r\n+yfpj45IAeFDLbBSEr0HvFTO8diYJN+tvUYru3kH8QI16RaU0hVQEjmpWvzI\r\n2QaaIwMH/13BCL/8irhmZHn3NHDlaORCea8=\r\n=LWr4\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-next.20_1667819953236_0.0499231377620688"},"_hasShrinkwrap":false},"2.0.0-beta.1":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.1","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-beta.1","@miniplex/react":"2.0.0-beta.1"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n> **Warning** You are looking at the work-in-progress documentation for the upcoming **version 2.0** of Miniplex and its companion libraries. If you're looking for 1.0 documentation, [please go here](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some archetype queries: */\nconst archetypes = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: archetypes.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poison\">) {\n  world.addComponent(entity, \"poison\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of archetypes.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of archetypes.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of archetypes.health.where(\n    ({ health }) => health.current <= 0\n  )) {\n    world.removeEntity(entity)\n  }\n}\n\n/* React to entities appearing/disappearing in archetypes: */\narchetypes.poisoned.onEntityAdded((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [@miniplex/react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\n> **Warning** Since this is the documentation for the upcoming 2.0 version of Miniplex, we will be using the `next` tag for installation. If you'd rather use the stable release of the library, [please refer to the 1.0 documentation](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex@next\nyarn add miniplex@next\npnpm add miniplex@next\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Before we talk about using Miniplex in React, let's start with the basics!\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant archetypes, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n>\n> Please read the \"Advanced Usage\" chapter below for some important notes on these!\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` archetype we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Nested Archetypes\n\nArchetypes are the main way to query entities in Miniplex. They are created by calling the `with` method on a world, and can be thought of as something akin to database indices.\n\nNext to `with`, there is also `without`, which creates an archetype that matches entities that do _not_ have any of the specified components.\n\n`with` and `without` can be nested:\n\n```ts\nconst movable = world.with(\"position\", \"velocity\")\nconst movableAndActive = movable.without(\"paused\")\nconst movableAndDead = movable.with(\"dead\")\n```\n\nIt is very important to understand that this will create _three_ archetypes; one that matches entities that have both `position` and `velocity`, another that matches entities from the first archetype that also do not have the `paused` component, and a third that matches entities from the first archetype that also have the `dead` component.\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    B-->D[\"with('dead')\"];\n```\n\nEvery time an entity is added to the world or has a component added or removed, all relevant archetypes are updated and asked to re-evaluate the changed entity. This update trickles down to all archetypes, and stops with archetypes that reject the entity.\n\nIn larger projects, the structure of your archetype waterfall can have a significant impact on performance; in some cases, it can be beneficial to create a large number of small, nested archetypes, while in other cases it can be beneficial to create fewer, larger archetypes.\n\n### Combining `with` and `without` queries\n\nYou can create a combined query that looks for both the presence as well as the absence of specific components through the `archetype` function:\n\n```ts\nconst movableAndActive = world.archetype({\n  with: [\"position\", \"velocity\"],\n  without: [\"paused\"]\n})\n```\n\nThis will create a single archetype wrapping the two queries, matching entities that have both `position` and `velocity` components, but do not have the `paused` component.\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over archetypes using `for...of`\n\nThe world as well as all archetypes derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in an archetype, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function and its shorthand friends (`with`, `without`) aim to be idempotent and will reuse existing archetypes for the same queries passed to them. Checking if an archetype already exists for the given query is a comparatively heavyweight function, thought, and you are advised to, wherever possible, reuse previously created archetypes.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if an archetype for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Create nested archetypes with caution\n\nMiniplex does not optimize queries automatically, so the following code will create more archetypes than you probably need:\n\n```ts\nconst a = world.with(\"position\", \"velocity\").without(\"paused\")\nconst b = world.without(\"paused\").with(\"position\", \"velocity\")\n```\n\nNow `a` and `b` contain exactly the same entities, but they are in fact two completely separate branches of the archetype tree:\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    A-->D[\"without('paused')\"];\n    D-->E[\"with('position', 'velocity')\"];\n```\n\nEverything will still work fine, but now the system is unnecessarily doing work twice.\n\n> **Note** A future version of Miniplex will likely include a way to optimize cases like this automatically, but for now, you should be careful when creating nested archetypes.\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.1","_integrity":"sha512-hLmW4Q6l8xQM3xhIGY+YeW1LBGMdD9di2KHUYv9xsFe4s2ZTR7QB/sT/qWkl35WS9jJrtLEE6JsyLmfvJ3K5DQ==","_resolved":"/tmp/e8555ef7b0d1b40dd9d48b7e62873a89/miniplex-2.0.0-beta.1.tgz","_from":"file:miniplex-2.0.0-beta.1.tgz","_nodeVersion":"16.18.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-hLmW4Q6l8xQM3xhIGY+YeW1LBGMdD9di2KHUYv9xsFe4s2ZTR7QB/sT/qWkl35WS9jJrtLEE6JsyLmfvJ3K5DQ==","shasum":"180d950c5c7e530fe0b1b520be28054d32400fe9","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.1.tgz","fileCount":16,"unpackedSize":25498,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDp4pRnS7qa82m3IHQILRWpq/sstRA6Lx21jLXflFQY2gIhAPSFFb12W0sUwPHEeVPAaZ8yLily5I6N5a7aeHJVGsJx"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjakMrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrY3A/+MMz5LBHbkHRKtbDdXGm4RhSImfCX+riyNjM8Rf/WPt6YYcyL\r\nnY2tdcmE4/y/qhNsBXtVimt6eHhXaDc87B2PQnT2eX0t4DiOzCuX2sT2Wp4g\r\nIz7er3GFu/wheMwyCf5WNgx8MQXatVHxV1A+4C5Qx00jrln7hjW6BAHlzwk7\r\nlYkGh9gNEtCSaUFWIJ0lmfnsh2pJrZernDz8e7iua/wx9Ht3//+kd4pspjIw\r\namnu6nF3wllas5uDg82ggmR4xLEsKKoGRGqT8NVxtj/6F0TnGp0Zg2KJ+x90\r\nVgQMlWcGtJJysbZHAKdxEn63gRArO1+fBbwFwDnduVHAFg7Xa4RQagerGg58\r\nSKYfE4qqRrOfZEVFpzI4NDM5975eiOR5gy8rw6JN7LnloPVUkBq/EI02jn2B\r\nXnd9eJARB2Sth7TTVBH2JNVeLPX+V36Juk8yPlna05ydtoRDz1y+MljrcyaW\r\nMnNwUU6D+3R4wJel5uPUF3lOp6UDEOAYIN1mJ4M0CAC3+HQBLzBVIIcx9o9S\r\nWizHVI2dHQXcaiNNBKOAmqOIvvz+wjtIzIoYDO3hDsdxqU+viw5+Xkfiu1vQ\r\ni+AQqzRtyzsLh6cU7DzSgqCvuM0U5QnB9rrDxuarBwaOG8vPkqjEmXpiTFzS\r\nS486JGQpYXA+mwl5gCu8/8Uz48Ojjiw5/YA=\r\n=CtkM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.1_1667908394928_0.6626184818663194"},"_hasShrinkwrap":false},"2.0.0-beta.2":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.2","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-beta.2","@miniplex/react":"2.0.0-beta.1"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n> **Warning** You are looking at the work-in-progress documentation for the upcoming **version 2.0** of Miniplex and its companion libraries. If you're looking for 1.0 documentation, [please go here](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n## Miniplex 2.0 Beta 1 now available!\n\n⚠️ **The first beta of this library's upcoming 2.0 release is out. Please check the [announcement post](https://github.com/hmans/miniplex/discussions/258) for details, including upgrade instructions.**\n\n## Testimonials\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**. - [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752)\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some archetype queries: */\nconst archetypes = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: archetypes.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poison\">) {\n  world.addComponent(entity, \"poison\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of archetypes.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of archetypes.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of archetypes.health.where(\n    ({ health }) => health.current <= 0\n  )) {\n    world.removeEntity(entity)\n  }\n}\n\n/* React to entities appearing/disappearing in archetypes: */\narchetypes.poisoned.onEntityAdded((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [@miniplex/react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\n> **Warning** Since this is the documentation for the upcoming 2.0 version of Miniplex, we will be using the `next` tag for installation. If you'd rather use the stable release of the library, [please refer to the 1.0 documentation](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex@next\nyarn add miniplex@next\npnpm add miniplex@next\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Before we talk about using Miniplex in React, let's start with the basics!\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant archetypes, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n>\n> Please read the \"Advanced Usage\" chapter below for some important notes on these!\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` archetype we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Nested Archetypes\n\nArchetypes are the main way to query entities in Miniplex. They are created by calling the `with` method on a world, and can be thought of as something akin to database indices.\n\nNext to `with`, there is also `without`, which creates an archetype that matches entities that do _not_ have any of the specified components.\n\n`with` and `without` can be nested:\n\n```ts\nconst movable = world.with(\"position\", \"velocity\")\nconst movableAndActive = movable.without(\"paused\")\nconst movableAndDead = movable.with(\"dead\")\n```\n\nIt is very important to understand that this will create _three_ archetypes; one that matches entities that have both `position` and `velocity`, another that matches entities from the first archetype that also do not have the `paused` component, and a third that matches entities from the first archetype that also have the `dead` component.\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    B-->D[\"with('dead')\"];\n```\n\nEvery time an entity is added to the world or has a component added or removed, all relevant archetypes are updated and asked to re-evaluate the changed entity. This update trickles down to all archetypes, and stops with archetypes that reject the entity.\n\nIn larger projects, the structure of your archetype waterfall can have a significant impact on performance; in some cases, it can be beneficial to create a large number of small, nested archetypes, while in other cases it can be beneficial to create fewer, larger archetypes.\n\n### Combining `with` and `without` queries\n\nYou can create a combined query that looks for both the presence as well as the absence of specific components through the `archetype` function:\n\n```ts\nconst movableAndActive = world.archetype({\n  with: [\"position\", \"velocity\"],\n  without: [\"paused\"]\n})\n```\n\nThis will create a single archetype wrapping the two queries, matching entities that have both `position` and `velocity` components, but do not have the `paused` component.\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over archetypes using `for...of`\n\nThe world as well as all archetypes derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in an archetype, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function and its shorthand friends (`with`, `without`) aim to be idempotent and will reuse existing archetypes for the same queries passed to them. Checking if an archetype already exists for the given query is a comparatively heavyweight function, thought, and you are advised to, wherever possible, reuse previously created archetypes.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if an archetype for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Create nested archetypes with caution\n\nMiniplex does not optimize queries automatically, so the following code will create more archetypes than you probably need:\n\n```ts\nconst a = world.with(\"position\", \"velocity\").without(\"paused\")\nconst b = world.without(\"paused\").with(\"position\", \"velocity\")\n```\n\nNow `a` and `b` contain exactly the same entities, but they are in fact two completely separate branches of the archetype tree:\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    A-->D[\"without('paused')\"];\n    D-->E[\"with('position', 'velocity')\"];\n```\n\nEverything will still work fine, but now the system is unnecessarily doing work twice.\n\n> **Note** A future version of Miniplex will likely include a way to optimize cases like this automatically, but for now, you should be careful when creating nested archetypes.\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.2","_integrity":"sha512-ZvW8mgbhFaoohqA14A/r87rk7QrTrJgEgHAgh4MLr0l924IZdf2rRFcM8kAfi2KsCsx5IYzhtlUnYpW7kYrfEg==","_resolved":"/tmp/5592e0dcc3c90918b7fccaa1d842c430/miniplex-2.0.0-beta.2.tgz","_from":"file:miniplex-2.0.0-beta.2.tgz","_nodeVersion":"16.18.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-ZvW8mgbhFaoohqA14A/r87rk7QrTrJgEgHAgh4MLr0l924IZdf2rRFcM8kAfi2KsCsx5IYzhtlUnYpW7kYrfEg==","shasum":"d890a1806592f587b312283f459fcbde27dd05aa","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.2.tgz","fileCount":16,"unpackedSize":25743,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFjnH+l9XTnguHTKjN6aGG6/dOTz3vqtHG74GJlHORpwAiEA9pp9PxzANUbZc2iMW8HVcyZcUpVNO6469jihul2OZYk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjcfaNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpekg/8CRsRvVGNHmotlyVqGbL2/wSJsVjKENBUweK9fN9WCrXC6UXu\r\nLldvcfJLTafeD3CwazFuGysHxYZWcsJZy1IrdHjyXqDMKTBFEYXm8KoHrSUT\r\nlDHc05exxs7dnEGqQ+Oa7PRC+kUw3Jv1hdR6Kvn8LFjr4P2Jle1vMzp/Fy7j\r\nHp6FWmWw8XmZYupWrvY3soHmzojOfUgcsqmLATWdRIzrakscSVvKNKmFkIFi\r\nIYV9yOs8H1J4x+7zMtLRw+GkQshuYAb6IJCYl+htDnrfr60eBN4XtqdC5JaI\r\nIjCqor0CbcOi+7UjK/q+EfkWIIV1NmxakpeR4gpJulu8+mBw8gZPa3kPi8o2\r\nvG84eUIMYrSgutarK1ZcpILV1dVaWHMRYTmzo0ke9x/ZOdu0q7ldzsojhiEe\r\ncH1Bwdo92GeSejtsUuDtOYSRl9plLdLRu/7KuE0H2FPxNyOta6vctETsWKWY\r\nVxJM70Cgg9nemGAxqu0hq6yf4KvsFW9OGbsG6Nz7ks6qwCwnpSlWdtXZlHqm\r\nIiitwsC3h9evojzpUehZe9rIflCf0o+kE47I+IcvorMgZsLChOz7JMB5/+hP\r\nj5Gl9IPIl5fQb5C6r2l3E6vvDmkOaX0AGBIb+8HLPUMWC8qNbHROHkc56Lj7\r\nZHJ/zfQuyYpBlnrKsOlmvMKVFrHGd8sAT8c=\r\n=Udnu\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.2_1668413069305_0.5863894148945894"},"_hasShrinkwrap":false},"2.0.0-beta.3":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.3","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-beta.3","@miniplex/react":"2.0.0-beta.3"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n> **Warning** You are looking at the work-in-progress documentation for the upcoming **version 2.0** of Miniplex and its companion libraries. If you're looking for 1.0 documentation, [please go here](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\n## Miniplex 2.0 Beta 1 now available!\n\n⚠️ **The first beta of this library's upcoming 2.0 release is out. Please check the [announcement post](https://github.com/hmans/miniplex/discussions/258) for details, including upgrade instructions.**\n\n## Testimonials\n\nFrom [Jonathan Verrecchia](https://twitter.com/verekia):\n\n> **Miniplex has been the backbone of my games for the past 6 months and it has been a delightful experience.** The TypeScript support and React integration are excellent, and the API is very clear and easy to use, even as a first ECS experience.\n\nFrom [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752):\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**.\n\nFrom [VERYBOMB](https://twitter.com/verybomb):\n\n> Rewrote my game with Miniplex and my **productivity has improved immeasurably** ever since. Everything about it is so intuitive and elegant.\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some archetype queries: */\nconst archetypes = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: archetypes.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poison\">) {\n  world.addComponent(entity, \"poison\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of archetypes.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of archetypes.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of archetypes.health.where(\n    ({ health }) => health.current <= 0\n  )) {\n    world.removeEntity(entity)\n  }\n}\n\n/* React to entities appearing/disappearing in archetypes: */\narchetypes.poisoned.onEntityAdded((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [@miniplex/react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypes**, with individual archetypes representing a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities or archetypes (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\n> **Warning** Since this is the documentation for the upcoming 2.0 version of Miniplex, we will be using the `next` tag for installation. If you'd rather use the stable release of the library, [please refer to the 1.0 documentation](https://github.com/hmans/miniplex/tree/miniplex%401.0.0).\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex@next\nyarn add miniplex@next\npnpm add miniplex@next\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. Before we talk about using Miniplex in React, let's start with the basics!\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant archetypes, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **archetypes** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create an archetype for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n>\n> Please read the \"Advanced Usage\" chapter below for some important notes on these!\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` archetype we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all associated archetypes.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Nested Archetypes\n\nArchetypes are the main way to query entities in Miniplex. They are created by calling the `with` method on a world, and can be thought of as something akin to database indices.\n\nNext to `with`, there is also `without`, which creates an archetype that matches entities that do _not_ have any of the specified components.\n\n`with` and `without` can be nested:\n\n```ts\nconst movable = world.with(\"position\", \"velocity\")\nconst movableAndActive = movable.without(\"paused\")\nconst movableAndDead = movable.with(\"dead\")\n```\n\nIt is very important to understand that this will create _three_ archetypes; one that matches entities that have both `position` and `velocity`, another that matches entities from the first archetype that also do not have the `paused` component, and a third that matches entities from the first archetype that also have the `dead` component.\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    B-->D[\"with('dead')\"];\n```\n\nEvery time an entity is added to the world or has a component added or removed, all relevant archetypes are updated and asked to re-evaluate the changed entity. This update trickles down to all archetypes, and stops with archetypes that reject the entity.\n\nIn larger projects, the structure of your archetype waterfall can have a significant impact on performance; in some cases, it can be beneficial to create a large number of small, nested archetypes, while in other cases it can be beneficial to create fewer, larger archetypes.\n\n### Combining `with` and `without` queries\n\nYou can create a combined query that looks for both the presence as well as the absence of specific components through the `archetype` function:\n\n```ts\nconst movableAndActive = world.archetype({\n  with: [\"position\", \"velocity\"],\n  without: [\"paused\"]\n})\n```\n\nThis will create a single archetype wrapping the two queries, matching entities that have both `position` and `velocity` components, but do not have the `paused` component.\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct archetypes. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over archetypes using `for...of`\n\nThe world as well as all archetypes derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in an archetype, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.archetype(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse archetypes where possible\n\nThe `archetype` function and its shorthand friends (`with`, `without`) aim to be idempotent and will reuse existing archetypes for the same queries passed to them. Checking if an archetype already exists for the given query is a comparatively heavyweight function, thought, and you are advised to, wherever possible, reuse previously created archetypes.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.archetype(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if an archetype for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  const movingEntities = world.archetype(\"position\", \"velocity\")\n\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n### Create nested archetypes with caution\n\nMiniplex does not optimize queries automatically, so the following code will create more archetypes than you probably need:\n\n```ts\nconst a = world.with(\"position\", \"velocity\").without(\"paused\")\nconst b = world.without(\"paused\").with(\"position\", \"velocity\")\n```\n\nNow `a` and `b` contain exactly the same entities, but they are in fact two completely separate branches of the archetype tree:\n\n```mermaid\ngraph TD;\n    A[world]-->B[\"with('position', 'velocity')\"];\n    B-->C[\"without('paused')\"];\n    A-->D[\"without('paused')\"];\n    D-->E[\"with('position', 'velocity')\"];\n```\n\nEverything will still work fine, but now the system is unnecessarily doing work twice.\n\n> **Note** A future version of Miniplex will likely include a way to optimize cases like this automatically, but for now, you should be careful when creating nested archetypes.\n\n## Questions?\n\nFind me on [Twitter](https://twitter.com/hmans) or the [Poimandres Discord](https://discord.gg/aAYjm2p7c7).\n\n## License\n\n```\nCopyright (c) 2022 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.3","_integrity":"sha512-mGtuJgyC8G/SSzaZZs1XwaKViFk1z5r211nsiitg1OC7S/+BZ/kG8fsDKmt6Fl2Z4/zpRiScWNcl+1hasbAOVw==","_resolved":"/tmp/7f983694fde384780b50ea91506fd95a/miniplex-2.0.0-beta.3.tgz","_from":"file:miniplex-2.0.0-beta.3.tgz","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-mGtuJgyC8G/SSzaZZs1XwaKViFk1z5r211nsiitg1OC7S/+BZ/kG8fsDKmt6Fl2Z4/zpRiScWNcl+1hasbAOVw==","shasum":"5234ac1199e1ade4846de4c247f943f775956dd2","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.3.tgz","fileCount":16,"unpackedSize":26246,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHuclkrjIRUvlbsNaAsePe1BoLXr4q9XOyLcP91maIU7AiEAg3l/51miVCwvGGvDZ0k2GGPItdjMiLKAmjUcWgV22+0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjh0CQACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqlVg/+JpRWM9In9C2zG29msMrSo41EV3xxa/4fR4BdHV63dZok158Y\r\nWoWzyKZOueJtZ1JHmjTBUvH62bvQOb7FwPMD1SLcDRkZL66OzV5lh0AH7OD8\r\n0nUjtRlhN7zjZHEdrnAnUcocZ5h9o4VUDuXRqldrEsOGIbDpnhA8KnmSryJd\r\ndYeXhbfzpq1PnhjORVYmwOYXvIDIT/DbmT6OWUTv/7SA39iR8dwwYkyx4TSY\r\nOdH05Q/guuPp914jueSUzvpsNXCOGalCA0QqDxcBD5Hsq4c+gh6POd6i4dXh\r\niWYPEHl+P9n+b9rQJii5IdIP7ShS1UNEn8bvdQ6sMxsezzFFpPy9Ya6R46qc\r\nv8aLPVPhuplAKyq9xRzN6upbDyXe0zfBdCJUuRZRt8cn3+zOZXqY5Dsv+OF8\r\nADWFqFpAPZqmf0btAmzuSA0Cv4aK2C+2NuQcP6dWfEnmVehox7jRn+sFVpst\r\nCPhz4eoSCxkzERM2bs8OSesg8tYI1G/FCS4gTlN7yuZcJ0zlA45QbG7FeEUu\r\nPEB2BAhWATxUv7HKWZuDfFBgVGUClxXbIRtIGItt2l0cRQ41spKLbMXWB+Ju\r\nFlViZnw4/F0UrPbE8zTPO+/jgRLZHkC/HY2E3RiuztvaGYE51KjdB/l44hvr\r\nTLtapMhHqiOpJrhDmiuKk8YypTLmu5fxyTk=\r\n=YChm\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.3_1669808272706_0.5025408355395993"},"_hasShrinkwrap":false},"2.0.0-beta.4":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.4","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","preconstruct":{"entrypoints":["index.ts","react.ts"]},"license":"MIT","devDependencies":{"react":"^18.2.0","react-dom":"^18.2.0"},"dependencies":{"@hmans/queue":"^0.0.1","@miniplex/core":"2.0.0-beta.4","@miniplex/react":"2.0.0-beta.4"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\nFrom [verekia](https://twitter.com/verekia):\n\n> **Miniplex has been the backbone of my games for the past year and it has been a delightful experience.** The TypeScript support and React integration are excellent, and the API is very clear and easy to use, even as a first ECS experience.\n\nFrom [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752):\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**.\n\nFrom [VERYBOMB](https://twitter.com/verybomb):\n\n> Rewrote my game with Miniplex and my **productivity has improved immeasurably** ever since. Everything about it is so intuitive and elegant.\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Usage with React](#usage-with-react)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some queries: */\nconst queries = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: queries.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poisoned\">) {\n  world.addComponent(entity, \"poisoned\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of queries.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of queries.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of queries.health) {\n    if (entity.health.current <= 0) {\n      world.remove(entity)\n    }\n  }\n}\n\n/* React to entities appearing/disappearing in queries: */\nqueries.poisoned.onEntityAdded.subscribe((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [@miniplex/react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypal queries**, with individual queries indexing and holding a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex\nyarn add miniplex\npnpm add miniplex\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. This document focuses on how to use Miniplex without a framework, but please also check out the framework-specific documentation available:\n\n- [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/miniplex-react#readme)\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant queries, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **queries** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create a query for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` query we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all existing queries.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Reacting to added/removed entities\n\n**TODO**\n\n### Predicate Queries using `where`\n\n**TODO**\n\n### Queueing\n\n**TODO**\n\n### ID Generation\n\n**TODO**\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct queries. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over queries using `for...of`\n\nThe world as well as all queries derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in a query, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.with(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse queries where possible\n\nThe functions creating and returning queries (`with`, `without`, `where`) aim to be idempotent and will reuse existing queries for the same set of query attributes. Checking if a query for a specific set of query attributes already exists is a comparatively heavyweight function, though, and you are advised to, wherever possible, reuse previously created queries.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.with(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if a query for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  for (const { position, velocity } of world.with(\"position\", \"velocity\")) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nIf you have questions about Miniplex, you're invited to post it in our [Discussions section](https://github.com/hmans/miniplex/discussions) on GitHub.\n\n## License\n\n```\nCopyright (c) 2023 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.4","_integrity":"sha512-+aYqCdB1Gbr9KPP1wPcfuwsJMl7DwA03VE0vW0r1vnCwJxsjXmO0BrZUhdsKW7w2sBY3wfxXs2r160AAC9uLGQ==","_resolved":"/tmp/9c2c36e013b8ddeaed06e26a477b5a58/miniplex-2.0.0-beta.4.tgz","_from":"file:miniplex-2.0.0-beta.4.tgz","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-+aYqCdB1Gbr9KPP1wPcfuwsJMl7DwA03VE0vW0r1vnCwJxsjXmO0BrZUhdsKW7w2sBY3wfxXs2r160AAC9uLGQ==","shasum":"f136a7e749a44a4945e93bc182ef86f97bf1181e","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.4.tgz","fileCount":29,"unpackedSize":31990,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGcZsRVv+obHpgOCkJZmgaNvQs3v1BmuAk8vn8XWGanHAiEAlJkjjslRnmnfMUDQm32xX9s8f/f+pMXBGTVHshuRJBA="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.4_1688926292211_0.5369236520092102"},"_hasShrinkwrap":false},"2.0.0-beta.5":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.5","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","devDependencies":{"@types/node":"^20.4.1","chalk":"^5.3.0","react":"^18.2.0","react-dom":"^18.2.0","tsx":"^3.12.7"},"dependencies":{"@hmans/id":"^0.0.1","@hmans/queue":"^0.0.1","@miniplex/bucket":"2.0.0-beta.4"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"scripts":{"benchmark":"tsx benchmark.ts","build":"preconstruct build"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n[![Tests](https://img.shields.io/github/workflow/status/hmans/miniplex/Tests?label=CI&style=for-the-badge)](https://github.com/hmans/miniplex/actions/workflows/tests.yml)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\nFrom [verekia](https://twitter.com/verekia):\n\n> **Miniplex has been the backbone of my games for the past year and it has been a delightful experience.** The TypeScript support and React integration are excellent, and the API is very clear and easy to use, even as a first ECS experience.\n\nFrom [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752):\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**.\n\nFrom [VERYBOMB](https://twitter.com/verybomb):\n\n> Rewrote my game with Miniplex and my **productivity has improved immeasurably** ever since. Everything about it is so intuitive and elegant.\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Usage with React](#usage-with-react)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some queries: */\nconst queries = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: queries.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poisoned\">) {\n  world.addComponent(entity, \"poisoned\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of queries.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of queries.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of queries.health) {\n    if (entity.health.current <= 0) {\n      world.remove(entity)\n    }\n  }\n}\n\n/* React to entities appearing/disappearing in queries: */\nqueries.poisoned.onEntityAdded.subscribe((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypal queries**, with individual queries indexing and holding a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex\nyarn add miniplex\npnpm add miniplex\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. This document focuses on how to use Miniplex without a framework, but please also check out the framework-specific documentation available:\n\n- [miniplex-react](https://github.com/hmans/miniplex/tree/main/packages/react#readme)\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant queries, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **queries** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create a query for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` query we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all existing queries.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Reacting to added/removed entities\n\n**TODO**\n\n### Predicate Queries using `where`\n\n**TODO**\n\n### Queueing\n\n**TODO**\n\n### ID Generation\n\n**TODO**\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct queries. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over queries using `for...of`\n\nThe world as well as all queries derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in a query, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.with(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse queries where possible\n\nThe functions creating and returning queries (`with`, `without`, `where`) aim to be idempotent and will reuse existing queries for the same set of query attributes. Checking if a query for a specific set of query attributes already exists is a comparatively heavyweight function, though, and you are advised to, wherever possible, reuse previously created queries.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.with(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if a query for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  for (const { position, velocity } of world.with(\"position\", \"velocity\")) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nIf you have questions about Miniplex, you're invited to post it in our [Discussions section](https://github.com/hmans/miniplex/discussions) on GitHub.\n\n## License\n\n```\nCopyright (c) 2023 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.5","_integrity":"sha512-//1CUj9sXR9jkDii4rsnUlqQ9eOygz6dmTzJew9JlsJxZv6CwEkMZ68CpFECRRbcnUaTXfhG4o0kl5zpO0wqMg==","_resolved":"/tmp/70dee25b02c230fc30f22188fe550c43/miniplex-2.0.0-beta.5.tgz","_from":"file:miniplex-2.0.0-beta.5.tgz","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-//1CUj9sXR9jkDii4rsnUlqQ9eOygz6dmTzJew9JlsJxZv6CwEkMZ68CpFECRRbcnUaTXfhG4o0kl5zpO0wqMg==","shasum":"2f2b3f3af55b337c25bc75448f2b144375cc1f1e","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.5.tgz","fileCount":12,"unpackedSize":87616,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5Pp1kEK7IgSCUtDEy+P1fo24xsvKyMIvMW1UUBPOw6AiBXgLWKLTF0/bRoTLzbFh7SfpVavTkcSQ/dGkkeMjzvAQ=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.5_1689004279004_0.5928492618709864"},"_hasShrinkwrap":false},"2.0.0-beta.6":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0-beta.6","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","devDependencies":{"@types/node":"^20.4.2","chalk":"^5.3.0","react":"^18.2.0","react-dom":"^18.2.0","tsx":"^3.12.7"},"dependencies":{"@hmans/id":"^0.0.1","@hmans/queue":"^0.0.1","@miniplex/bucket":"2.0.0-beta.4"},"peerDependencies":{"react":">=16.8"},"peerDependenciesMeta":{"react":{"optional":true}},"scripts":{"benchmark":"tsx benchmark.ts","build":"preconstruct build"},"readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/hmans/miniplex/tests.yml?style=for-the-badge)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n## Testimonials\n\nFrom [verekia](https://twitter.com/verekia):\n\n> **Miniplex has been the backbone of my games for the past year and it has been a delightful experience.** The TypeScript support and React integration are excellent, and the API is very clear and easy to use, even as a first ECS experience.\n\nFrom [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752):\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**.\n\nFrom [VERYBOMB](https://twitter.com/verybomb):\n\n> Rewrote my game with Miniplex and my **productivity has improved immeasurably** ever since. Everything about it is so intuitive and elegant.\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some queries: */\nconst queries = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: queries.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poisoned\">) {\n  world.addComponent(entity, \"poisoned\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of queries.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of queries.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of queries.health) {\n    if (entity.health.current <= 0) {\n      world.remove(entity)\n    }\n  }\n}\n\n/* React to entities appearing/disappearing in queries: */\nqueries.poisoned.onEntityAdded.subscribe((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities of specific types.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you -- and rightfully so, for Miniplex is, first and foremost, a very straight-forward ECS implementation!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive -- but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. [This post](https://community.amethyst.rs/t/archetypal-vs-grouped-ecs-architectures-my-take/1344) has a nice summary:\n\n> An ECS library can essentially thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Headline Features\n\n- A very strong focus on **developer experience**. Miniplex aims to be the most convenient to use ECS implementation while still providing great performance.\n- **[Tiny package size](https://bundlephobia.com/package/miniplex)** and **minimal dependencies**.\n- React glue available through [miniplex-react](https://www.npmjs.com/package/miniplex-react), maybe more in the future?\n- Can power your entire project or just parts of it.\n- Written in **TypeScript**, with full type checking for your entities.\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety.\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, and instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypal queries**, with individual queries indexing and holding a subset of your world's entities that have (or don't have) a specific set of components, and/or match a specific predicate.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities (instead of numerical IDs). Miniplex provides a lightweight mechanism to generate unique IDs for your entities, but it is entirely optional. In more complex projects that need stable entity IDs, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex\nyarn add miniplex\npnpm add miniplex\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. This document focuses on how to use Miniplex without a framework, but please also check out the framework-specific documentation available:\n\n- [miniplex-react](https://github.com/hmans/miniplex/blob/main/packages/react/README.md)\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate concerns.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant queries, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_!\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nWe're going to write some code that moves entities according to their velocity. You will typically implement this as something called a **system**, which, in Miniplex, are typically just normal functions that fetch the entities they are interested in, and then perform some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **queries** that can be thought of as something akin to database indices.\n\nSince we're going to move entities, we're interested in entities that have both the `position` and `velocity` components, so let's create a query for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` query we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all existing queries.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\n### Reacting to added/removed entities\n\nInstances of `World` and `Query` provide the built-in `onEntityAdded` and `onEntityRemoved` events that you can subscribe to to be notified about entities appearing or disappearing.\n\nFor example, in order to be notified about any entity being added to the world, you may do this:\n\n```ts\nworld.onEntityAdded.subscribe((entity) => {\n  console.log(\"A new entity has been spawned:\", entity)\n})\n```\n\nThis is useful for running system-specific initialization code on entities that appear in specific queries:\n\n```ts\nconst withHealth = world.with(\"health\")\n\nwithHealth.onEntityAdded.subscribe((entity) => {\n  entity.health.current = entity.health.max\n})\n```\n\n### Predicate Queries using `where`\n\nTypically, you'll want to build queries the check entities for the _presence_ of specific components; you have been using the `with` and `without` functions for this so far. But there may be the rare case where you want to query by _value_; for this, Miniplex provides the `where` function. It allows you to specify a predicate function that your entity will be checked against:\n\n```ts\nconst damagedEntities = world\n  .with(\"health\")\n  .where(({ health }) => health.current < health.max)\n\nconst deadEntities = world.with(\"health\").where(({ health }) => health <= 0)\n```\n\nIt is _extremely_ important to note that queries that use `where` are in no way reactive; if the values within the entity change in a way that would change the result of your predicate function, Miniplex will _not_ pick this up automatically.\n\nInstead, once you know that you are using `where` to inspect component _values_, you are required to signal an updated entity by calling the `reindex` function:\n\n```ts\nfunction damageEntity(entity: With<Entity, \"health\">, amount: number) {\n  entity.health.current -= amount\n  world.reindex(entity)\n}\n```\n\nDepending on the total number of queries you've created, reindexing can be a relatively expensive operation, so it is recommended that you use this functionality with care. Most of the time, it is more efficient to model things using additional components. The above example could, for example, be rewritten like this:\n\n```ts\nconst damagedEntities = world.with(\"health\", \"damaged\")\n\nconst deadEntities = world.with(\"health\", \"dead\")\n\nfunction damageEntity(entity: With<Entity, \"health\">, amount: number) {\n  entity.health.current -= amount\n\n  if (entity.health.current < entity.health.max) {\n    world.addComponent(entity, \"damaged\")\n  }\n\n  if (entity.health.current <= 0) {\n    world.addComponent(entity, \"dead\")\n  }\n}\n```\n\n### ID Generation\n\nWhen interacting with Miniplex, entities are typically identified using their _object identities_, which is one of the ways where Miniplex is different from typical ECS implementations, which usually make use of numerical IDs.\n\nMost Miniplex workloads can be implemented without the use of numerical IDs, but if you ever _do_ need such an identifier for your entities &ndash; possibly because you're wiring them up to another non-Miniplex system that expects them &ndash; Miniplex worlds provide a lightweight mechanism to generate them:\n\n```ts\nconst entity = world.add({ count: 10 })\nconst id = world.id(entity)\n```\n\nYou can later use this ID to look up the entity in the world:\n\n```ts\nconst entity = world.entity(id)\n```\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct queries. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over queries using `for...of`\n\nThe world as well as all queries derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in a query, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.with(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse queries where possible\n\nThe functions creating and returning queries (`with`, `without`, `where`) aim to be idempotent and will reuse existing queries for the same set of query attributes. Checking if a query for a specific set of query attributes already exists is a comparatively heavyweight function, though, and you are advised to, wherever possible, reuse previously created queries.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.with(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if a query for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  for (const { position, velocity } of world.with(\"position\", \"velocity\")) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nIf you have questions about Miniplex, you're invited to post them in our [Discussions section](https://github.com/hmans/miniplex/discussions) on GitHub.\n\n## License\n\n```\nCopyright (c) 2023 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md","_id":"miniplex@2.0.0-beta.6","_integrity":"sha512-HvahdXzrUgXsX516WonAyhTSYYmTY1QmkW2+NaugmdxH67xWp9b5JBWWk9dYJYecIW+OfZVuGrQtwxikk0+usA==","_resolved":"/tmp/9720fe607e6e2c03e2fe822ef61a43a7/miniplex-2.0.0-beta.6.tgz","_from":"file:miniplex-2.0.0-beta.6.tgz","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-HvahdXzrUgXsX516WonAyhTSYYmTY1QmkW2+NaugmdxH67xWp9b5JBWWk9dYJYecIW+OfZVuGrQtwxikk0+usA==","shasum":"325bf83f611d6f78bf465bcf49628e724c3883b9","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0-beta.6.tgz","fileCount":12,"unpackedSize":90744,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICWM/Gvm6SuE/+zNEZy1BgAutNBuhBWc1ZrnMr2oTW+HAiA605Zn1j/GCe3HmSjdV8WKBCJNIKd+Vl8FSgcWf/iMQg=="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0-beta.6_1689424984367_0.9783012735877084"},"_hasShrinkwrap":false},"2.0.0":{"name":"miniplex","author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"sideEffects":false,"version":"2.0.0","main":"dist/miniplex.cjs.js","module":"dist/miniplex.esm.js","types":"dist/miniplex.cjs.d.ts","license":"MIT","devDependencies":{"chalk":"^5.3.0","tsx":"^3.12.7"},"dependencies":{"@hmans/id":"^0.0.1","@hmans/queue":"^0.0.1","@miniplex/bucket":"2.0.0"},"scripts":{"benchmark":"tsx benchmark.ts","build":"preconstruct build"},"_id":"miniplex@2.0.0","_integrity":"sha512-pJlxmlPf5Qyx12amgOCyRE6Lzw28ct2G0lF9xn7/xudLtA/xDOUnCIU2xOxCk8GkjePYctcNpjmFshJp/Ht66A==","_resolved":"/tmp/ea2ef178b9f933133dba98fec7a65858/miniplex-2.0.0.tgz","_from":"file:miniplex-2.0.0.tgz","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-pJlxmlPf5Qyx12amgOCyRE6Lzw28ct2G0lF9xn7/xudLtA/xDOUnCIU2xOxCk8GkjePYctcNpjmFshJp/Ht66A==","shasum":"5d0be39b78a838bf35702d7e5de26c4df87f70bf","tarball":"https://registry.npmjs.org/miniplex/-/miniplex-2.0.0.tgz","fileCount":11,"unpackedSize":107893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCQH0hUbvOGNRk+y9z6V3hNCqhejLK59CHeukW1hAkbngIgAIJBCrFh9dmh9/mQZtwYYqndsz5t9O8/1Aoh1VkERmE="}]},"_npmUser":{"name":"hendrik.mans","email":"hendrik@mans.de"},"directories":{},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/miniplex_2.0.0_1689506792741_0.31883151379504415"},"_hasShrinkwrap":false}},"time":{"created":"2022-02-12T07:40:11.243Z","0.3.0":"2022-02-12T07:40:11.401Z","modified":"2023-07-16T11:26:33.188Z","0.3.1":"2022-02-12T13:20:07.563Z","0.3.2":"2022-02-12T14:45:42.239Z","0.3.3":"2022-02-12T15:34:38.583Z","0.3.4":"2022-02-12T15:38:44.535Z","0.3.5":"2022-02-12T18:50:45.483Z","0.3.6":"2022-02-13T12:44:13.016Z","0.3.7":"2022-02-13T14:20:37.318Z","0.3.8":"2022-02-13T16:25:48.082Z","0.3.9":"2022-02-14T18:32:45.389Z","0.3.11":"2022-02-15T04:46:30.265Z","0.4.0":"2022-02-16T15:46:24.935Z","0.5.0":"2022-02-17T13:16:52.368Z","0.5.1":"2022-02-18T15:29:15.765Z","0.5.2":"2022-02-18T17:47:10.525Z","0.5.3":"2022-02-19T16:27:55.906Z","0.5.4":"2022-02-20T13:31:38.780Z","0.5.5":"2022-02-21T18:06:29.785Z","0.5.6":"2022-02-21T18:15:14.647Z","0.5.7":"2022-02-21T18:26:38.741Z","0.5.8":"2022-02-21T18:35:25.247Z","0.6.0":"2022-03-09T18:53:32.434Z","0.6.1":"2022-03-10T16:37:37.063Z","0.6.2":"2022-03-11T12:26:26.550Z","0.6.3":"2022-03-11T15:45:54.917Z","0.7.0":"2022-03-14T15:55:17.857Z","0.7.1":"2022-03-14T16:55:56.639Z","0.7.2":"2022-03-23T19:01:16.649Z","0.8.0-0":"2022-03-25T12:24:05.268Z","0.8.0-1":"2022-03-25T18:31:57.741Z","0.8.0-2":"2022-03-27T15:13:57.460Z","0.8.0-4":"2022-03-31T14:22:38.986Z","0.8.0":"2022-03-31T14:24:15.661Z","0.8.1":"2022-03-31T14:45:43.302Z","0.9.0":"2022-04-01T13:57:44.143Z","0.9.1":"2022-04-20T19:24:44.218Z","0.9.2":"2022-04-23T19:40:48.992Z","0.10.0":"2022-04-29T15:06:40.599Z","0.10.1":"2022-05-06T18:54:24.777Z","0.10.2":"2022-07-02T19:22:36.213Z","0.10.3":"2022-08-02T14:48:21.312Z","0.10.4":"2022-08-13T09:48:50.866Z","0.10.5":"2022-08-13T10:00:26.790Z","0.0.0-canary-20220924150908":"2022-09-24T15:09:20.766Z","0.0.0-canary-20220925113205":"2022-09-25T11:32:13.663Z","0.0.0-canary-20220925113423":"2022-09-25T11:34:59.906Z","0.11.0-next.0":"2022-09-25T12:25:39.978Z","1.0.0-next.1":"2022-09-26T07:17:54.875Z","0.0.0-canary-20220926080217":"2022-09-26T08:02:26.266Z","1.0.0-next.5":"2022-09-29T09:20:40.506Z","1.0.0-next.6":"2022-09-29T11:04:30.792Z","0.0.0-canary-20220930161643":"2022-09-30T16:17:00.486Z","0.0.0-canary-20220930161815":"2022-09-30T16:18:23.184Z","0.0.0-canary-20220930162615":"2022-09-30T16:26:22.017Z","0.0.0-canary-20221003160633":"2022-10-03T16:06:47.691Z","0.0.0-canary-20221003172623":"2022-10-03T17:26:33.749Z","0.0.0-canary-20221003185021":"2022-10-03T18:50:33.211Z","0.0.0-canary-20221004084019":"2022-10-04T08:40:27.516Z","1.0.0":"2022-10-04T08:42:51.419Z","2.0.0-next.0":"2022-10-13T09:47:11.104Z","2.0.0-next.1":"2022-10-13T10:26:10.535Z","2.0.0-next.3":"2022-10-14T08:45:02.818Z","2.0.0-next.4":"2022-10-14T10:24:01.653Z","2.0.0-next.5":"2022-10-15T09:02:48.848Z","2.0.0-next.6":"2022-10-15T10:43:42.305Z","2.0.0-next.7":"2022-10-15T11:06:42.073Z","2.0.0-next.8":"2022-10-17T14:37:13.037Z","2.0.0-next.9":"2022-10-17T17:01:52.215Z","2.0.0-next.10":"2022-10-19T08:53:07.132Z","0.0.0-canary-20221019154835":"2022-10-19T15:49:00.721Z","2.0.0-next.11":"2022-10-27T06:45:47.594Z","0.0.0-canary-20221029092412":"2022-10-29T09:24:32.702Z","2.0.0-next.12":"2022-10-30T14:29:05.279Z","2.0.0-next.13":"2022-10-30T14:35:12.027Z","2.0.0-next.14":"2022-10-30T15:59:14.614Z","2.0.0-next.15":"2022-10-31T10:49:33.938Z","2.0.0-next.16":"2022-10-31T13:26:54.040Z","2.0.0-next.17":"2022-10-31T15:16:34.866Z","2.0.0-next.18":"2022-11-02T09:00:56.710Z","2.0.0-next.19":"2022-11-02T15:16:59.598Z","2.0.0-next.20":"2022-11-07T11:19:13.429Z","2.0.0-beta.1":"2022-11-08T11:53:15.264Z","2.0.0-beta.2":"2022-11-14T08:04:29.432Z","2.0.0-beta.3":"2022-11-30T11:37:52.878Z","2.0.0-beta.4":"2023-07-09T18:11:32.389Z","2.0.0-beta.5":"2023-07-10T15:51:19.212Z","2.0.0-beta.6":"2023-07-15T12:43:04.562Z","2.0.0":"2023-07-16T11:26:33.024Z"},"maintainers":[{"name":"hendrik.mans","email":"hendrik@mans.de"}],"description":"A developer-friendly entity management system for games and similarly demanding applications, based on ECS architecture.","homepage":"https://github.com/hmans/miniplex","keywords":["gamedev","ecs","entity-component-system","state","state-management"],"author":{"name":"Hendrik Mans","email":"hendrik@mans.de","url":"https://hendrik.mans.de"},"license":"MIT","readme":"![Miniplex](https://user-images.githubusercontent.com/1061/193760498-fb6b4d42-f48b-48b4-b7c1-b5b5674df55c.jpg)  \n[![Version](https://img.shields.io/npm/v/miniplex-react?style=for-the-badge)](https://www.npmjs.com/package/miniplex-react)\n![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/hmans/miniplex/tests.yml?style=for-the-badge)\n[![Downloads](https://img.shields.io/npm/dt/miniplex.svg?style=for-the-badge)](https://www.npmjs.com/package/miniplex)\n[![Bundle Size](https://img.shields.io/bundlephobia/min/miniplex?style=for-the-badge&label=bundle%20size)](https://bundlephobia.com/result?p=miniplex)\n\n# Miniplex - the gentle game entity manager.\n\n- 🚀 Manages your game entities using the Entity Component System pattern.\n- 🍳 Focuses on ease of use and developer experience.\n- 💪 Can power your entire project, or just parts of it.\n- 🧩 Written in TypeScript, for TypeScript. (But works in plain JavaScript, too!)\n- ⚛️ [React bindings available](https://www.npmjs.com/package/miniplex-react). They're great! (But Miniplex works in any environment.)\n- 📦 Tiny package size and minimal dependencies.\n\n## Testimonials\n\nFrom [verekia](https://twitter.com/verekia):\n\n> **Miniplex has been the backbone of my games for the past year and it has been a delightful experience.** The TypeScript support and React integration are excellent, and the API is very clear and easy to use, even as a first ECS experience.\n\nFrom [Brian Breiholz](https://twitter.com/BrianBreiholz/status/1577182839509962752):\n\n> Tested @hmans' Miniplex library over the weekend and after having previously implemented an ECS for my wip browser game, I have to say **Miniplex feels like the \"right\" way to do ECS in #r3f**.\n\nFrom [VERYBOMB](https://twitter.com/verybomb):\n\n> Rewrote my game with Miniplex and my **productivity has improved immeasurably** ever since. Everything about it is so intuitive and elegant.\n\n## Table of Contents\n\n- [Example](#example)\n- [Overview](#overview)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Usage](#advanced-usage)\n- [Best Practices](#best-practices)\n\n## Example\n\n```ts\n/* Define an entity type */\ntype Entity = {\n  position: { x: number; y: number }\n  velocity?: { x: number; y: number }\n  health?: {\n    current: number\n    max: number\n  }\n  poisoned?: true\n}\n\n/* Create a world with entities of that type */\nconst world = new World<Entity>()\n\n/* Create an entity */\nconst player = world.add({\n  position: { x: 0, y: 0 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create another entity */\nconst enemy = world.add({\n  position: { x: 10, y: 10 },\n  velocity: { x: 0, y: 0 },\n  health: { current: 100, max: 100 }\n})\n\n/* Create some queries: */\nconst queries = {\n  moving: world.with(\"position\", \"velocity\"),\n  health: world.with(\"health\"),\n  poisoned: queries.health.with(\"poisoned\")\n}\n\n/* Create functions that perform actions on entities: */\nfunction damage({ health }: With<Entity, \"health\">, amount: number) {\n  health.current -= amount\n}\n\nfunction points(entity: With<Entity, \"poisoned\">) {\n  world.addComponent(entity, \"poisoned\", true)\n}\n\n/* Create a bunch of systems: */\nfunction moveSystem() {\n  for (const { position, velocity } of queries.moving) {\n    position.x += velocity.x\n    position.y += velocity.y\n  }\n}\n\nfunction poisonSystem() {\n  for (const { health, poisoned } of queries.poisoned) {\n    health.current -= 1\n  }\n}\n\nfunction healthSystem() {\n  for (const entity of queries.health) {\n    if (entity.health.current <= 0) {\n      world.remove(entity)\n    }\n  }\n}\n\n/* React to entities appearing/disappearing in queries: */\nqueries.poisoned.onEntityAdded.subscribe((entity) => {\n  console.log(\"Poisoned:\", entity)\n})\n```\n\n## Overview\n\n**Miniplex is an entity management system for games and similarly demanding applications.** Instead of creating separate buckets for different types of entities (eg. asteroids, enemies, pickups, the player, etc.), you throw all of them into a single store, describe their properties through components, and then write code that performs updates on entities that have specific component configurations.\n\nIf you're familiar with **Entity Component System** architecture, this will sound familiar to you &ndash; and rightfully so, for Miniplex is, first and foremost, a very straight-forward implementation of this pattern!\n\nIf you're hearing about this approach for the first time, maybe it will sound a little counter-intuitive &ndash; but once you dive into it, you will understand how it can help you decouple concerns and keep your codebase well-structured and maintainable. A nice forum post that I can't link to because it's gone offline had a nice explanation:\n\n> An ECS library can essentially be thought of as an API for performing a loop over a homogeneous set of entities, filtering them by some condition, and pulling out a subset of the data associated with each entity. The goal of the library is to provide a usable API for this, and to do it as fast as possible.\n\nFor a more in-depth explanation, please also see Sander Mertens' wonderful [Entity Component System FAQ](https://github.com/SanderMertens/ecs-faq).\n\n### Differences from other ECS libraries\n\nIf you've used other Entity Component System libraries before, here's how Miniplex is different from some of them:\n\n#### Entities are just normal JavaScript objects\n\nEntities are just **plain JavaScript objects**, and components are just **properties on those objects**. Component data can be **anything** you need, from primitive values to entire class instances, or even [entire reactive stores](https://github.com/hmans/statery). Miniplex puts developer experience first, and the most important way it does this is by making its usage feel as natural as possible in a JavaScript environment.\n\nMiniplex does not expect you to programmatically declare component types before using them; if you're using TypeScript, you can provide a type describing your entities and Miniplex will provide full edit- and compile-time type hints and safety. (Hint: you can even write some classes and use their instances as entities!)\n\n#### Miniplex does not have a built-in notion of systems\n\nUnlike the majority of ECS libraries, Miniplex does not have any built-in notion of systems, and does not perform any of its own scheduling. This is by design; your project will likely already have an opinion on how to schedule code execution, informed by whatever framework you are using; instead of providing its own and potentially conflicting setup, Miniplex will neatly snuggle into the one you already have.\n\nSystems are extremely straight-forward: just write simple functions that operate on the Miniplex world, and run them in whatever fashion fits best to your project (`setInterval`, `requestAnimationFrame`, `useFrame`, your custom ticker implementation, and so on.)\n\n#### Archetypal Queries\n\nEntity queries are performed through **archetypal queries**, with individual queries indexing and holding a subset of your world's entities that have (or don't have) a specific set of components.\n\n#### Focus on Object Identities over numerical IDs\n\nMost interactions with Miniplex are using **object identity** to identify entities (instead of numerical IDs). Miniplex provides an optional lightweight mechanism to generate unique IDs for your entities if you need them. In more complex projects that need stable entity IDs, especially when synchronizing entities across the network, the user is encouraged to implement their own ID generation and management.\n\n## Installation\n\nAdd the `miniplex` package to your project using your favorite package manager:\n\n```bash\nnpm add miniplex\nyarn add miniplex\npnpm add miniplex\n```\n\n## Basic Usage\n\nMiniplex can be used in any JavaScript or TypeScript project, regardless of which extra frameworks you might be using. This document focuses on how to use Miniplex without a framework, but please also check out the framework-specific documentation available:\n\n- [miniplex-react](https://github.com/hmans/miniplex/blob/main/packages/react/README.md)\n\n### Creating a World\n\nMiniplex manages entities in **worlds**, which act as containers for entities as well as an API for interacting with them. You can have one big world in your project, or several smaller worlds handling separate sections of your game.\n\n```ts\nimport { World } from \"miniplex\"\n\nconst world = new World()\n```\n\n### Typing your Entities (optional, but recommended!)\n\nIf you're using TypeScript, you can define a type that describes your entities and provide it to the `World` constructor to get full type support in all interactions with it:\n\n```ts\nimport { World } from \"miniplex\"\n\ntype Entity = {\n  position: { x: number; y: number; z: number }\n  velocity?: { x: number; y: number; z: number }\n  health?: number\n  paused?: true\n}\n\nconst world = new World<Entity>()\n```\n\n### Creating Entities\n\nThe main interactions with a Miniplex world are creating and destroying entities, and adding or removing components from these entities. Entities are just plain JavaScript objects that you pass into the world's `add` and `remove` functions, like here:\n\n```ts\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\n```\n\nWe've directly added a `position` component to the entity. If you're using TypeScript, the component values here will be type-checked against the type you provided to the `World` constructor.\n\n> **Note** Adding the entity will make it known to the world and all relevant queries, but it will not change the entity object itself in any way. In Miniplex, entities can _live in multiple worlds at the same time_! This allows you to split complex simulations into entirely separate worlds, each with their own queries, even though they might share some (or all) entities.\n\n### Adding Components\n\nThe `World` instance provides `addComponent` and `removeComponent` functions for adding and removing components from entities. Let's add a `velocity` component to the entity. Note that we're passing the entity itself as the first argument:\n\n```ts\nworld.addComponent(entity, \"velocity\", { x: 10, y: 0, z: 0 })\n```\n\nNow the entity has two components: `position` and `velocity`.\n\n### Querying Entities\n\nLet's write some code that moves entities, which have a `position`, according to their `velocity`. You will typically implement this as something called a **system**, which, in Miniplex, is typically just a normal function that fetches the entities it is interested in, and then performs some operation on them.\n\nFetching only the entities that a system is interested in is the most important part in all this, and it is done through something called **queries** that can be thought of as something similar to database indices.\n\nSince we're going to _move_ entities, we're interested in entities that have both the `position` and `velocity` components, so let's create a query for that:\n\n```ts\n/* Get all entities with position and velocity */\nconst movingEntities = world.with(\"position\", \"velocity\")\n```\n\n> **Note** There is also `without`, which will return all entities that do _not_ have the specified components:\n>\n> ```ts\n> const active = world.without(\"paused\")\n> ```\n>\n> Queries can also be nested:\n>\n> ```ts\n> const movingEntities = world.with(\"position\", \"velocity\").without(\"paused\")\n> ```\n\n### Implementing Systems\n\nNow we can implement a system that operates on these entities! Miniplex doesn't have an opinion on how you implement systems – they can be as simple as a function. Here's a system that uses the `movingEntities` query we created in the previous step, iterates over all entities in it, and moves them according to their velocity:\n\n```ts\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n**Note:** Since entities are just plain JavaScript objects, they can easily be destructured into their components, like we're doing above.\n\nNow all we need to do is make sure that this system is run on a regular basis. If you're writing a game, the framework you are using will already have a mechanism that allows you to execute code once per frame; just call the `movementSystem` function from there!\n\n### Destroying Entities\n\nAt some point we may want to remove an entity from the world (for example, an enemy spaceship that got destroyed by the player). We can do this through the world's `remove` function:\n\n```ts\nworld.remove(entity)\n```\n\nThis will immediately remove the entity from the Miniplex world and all existing queries.\n\n> **Note** While this will remove the entity object from the world, it will not destroy or otherwise change the object itself. In fact, you can just add it right back into the world if you want to!\n\n## Advanced Usage\n\nWe're about to dive into some advanced usage patterns. Please make sure you're familiar with the basics before continuing.\n\n### Reacting to added/removed entities\n\nInstances of `World` and `Query` provide the built-in `onEntityAdded` and `onEntityRemoved` events that you can subscribe to to be notified about entities appearing or disappearing.\n\nFor example, in order to be notified about any entity being added to the world, you may do this:\n\n```ts\nworld.onEntityAdded.subscribe((entity) => {\n  console.log(\"A new entity has been spawned:\", entity)\n})\n```\n\nThis is useful for running system-specific initialization code on entities that appear in specific queries:\n\n```ts\nconst withHealth = world.with(\"health\")\n\nwithHealth.onEntityAdded.subscribe((entity) => {\n  entity.health.current = entity.health.max\n})\n```\n\n### Predicate Queries using `where`\n\nTypically, you'll want to build queries the check entities for the _presence_ of specific components; you have been using the `with` and `without` functions for this so far. But there may be the rare case where you want to query by _value_; for this, Miniplex provides the `where` function. It allows you to specify a predicate function that your entity will be checked against:\n\n```ts\nconst damagedEntities = world\n  .with(\"health\")\n  .where(({ health }) => health.current < health.max)\n\nconst deadEntities = world.with(\"health\").where(({ health }) => health <= 0)\n```\n\nIt is _extremely_ important to note that queries that use `where` are in no way reactive; if the values within the entity change in a way that would change the result of your predicate function, Miniplex will _not_ pick this up automatically.\n\nInstead, once you know that you are using `where` to inspect component _values_, you are required to signal an updated entity by calling the `reindex` function:\n\n```ts\nfunction damageEntity(entity: With<Entity, \"health\">, amount: number) {\n  entity.health.current -= amount\n  world.reindex(entity)\n}\n```\n\nDepending on the total number of queries you've created, reindexing can be a relatively expensive operation, so it is recommended that you use this functionality with care. Most of the time, it is more efficient to model things using additional components. The above example could, for example, be rewritten like this:\n\n```ts\nconst damagedEntities = world.with(\"health\", \"damaged\")\n\nconst deadEntities = world.with(\"health\", \"dead\")\n\nfunction damageEntity(entity: With<Entity, \"health\">, amount: number) {\n  entity.health.current -= amount\n\n  if (entity.health.current < entity.health.max) {\n    world.addComponent(entity, \"damaged\")\n  }\n\n  if (entity.health.current <= 0) {\n    world.addComponent(entity, \"dead\")\n  }\n}\n```\n\n### ID Generation\n\nWhen interacting with Miniplex, entities are typically identified using their _object identities_, which is one of the ways where Miniplex is different from typical ECS implementations, which usually make use of numerical IDs.\n\nMost Miniplex workloads can be implemented without the use of numerical IDs, but if you ever _do_ need such an identifier for your entities &ndash; possibly because you're wiring them up to another non-Miniplex system that expects them &ndash; Miniplex worlds provide a lightweight mechanism to generate them:\n\n```ts\nconst entity = world.add({ count: 10 })\nconst id = world.id(entity)\n```\n\nYou can later use this ID to look up the entity in the world:\n\n```ts\nconst entity = world.entity(id)\n```\n\n## Best Practices\n\n### Use `addComponent` and `removeComponent` for adding and removing components\n\nSince entities are just normal objects, you might be tempted to just add new properties to (or delete properties from) them directly. **This is a bad idea** because it will skip the indexing step needed to make sure the entity is listed in the correct queries. Please always go through `addComponent` and `removeComponent`!\n\nIt is perfectly fine to mutate component _values_ directly, though.\n\n```ts\n/* ✅ This is fine: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.position.x = 10\n\n/* ⛔️ This is not: */\nconst entity = world.add({ position: { x: 0, y: 0, z: 0 } })\nentity.velocity = { x: 10, y: 0, z: 0 }\n```\n\n### Iterate over queries using `for...of`\n\nThe world as well as all queries derived from it are _iterable_, meaning you can use them in `for...of` loops. This is the recommended way to iterate over entities in a query, as it is highly performant, and iterates over the entities _in reverse order_, which allows you to safely remove entities from within the loop.\n\n```ts\nconst withHealth = world.with(\"health\")\n\n/* ✅ Recommended: */\nfor (const entity of withHealth) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Avoid: */\nfor (const entity of withHealth.entities) {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n}\n\n/* ⛔️ Especially avoid: */\nwithHealth.entities.forEach((entity) => {\n  if (entity.health <= 0) {\n    world.remove(entity)\n  }\n})\n```\n\n### Reuse queries where possible\n\nThe functions creating and returning queries (`with`, `without`, `where`) aim to be idempotent and will reuse existing queries for the same set of query attributes. Checking if a query for a specific set of query attributes already exists is a comparatively heavyweight function, though, and you are advised to, wherever possible, reuse previously created queries.\n\n```ts\n/* ✅ Recommended: */\nconst movingEntities = world.with(\"position\", \"velocity\")\n\nfunction movementSystem() {\n  for (const { position, velocity } of movingEntities) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n\n/* ⛔️ Avoid: */\nfunction movementSystem(world) {\n  /* This will work, but now the world needs to check if a query for \"position\" and \"velocity\" already exists every time this function is called, which is pure overhead. */\n  for (const { position, velocity } of world.with(\"position\", \"velocity\")) {\n    position.x += velocity.x\n    position.y += velocity.y\n    position.z += velocity.z\n  }\n}\n```\n\n## Questions?\n\nIf you have questions about Miniplex, you're invited to post them in our [Discussions section](https://github.com/hmans/miniplex/discussions) on GitHub.\n\n## License\n\n```\nCopyright (c) 2023 Hendrik Mans\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n```\n","readmeFilename":"README.md"}