{"_id":"racehorse","_rev":"30-66b3cb8f5d642f42927909e9602d26eb","name":"racehorse","dist-tags":{"latest":"1.11.0","next":"1.10.2-next.de44275"},"versions":{"0.0.1":{"name":"racehorse","version":"0.0.1","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.1","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"6f8a31bfb49008ac68ef82a6bd5b6bad8bc6c028","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.1.tgz","fileCount":5,"integrity":"sha512-OC3juM0ojPb5RL+f2SdqV6rVQr1LxvzmIKwRDkXmDN7YmAAsBj4SIjgoN6N0Roxx+OK8Mp/apzYuIumUWubX3w==","signatures":[{"sig":"MEUCIQCGGFgOLoxWWf3nE/NLNXCEgYSSEx5NjRv5CrJDyWdKGwIgMcIJ0Aebm3JSFoG0oMsrgSWNLm/Db3E4Y8Edsu6v5GA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":51012,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj4+RNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpwnA/+NZMXXEmM5O+kMQIphGux6yDfjTYpE4A9E+jXBG1aE9jNxtc9\r\nxYNN9GHvQjruIl2oi6D4x3rWW2Wl9kSforF2hT5BggftWHbBENfXtSU9Zvvc\r\nKa4gDD8iBI1z2N7RQgbdtwZiS4yP1Geu3CXqLhZImybBtHPynsN/7C47PAgy\r\n8NfAhlAO2qD5vrCtJy00Q6jC6RnzUGGxvHE0ijre1XolRRUdGz9ofveY7mCH\r\nT+WzUJPHoOx7UIWpQSA8Y3MjAPcfTFrR7q5uuRoqodo5LIO0zfO8ZJoHLPwf\r\nWWeqs+F/qBPE5CM8rdaRpb6PWeiqLFRYu1iNVc7HUq+qgRLFf0ejHJGQ+5CR\r\np19khbRUMCPdGAJxT6B+1HR6P9MWczlcjY86n1y8uOMdXJbI7jo4repiZvos\r\n0IUZu8CfOVZ5Rtw4kiWz+YAGqX48YidJMxwbzUDR2vrcw1ZUG+0PiFb27hT2\r\nbw5ZMIQcLCKhDmk16VK6fdpyFPhOtxTcA6TUO5jVJrW93akjFVM2KKstRU/t\r\nAoAemvPqIUsPRJnDzY4xwwKimjpJkbGUt6cCbB7vDlRiHLsS/tBj8Pwvo1pK\r\nPIEc5U3hVcdec6FNKb9XQ7INu6ktcPGUH11DDqrQZwdYUhFTXTCOJa4Phgb0\r\nJoy5jBTESr9d+juqpZ2oNnP3GtLdhXiXFmA=\r\n=Nams\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"b914c5d66c4a50151efa7d4a602e78eba7bc4809","scripts":{"test":"jest","build":"rollup --config --configPlugin typescript","clean":"rimraf lib"},"typedoc":{"entryPoint":"./src/main/index.ts","displayName":"Racehorse"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"8.5.1","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"16.14.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.1_1675879501454_0.19300017599738162","host":"s3://npm-registry-packages"}},"0.0.2":{"name":"racehorse","version":"0.0.2","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.2","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"e52898620de69fb58d43c382573665230d022c98","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.2.tgz","fileCount":5,"integrity":"sha512-EHqQyyDWFZcx27qKLSj8nWvLmrLYPy3znzDm/IxnW3uWJUv4RsPyN64EjilcjhQ7UI7hUzkVclCOaAlmvlHTPQ==","signatures":[{"sig":"MEYCIQD0kGVfhmTM1Gt94Ak5kaKZfsshdaVGhfhHkb3qI5raGQIhANGgFT95CtId/96swyxDqbhy9EquWgzWEDGDJYgdXB/8","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":27186,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGPENACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr/ww/8DCiLQzmgZ5vYMR3rGrhm3Z0YiudREsKbnDVSEodzj2xV3kE5\r\n10S72jhmqsH4dASe8IA9UP2EbGWFqw3MQFSC9Gb7Ol/bFZQ7JHOtBxW8huzc\r\nj22BDUwk1N15BE72ZgN0IOJz5x1XZeVUCxgHvba33Ow0LYLxqx0ukRM8t7D+\r\nncFjxHhzZ31BmBeUUGJvZOkfRk1IWsECgaahrqP1XSUeQ2uiEaF5EI80wGYu\r\nFp2ASoHC0G8RwiC/4XJChILFHnBcaP+xENPKbovigUWTsU7Raidt6y4GYFPv\r\nbl2WD35N5TwDkEgelSDCfmn/MPDUOvuRrpmmC8i6ddOtnAigsihelF+0Hbn8\r\nZMx8T5oHWK0QY+3aLAUb73kH5daEwgu533yPY/Ad4AhoeMFqdvoGCOqe9PwU\r\n3huo5/ua8y41k14yV3oxnWYe7ZQktI0t5Fjydt+B0m5kUUezvcjqU3SV4Bwn\r\n4TqhXQqdlwAZOU9i88d1dSG+I/s5SBHBQAclN4aceM+8hnzgn++3B/6iX7Y+\r\nJ/T69j2nbExW6ks9M6ZY34uvM/UlVNBskG57OYdpfSQ/yT1kleGvnnBsK5Ma\r\nKFMz4Ti8mx+JfF3nTdxtOiRaQh+Oibswywsn7BCwVxujy2zbHnUDbEsCTZyw\r\n+6fImtXm2V3YMI8Cg+qcLq/Ybi4ZTH+yaGY=\r\n=cSb0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"7836133fce27f434ee6f714865e9adeff45c4b06","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.mjs","clean":"rimraf ./lib"},"typedoc":{"entryPoint":"./src/main/index.ts","readmeFile":"none"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.5.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"18.15.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.2_1679356173075_0.27964051599820894","host":"s3://npm-registry-packages"}},"0.0.3":{"name":"racehorse","version":"0.0.3","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.3","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"2fe6a7030dfcbcd240ec894eb6db7b19416305e8","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.3.tgz","fileCount":5,"integrity":"sha512-2TbUuWVHu8XFB9iKUBMQaMEvivTwG0VJ9HuMqid4it/rxZgozUjWM/6oQiJiERUqD/l6ERF24Ws6vySkbFiNvA==","signatures":[{"sig":"MEUCIQCUb/ZuL7VDJXFt3gOnBBRpm7vVtLv5mfyGNioAc1HHwgIgKD5llM8MMcyLefsmUPPl2qPZ6yGSA9lMabestnaL0Bw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":35708,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkQB7dACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqWiA/+JOc1Qu9ANTDH5xBFuGB47io8BStm8DtRX12kFNbBm9b7xigS\r\n59pTkaJOhDqHfaKISXrqaUKdkvNyhdf/e+0f4tlmuaksnVtEMYhxttE6tYY5\r\niBtPlFph5+M2YqhK/i0LXb/NoqLJ13uMovh0roy0BuWgRg+y1dCRWFsOOE0/\r\nLoNF1zYQvmRZVHVNE3iDnLHGVHJIiN6v8lJ2iHdB+K2mBweoSpW+qP09i3at\r\n2F1MKFNsIU/z4VNM+STUkVcdaFd9YIB01AbQLxrY8Cm6uMjl6IqlHAe8HN0y\r\n13kk+8ZlNgG+SKjlrZuPu4KfRNhyNWcopeQZYR0XeRihBuU/8yq86Z7Zmyl6\r\n3GQkb00sEOfBz/HETUvS1COwVHVAO3crymKLZ+Ns6go4Xbgg2n64fENxyPgX\r\nYEM/wD5JHgPYjmXFWTRpe4R4PqlCapV1NmHddxtIUYVYiEbInli7CsnnrKQ4\r\nHqYgP9rTf1h/gQZiyddLme0U5nvBIg5LA1QId2cOUMOY9k4yUXUnCqyDeSk2\r\nlcrDLvVpJObZB2ClRnArj+yaCGxjv+R9uSjJNpR1PzkrV33iCMVRhi9o1vJZ\r\n/jcApSoSp0v04ks8eLy4yzeWSC1g1lr4XN0dMF9hiLZ7a5daw+ULAyxSjhg+\r\nCKcRZCuP5pzE7T6pkmNoTh34IKIECFDuUsc=\r\n=5Sje\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"c008099c7221c4f97bf2d098d61c33b10c471782","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.mjs","clean":"rimraf ./lib"},"typedoc":{"entryPoint":"./src/main/index.ts","readmeFile":"none"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.5.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"18.15.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.3_1681923805625_0.23160656536759006","host":"s3://npm-registry-packages"}},"0.0.4":{"name":"racehorse","version":"0.0.4","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.4","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"cbd581d3e1c616985ae06429e01e3aef8fe57547","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.4.tgz","fileCount":5,"integrity":"sha512-+A2NzOqHIRQh4NiKFwjxsy4mylsGok/IR38Jq4SQDCSdn2Sk8ZfjtWn7dLGRjcwvd8TEzAs8lA9tzCmUqTw3tA==","signatures":[{"sig":"MEUCIDacs2WnSbtMAbFL3XYrrbj8ympcmxo7UIfOz+R/A+kMAiEAtg1t0od4/FDRQTDux9XEOyXPkGLZlUSOVR35JY7FoLU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":35390,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkRrn7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoH6w//TXzw1CNfCLut657827s/4rkcmReTRv+YJEx4gq2jIreh1dSf\r\nWDMgNBRL3niQaAg3TLzwvjvCjF76lkkGAwFXH4W+HEmhlqg5OCG6cJQS3tEv\r\njrgXBmeJHnpltjpdwzaHXkRdIzjndCc9TjZ6jXn6NuR/0vvaPaTrxzR7BdfC\r\npfnYdP5tyDu439EbqRTNGAyJIY/aatD+hqeQOdi1CVp8EGCAhq8kt+8d88oH\r\nW4/B5QDF8DH0DI3CuGWXwOwM5vmEKCBL1oSJiL8E3aZGoz8jzTTDEDkFkzQq\r\n/HHQ+DmtkqJE57r9MX5Ojqc6ypa+Py9i80xsJg3kDgxo237EDlGnF1ykkPxs\r\nVFt28vjolYU1A83E5rHqK6/pwFNhOjoZJSHTTexbznOq46yPahQ4rH8FipEW\r\nSP7ICfb1WRTh3hbpXoEjy7gaerIuVGdrGuGzdtPCE/amiR0/z3utYg9uoU4s\r\ntRHDFx7nixQWC+52Ot+J8Y+GTZSfvRU4bMpvfln+13WCfL+HCGlfLi7dtctN\r\nmPyDkVu9v7OPA5sYhjZJd2ONJW/X4MW2A16B8mIbg33pYU7OZPvB9RHlHGix\r\nvxj6PTRj5HY5Vw2feoKH7vYrIKbNP225Rf6lTEjNhTEeglQQt+Xtw0qxX+B+\r\nMFVXo3JOgt5hmYnZioS/OTA+W0uJxtwnOfs=\r\n=NHvB\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"69db68bbef8915895ae9125dc85c7f440c217c68","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.mjs","clean":"rimraf ./lib"},"typedoc":{"entryPoint":"./src/main/index.ts","readmeFile":"none"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.5.1","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"18.16.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.4_1682356731201_0.5414324070400058","host":"s3://npm-registry-packages"}},"0.0.5":{"name":"racehorse","version":"0.0.5","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.5","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"27155354ccb1566e51e86f01d462356d72dd4f94","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.5.tgz","fileCount":5,"integrity":"sha512-9kMzqbbcL6j/SGwsHtk8I9PDmLhqyDUuPGzglTE8j3wZAu+keGDdxUv61f6RUP3BlrOKT2XJfsutIV2UogeJ0Q==","signatures":[{"sig":"MEUCIGR+RfDdqOaBytqjMcICywP4EyqccjNDElGxriIbjx8ZAiEAi+nPc/U0K3W1Ho234UFG7kfGVBO48GUiKzL869W8QrY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":44596,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkSrUjACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoDBQ/+Jc+3r6N4JQS0t4GlhgIDspEfUFAmmMMPohG4jRnC9xiyOrRg\r\nTRJxS5ExgLgyMOxl6wzwnlM0jXS8lNk2P9DkH8OjaXhZahCnFgdMl4SWGZsA\r\nUCyxqzcWUEZBnu1Um9jlGh2yAesDhAgEw1SMYSF9yfxLHJQTDV4Xq66Ct1jU\r\n5BUZ9vo/d8LjdXQID8y8sDfucIegUM0bfi/Wj7ex8A6LjpA+HBcoV1/d62Bh\r\n5pApt/9AMUMAFgr7wBHRbT/bZDLUi/cX80v/wCqr3Rwbpeh9ZImj/RRaTHDw\r\n8wM+lpnF5pKwHxdQewnVNWp6lpyv3ZmPshbJEslu2cAm2OxBuAq61MbhvuE5\r\n7db+I0jMSh8tGteFX24nkAKnAstsvhcRTnre7ddBkiOlqa1euRb+niNkPqnv\r\n9GHX8plH3XFqAWW/qtRH9zXFyXvqVtaS8sTG4ino51aM9UDN6uYe1XIb35NZ\r\ndd9EFVpXgaZIHxtAt387sMzXF2oLSGBi7uO+QPVE9KeDfs52vKUgXBf790x1\r\n7GuuEj2JTsXyAeRbMEGu9vg7thry48Y+IEwbXDiymYUrh3Z5TdAkUu78Mwom\r\ncRlzh1bLrCX1V8GQXBri1SjfkoU3w8FGTTyAKF9wi6ZPkTGvjR5n1qGQp+R1\r\nwV/GCgEgO17AaQ6lg85+8t6mt8+S5lxWXEM=\r\n=3dQ/\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"78249c9626dcb6b21a0f531a913798646b71ee28","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.mjs","clean":"rimraf ./lib"},"typedoc":{"entryPoint":"./src/main/index.ts","readmeFile":"none"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.5.1","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"18.16.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.5_1682617634955_0.5916938810040202","host":"s3://npm-registry-packages"}},"0.0.6":{"name":"racehorse","version":"0.0.6","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.6","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"0db77821946fb83761bd90420a39fb621201a2a2","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.6.tgz","fileCount":5,"integrity":"sha512-9O2jhCSwIhjCqw4kI/c9wnWm4O4KpIFb4hV53qJ69DaApaEGU5Zl2Ub6Of31LffT3AsZyiMBdO7TSNyGj+mX6w==","signatures":[{"sig":"MEUCID7qMhicpCc1uzq+pXjGQBXiI8alwZ6sNPujKaGzmVbIAiEA9bcPZ5zXiJpvBu+r7QJLeb9AfVuhdnMXuISk7WYXNbs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":49822},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"cbd7c0d5aa4caec69232338daebf6e2cf66d5a30","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.mjs","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.6.6","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.2.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.6_1686069700593_0.38305390794338656","host":"s3://npm-registry-packages"}},"0.0.7":{"name":"racehorse","version":"0.0.7","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.7","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"6774f333cb78ee678d693440ef780fc7ba538f3a","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.7.tgz","fileCount":5,"integrity":"sha512-YkobziVfvL7rwLAhO8KVTGwqxnN8JLLifA9igCkfVzpRKaVDyUk5CIm+LeB+zcw5xddqQgqPMW+CwRff/cZpjA==","signatures":[{"sig":"MEUCIQCXH6ubJ4+ZaWrS5r6G2K1AxftQN54ibtFWlfhD4RtAgwIgRHFAI7aMr/HQhgKIA7S/XlRUAbth0l2ehyHGMk1Hfmo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":62926},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"eade8da3375481e06a084e9e7eadf249019bfc4e","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.6.7","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.3.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.7_1686742298960_0.25830247000721496","host":"s3://npm-registry-packages"}},"0.0.8":{"name":"racehorse","version":"0.0.8","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.8","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"b08033f5f5a07d4422b9f3567198fca2ec207adb","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.8.tgz","fileCount":5,"integrity":"sha512-LfiuvQTsu59RW2Mx1l+vCa9ip7ZsGQQfCsbWXRNOQ7A3irbjDaA64UzeHY0FJpqNScO7ZfSNhs8WZBmI1sNgcg==","signatures":[{"sig":"MEYCIQCKFu62llKnw2piuyR8o/ACTma+5z9D5Q8KnVZW13+K8QIhAIJrJogjloHb7/dxBzdoBfDznV845P4yuNTZ0bv6YNU5","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":63067},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"f1b76c57f3529884304fe5390f79e633299d13bb","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.6.7","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.3.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.8_1686748239498_0.131494702592168","host":"s3://npm-registry-packages"}},"0.0.9":{"name":"racehorse","version":"0.0.9","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@0.0.9","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"7ca7b5c1804d0f8f0b29ef8fdea943b4b9a13685","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-0.0.9.tgz","fileCount":5,"integrity":"sha512-41uRAYNqk3WYI12vVlH9qN4dl0r3tDI0D4cVa80s/LP2TU7sqapnsv+WRmK0CgzdWhUSaibIFMOwKPP5pRDRpQ==","signatures":[{"sig":"MEQCIAVT9tBpfaP//pPIsHsPjSpimOlTMOxL3c6kiD2mnZTJAiA9RqIiXedvTaC0B2H4XnOm1XqiE1wB8IzLot2YVeapxQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":84442},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"e007d33ccf713b79431762197be2fb6b724f3371","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.8.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.5.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_0.0.9_1692184083103_0.2623973075894337","host":"s3://npm-registry-packages"}},"1.0.0":{"name":"racehorse","version":"1.0.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.0.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"04815b0115aafe2baa87cbdd199c0b061250ec3e","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.0.0.tgz","fileCount":5,"integrity":"sha512-exM3LOPhpzftgmwhaL+rhLisTo6s34uWlYsmJHP4CuPgXXkLkFpzDGpeu/QYBIUc3HWQEw6Zf9NRLGU88OVlfg==","signatures":[{"sig":"MEQCIA3jBvQajzsijRj5bZWaQ0CljCW4B45HQFF62iUWI1sDAiAlx5tYjH+C46PiR8pszp+SDd5KahsvTCHuIvPdZJl1lQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":84584},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"813b03ce5cf21ffceb930b7ca64aa7a0bff6e62a","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.8.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.5.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.0.0_1692640212802_0.5027026700715884","host":"s3://npm-registry-packages"}},"1.1.0":{"name":"racehorse","version":"1.1.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.1.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"9eaaafb4bbacc019cf8c6ba799e95090de4a4b81","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.1.0.tgz","fileCount":5,"integrity":"sha512-XVG/oQFuYAEOzKPxiCQr2KNUvRun7WPgbfdBUckAKBmPUmXUCoz3ZIX6q8g/ylwvq24AMnafzAcGDal9LDeztQ==","signatures":[{"sig":"MEQCIDzlDV1LNFG7tBkdsH7N9APyvn8wXT2Vl39LDgy6Uz2JAiBo1ro37yNE/hL65pWK0Liz3w2AJ7Na4ajFQ7RKZvM0AA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":85479},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"0d5db62e58a5cc0d1ea815b6b0053a86304649d3","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"9.8.1","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.6.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.1.0_1694781425974_0.8781841811448006","host":"s3://npm-registry-packages"}},"1.2.0":{"name":"racehorse","version":"1.2.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.2.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"de3962e04d0de036bfe8d069e157ef3e3498a18b","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.2.0.tgz","fileCount":5,"integrity":"sha512-+M4oEdd0PoxRa45uxHKQLBEMbzoYQ9/3ivS0xYuM6lWpChrdK1SGob4tphZ1Ad4REpctOEbW/PUZVMwMhU6KLQ==","signatures":[{"sig":"MEUCIQDrUL6q2YRPv6nDtaVO69Ap0AOGyaIVRGp2YjCE+G1ThwIgOGZImAIPeg+SrlKkzB9SUQFUgqUp/6pg2dtFVOmFRtQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101069},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"c7c2d9dc51d794c6fa61f39bd564b1992525d2a4","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.1.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.7.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.2.0_1695163929896_0.5197996132515368","host":"s3://npm-registry-packages"}},"1.3.0":{"name":"racehorse","version":"1.3.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.3.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"0871cab3093f5b8dde5f4d4bcf7847fffe9db02b","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.3.0.tgz","fileCount":5,"integrity":"sha512-7C7F645ABHsOVwcPQVQDi6NtWnKbgFShuc3dZB2A4Q+2UKWY1nFrQgiOfMnCDLVc54+MqVmtmRjlTUgVxpJOPQ==","signatures":[{"sig":"MEUCIAt5sC9FkM3Fx4zWP4MoDcQ+fRFyUDSFKOrtc4/TuuQXAiEAuTahZLLZt1mRF9p8hNeX0l7n4VGO+FzVz9OfgALRxPc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":102980},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"b850c7088da585930bc2ce4caef65abc1efecfe6","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.1.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.7.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.3.0_1695329129926_0.06691243229516441","host":"s3://npm-registry-packages"}},"1.4.0":{"name":"racehorse","version":"1.4.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.4.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"f82224cdf80a31c53881563c1d15196b3a7d3b58","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.4.0.tgz","fileCount":5,"integrity":"sha512-MaB+2QjJMqNeip/cdHsXIK3YKdNeL91JhLAqnFTYYVWfv6Nf/HQUBW1SQPutp3cJuoGiznz59xo0paJc/krSQQ==","signatures":[{"sig":"MEYCIQD4qBo4u6x6H0MFWap/PZ9cuhfgMTBeORq4tiiqka/ovwIhAKCtcgxa3kNNYvCiy4c7yA97bHNryF86NMEAoefoZxeT","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115265},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"4658da5cf37ac3080dcdb97f8833fe3f093f2f58","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.1.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.9.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^3.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.4.0_1698363430438_0.542633050681393","host":"s3://npm-registry-packages"}},"1.4.1":{"name":"racehorse","version":"1.4.1","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.4.1","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"3fcebc9f144d15ee516e05c38e5bdedc07c0f747","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.4.1.tgz","fileCount":5,"integrity":"sha512-0PjgEkWTqcBbufP7MiUmvUnybTjL73dkLPN3jO6OPj43j3TMmwbwhL1R67lXeo0YCky5IsDoo+PGrhuRuzNRjA==","signatures":[{"sig":"MEQCIAOZBatSch2LM9dD78Hhx4xaWiV7w7yZbq0y2/UjERRcAiBRUYhwN9L8kk+q1snUBNb9IZ9kI6taX98e5SBtocvmZg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":118783},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","gitHead":"73713648893b46ac52684f5ccddcc3b896ac36b8","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf ./lib"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.3","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.10.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.4.1_1702477026128_0.6192518423542908","host":"s3://npm-registry-packages"}},"1.4.2":{"name":"racehorse","version":"1.4.2","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.4.2","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"695d24f327407684841621ce6420fbe76dd8a832","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.4.2.tgz","fileCount":113,"integrity":"sha512-yuGKYU+qjsmmh3beDkp+HEDLEHddL9xS/sCwhKTB9kpNw1sP1zKqrQF04uU83vpoU+bPGkrVgOtKbq6nxbeSCA==","signatures":[{"sig":"MEQCIHNU9Ch+Z9+fEE9/BqMwVWW1/V5GLxHX2X+apEYsT4v5AiAcb9YEX9+jrBDX78WzlTpDZ2R1+x0qeiHpH3a0qZ810w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":294059},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"ffa62401f32b44439f085c9c43dbadd05491d552","scripts":{"test":"jest --config ../../jest.config.js","build":"cp -R src/main lib && rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.3","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.10.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.4.2_1702578443583_0.7347180876031516","host":"s3://npm-registry-packages"}},"1.4.3":{"name":"racehorse","version":"1.4.3","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.4.3","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"c60aa8c23468a8f6045a3b45f20bbc61340926e8","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.4.3.tgz","fileCount":69,"integrity":"sha512-yY/CGVPLG2G1o1tAEAddWuJCy5+28YGV3abzBus5Rw8DQt/IvWGlI5C+++GyDTDs1N3bVm2kwyaAcnUrisDoSA==","signatures":[{"sig":"MEYCIQCfPr3Y6kbZ9pGS3buHiEIyomB1HExGKrehcQqDn4GtvQIhAOqMbGON+l0Jr8LpElqb4XYIs4UneATIarrJp92KwUAh","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":131696},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"4354c05592150d446cce118dc36d6fe350a64c51","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.3","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.10.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.4.3_1702582743586_0.6409424626629019","host":"s3://npm-registry-packages"}},"1.5.0":{"name":"racehorse","version":"1.5.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.5.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"e6067ddab2a05c6a979f4f5c508325b000e06be3","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.5.0.tgz","fileCount":72,"integrity":"sha512-sFv3X+Fwim66FUuMZopRirHPAUpd01QiOaC8HMGI309Cv9O98k/nrx4/GlBQF8FzFdhfIlKRRc088pOpOrBBTg==","signatures":[{"sig":"MEYCIQDQE0AuokeRfa6PFNABb9FQQDFEj82VXdab7+UU2nsKDgIhAJCq11IYYFZtYrXZTChHLbloRfHHDbeaj6uPrCtKpWJZ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":144633},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"c9af1f6e153db1fadce466410afe9fb445ae4ead","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.3","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.10.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.5.0_1703526798096_0.9190585035403422","host":"s3://npm-registry-packages"}},"1.6.0":{"name":"racehorse","version":"1.6.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.6.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"83eb0c62f4359cb7e2724f15a33d885ca1ee9b77","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.6.0.tgz","fileCount":72,"integrity":"sha512-RFuNKTPNxWwj63I54Y3PH8Bz7ILOlODI4jbIfGEB/zPxazCjXU3TkfyvzfVZocCPJsFe93HDEYD55Zt70y3koQ==","signatures":[{"sig":"MEUCIQCUrV1t09e1JIdxxXYaR0p1ilLvzG3DD3KlVRluvgK5PwIgJWgOtOuAT8mo0qtQZ6w69izIh5LDnH8d3AdezPLGYTg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":145050},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"0513252860f5a94b9e09aa7679897b0f6f67a620","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.4","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.6.0_1706801532385_0.013042336480429517","host":"s3://npm-registry-packages"}},"1.6.1":{"name":"racehorse","version":"1.6.1","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.6.1","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"a058559a00700a127743d791305308e22771cc91","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.6.1.tgz","fileCount":72,"integrity":"sha512-RfLbQV3sLm0rspaGNa3hEXZU61lVC3DryIpVTodnYZVUNfXyO/VqH90lEZc/mp51EO/m3Z3CgaMferrJeomz1w==","signatures":[{"sig":"MEUCIQC1Ijffqv1EjH+Y5OFWkLbb32LgtC1ZLaGswhhhO1yr9AIgKk5tVodvy6IQott9Rg9DxsCwAS2k4OZxy4uzdIhOJGo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":147117},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"a4c07aa903993b16ac6e0c17d4e97cc58a9cc8dc","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.4","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^4.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.6.1_1707137456652_0.6911780707122024","host":"s3://npm-registry-packages"}},"1.6.2":{"name":"racehorse","version":"1.6.2","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.6.2","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"e75473251b2e65c50342f8c11bd29a07f0564c73","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.6.2.tgz","fileCount":73,"integrity":"sha512-W7H5v2RP5JzwHky3uOyMZ/6I1/BIapCfawjc0OYsJiRAJKsM2iQq5SwioNu8McdWeHLJTJtGU6pSihUzHwEYNQ==","signatures":[{"sig":"MEYCIQCQ6jx7VPDmrBWn2zdwvKFf1cFJp39GRMVQUn+MCMexLgIhALxm3CSta5rjkn+TMnyRyjAAO/SF+TGxN/K8PhF5bcgT","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":152535},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"1db0c57bcd4c323948f39534b619ef7e9d3d760e","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.4","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^5.0.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.6.2_1709291189884_0.46116492920086594","host":"s3://npm-registry-packages"}},"1.6.3":{"name":"racehorse","version":"1.6.3","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.6.3","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"5c32fd2e14a6e2ead5e16b619490cac4faf4a4f0","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.6.3.tgz","fileCount":73,"integrity":"sha512-itMTvRdXzh+nzK/xBJiihk8j5CWzZ1rSOi85EoKB+vmlC3KXZjNDcm4ux3AY/U/DJDGInCLREu3CsKwk2QTkUA==","signatures":[{"sig":"MEYCIQCcQzJsBSlt3wXyJSwKYrm/jVeUgR2JaBM41O3yLBl2qgIhAN/wqhfjrldhox6SzOMcYh0yzqCXdujVZAAJLT4WfNWh","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":156067},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"dcf3c02a21453857c06e19c0a4bc850e0e8dfd27","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.2.4","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^5.0.1"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.6.3_1710168370504_0.7688848860113096","host":"s3://npm-registry-packages"}},"1.7.0":{"name":"racehorse","version":"1.7.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.7.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"a6b2a2327395379e85a2740df316b183c14c3c2f","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.7.0.tgz","fileCount":79,"integrity":"sha512-OnfBCo8dJzku6NH1IuQ4m/t/bh8hQ6vOxmp+Z4f7ooDMHmxBx5SZrbxj+/ZwZcKX+1F+GuMNPYTok+gjBR2b6w==","signatures":[{"sig":"MEUCIAmBVCBUt0b4eV8Pt3wBkijwWtVp2LvUXqR/1O9tkEXvAiEA+qpczx+hZQn6x5EnrZBb/b4qABniA5wb0Eyu3boF2I0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":180356},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"c98686cd9bbc567368b373081c33bb092693dfb2","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.7.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.14.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.7.0_1718204160452_0.2618938060277478","host":"s3://npm-registry-packages"}},"1.8.0":{"name":"racehorse","version":"1.8.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.8.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"2ddd49223b5e67820d2952ea9c5295ace8e21f94","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.8.0.tgz","fileCount":88,"integrity":"sha512-jbgVNrwF1Sfht1GOmcBhTf/CMAc5N6itLOMnc9Eh53cshqla+hfc4EkHdk7DVUxG60Xx+riXmMyIKBJ/w/ulfg==","signatures":[{"sig":"MEQCIHQ59Iu3F2+CXGfQsbQNx0eajJ4qsIIcdSctIrE6njBcAiA47JOQWNEBayvl+k7BqqDUSRavCs777mKRISHXZmpgZw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":208764},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"31673439e0e64ec783d09e848bff5b23ddb8d078","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.8.2","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.17.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.8.0_1728571333773_0.5706289404884517","host":"s3://npm-registry-packages"}},"1.9.0":{"name":"racehorse","version":"1.9.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.9.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"75e5f84db553b4e899a4516f5eee1f5ee7944f8c","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.9.0.tgz","fileCount":88,"integrity":"sha512-dBrPqHv6bYLgGwKRh9Z6JH3BV3PSPiWVjH6CQwiy3vRHghRKtKsElg2AJRZ0dTSlhPGdA08ebe0jMTob8HISlg==","signatures":[{"sig":"MEQCIAbWbLMYbO2xiAkdWCcqh9e7JWEPzrq997UQ5tfz4BzpAiAF9TcRkhglJR5k95XzIkbHoywhtzZ+jk7yqZRNg8MXLA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":208808},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"9bae11121f074fde3b46b9917f6676e55b976adc","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.8.2","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.18.3","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.9.0_1742303905413_0.03153852279412095","host":"s3://npm-registry-packages-npm-production"}},"1.9.1":{"name":"racehorse","version":"1.9.1","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.9.1","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"716b2b7878efb6be95e5a2e9073e25847fbd4c76","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.9.1.tgz","fileCount":88,"integrity":"sha512-FQ7Qpo9tb6omQ6w///btK8c2tMxf+PfBnKWE4Hd+hHFXIL9e0EXOdywQ1+aLpiB3J7lfr3zSWNDjS6p+BAh9zw==","signatures":[{"sig":"MEUCIQCtiOj/uS/h0ph6xS/Ex8sViIeYCOBpbopqMnc8Qktn1AIgJdd7YJAQ8Z+UG/LFagj/2PgFZGixY8Cr/UaaRXsfNec=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":208892},"main":"./lib/index.js","types":"./lib/index.d.ts","module":"./lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"d093a5c93571f7535b9d0736e133559ed9236c8c","scripts":{"test":"jest --config ../../jest.config.js","build":"rollup --config ../../rollup.config.js","clean":"rimraf lib","prepack":"cp ../../LICENSE.txt ./","postpack":"rimraf LICENSE.txt"},"_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.8.2","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"20.19.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.9.1_1742564033478_0.32419271125789084","host":"s3://npm-registry-packages-npm-production"}},"1.10.0":{"name":"racehorse","version":"1.10.0","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.10.0","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"2172b359f9e39595c7032c78b136368239d2e496","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.10.0.tgz","fileCount":87,"integrity":"sha512-EnHKgcJoDdY5X6vSYT9oRtUMDCy8RWT8zsqjePDs9ei2G1Yu8KTbNCXvQOmWa8yFc8lKBEg3ZKertGKZJdIMog==","signatures":[{"sig":"MEUCIQClMQgQfQMc4QCIE1otLIiz+kbNxzyI1qYlxgcJuy0kTAIgUiDFTDqX3oh739UsIEl4a3mkrwgqdi9osGc83O9IEpg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":242958},"main":"./index.js","types":"./index.d.ts","module":"./index.mjs","exports":{".":{"types":"./index.d.ts","import":"./index.mjs","require":"./index.js"},"./package.json":"./package.json"},"gitHead":"16b57bdd4d07729a6992373e1283916c326f4047","_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.9.2","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"22.15.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.10.0_1747995878055_0.985091083718856","host":"s3://npm-registry-packages-npm-production"}},"1.10.1":{"name":"racehorse","version":"1.10.1","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.10.1","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"b0ae6ec8242a2fcf2f10ede9e177c3adcd0daaf1","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.10.1.tgz","fileCount":90,"integrity":"sha512-dTOobsso70UETOnAxaPsbKlRYSC68ZZl2gr4eKMntpJmoK2txAxgliyunAIJOl27eD0UcO2vMrjG5Nav/7McAA==","signatures":[{"sig":"MEYCIQCa80iOLkKx7B5FCxi4dWcYvKj0+k7LwGRAQPa0Os70tgIhAMpe1K2pvlIjrcN5/qMajy1HYvVbGjIkfS2FAu8PgKcj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249034},"main":"./index.js","types":"./index.d.ts","module":"./index.mjs","exports":{".":{"types":"./index.d.ts","import":"./index.mjs","require":"./index.js"},"./package.json":"./package.json"},"gitHead":"b7131b169c289f3e5d806eb814d3d80c1d703f69","_npmUser":{"name":"smikhalevski","email":"smikhalevski@gmail.com"},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"10.9.2","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"22.17.1","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/racehorse_1.10.1_1754645804487_0.35980152018477507","host":"s3://npm-registry-packages-npm-production"}},"1.10.2-next.de44275":{"name":"racehorse","version":"1.10.2-next.de44275","keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","_id":"racehorse@1.10.2-next.de44275","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"homepage":"https://github.com/smikhalevski/racehorse#readme","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"dist":{"shasum":"405dba3823eb95ef30482ff68a47a3f4f8d46f94","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.10.2-next.de44275.tgz","fileCount":61,"integrity":"sha512-k4wIEAHmLttzEWlS0p1ACS2ccrSgjqjqviaMchZVqphsd2j1au9OQhLlsKKHQidqzGRSeVzjAJVAfRGoqD6JWQ==","signatures":[{"sig":"MEQCIAUs3UkLLfs2nlDk425QTfBXCESqooDcTBF6bkgw4p4KAiBsNnNpJwn/FBBoLD4CWQpaVhn+xSknSa6DXY79p5N0zw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/racehorse@1.10.2-next.de44275","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":191715},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":"./index.js","./package.json":"./package.json"},"gitHead":"de4427508b7fe5400a34fc7c159256f8ca089c7e","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:0a3241b3-0f1f-4126-bcd9-ee6555380835"}},"repository":{"url":"git+https://github.com/smikhalevski/racehorse.git","type":"git"},"_npmVersion":"11.13.0","description":"JS bindings for Racehorse.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.2"},"_hasShrinkwrap":false,"readmeFilename":"README.md","_npmOperationalInternal":{"tmp":"tmp/racehorse_1.10.2-next.de44275_1781814515887_0.5154817646727203","host":"s3://npm-registry-packages-npm-production"}},"1.11.0":{"name":"racehorse","version":"1.11.0","description":"JS bindings for Racehorse.","type":"module","main":"./index.js","types":"./index.d.ts","exports":{".":"./index.js","./package.json":"./package.json"},"sideEffects":false,"repository":{"type":"git","url":"git+https://github.com/smikhalevski/racehorse.git"},"keywords":["android"],"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"homepage":"https://github.com/smikhalevski/racehorse#readme","dependencies":{"locale-matcher":"^2.0.0","parallel-universe":"^6.1.2"},"gitHead":"ece689f8d82a54d19e7c56871ff3027d99550e76","_id":"racehorse@1.11.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-1JdB53pPS+IlgESwFwm2YbHELbz0bL5KDgrnuCIgemVB9+5Hg6y6BEW5A/msPTZ3DrXt4z2FTREAkWhN8uFzoQ==","shasum":"6b698bbd428864e636e6a800ff2e61eb50a20ff1","tarball":"https://registry.npmjs.org/racehorse/-/racehorse-1.11.0.tgz","fileCount":61,"unpackedSize":191702,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/racehorse@1.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICp9HcGp9vwjFPFwMQtF5saOEUwB0OYVvhsqzkcOzgSEAiEArfeK0VXKQrqHOGFfxEbl43YHrUlHb/wu8Xlz7uqrtbo="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:0a3241b3-0f1f-4126-bcd9-ee6555380835"}},"directories":{},"maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/racehorse_1.11.0_1783515934216_0.45874847706124555"},"_hasShrinkwrap":false}},"time":{"created":"2023-02-08T18:05:01.454Z","modified":"2026-07-08T13:05:34.645Z","0.0.1":"2023-02-08T18:05:01.648Z","0.0.2":"2023-03-20T23:49:33.283Z","0.0.3":"2023-04-19T17:03:25.822Z","0.0.4":"2023-04-24T17:18:51.333Z","0.0.5":"2023-04-27T17:47:15.152Z","0.0.6":"2023-06-06T16:41:40.798Z","0.0.7":"2023-06-14T11:31:39.159Z","0.0.8":"2023-06-14T13:10:39.733Z","0.0.9":"2023-08-16T11:08:03.274Z","1.0.0":"2023-08-21T17:50:13.077Z","1.1.0":"2023-09-15T12:37:06.149Z","1.2.0":"2023-09-19T22:52:10.120Z","1.3.0":"2023-09-21T20:45:30.129Z","1.4.0":"2023-10-26T23:37:10.663Z","1.4.1":"2023-12-13T14:17:06.346Z","1.4.2":"2023-12-14T18:27:23.814Z","1.4.3":"2023-12-14T19:39:03.840Z","1.5.0":"2023-12-25T17:53:18.298Z","1.6.0":"2024-02-01T15:32:12.546Z","1.6.1":"2024-02-05T12:50:56.814Z","1.6.2":"2024-03-01T11:06:30.037Z","1.6.3":"2024-03-11T14:46:10.679Z","1.7.0":"2024-06-12T14:56:00.797Z","1.8.0":"2024-10-10T14:42:14.064Z","1.9.0":"2025-03-18T13:18:25.654Z","1.9.1":"2025-03-21T13:33:53.659Z","1.10.0":"2025-05-23T10:24:38.243Z","1.10.1":"2025-08-08T09:36:44.665Z","1.10.2-next.de44275":"2026-06-18T20:28:36.036Z","1.11.0":"2026-07-08T13:05:34.357Z"},"bugs":{"url":"https://github.com/smikhalevski/racehorse/issues"},"author":{"name":"Savva Mikhalevski","email":"smikhalevski@gmail.com"},"license":"MIT","homepage":"https://github.com/smikhalevski/racehorse#readme","keywords":["android"],"repository":{"type":"git","url":"git+https://github.com/smikhalevski/racehorse.git"},"description":"JS bindings for Racehorse.","maintainers":[{"name":"smikhalevski","email":"smikhalevski@gmail.com"}],"readme":"<p align=\"center\">\n  <a href=\"#readme\"><picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"./images/logo-dark.png\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"./images/logo-light.png\" />\n    <img alt=\"Racehorse\" src=\"./images/logo-light.png\" width=\"500\" />\n  </picture></a>\n</p>\n\n<br/>\n\n<!--ARTICLE-->\n\n<!--OVERVIEW-->\n\nThe pluggable bridge for WebView-based Android apps that marshals events between the web layer and native Android.\n\n- Kotlin and TypeScript first.\n- Plugin-based architecture.\n- Can be integrated into any Android 28+ app.\n- Enables [app auto updates](#evergreen-plugin) without Google Play releases.\n- First-class React support.\n- Check out the [example app](#example-app) and the [Cookbook](#cookbook)!\n\n<!--/OVERVIEW-->\n\n<br>\n\n```sh\nnpm install --save-prod racehorse\n```\n\n<br>\n\n<!--/ARTICLE-->\n\n<!--TOC-->\n\n<span class=\"toc-icon\">🚀&ensp;</span>**Features**\n\n- [Overview](#overview)\n- [Example app](#example-app)\n- [Request-response event chains](#request-response-event-chains)\n- [Event subscriptions](#event-subscriptions)\n- [WebView events](#webview-events)\n- [Check supported events](#check-supported-events)\n- [Proguard](#proguard)\n\n<span class=\"toc-icon\">🔌&ensp;</span>**Plugins**\n\n- [Activity](#activity-plugin)\n- [Asset loader](#asset-loader-plugin)\n- [Biometric](#biometric-plugin)\n- [Biometric encrypted storage](#biometric-encrypted-storage-plugin)\n- [Contacts](#contacts-plugin)\n- [Deep link](#deep-link-plugin)\n- [Device](#device-plugin)\n- [Downloads](#download-plugin)\n- [Encrypted storage](#encrypted-storage-plugin)\n- [Evergreen](#evergreen-plugin)\n- [Facebook Login](#facebook-login-plugin)\n- [Facebook Share](#facebook-share-plugin)\n- [File chooser](#file-chooser-plugin)\n- [File system](#file-system-plugin)\n- [Google Pay](#google-pay-plugin)\n- [Google Play referrer](#google-play-referrer-plugin)\n- [Google Sign-In](#google-sign-in-plugin)\n- [HTTPS](#https-plugin)\n- [Keyboard](#keyboard-plugin)\n- [Network](#network-plugin)\n- [Notifications](#notifications-plugin)\n- [Permissions](#permissions-plugin)\n\n<span class=\"toc-icon\">🍪&ensp;</span>**Cookbook**\n\n- [Blur preview on recent apps screen](#blur-preview-on-recent-apps-screen)\n\n<span class=\"toc-icon\">🔎&ensp;</span>**Resources**\n\n- [API docs](https://smikhalevski.github.io/racehorse/)\n\n<!--/TOC-->\n\n<!--ARTICLE-->\n\n# Overview\n\nRacehorse is the pluggable bridge that marshals events between the web app and the native Android app. To showcase how\nRacehorse works, let's create a plugin that would display\n[an Android-native toast](https://developer.android.com/guide/topics/ui/notifiers/toasts) when the web app requests it.\n\nLet's start by adding required Racehorse dependencies. In your `app/build.gradle.kts` add:\n\n```kotlin\nplugins {\n    id(\"org.jetbrains.kotlin.plugin.serialization\")\n}\n\ndependencies {\n    implementation(\"org.racehorse:racehorse:1.10.1\")\n    implementation(\"org.greenrobot:eventbus:3.3.1\")\n    implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3\")\n}\n```\n\nIn root-level `build.gradle.kts` add:\n\n```kotlin\nplugins {\n    id(\"org.jetbrains.kotlin.plugin.serialization\")\n}\n```\n\nInstall web dependencies:\n\n```shell\nnpm install racehorse\n```\n\nIf you're planning to use React, consider a Racehorse React integration package:\n\n```shell\nnpm install @racehorse/react\n```\n\nIn Android app, create a WebView:\n\n```kotlin\nimport android.webkit.WebView\n\nval webView = WebView(activity)\n// or\n// val webView = activity.findViewById<WebView>(R.id.web_view)\n```\n\nCreate an\n[`EventBridge`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-event-bridge/index.html)\ninstance that would be responsible for event marshalling:\n\n```kotlin\nimport org.racehorse.EventBridge\n\nval eventBridge = EventBridge(webView).apply { enable() }\n```\n\nRacehorse uses a [Greenrobot EventBus](https://greenrobot.org/eventbus) to deliver events to subscribers, so the bridge\nmust be registered in the event bus:\n\n```kotlin\nimport org.greenrobot.eventbus.EventBus\n\nEventBus.getDefault().register(eventBridge)\n```\n\nHere's an event that is posted from the web to Android through the bridge:\n\n```kotlin\npackage com.example\n\nimport kotlinx.serialization.Serializable\nimport org.racehorse.WebEvent\n\n@Serializable\nclass ShowToastEvent(val message: String) : WebEvent\n```\n\nNote that `ShowToastEvent` implements the\n[`WebEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-web-event/index.html)\nmarker interface. This is the baseline requirement that events must conform to in order to support marshalling from the\nweb app to Android.\n\nNow let's add an event subscriber that would receive incoming `ShowToastEvent` and display a toast:\n\n```kotlin\npackage com.example\n\nimport android.content.Context\nimport android.widget.Toast\nimport org.greenrobot.eventbus.Subscribe\n\nclass ToastPlugin(val context: Context) {\n\n    @Subscribe\n    fun onShowToast(event: ShowToastEvent) {\n        Toast.makeText(context, event.message, Toast.LENGTH_SHORT).show()\n    }\n}\n```\n\nRegister `ToastPlugin` in the event bus to enable event subscriptions:\n\n```kotlin\nEventBus.getDefault().register(ToastPlugin(activity))\n```\n\nNow the native part is set up, and we can send an event from the web app:\n\n```js\nimport { eventBridge } from 'racehorse';\n\neventBridge.requestAsync({\n  // 🟡 The event class name\n  type: 'com.example.ShowToastEvent',\n  payload: {\n    message: 'Hello, world!',\n  },\n});\n```\n\nThe last step is to load the web app into the WebView. You can do this in any way that fits your needs — Racehorse\ndoesn't restrict this process in any way. For example, if your web app is running on your local machine on port 1234,\nyou can load the web app in the WebView using this snippet:\n\n```kotlin\nwebView.loadUrl(\"https://10.0.2.2:1234\")\n```\n\n# Example app\n\nThe example app consists of two parts: [the web app](https://github.com/smikhalevski/racehorse/tree/master/web/example)\nand [the Android app](https://github.com/smikhalevski/racehorse/tree/master/android/example). To launch the app in the\nemulator, follow the steps below.\n\nClone this repo:\n\n```shell\ngit clone git@github.com:smikhalevski/racehorse.git\ncd racehorse\n```\n\nInstall packages and build Racehorse packages and the example app:\n\n```shell\nnpm ci\nnpm run build\n```\n\nStart the web server that would serve the app for the debug build:\n\n```shell\ncd web/example\nnpm start\n```\n\nOpen `<racehorse>/android` in Android Studio and run the `example` app.\n\n# Request-response event chains\n\nIn the [Overview](#overview) section we used an event that extends the\n[`WebEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-web-event/index.html) interface.\nSuch events don't imply a response. To create a request-response chain, at least two events are required:\n\n```kotlin\npackage com.example\n\nimport android.os.Build\nimport org.greenrobot.eventbus.Subscribe\nimport org.racehorse.RequestEvent\nimport org.racehorse.ResponseEvent\n\nclass GetDeviceModelRequestEvent : RequestEvent()\n\nclass GetDeviceModelResponseEvent(val deviceModel: String) : ResponseEvent()\n\nclass DeviceModelPlugin {\n\n    @Subscribe\n    fun onGetDeviceModel(event: GetDeviceModelRequestEvent) {\n        event.respond(GetDeviceModelResponseEvent(Build.MODEL))\n    }\n}\n```\n\nRequest and response events are instances of\n[`ChainableEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-chainable-event/index.html).\nEvents in the chain share the same `requestId`. When a\n[`ResponseEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-response-event/index.html)\nis posted to the event bus, it is marshalled to the web app and resolves a promise returned from\n[`eventBridge.requestAsync`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.EventBridge.html#requestasync):\n\n```ts\nimport { eventBridge } from 'racehorse';\n\nconst deviceModel = await eventBridge\n  .requestAsync({ type: 'com.example.GetDeviceModelRequestEvent' })\n  .then(event => event.payload.deviceModel);\n```\n\nIf an exception is thrown in `DeviceModelPlugin.onGetDeviceModel`, the promise is _rejected_ with an\n[`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) instance.\n\n## Synchronous requests\n\nIf all events in the event chain are handled on\n[the posting thread](https://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/) on the Android side,\nthen a request can be handled synchronously on the web side. In the `DeviceModelPlugin` example, `onGetDeviceModel` is\ncalled on the posting thread since we didn't specify a thread mode for the\n[`@Subscribe`](https://github.com/greenrobot/EventBus#eventbus-in-3-steps) annotation. This allows the web to perform\na synchronous request:\n\n```ts\nimport { eventBridge } from 'racehorse';\n\nconst { deviceModel } = eventBridge.request({ type: 'com.example.GetDeviceModelRequestEvent' }).payload;\n```\n\nIf your app initializes an event bridge after the WebView was created, you may need to establish the connection\nmanually before using synchronous requests:\n\n```ts\nawait eventBridge.connect();\n```\n\n# Event subscriptions\n\nWhile the web app can post a request event to Android, it is frequently required that Android post an event to the web\napp without an explicit request. This can be achieved using subscriptions.\n\nLet's define an event that Android can post to the web:\n\n```kotlin\npackage com.example\n\nimport org.racehorse.NoticeEvent\n\nclass BatteryLowEvent : NoticeEvent\n```\n\nTo receive this event in the web app, add a listener:\n\n```js\nimport { eventBridge } from 'racehorse';\n\neventBridge.subscribe(event => {\n  if (event.type === 'com.example.BatteryLowEvent') {\n    // Handle the event here\n  }\n});\n```\n\nTo subscribe to an event of a given type, you can use a shortcut:\n\n```js\nimport { eventBridge } from 'racehorse';\n\neventBridge.subscribe('com.example.BatteryLowEvent', payload => {\n  // Handle the event payload here\n});\n```\n\nIf you have [an `EventBridge` registered](#overview) in the event bus, then you can post a `BatteryLowEvent` from\nanywhere in your Android app and it will be delivered to a subscriber in the web app:\n\n```kotlin\nEventBus.getDefault().post(BatteryLowEvent())\n```\n\n# WebView events\n\nRacehorse provides clients for the WebView which post WebView-related events to the event bus, so you can subscribe to\nthem in your plugins. To init clients, set them on the WebView instance:\n\n```kotlin\nimport org.racehorse.webview.RacehorseWebChromeClient\nimport org.racehorse.webview.RacehorseWebViewClient\n\nwebView.webChromeClient = RacehorseWebChromeClient()\nwebView.webViewClient = RacehorseWebViewClient()\n```\n\nNow you can subscribe to\n[all events that a WebView instance posts](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse.webview/index.html):\n\n```kotlin\nimport org.greenrobot.eventbus.Subscribe\nimport org.racehorse.webview.ConsoleMessageEvent\n\nclass MyPlugin {\n\n    @Subscribe\n    fun onConsoleMessage(event: ConsoleMessageEvent) {\n        // Handle the event here\n    }\n}\n\nEventBus.getDefault().register(MyPlugin())\n```\n\n# Check supported events\n\nThe web app can check that an event is supported by the Android binary. For example, to check that the app supports\nGoogle Pay card tokenization, you can use:\n\n```ts\nimport { eventBridge } from 'racehorse';\n\neventBridge.isSupported('org.racehorse.GooglePayTokenizeEvent');\n// ⮕ true\n```\n\n# Proguard\n\n`org.racehorse:racehorse` is an Android library (AAR) that provides its own\n[proguard rules](https://github.com/smikhalevski/racehorse/tree/master/android/racehorse/proguard-rules.pro), so no\nadditional action is needed. Proguard rules prevent obfuscation of events and related classes available in Racehorse.\n\nFor example, this class and its members won't be minified:\n\n```kotlin\nclass ShowToastEvent(val message: String) : WebEvent\n```\n\n# Activity plugin\n\n[`ActivityManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.ActivityManager.html) starts\nactivities and provides info about the activity that renders the WebView.\n\nAdd the Lifecycle dependency to your Android app:\n\n```kotlin\ndependencies {\n    implementation(\"androidx.lifecycle:lifecycle-process:2.8.5\")\n}\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.ActivityPlugin\n\nEventBus.getDefault().register(ActivityPlugin().apply { enable() })\n```\n\nStart a new activity. For example, here's how to open the Settings app and navigate the user to notification settings:\n\n```ts\nimport { activityManager, Intent } from 'racehorse';\n\nactivityManager.startActivity({\n  action: 'android.settings.APP_NOTIFICATION_SETTINGS',\n  flags: Intent.FLAG_ACTIVITY_NEW_TASK,\n  extras: {\n    'android.provider.extra.APP_PACKAGE': activityManager.getActivityInfo().packageName,\n  },\n});\n```\n\nSynchronously read the status of the current activity or subscribe to its changes:\n\n```ts\nimport { activityManager, ActivityState } from 'racehorse';\n\nactivityManager.getActivityState();\n// ⮕ ActivityState.BACKGROUND\n\nactivityManager.subscribe(state => {\n  // React to activity state changes\n});\n\nactivityManager.subscribe('foreground', () => {\n  // React to activity entering foreground\n});\n```\n\nIf you are using React, refer to the\n[`useActivityState`](https://smikhalevski.github.io/racehorse/functions/_racehorse_react.useActivityState.html)\nhook, which re-renders a component when the activity state changes.\n\n```tsx\nimport { useActivityState } from '@racehorse/react';\n\nconst state = useActivityState();\n// ⮕ ActivityState.BACKGROUND\n```\n\n# Asset loader plugin\n\nThe asset loader plugin requires [WebView events](#webview-events) to be enabled.\n\nAdd the WebKit dependency:\n\n```kotlin\ndependencies {\n    implementation(\"androidx.webkit:webkit:1.11.0\")\n}\n```\n\nLoad static assets from a directory on the device when a particular URL is requested in the WebView:\n\n```kotlin\nimport androidx.webkit.WebViewAssetLoader\nimport org.racehorse.AssetLoaderPlugin\nimport org.racehorse.StaticPathHandler\n\nEventBus.getDefault().register(\n    AssetLoaderPlugin(activity).apply {\n        registerAssetLoader(\n            \"https://example.com\",\n            StaticPathHandler(File(activity.filesDir, \"www\"))\n        )\n    }\n)\n\nwebView.loadUrl(\"https://example.com\")\n```\n\nDuring development, if you're running a server on localhost, use `ProxyPathHandler` to serve content to the WebView:\n\n```kotlin\nAssetLoaderPlugin(activity).apply {\n    registerAssetLoader(\n        \"https://example.com\",\n        ProxyPathHandler(\"http://10.0.2.2:10001\")\n    )\n}\n```\n\n`AssetLoaderPlugin` will open a URL in an external browser app if it isn't handled by any of the registered asset\nloaders. Since in the example above only `https://example.com` is handled by the asset loader, all other URLs are\nopened externally:\n\n```js\n// This would open a browser app and load google.com\nwindow.location.href = 'https://google.com';\n```\n\nTo disable this behaviour:\n\n```kotlin\nAssetLoaderPlugin(activity).apply {\n    isUnhandledRequestOpenedInExternalBrowser = false\n}\n```\n\n# Biometric plugin\n\n[`BiometricManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.BiometricManager.html) provides\nthe status of biometric support and allows enrolling for biometric auth.\n\nAdd the [Biometric](https://developer.android.com/jetpack/androidx/releases/biometric#declaring_dependencies) dependency\nto your Android app:\n\n```kotlin\ndependencies {\n    implementation(\"androidx.biometric:biometric:1.2.0-alpha05\")\n}\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.BiometricPlugin\n\nEventBus.getDefault().register(BiometricPlugin(activity))\n```\n\nRead the biometric status or enroll biometric:\n\n```ts\nimport { biometricManager, BiometricAuthenticator } from 'racehorse';\n\nbiometricManager.getBiometricStatus([BiometricAuthenticator.BIOMETRIC_WEAK]);\n// ⮕ BiometricStatus.NONE_ENROLLED\n\nbiometricManager.enrollBiometric();\n// ⮕ Promise<boolean>\n```\n\n# Biometric encrypted storage plugin\n\n[`BiometricEncryptedStorageManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.BiometricEncryptedStorageManager.html)\nenables file-based persistence of biometric-protected data.\n\nAdd the [Biometric](https://developer.android.com/jetpack/androidx/releases/biometric#declaring_dependencies) dependency\nto your Android app:\n\n```kotlin\ndependencies {\n    implementation(\"androidx.biometric:biometric:1.2.0-alpha05\")\n}\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.BiometricEncryptedStoragePlugin\n\nEventBus.getDefault().register(\n    BiometricEncryptedStoragePlugin(\n        activity,\n\n        // The directory where encrypted data is stored\n        File(activity.filesDir, \"biometric_storage\")\n    )\n)\n```\n\nRead and write encrypted key-value pairs to the storage:\n\n```ts\nimport { biometricEncryptedStorageManager, BiometricAuthenticator } from 'racehorse';\n\nawait biometricEncryptedStorageManager.set('foo', 'bar', {\n  title: 'Authentication required',\n  authenticators: [BiometricAuthenticator.BIOMETRIC_STRONG],\n});\n// ⮕ true\n\nawait biometricEncryptedStorageManager.get('foo');\n// ⮕ 'bar'\n```\n\nTo allow device credential authentication, provide an\n[`authenticationValidityDuration`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.BiometricConfig.html#authenticationvalidityduration)\nvalue greater than or equal to 0:\n\n```ts\nawait biometricEncryptedStorageManager.set('foo', 'bar', {\n  authenticators: [BiometricAuthenticator.DEVICE_CREDENTIAL],\n  authenticationValidityDuration: 0,\n});\n```\n\nIf a user enrolls biometric auth (for example, updates fingerprints stored on the device), all secret keys used by\nthe biometric-encrypted storage are invalidated and values become inaccessible.\n\n```js\nif (biometricEncryptedStorageManager.has(key)) {\n  // Storage contains the key\n\n  biometricEncryptedStorageManager.get(key).then(value => {\n    if (value !== null) {\n      // The value was successfully decrypted\n    } else {\n      // User authentication failed, or key was invalidated\n    }\n  });\n}\n```\n\nIf the user has not enrolled for biometric authentication, `set()` returns `false`. Check the enrollment status via\nthe [Biometric plugin](#biometric-plugin) before using the store:\n\n```ts\nif (biometricManager.getBiometricStatus([BiometricAuthenticator.BIOMETRIC_STRONG]) === BiometricStatus.SUPPORTED) {\n  await biometricEncryptedStorageManager.set('foo', 'bar');\n}\n```\n\n# Contacts plugin\n\n[`ContactsManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.ContactsManager.html) provides access\nto contacts stored on the device.\n\nAdd the contacts permission to the app manifest:\n\n```xml\n<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.ContactsPlugin\n\nEventBus.getDefault().register(ContactsPlugin(activity))\n```\n\nAsk a user to pick a contact or get a contact by its ID:\n\n```ts\nimport { contactsManager } from 'racehorse';\n\ncontactsManager.pickContact();\n// ⮕ Promise<Contact | null>\n\ncontactsManager.getContact(42);\n// ⮕ Contact | null\n```\n\n# Deep link plugin\n\n[`DeepLinkManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.DeepLinkManager.html) provides access\nto deep links inside your web app.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.DeepLinkPlugin\n\nEventBus.getDefault().register(DeepLinkPlugin())\n```\n\nOverride\n[`onNewIntent`](<https://developer.android.com/reference/android/app/Activity#onNewIntent(android.content.Intent)>)\nin the main activity of your app and post the deep link event:\n\n```kotlin\noverride fun onNewIntent(intent: Intent) {\n    super.onNewIntent(intent)\n\n    eventBus.post(OpenDeepLinkEvent(intent))\n}\n```\n\nSubscribe to new intents in the web app:\n\n```ts\nimport { deepLinkManager } from 'racehorse';\n\ndeepLinkManager.subscribe(intent => {\n  // Handle the deep link intent\n});\n```\n\n# Device plugin\n\n[`DeviceManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.DeviceManager.html) provides access\nto various device settings.\n\nAdd the compat library dependency, which is used for window insets acquisition:\n\n```kotlin\ndependencies {\n    implementation(\"androidx.appcompat:appcompat:1.7.0\")\n}\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.DevicePlugin\n\nEventBus.getDefault().register(DevicePlugin(activity))\n```\n\nSynchronously get device info, locale, or other data:\n\n```ts\nimport { deviceManager } from 'racehorse';\n\ndeviceManager.getDeviceInfo().apiLevel;\n// ⮕ 33\n\ndeviceManager.getPreferredLocales();\n// ⮕ ['en-US']\n```\n\nIf you are using React, refer to the\n[`useWindowInsets`](https://smikhalevski.github.io/racehorse/functions/_racehorse_react.useWindowInsets.html) hook\nto synchronize document paddings and window insets:\n\n```ts\nimport { useLayoutEffect } from 'react';\nimport { useWindowInsets } from '@racehorse/react';\n\nconst windowInsets = useWindowInsets();\n\nuseLayoutEffect(() => {\n  document.body.style.padding =\n    windowInsets.top + 'px ' + windowInsets.right + 'px ' + windowInsets.bottom + 'px ' + windowInsets.left + 'px';\n}, [windowInsets]);\n```\n\n# Download plugin\n\n[`DownloadManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.DownloadManager.html) allows starting\nand monitoring file downloads.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.DownloadPlugin\n\nEventBus.getDefault().register(DownloadPlugin(activity))\n```\n\nRead previously started downloads or start a new one:\n\n```ts\nimport { downloadManager } from 'racehorse';\n\ndownloadManager.addDownload('http://example.com/my.zip').then(id => {\n  downloadManager.getDownload(id);\n  // ⮕ Download { id: 1, status: 4, uri: 'http://example.com/my.zip' }\n});\n\ndownloadManager.getAllDownloads();\n```\n\nA [`Download`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.Download.html) instance carries the\ndownload status, progress, and file details.\n\nA storage permission must be added to support Android devices with API level <= 29:\n\n```xml\n<uses-permission\n    android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"\n    tools:ignore=\"ScopedStorage\"/>\n```\n\n## Android 29 support\n\nOn Android 29, a `SecurityException` is thrown when calling the deprecated method\n[`DownloadManager.addCompletedDownload`](<https://developer.android.com/reference/android/app/DownloadManager#addCompletedDownload(java.lang.String,%20java.lang.String,%20boolean,%20java.lang.String,%20java.lang.String,%20long,%20boolean)>)\nif the `android.permission.WRITE_EXTERNAL_STORAGE` permission isn't granted. This method is used by Racehorse to\npopulate the list of previous downloads when a data URI is downloaded. To fix this exception,\n[the legacy external storage model](https://developer.android.com/training/data-storage/use-cases#opt-out-in-production-app)\nmust be enabled in the Android manifest for API level 29.\n\nCreate a resource file for default config values at `src/main/res/values/config.xml`:\n\n```xml\n<resources>\n    <bool name=\"request_legacy_external_storage\">false</bool>\n</resources>\n```\n\nCreate a resource file specific to API level 29 at `src/main/res/values-v29/config.xml`:\n\n```xml\n<resources>\n    <bool name=\"request_legacy_external_storage\">true</bool>\n</resources>\n```\n\nConfigure the legacy external storage setting in the Android manifest file:\n\n```xml\n<application\n    android:requestLegacyExternalStorage=\"@bool/request_legacy_external_storage\"\n/>\n```\n\n## Downloadable links\n\nDownloadable links have a [`download`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) attribute:\n\n```html\n<a\n  href=\"data:image/gif;base64,R0lGODlhBwAGAJEAAAAAAP////RDNv///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAADACwAAAAABwAGAAACCpxkeMudOyKMkhYAOw==\"\n  download\n>\n  Download image\n</a>\n```\n\nInitialize the\n[`DownloadPlugin`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-download-plugin/index.html)\nas described in the previous section, and add a Racehorse listener to enable automatic handling of downloadable links:\n\n```kotlin\nimport org.racehorse.webview.RacehorseDownloadListener\n\nwebView.setDownloadListener(RacehorseDownloadListener())\n```\n\n# Encrypted storage plugin\n\n[`EncryptedStorageManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.EncryptedStorageManager.html)\nenables file-based persistence of password-protected data.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.EncryptedStoragePlugin\n\nEventBus.getDefault().register(\n    EncryptedStoragePlugin(\n        // The directory where encrypted data is stored\n        File(activity.filesDir, \"storage\"),\n\n        // The salt required to generate the encryption key\n        BuildConfig.APPLICATION_ID.toByteArray()\n    )\n)\n```\n\nRead and write encrypted key-value pairs to the storage:\n\n```ts\nimport { encryptedStorageManager } from 'racehorse';\n\nconst PASSWORD = '12345';\n\nawait encryptedStorageManager.set('foo', 'bar', PASSWORD);\n// ⮕ true\n\nawait encryptedStorageManager.get('foo', PASSWORD);\n// ⮕ 'bar'\n```\n\n# Evergreen plugin\n\n[`EvergreenManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.EvergreenManager.html) provides\na way to update your app using an archive downloadable from your server.\n\nYou can find an extensive demo of evergreen plugin usage [in the example app](#example-app).\n\nInit the plugin and start the update download process:\n\n```kotlin\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport org.racehorse.evergreen.EvergreenPlugin\n\nclass MyActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        val evergreenPlugin = EvergreenPlugin(File(filesDir, \"app\"))\n\n        EventBus.getDefault().register(evergreenPlugin)\n\n        Thread {\n            // 🟡 Start the update process\n            evergreenPlugin.start(version = \"1.0.0\", updateMode = UpdateMode.MANDATORY) {\n                URL(\"http://example.com/bundle.zip\").openConnection()\n            }\n        }.start()\n    }\n}\n```\n\nThe snippet above downloads `bundle.zip`, unpacks it, and stores the assets in the `<filesDir>/app` directory. These\nassets are labeled as version 1.0.0. During future app launches, the plugin will notice it already has the assets for\nversion 1.0.0 and will skip the download. If the version changes, the update bundle will be downloaded again.\n\nAfter the update is downloaded, a\n[`BundleReadyEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse.evergreen/-bundle-ready-event/index.html)\nevent is posted. You can use the [`AssetLoaderPlugin`](#asset-loader-plugin) to load resources provided by the evergreen\nplugin:\n\n```kotlin\n@Subscribe(threadMode = ThreadMode.MAIN)\nfun onBundleReady(event: BundleReadyEvent) {\n\n    EventBus.getDefault().register(\n        // Loads static assets when a particular URL is requested\n        AssetLoaderPlugin(\n            activity,\n            WebViewAssetLoader.Builder()\n                .setDomain(\"example.com\")\n                .addPathHandler(\n                    \"/\",\n                    // 🟡 Use assets provided by the evergreen plugin\n                    StaticPathHandler(event.appDir)\n                )\n                .build()\n        )\n    )\n\n    webView.loadUrl(\"https://example.com\")\n}\n```\n\nEvergreen plugin keeps track of downloaded bundles:\n\n- The master bundle contains the current assets of the web app.\n- The pending update bundle contains assets that were downloaded but not yet applied as master.\n\n<!--HIDDEN-->\n\nBelow is the diagram of events posted by the evergreen plugin.\n\n```mermaid\ngraph TD\n\nstart[\"start(version, updateMode)\"]\n--> HasMasterBundle\n\nHasMasterBundle{{Has master bundle?}}\n-->|Yes| IsSameVersionAsMasterBundle{{Is same version as master bundle?}}\n\nHasMasterBundle\n-->|No| MandatoryUpdate\n\nIsSameVersionAsMasterBundle\n-->|Yes| MainBundleReadyEvent([BundleReadyEvent])\n\nIsSameVersionAsMasterBundle\n-->|No| HasPendingUpdateBundle{{Has pending update bundle?}}\n\nHasPendingUpdateBundle\n-->|Yes| IsSameVersionAsPendingUpdateBundle{{Is same version as pending update bundle?}}\n\nIsSameVersionAsPendingUpdateBundle\n-->|Yes| MainBundleReadyEvent\n\nIsSameVersionAsPendingUpdateBundle\n-->|No| IsMandatoryUpdateMode\n\nHasPendingUpdateBundle\n-->|No| IsMandatoryUpdateMode{{Is mandatory update mode?}}\n\nIsMandatoryUpdateMode\n---|No| BundleReadyEvent([\"BundleReadyEvent ¹\"])\n--> OptionalUpdate\n\nIsMandatoryUpdateMode\n--->|Yes| MandatoryUpdate\n\nsubgraph OptionalUpdate [Optional update]\ndirection TB\nOptionalUpdateStartedEvent([UpdateStartedEvent])\n--> OptionalUpdateProgressEvent([UpdateProgressEvent])\n--> OptionalUpdateReadyEvent([UpdateReadyEvent])\nend\n\nsubgraph MandatoryUpdate [Mandatory update]\ndirection TB\nMandatoryUpdateStartedEvent([UpdateStartedEvent])\n--> MandatoryUpdateProgressEvent([UpdateProgressEvent])\n--> MandatoryBundleReadyEvent([BundleReadyEvent])\nend\n```\n\n¹ The app is started with the assets from the available master bundle while the update is downloaded in the background.\n\n<!--/HIDDEN-->\n\nYou can monitor background updates and apply them as soon as they are ready:\n\n```ts\nimport { evergreenManager } from 'racehorse';\n\n// 1️⃣ Wait for the update bundle to be downloaded\nevergreenManager.subscribe('ready', () => {\n  // 2️⃣ Apply the update\n  evergreenManager.applyUpdate().then(() => {\n    // 3️⃣ Reload the web app to use the latest assets\n    window.location.reload();\n  });\n});\n```\n\n# Facebook Login plugin\n\n[`FacebookLoginManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.FacebookLoginManager.html)\nenables Facebook Login support.\n\nGo to [developers.facebook.com](https://developers.facebook.com/docs/facebook-login/android/), register your app, and\nadd the required dependencies and configurations.\n\nInitialize the Facebook SDK and register the plugin in your Android app:\n\n```kotlin\nimport com.facebook.FacebookSdk\nimport org.racehorse.FacebookLoginPlugin\n\nFacebookSdk.sdkInitialize(activity)\n\nEventBus.getDefault().register(FacebookLoginPlugin(activity))\n```\n\nRequest sign-in from the web app loaded into the WebView:\n\n```ts\nimport { facebookLoginManager } from 'racehorse';\n\nfacebookLoginManager.logIn().then(accessToken => {\n  // The accessToken is non-null if log-in succeeded\n});\n```\n\n# Facebook Share plugin\n\n[`FacebookShareManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.FacebookShareManager.html)\nenables Facebook social sharing.\n\nGo to [developers.facebook.com](https://developers.facebook.com/docs/facebook-login/android/), register your app, and\nadd the required dependencies and configurations.\n\nInitialize the Facebook SDK and register the plugin in your Android app:\n\n```kotlin\nimport com.facebook.FacebookSdk\nimport org.racehorse.FacebookSharePlugin\n\nFacebookSdk.sdkInitialize(activity)\n\nEventBus.getDefault().register(FacebookSharePlugin(activity))\n```\n\nTrigger the Facebook social sharing flow:\n\n```ts\nimport { facebookShareManager } from 'racehorse';\n\nfacebookShareManager.shareLink({\n  contentUrl: 'http://example.com',\n});\n```\n\n# File chooser plugin\n\nThe file chooser plugin requires [WebView events](#webview-events) to be enabled. This plugin enables file inputs in\nthe web app.\n\nFor example, if you have a file input:\n\n```html\n<input type=\"file\" />\n```\n\nYou can register a plugin to make this input open a file chooser dialog:\n\n```kotlin\nimport org.racehorse.FileChooserPlugin\n\nEventBus.getDefault().register(FileChooserPlugin(activity))\n```\n\nIf you don't need camera support for file inputs, the plugin doesn't require any additional configuration.\n\n## Enabling camera capture\n\nCamera capture requires a temporary file storage location to write captured files to.\n\nDeclare a provider in your app manifest:\n\n```xml\n<manifest>\n    <application>\n        <provider\n            android:name=\"androidx.core.content.FileProvider\"\n            android:authorities=\"${applicationId}.provider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/file_paths\"/>\n        </provider>\n    </application>\n</manifest>\n```\n\nAdd a provider paths descriptor to XML resources, for example at `src/main/res/xml/file_paths.xml`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n    <cache-path name=\"cacheDir\" path=\"/\"/>\n</paths>\n```\n\nInitialize the plugin in your Android app, providing the authority of the provider you created and the path defined in\nthe descriptor:\n\n```kotlin\nimport org.racehorse.FileChooserPlugin\nimport org.racehorse.TempCameraFileFactory\n\nEventBus.getDefault().register(\n    FileChooserPlugin(\n        activity,\n\n        TempCameraFileFactory(\n            activity,\n            activity.cacheDir,\n            BuildConfig.APPLICATION_ID + \".provider\"\n        )\n    )\n)\n```\n\nIf you want to store images and videos in the gallery app after they were captured through the file chooser, use\n[`GalleryCameraFileFactory`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-gallery-camera-file-factory/index.html).\n\n# File system plugin\n\n[`FsManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.FsManager.html) enables file system CRUD\noperations.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.FsPlugin\n\nEventBus.getDefault().register(FsPlugin(activity))\n```\n\nAccess files stored on the device from a WebView:\n\n```ts\nimport { fsManager, Directory } from 'racehorse';\n\nconst file = fsManager.open(Directory.CACHE, 'temp.txt');\n\nawait file.writeText('Hello world!');\n\nawait file.readDataUri();\n// ⮕ 'data:text/plain;base64,SGVsbG8gd29ybGQh'\n```\n\n## Serving local files\n\nTo load an arbitrary file from the WebView, use\n[`localUrl`](https://smikhalevski.github.io/racehorse/classes/racehorse.File.html#localurl):\n\n```ts\nimport { contactsManager, fsManager } from 'racehorse';\n\nconst contact = await contactsManager.pickContact();\n\nconst photoUrl = fsManager.open(contact.photoUri).localUrl;\n// ⮕ 'https://racehorse.local/fs?uri=…'\n```\n\nThe local URL can be used as a source for an image or an iframe:\n\n```ts\ndocument.getElementsByTagName('img')[0].src = photoUrl;\n```\n\n# Google Pay plugin\n\n[`GooglePayManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.GooglePayManager.html) enables\n[Android Push Provisioning](https://developers.google.com/pay/issuers/apis/push-provisioning/android) support.\n\n[Set up the development environment](https://developers.google.com/pay/issuers/apis/push-provisioning/android/setup)\nso the TapAndPay SDK is available in your app.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.GooglePayPlugin\n\nclass MainActivity : AppCompatActivity() {\n\n    private lateinit var googlePayPlugin: GooglePayPlugin\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        googlePayPlugin = GooglePayPlugin(this)\n\n        EventBus.getDefault().register(googlePayPlugin)\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n\n        // 🟡 Dispatch results back to the plugin\n        googlePayPlugin.dispatchResult(requestCode, resultCode, data)\n    }\n}\n```\n\nCheck that Google Pay is supported and properly configured by retrieving the current environment:\n\n```ts\nawait googlePayManager.getEnvironment();\n// ⮕ 'production'\n```\n\nThis call may throw an `ApiException` error that provides insight into configuration and availability issues.\n\nTo get token info from the wallet:\n\n```ts\nasync function getTokenInfo(lastFour: string): GooglePayTokenInfo | undefined {\n  (await googlePayManager.listTokens()).find(\n    tokenInfo =>\n      (tokenInfo.dpanLastFour === lastFour || tokenInfo.fpanLastFour === lastFour) &&\n      tokenInfo.tokenServiceProvider === GooglePayTokenServiceProvider.MASTERCARD\n  );\n}\n```\n\nTo tokenize a card or resume a previously aborted tokenization:\n\n```ts\nasync function tokenizeCard(lastFour: string): GooglePayTokenInfo {\n  const tokenInfo = await getTokenInfo(lastFour);\n\n  if (!tokenInfo || tokenInfo.tokenState === GooglePayTokenState.UNTOKENIZED) {\n    // 1️⃣ The card isn't tokenized\n    await googlePayManager.pushTokenize({\n      lastFour: lastFour,\n      network: GooglePayCardNetwork.MASTERCARD,\n      tokenServiceProvider: GooglePayTokenServiceProvider.MASTERCARD,\n      // opaquePaymentCard\n      // userAddress\n      // displayName\n    });\n  } else if (tokenInfo.tokenState === GooglePayTokenState.ACTIVE) {\n    // 2️⃣ Card is already tokenized\n    return tokenInfo;\n  } else {\n    // 3️⃣ Resume card tokenization (yellow path)\n    await googlePayManager.tokenize({\n      tokenId: tokenInfo.issuerTokenId,\n      network: GooglePayCardNetwork.MASTERCARD,\n      tokenServiceProvider: GooglePayTokenServiceProvider.MASTERCARD,\n      // displayName\n    });\n  }\n\n  return getTokenInfo(lastFour);\n}\n```\n\nTo open the wallet app and reveal the tokenized card:\n\n```ts\nasync function revealCard(lastFour: string): Promise<boolean> {\n  const tokenInfo = await getTokenInfo(lastFour);\n\n  return tokenInfo ? googlePayManager.viewToken(tokenInfo.issuerTokenId, tokenInfo.tokenServiceProvider) : false;\n}\n```\n\n# Google Play referrer plugin\n\n[`GooglePlayReferrerManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.GooglePlayReferrerManager.html)\nfetches the [Google Play referrer](https://developer.android.com/google/play/installreferrer/library) information.\n\nAdd the Google Play referrer SDK dependency to your Android app:\n\n```kotlin\ndependencies {\n    implementation(\"com.android.installreferrer:installreferrer:2.2\")\n}\n```\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.GooglePlayReferrerPlugin\n\nEventBus.getDefault().register(GooglePlayReferrerPlugin(activity))\n```\n\nRead the Google Play referrer:\n\n```ts\nimport { googlePlayReferrerManager } from 'racehorse';\n\ngooglePlayReferrerManager.getGooglePlayReferrer();\n// ⮕ Promise<string>\n```\n\n# Google Sign-In plugin\n\n[`GoogleSignInManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.GoogleSignInManager.html)\nenables Google Sign-In support.\n\nGo to [console.firebase.google.com](https://console.firebase.google.com), set up a new project, and configure an\nAndroid app following all instructions. Use the `applicationId` of your app and the SHA-1 used for app signing. You can\nuse Gradle to retrieve SHA-1:\n\n```shell\n./gradlew signingReport\n```\n\nGo to [Google Cloud Console](https://console.cloud.google.com/apis/credentials) for your project and add an OAuth\nclient ID for Android.\n\nAdd the Google Sign-In SDK dependencies to your Android app:\n\n```kotlin\ndependencies {\n    implementation(\"com.google.android.gms:play-services-auth:21.2.0\")\n    implementation(platform(\"com.google.firebase:firebase-bom:32.1.2\"))\n}\n```\n\nRegister the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.GoogleSignInPlugin\n\nEventBus.getDefault().register(GoogleSignInPlugin(activity))\n```\n\nRequest sign-in from the web app loaded into a WebView:\n\n```ts\nimport { googleSignInManager } from 'racehorse';\n\ngoogleSignInManager.signIn().then(account => {\n  // The account is non-null if sign-in succeeded\n});\n```\n\n# HTTPS plugin\n\nThe HTTPS plugin requires [WebView events](#webview-events) to be enabled. It forces the WebView to ignore certificate\nissues.\n\n```kotlin\nimport org.racehorse.HttpsPlugin\n\nEventBus.getDefault().register(HttpsPlugin())\n```\n\n# Keyboard plugin\n\n[`KeyboardManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.KeyboardManager.html) toggles\nthe software keyboard and notifies about keyboard animations.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.KeyboardPlugin\n\nEventBus.getDefault().register(KeyboardPlugin(activity).apply { enable() })\n```\n\nSynchronously read the keyboard height, or show/hide the keyboard:\n\n```ts\nimport { keyboardManager } from 'racehorse';\n\nkeyboardManager.showKeyboard();\n// ⮕ true\n\nkeyboardManager.getKeyboardHeight();\n// ⮕ 630\n```\n\nSubscribe to the keyboard manager to receive notifications when a keyboard animation starts:\n\n```ts\nkeyboardManager.subscribe(animation => {\n  // Handle the started animation here.\n});\n```\n\nIf you are using React, use the\n[`useKeyboardAnimation`](https://smikhalevski.github.io/racehorse/functions/_racehorse_react.useKeyboardAnimation.html)\nhook to subscribe to keyboard animations from a component:\n\n```tsx\nimport { useKeyboardAnimation } from '@racehorse/react';\n\nuseKeyboardAnimation((animation, signal) => {\n  // Signal is aborted if the animation is cancelled.\n});\n```\n\nUse [`runAnimation`](https://smikhalevski.github.io/racehorse/functions/racehorse.runAnimation.html) to run the\nanimation. For example, if your\n[app is rendered edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge), you can animate\nthe bottom padding to compensate for the height of the keyboard.\n\n```ts\nimport { useKeyboardAnimation, runAnimation } from '@racehorse/react';\n\nuseKeyboardAnimation((animation, signal) => {\n  // Run the animation in sync with the native keyboard animation.\n  runAnimation(\n    animation,\n    {\n      onProgress(animation, fraction, percent) {\n        const keyboardHeight = animation.startValue + (animation.endValue - animation.startValue) * fraction;\n\n        document.body.style.paddingBottom = keyboardHeight + 'px';\n      },\n    },\n    signal\n  );\n});\n```\n\nYou may also want to scroll the window to prevent the focused element from being obscured by the keyboard. Use\n[`scrollToElement`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.scrollToElement.html) to animate\nscrolling in sync with the keyboard animation:\n\n```ts\nimport { useKeyboardAnimation, scrollToElement } from '@racehorse/react';\n\nuseKeyboardAnimation((animation, signal) => {\n  // Ensure there's an active element to scroll to.\n  if (document.activeElement === null && !document.hasFocus()) {\n    return;\n  }\n\n  scrollToElement(document.activeElement, {\n    // Scroll animation will have the same duration and easing as the keyboard animation.\n    animation,\n    paddingBottom: animation.endValue,\n    signal,\n  });\n});\n```\n\nCheck out [the example app](https://github.com/smikhalevski/racehorse/tree/master/web/example/src/App.tsx#L45) for\nreal-world keyboard animation handling.\n\n<br/>\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/smikhalevski/racehorse/refs/heads/master/images/keyboard-animation.gif\" alt=\"Keyboard animation\" width=\"300\"/>\n</p>\n\n# Network plugin\n\n[`NetworkManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.NetworkManager.html) enables network\nconnection monitoring support.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.NetworkPlugin\n\nval networkPlugin = NetworkPlugin(activity)\n\nEventBus.getDefault().register(networkPlugin)\n```\n\nEnable the plugin when the app resumes and disable it when the app pauses:\n\n```kotlin\nfun onResume() {\n    super.onResume()\n    networkPlugin.enable()\n}\n\nfun onPause() {\n    super.onPause()\n    networkPlugin.disable()\n}\n```\n\nSynchronously read the network connection status or subscribe to changes:\n\n```ts\nimport { networkManager } from 'racehorse';\n\nnetworkManager.getNetworkStatus().isConnected;\n// ⮕ true\n\nnetworkManager.subscribe(status => {\n  // React to network status changes\n});\n```\n\nIf you are using React, refer to the\n[`useNetworkStatus`](https://smikhalevski.github.io/racehorse/functions/_racehorse_react.useNetworkStatus.html)\nhook, which re-renders a component when the network status changes.\n\n```tsx\nimport { useNetworkStatus } from '@racehorse/react';\n\nconst status = useNetworkStatus();\n\nstatus.isConnected;\n// ⮕ true\n\nstatus.type;\n// ⮕ 'wifi'\n```\n\n# Notifications plugin\n\n[`NotificationsManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.NotificationsManager.html)\nprovides access to Android system notification status.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.NotificationsPlugin\n\nEventBus.getDefault().register(NotificationsPlugin(activity))\n```\n\nSynchronously check that notifications are enabled:\n\n```ts\nimport { notificationsManager } from 'racehorse';\n\nnotificationsManager.areNotificationsEnabled();\n// ⮕ true\n```\n\n# Permissions plugin\n\n[`PermissionsManager`](https://smikhalevski.github.io/racehorse/interfaces/racehorse.PermissionsManager.html)\nallows checking and requesting application permissions.\n\nInitialize the plugin in your Android app:\n\n```kotlin\nimport org.racehorse.PermissionsPlugin\n\nEventBus.getDefault().register(PermissionsPlugin(activity))\n```\n\nCheck that a permission is granted, or ask for permissions:\n\n```ts\nimport { permissionsManager } from 'racehorse';\n\npermissionsManager.isPermissionGranted('android.permission.ACCESS_WIFI_STATE');\n// ⮕ true\n\npermissionsManager.askForPermission('android.permission.CALL_PHONE');\n// ⮕ Promise<boolean>\n```\n\n# Cookbook\n\n## Blur preview on recent apps screen\n\nPost a custom\n[`NoticeEvent`](https://smikhalevski.github.io/racehorse/android/racehorse/org.racehorse/-notice-event/index.html) in\n[`onWindowFocusChanged`](<https://developer.android.com/reference/android/app/Activity#onWindowFocusChanged(boolean)>):\n\n```kotlin\npackage com.myapplication\n\nimport org.greenrobot.eventbus.EventBus\nimport org.racehorse.NoticeEvent\n\nclass WindowFocusChangedEvent(val hasFocus: Boolean) : NoticeEvent\n\nclass MainActivity {\n\n    // Don't forget to init Racehorse here\n\n    override fun onWindowFocusChanged(hasFocus: Boolean) {\n        EventBus.getDefault().post(WindowFocusChangedEvent(hasFocus))\n    }\n}\n```\n\nIn the web app, subscribe to this event and apply a blur filter to the body:\n\n```ts\neventBridge.subscribe('com.myapplication.WindowFocusChangedEvent', payload => {\n  document.body.style.filter = payload.hasFocus ? 'none' : 'blur(30px)';\n});\n```\n\nNow your application will appear blurred when it moves to the background and unblurred when it returns to the\nforeground.\n\n<!--/ARTICLE-->\n","readmeFilename":"README.md"}