{"_id":"@hilma/tools","_rev":"39-eeeffa5ed6416df7675632b8f2e11be0","name":"@hilma/tools","dist-tags":{"latest":"1.1.0","beta":"0.0.0-XhUgS5tz"},"versions":{"0.1.0":{"version":"0.1.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"husky":{"hooks":{"pre-commit":"tsdx lint"}},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"description":"Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it.","_id":"@hilma/tools@0.1.0","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-XlaBhhC4A297T7xtnNeklnC7fm52mqcLUGaW1JJFsEaH18GvQIIbjmTDyJl/ojZEhvzzoEzkwacyGDolQWr1vw==","shasum":"d531cfea2d338aec901bc6be3a2a0e23764438c7","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.0.tgz","fileCount":38,"unpackedSize":259581,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezl/iCRA9TVsSAnZWagAARdIP/0T7yhBerGsYksTWKrnB\nT2DYMgxrLx5z2J5f1rlgftRGI08Ks60RqCdSdlETM0E3lrOQ0nFW/KA32A9L\n6kBYZSNTlZhE+VE1qwplYdzGWzJ/cor+SukgajOK6gb/C3Dr2bbMGj5BLvV/\necsPE+9AvVrC4CLnxjEeonxsNY8ndf5eNcXTVp+I3I9B0cQrbqzMi0NOTv/H\ngLS6QkJqpSWNGBR3QPmW/eEN0XvS05JIQ0fCLnhvC6ovxgRpNbqRG+hvVYf4\n3b/6I2RVIJoa4bzcm0X1QhlnG9CNF3OhLW1t8TipiSnZNg/fiBIh3xUOhZCd\nHf8b/XqG8Jfyk9CHrcNNnPG+hJSio6kghOQv6hgrTswucBF8aAVRozuuUHWt\n4A1jSwKCmMjYN53JQXCeZ2h/ntXwq9vs3AqDQresU/mUhRhOx9Plm4KtO5Lg\nSi9timfRRRCaTNEELgTYZf/9bNhqruvo4jRxeQLJHSdoFaududALKhpV7cU9\n3wxrJDrW3KFYS8sG/t7VeO/kBYZVz/LkOz/8M8LxZwx0aKyCS03ftoaFYCsl\ny0axXYpPHXbjLnVADD0RUtHlCpifBW+ivEPjwabAhHg/PAgFYcntI6sTn2nN\nVVPWfylCd1nybivwLOq+yTWPJPL1gcV4fJK05Tx1lAjI72mCl+hWGZPCQqDQ\nWjIV\r\n=DR/1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6vpTphAHCMMXNHlAZ73m4zqAeYGDo9Jz3Yx7TSoJ3pwIgJJ79aH+JNIlm8KD6kAYTH+5ddMrS5S91niC0Ogek7uQ="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.0_1590583266019_0.1821606709075958"},"_hasShrinkwrap":false},"0.1.1":{"version":"0.1.1","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"husky":{"hooks":{"pre-commit":"tsdx lint"}},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"_id":"@hilma/tools@0.1.1","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-BUCXfUk/m0E+3MFYc02kn0LAyfAFT3yDGtON6P9NytSB4PMkMW7npVoacsVIT5MxFYNKT6C0pLX2dhw/YwOatg==","shasum":"b00a40c03e8d013394e31baeec695f720c4df081","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.1.tgz","fileCount":37,"unpackedSize":253338,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezmC3CRA9TVsSAnZWagAAcDYQAIxesrW0W434ZC4NOSGI\nFH0ZO8shE1bs8Qogm0vGQoG0cM2tLhXs7sy4Zm4LPEwzqyhbjZYJcOdh8hmn\nbAugYsRK+C3vR4oSYnsr45AlWdgedA6s+q53BGWwbsUqswod3gdDpiXm+luH\nVLrJ5np7nzEAfQwN+xlH8vdpYGKTHq+z4QOKveHBTPJav+e1TU28CjGjdUav\nsPtSt7S+mVo7zHSDXH1XpGf2ix+Ln4jeTFZFCYmixp8oPlfcxMjAxZ7RzF4x\nQPlUaf6y7Ndv1POfi6J5lDK6ejU9I6uXBVTmWRiH308bXH5MVtwX7ITY+bfL\n4PrFuDKOAzq3Tne6Me+jgEjAbuDtgDA9XF5wgomsGsda5KntMVpFCVvLiXe7\nKqokuNFs0TMyoKKhVJryBu22cj/fI12I9aSKRNY2YGOf4CJBSHvXkT0DilsM\njDFIoTgxV8BD0V8Yr9VteNRlHsdjkD6XyjrOsrn5XmEZ2MYiBuSJBkcbqB9K\nEO211mOL1/gdzKeWshK3CZmOli+6LLA0yGVn5z6FSlhfOf8GmNF2Jzd4XwUy\n0UGzoeZHt91FxXcuvZey/YD82OX4LpsmNkJPzs9VXMhozoxMLq6CZJdre9zD\n3rYIRKhBpDVE1T6FRLo/V58NV2ES9tkU/AK0WN6HXvUgEWtdV6HtSmOsYZ3j\nZrT5\r\n=9iMU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHcB3Rnk7eSNxI1ntjSsFuJA92MdbPbigQdDglCFhNX8AiBXintiK4oaXruz/XKj2of7p/yXm1XWw25x3sT0Dx94kQ=="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.1_1590583479295_0.4191283910242236"},"_hasShrinkwrap":false},"0.1.2":{"version":"0.1.2","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"husky":{"hooks":{"pre-commit":"tsdx lint"}},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"_id":"@hilma/tools@0.1.2","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-l6bSWrrqolpTs+hZQyYa8HiAC5zW45u3zXZ2d5EHksoUuRlpSLG0ZAuOT/G8fbV74qRXQFV6xlR3gyW56uSxHA==","shasum":"9b62bba58a2a97c9d6737010471d0bc52dfdd635","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.2.tgz","fileCount":37,"unpackedSize":253322,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJezmF3CRA9TVsSAnZWagAAv5UQAI+VGXZv6NsEA7mOnbOd\nubizpSOvibDBrSiV06u0pQTJAlXZmScJ2V2neBBPsI6zBxVReNXgeOUpO4pw\n7aa6kG1Rlr+mE/djEkjwu+Ndv1bIRoZHWv7RADTMLyOirkNT6e4hwAbju4CC\n7y28bPOgszLJFesBVPM3mJT4LfiYzf/al9dapaGP4F4LArjxU3Occ/kKAIQo\ncwgzmXcmSnzp9FeqmAYcz7HiowxdiXOpxU9mHh+fRSkN5wEGmnAqXiDhqlC2\nFpCfjH8af5a3R1cpzEaSW1fYj+W/nH3fG5L0dxovIMIqGyKpLgWsLke77PSA\nRnZrY8STQwWHlwJwaekXvcfFlpMpk+5PlMjcRMNcjy/CT0PunKdKsSTg2HYj\nAyjrtOobf5tr1oIR4A9zHhwRiYDe6CWgOFOsGsaEsYbX4CAvaHwoIsBqLqzN\nIPMiL3UBgVRr9AXHC0KJcIa61SCYmITdAEXOcu4kK8OTm8xbX07GebfNykxr\nd5DmvEhFlQVKB8y/i15VTYz1kDIElqZmtanAgsDBT8gC5Q/ldNEWAHS3dz/g\nvHmPWLmh0XrM06LFZGQcSvq86q30FXZfsfp5lzm1knxL0LiEb8+HhAOoxjsk\n/yoOcjiTyeAeWBFYkJme310b+Jmgate41x2qZen8Ew9l2QtAlFkiXkJhq7Jr\npfRE\r\n=EP+/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHGaJ95688SlWFEQGO4Zt2bg4HftRjFScae1lq0WJgBOAiEAvsGUnR/nk5DylN3L5d3glj9Fk7aQZzGzKgkv4LIjHi0="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.2_1590583671111_0.9659124834177293"},"_hasShrinkwrap":false},"0.1.3":{"version":"0.1.3","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"husky":{"hooks":{"pre-commit":"tsdx lint"}},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"_id":"@hilma/tools@0.1.3","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-nL34W7STzlcszSZa6A/q1ZqJS28ll5PaosuH+Y4UOLAJzETr4D4df7PQPptbYhnJNnaOBTktPArhMRuzYzDoNw==","shasum":"3ab81c507463fddd5e71ea0743cadf42e9e5c02c","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.3.tgz","fileCount":37,"unpackedSize":269785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3Rr1CRA9TVsSAnZWagAAlVEQAKJGlhaT6okyx1JFWzLG\nvFQlv+APfg5oIcXjdwVeSq2TAwblx0s6hKMd3kaMVB+jLORbiaM+j3FSy1jO\n6ReE6wnXf5gpSZM9Re2JFV/NDzZVkBpMwA99VoLbYzTRn1DV/VTNt6/5Gr5O\nYRjQJ7avUVeOQx3PecW3eZTD1djoE3daa7YiZ+hkFRwbrcvwYlWCLl9Fx0M3\no7TKF767Jvv/hQRak5s2FyxrS1GodOWaZ5C/CAURJQ2v/Q/NYGfF2SEFjjBH\npf+e7MrQBzKipSl4Ky3zSEqK7O2a6MyRbtyPZrDfk09X4pkdA6rdoRRDp6iK\nYAKk3nGBahpzEI6csbGN6UCOWtPyy5ztingR82tu3TAhQ1WH6zD/ADP925mN\now/gt4v998sERydM0q6djB2VqYlcxg84KdR6wXf2SAp1v8PhNLRGTARIeY1o\nVrMX66agpd/oxBbns+ZlEEzff0Epxd+dtjpmPBTqTuCfhfx3l9Wrmo9mwq/R\n/NpHZP9O2BDQaB6Juiguelxl3tbtsQs0udqWtVtuK1aZ6SC1vnTEFQcPVMmj\nWNLrneYHh48/ga3rWM+LYsu2vjkZoQhVa9QKFqXasqSamwdTZIFpmAWyf7uD\nxvTfcEnKtqZcJmFGnSQK9y3uktHHrMCkCi1ZTUooY9msZGKg1t6AGG5elO0N\nbp0S\r\n=NZpV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFIzHMvSsD/fT7apv88c4iOdr2qTVijp60qLyR+W7y/5AiBwR8DGG6FSYG5DVODXmQrAW5ceWIFEEctZrdGwYJsjaQ=="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.3_1591548660939_0.21367749457399565"},"_hasShrinkwrap":false},"0.1.4":{"version":"0.1.4","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"35c0ef69edd2492bd2c108073a3dd270cb0ded0f","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.4","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-z6o6MXq1GOZDcZkz37WYINw9ARZUfkoi/+hG610K+ZodbCaFSG6RaJFMLYQAbbcunBvwAy0QS/35YftwMWIpGQ==","shasum":"159ad8220f661129410188863505a28b79d9c758","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.4.tgz","fileCount":33,"unpackedSize":174563,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe3gQ1CRA9TVsSAnZWagAA9i0QAJMw0m8S+h/y7Gmf7iu9\nRy38dVWBP8u1CvngHbwfyk2STkF15+orr/clFJi3lZxG1QA+UF0w/pOL8vRx\nODCIvehTpHdQLC09ooOPyw2MIB+hPzJAmv/MDBGk6AFMhBmS5hWRTDYBxAJ6\nYPD535IqWoGpr9Vv4jUQCUKrVA+p+yLc39kUoYJeGYoFGjgzY0ngSBICi/2/\nJsagZsyfmQFm0U4/pJCxBdPydSvGt2reTNxGq2dGg4V1apLbcG/qjF7wJCk0\nfPHFO99tcSaB2ZKt9HhhHFq0gzYjWfbD2ydC7aiDLYQxF5nJXlKgNlxSz/Ku\n/Pc63qWueto3vLj55DWbnXsVhWxKrO9oKNjAfglFm7Nh/zQp1fKjaSy/IZnq\nnIcg/MilrOlcZSMIUE3ApNVfjSGvHUCTBQljIeIj7HyPiRDKa7BNTQr7kh5Y\nrzjy8Pc3Itvkea4g+qSv74txtYRgNCNx+QLSJSblK1UrY/Ryi4UeXaTFRFzb\nyHNbNPqjTMrc2euRBX4wyesfLbkK2UYsNxSVMeIjGMSSTBYJaznTjVm+V9C2\nbr4YjaBWAcZFszSneX/cJvQD60GD/nb/WLjFGCyfb/3srzIN2zgbCFLhAwCz\nMqY/7JlMH7Q9WG5idmPmjAjfgtNEKQDnEc9Ac/LkdLbzeUkcBddATjQWhUsC\nRGgA\r\n=dPoD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH8HCi/D/PW85HajuWJ9sg7ZksGSADDy8HeCaFVGdCrdAiEAw/03L6cwsS+4QhQOxAt4ST5NZM3vGEFFqTx/YXkNmK0="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.4_1591608372607_0.5645876647078578"},"_hasShrinkwrap":false},"0.1.5":{"version":"0.1.5","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"91c61ae4321aae9eb7dc44df28faa926ed9773d3","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.5","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-pL61PVPTtT0lzilSbaOmOHRlz0LlAOxqzxCJNsbSkkP+LjbYoL0GAmNEqQIuW3wqZNEudhe/6DCjb3Z6qqnYVQ==","shasum":"f755f663ed0ae9e7af9c0ae1f82af98b28c168b2","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.5.tgz","fileCount":35,"unpackedSize":258037,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe33xACRA9TVsSAnZWagAAwGIQAJ5CAatua0D5v5/wIG6g\nI6HGULWUGkc8ev+bq/FR5r96rPWm8mfklDlwceAKK4r3IhwWFkuY0jCZ5313\neJnpzgBt7WBLFNfHHUqFCt4P8ND6Ipx2gPnppWwOCOlSy2fSngMClB8bRCOR\nXDmff0MQdxyNzb3wKaTlKVB9zJPFsDD5reRAB8rVHpggQ8n3BCjJZf7SuBr6\ncn6fMTTMjjYnLucQ+g2L4GP06YSk7el8NbyJR+e2sRmOJlyYdjNxKGY4UwpB\npByAVnif+WrYNQM7kAwUPF2WUdvPSoqlMUi923BFHacTFN/kLK87Tkglv3Ar\nAmVYrRhQNHPYJ1aH3aQIxTr2zUszTISFNOExY+KFzEnT6qKQbl9ozg+i1fef\nxW5PdDYPOTeag5gECw/2jeEh4QGgORGR82noZ2HOtobQKYi1mLKmd4ySP6sa\nBqEdO6ltsDeJ5R7xrJF51HXkvuodmV49qCRTzOMlrpPgiLB433Q5Nlrf/y5g\n8fliFzC+PvYfXi2yd4cQW85WYfi7J7YlFYHqaxABdZ1aa5V7+VMsZHcL0s7T\nsXKjqdJfh7hxk3pYpLGV1qWVk7zeiwOmppdAoW+K+z2/ts1eziu91XQbEtLd\n8Nr7BGdRfGthkMMpRCB6bcCftUKvbbKbJDQPHiRc3qvFqPxgjOUqclDuyASA\nAHm7\r\n=05um\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAiECvLaJna6Cyo+MmsVX2d+bc3bjaT+qf8Hbzco7hOhAiBW1jZJgWGFrJUfcIxzHYOk6gBVMJxaw4xlO7+em/2GsA=="}]},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.5_1591704639367_0.8363027924728137"},"_hasShrinkwrap":false},"0.1.6":{"version":"0.1.6","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"91c61ae4321aae9eb7dc44df28faa926ed9773d3","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.6","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-I8kAO6wu+IWYqFa+o9Ig/UmlC8c55Rx7bviHs+TNJE1J5Fw7l3KXAPddbK31lC2Egy7K+oyC4BlMHDlvEz1gsA==","shasum":"0d4193319abb23f297383adf66780d1972933d34","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.6.tgz","fileCount":35,"unpackedSize":258290,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe5eGxCRA9TVsSAnZWagAACLEP/RBePS04T77Wn8lVAmlL\nSIFWJ0QLeXSI7GvuZc6QG3hYHyrJxt3OAbUitsz2B7XgL/KcQn2K0ifLuVn1\nBYn40o6nCtlqhrNQGpbY/6i0DY6Vr1gZOa7IF1QZA7B2g56K4SCVdzBUCgvO\nCctIy4HppUoQITLs0UKK9FpPrfIFWr9MiKRrP+B8D+Mx8XiY7es3QAWhrfs7\nrTBG4jV2LENyT7JI/t1BbeSC5KxDPjPj64A8GZrEtow8f3g2cLu6Yecn87Pq\npWTM6ENuoVdm29pkHx8sYF0IJjggzUgcvwm7UVygZ6EWHoD2FWPKnawqiT6I\ntonuExAJ6FqZykp8MoRwXHNj8QneKkzIH1N1/vvnHufJlQppdE9K3sqrMVkP\nFtOycv0QQzcrgpFoP1vgDIeA1LNTjSZByWzpv0KdmeWuGOsPU7m8rartCD8Q\nZPMd+k5yHJXVJoMiQk/RXghXgk2MQa5++NVkaphtjK994kyX9okguyfXfkuL\n/U/iXNaeVqMjDC4Gxn7SLewmSsJBDpHO5SBgt5HsNAC+kYGV1hcJWMCi/XhM\nw5zyBpDrMe3wMIBWiTjJoCEb9vhwhERQ2Sd7pb7Tl6EatgElTPkKrj/PcP66\nPBeeroOEjTCWjwmfIemkRMAKCeaf2T4nyE0LZBPuvLGBl6Mu0qwTgnrthMTi\nF72Q\r\n=WVAe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAa2MrsFNH1CqRh6RqeG+stI839fGYJwmghrboxCHIkkAiAVv4zbqEcW1mHawUcByrOVCeOIWSJ27/ztA4vn6jHR7g=="}]},"maintainers":[{"email":"elsa@carmel6000.amitnet.org","name":"elsasebagh"},{"email":"carmel6000dev@gmail.com","name":"hilma"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.6_1592123824576_0.2689306952045605"},"_hasShrinkwrap":false},"0.1.7":{"version":"0.1.7","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"2a6737fc30352074ab907a2c5fb86ea2b4ff63eb","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.7","_nodeVersion":"12.13.1","_npmVersion":"6.12.1","dist":{"integrity":"sha512-MVZIOtj8/uC61H31mvUs61uooOXIvxLA08mcZaKs1RwMkiijMC6cIoDrNKPxD1kjiWPQs321Rf9ugw3JoTk8zg==","shasum":"c52712aabf971caa1d6d0399d59ed14a6b8413e7","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.7.tgz","fileCount":35,"unpackedSize":258162,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe/HmYCRA9TVsSAnZWagAAU+UP/0wC8rH10gCs27oSrTka\nkZ93hZSFws4AaMpd9vVbOZeuon4rB+SuALxU6QmFjS4nUXgG5QE7gRKrgY+7\nD5TDA5sJgupI2f+otc7JJsOml1au8vl1Teudyeg9VQOWavhWvi9cxZEJIi80\n3ZytoDe4dnFCBbpPto0Gk/yjPyy+VE28ulWVpTpSFYKglDwUTmZdPhiz2Cep\nDC5/5Z79XpEtZObdjJbJyyGbDyQY3sSpnIpIXs8h38cSBCDcfmi2Ad43OSQT\nySmR6Ef9Oq/wGLt+Bm5VTaJVro5CIjlbYExLpHsvP+MAAy2ezcd3uu8bF11L\ngHwcOfJnB0EuGX9936uWVJ+zCtk7JLLVuApZhuxle/Xy5+p12TuFg0kdgUjD\nkK+HKV/BunI+da+z+zkV1L4qeaN91Bzh74JmcVTlBPSm0wlvB7SClGnxgoGj\nCdS8vrwV+MW7lScUNwcbJcDedFzgxzpp86Ueosi1O0STm47Ft6N5XnOBU59B\nOkZQq89eyc95sMOX2OCg40uxerf/pA2CBYlNvPClvILOhmfmcGB4zeSOag7T\nzp+wnUOeW0R1Bf1l4tZxJWCeBRqlU7o8wBTEk6Piad3vF2mNMEOgd843VF9/\npJhwbEke2topE5GYn4kvE4tocg4Bwt+5jsfei1dgBA4b7wXunWEqeDq7hStK\nToW5\r\n=B9de\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCE5WTQ8FTNWL246eqcAZ7Q/PBxzZvGshbiYcdig73m8wIhANY1MnFuhQJnQdfzNIT3svinmR74bIK8qXtdx7kSdOmF"}]},"maintainers":[{"email":"elsa@carmel6000.amitnet.org","name":"elsasebagh"},{"email":"carmel6000dev@gmail.com","name":"hilma"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.7_1593604504280_0.21648990730954587"},"_hasShrinkwrap":false},"0.1.8":{"version":"0.1.8","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"3f5e9a27b4289bd84a53c634ab30a15fe775c8eb","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.8","_nodeVersion":"12.18.2","_npmVersion":"6.14.6","dist":{"integrity":"sha512-QKjbYMd5I4pgq/J9OSFrOvy58a99ZGmQFtxKiMujRrmW6wTL8cNsB8eqIenIKjAWj9rgIT9kvHpwdK8X6PGrOQ==","shasum":"578ecaab9d908cc9a30f8c93b34b55126ab41a87","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.8.tgz","fileCount":35,"unpackedSize":261622,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfKnWQCRA9TVsSAnZWagAA++sP/Ax/wIyXbNPsvzWPJ1rg\nZ4oFQQ12uUoQS9HTWnG2METbdwx0Ocs+UhPWQllYVKv2ojw1awML3Wmo4Dth\nfrJ1AyN3krGK2J2Y7e/xsSowmyvkQbV/nSef4aBMBc6P72yU4KgkhoRgjdrE\nAclHZJKq7h7X5bn1onI8Qz5P22EZXJsJGOJEjnMCdFfx1C0WQ4V1b2Nq57eD\nVAEBgDleodRyLh4LGw5z3NpykkSYNs6iYz8QAgrrMfCq787QlafaUdu4RzW7\nQWQ7O/4p0I/Utj4g4alLiHyIMV3MPMa9OVz0t9sqv8GIo+sD08uohc2lPlZ6\niiUUJfsExdvtPdwbV0UlbqzarNVjpybWTUjPKEyF/u9xYig2fljX6UIP82Za\nMTld+IDud5W5dI6ZDidfBj0l91VNqySgN4yLDMKvEcroK+hTeFE/Jvel5HLU\n+jqzROKcxZGlT3zw8nNjfJbUyb8SPqyGEbTtTPPcpMn0q3Pu5XvIc8iqA4yE\njOnWEAyBHHkvDkyJG5wNUaExgnnCxN/1LS+9ID8kDNLN/zRkT3+gvOPedqDd\nD8q6KZ6DKoF5sxwWsurx1URjDas+3KnkihRUKSomMufOiHfCc+jsM2aNvfvt\nMzCgSLOlr1WFbKjphW8PY+XJCbd7LR7AdSTgcNFys0Y6Ck8O4hVkD3Fd6ZeG\nDnFb\r\n=dzIB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBDmPOh/kButFpZvde5l6UjP4DlnrmOKn0qH7w9d2VaeAiEAh9ZcyQU1kR/bohIpGURSQOeB9DBEKPp11PzPVdAAcRk="}]},"maintainers":[{"email":"elsa@carmel6000.amitnet.org","name":"elsasebagh"},{"email":"carmel6000dev@gmail.com","name":"hilma"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.8_1596618128348_0.9230602743097931"},"_hasShrinkwrap":false},"0.1.9":{"version":"0.1.9","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"4f3af70334fa53d3a14b5940b8d7ed4f6fd08e1d","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.9","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-45UXhAJJfOP4Hfo7/TIXEKDMV/apxvf7qHSd0OzdIJOoPs8xwqlQCWNPV+44TcSQzQJemhPuF03OMvCsPVbATQ==","shasum":"6fad6fc84a2bcc914cf3f500ae35ce337184a56b","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.9.tgz","fileCount":35,"unpackedSize":258197,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbDY4CRA9TVsSAnZWagAAYj8QAJNsNkrUZsEqkd2l4GDT\nNyktCFC8xpKAazaHvZTZooA8ZstV8vexcX7wcPp+XXpLlx6IKdgEXJpNyZn/\n2vdEuMtpPha5w4NFk6DuoSoZPl/TfXOHdQJRY1MsCi5+oKtSBYC3bhi2pkp3\nUIjz9DZN4DNaLsgumwm+Rs0Y4ITQdWwUcc2m6D6aDZl06ibdqKuVOdW1e9M/\nhzrQEKKNDNtq6pJb0cpSOZ7aRo+dphJNras+byBrdhy95nE4uGb194p+hQIi\nYkaFusS0PxckXeEMjl93nUvr1rCcwCHdujqtTJjGL1j6EY9eIovf/+q12Yqe\n+ihbyyDWTdkJXpMiNk9GY2IEVpQVVKXw81MYdSz/mBqNwxM3c4VrTqFEbeRC\nkHbc/nLvVXGjmS72+nQb1KgVwt/Kht5XXNa+geInp63zd+6gFtiIUElTvcV1\noFBdLHjNJJay8JtcmUktG6Emt/9wZ/Cd0CyRlAuRCHDJKF9l3swrngiP32nm\nAIJ8iqh0MWW1nZTHw4JsuJWcq6ZCXLBhrrCkehIpADTy8wDa5FSJr/Pciw9v\n3XYaM2NPyEqNGEA5ghwkLQwJfUkz/5nR3S/Ur5h0Ec8xK0j1H+ZanBkM9Dqx\np9VxXrE3Zz0Y6Jkgxqy6Ca3UEDcYI8JAvtLqi8d0Vs7ZMB/mLD4XfJyqT175\nJqBm\r\n=lRGA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKJFHNd9Ng0BNRHPAd2nKjOSn06a3RsLL7JqYClqV3GgIhAPuE5B/4Y/YA7fus6coVUTzuWtBvRuholzg3mjElNZwo"}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.9_1600927288212_0.21158450890237757"},"_hasShrinkwrap":false},"0.1.10":{"version":"0.1.10","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"3b8730b204a8b9a3683f095199ab0a9f86789dca","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.10","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-/LkDfBjF05eu38fOnZhSfaxGzEUzePlWXtch7J8BOftxfW36Y2F+YWbBvh9VOf1VWmk8U8fffsrSriJGtMWoDg==","shasum":"3b2245f87158e97e13917fbc900ca7443b82e75d","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.10.tgz","fileCount":35,"unpackedSize":258352,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfbFv0CRA9TVsSAnZWagAAuOQP/0RYdwXyzc1C+lafe2Lo\nMpSY0qF0jG+LvhQweao4cFKSFAw3v/1oyV7aYBL13h1jRu0PYwBebBn6yHa/\nCxljD2gpB/fH00QLA7D25ZyL5bkRmRKp+mc/LRg+ckFPnMfJJQ1q8HmduD9W\nuSc3utLVjGKyHxNv8eFxwdcXH2nm33QC98hCp/ZSXcJTynTovV7js5bZsRIo\nVmLWcZS57SwDOsJEt6GWI9vbnjA3IUfdtS2ilPeVeHaJPwo+L1IIaDhRrGVp\nN0J1s0y0D2V+7DoUYUXzEYDXZ7KUh9cpvbXhnW7iGuUOonf3/XKzlSeFyJq6\n0nuT44L8qwaxpTMgeBKFNOLtYZeGPq2tUEYaPM8CyAmNXn/+GX6mRge1WNNO\nyAYRoqYj15q0rqzWPHSoY+Avsf+wjFMShu9GlxCdyJugHnY1AfGIoRj1XyEM\nVEdE3K0jfS53+EZjwkMgPjiiEU+MClNDzvv+hv+seGVCfFvvJxQqkV/5syjF\nAqEHD5j4RPWaP6lfossGGT3zG1iKx1MFEg0N5a8Cf+zoPxvhrV/L1BkKBGuB\n9yam/HDUtKkAGolMpsS0nUXK3GEQlNfN6tfqSPaEkn5yMBs6o7xRT7YnMhLi\na26HEQdXyomu27HhBz1xwlcMcuOknbPMW8KoULUoFgpCWLmqxfgDV+POQXtV\nerkn\r\n=Q13N\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAEObgpxoo+w7b02CQOjDdaKGPJYRmuoAVQ7oIGUG6+oAiBZGkYLOPWFgDeN1WDE0LKPkmhIw//8Kv8Lb0PPoW8Tlg=="}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.10_1600936948191_0.5758776276400126"},"_hasShrinkwrap":false},"0.1.11":{"version":"0.1.11","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"b9aa5cd871f3fb6fc24425d88e9a156416ed7a12","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.11","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-X59c2JD1s8kjzeK0CeDobrm6fzdr72ltxi3SM+09pHlu2v+YtzXZPBvMvNd/5rn9IuIHt7g7Guyy6DP8/A6hEg==","shasum":"4822ced1e075bead34781b209826b30e4d539aa9","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.11.tgz","fileCount":39,"unpackedSize":261714,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfdZDhCRA9TVsSAnZWagAAc+gQAJTrXunkCUk+hIRrH7UA\nKbvGjhbQsdsOsUxcICyE4CfsKDjuZi2sORB2WeS6lvAUN8g8CzogQAGluOfH\nwlB2ZsG3xUkWlX2tS4wA5ZGV7xmyLRBH5F/R5ckJS0pmIoZ3PU3Weqi9pUPl\nM/Z2DF8QpU8Qo4FmW7NqcvXxatcU5tNSHBbiK6CejeX+GulVvdZNTtYmzcGW\nIBOaG0P9WodoPWvK9g34BsiNH+AnUeg7rGpV2rTbYyMeCbCbpHSz5WGrSVJ9\nc+2sL23/tB2wVv3WvE5V0BrPovXLA9HpraxXk31GEw6aeVZ032IOVHUblHV1\nWkksDUEylkmoZa2Z2kfRvg5wHkjQV8H6NDKhwtwocx7YxaEn6Qzp+WVzpw4z\n6y8kulq+dSmf5BQn3MwH9pQQgukhwgHTztVytuwE+WV7ZtXf/HBj8A0bRvai\neWHWsHTHqIA4veF/KGqQMOJs3gCs5OtwtvtoqWYYRoy/faa1ujVD+7FJrDC0\n2Q6h1F6A6RLy03M0BEhCOUrxAHfASKsc/nuHBRo9+UTPpQbaz5MBGuIkt0b4\nNXO6V6k0d06FKWWvYBc/dNwRHKex0pyBzUNjsB/WruHiPSy002rrRZ44FTRw\nqNLCXB2b6YfUzq1JscYc/o16+0EteLu3An0Rt27tkd+WSpcWhhFBBYYBxx47\nPP+6\r\n=jhR4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDxdMwQOBsmuoSXgvWH/obqzP2XeJtoVmNg96njQWWDhAIhAJ7C64M4zE1FcPe52NWjCgdUupNr5NMBqyEfXr0ppUZ8"}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.11_1601540321275_0.7450034302748216"},"_hasShrinkwrap":false},"0.1.12":{"version":"0.1.12","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"8a0ea80da0703e89b983dbdda233518681d63cef","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.12","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-vb33KanUXpfKBAFJkpFj/rupwG99XdwwXRzsFtd3t1PJts0c3VO0I90E9jgy4Liq5TUWNpA1QSv8VIUAAO7Icw==","shasum":"814f363a28b2bde4f1cf7a9fcb828f9e51fa0d09","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.12.tgz","fileCount":45,"unpackedSize":276130,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfj9SKCRA9TVsSAnZWagAA+foP/iDIRSYJLYdjfxZzcZU0\nzp2ejXB5Az+85tgZENSIuwfCuADxNVI97XGWeicvgEpUUs20WIHeANWeKmGi\n7tCwPlGGpRJQQcjiHkXzLx1Pnh9mblYj/20tKpZ1+hPpdVWQNio8MT7ri9Oq\n54sha5YX6lFQPDkJ1roCSkUoemqIbOADYoB3fiedaaecmAB/cbsGkm/O5jwN\n23aeUvqEODpiN6Yo9QnIXRTbHz1bmH4WPuS75fEvjFHcMnGB3xQO69BwYKgd\narwKtwW/TxkGfJi9QSIj2MyPwfrKnNXYjC93O2naIpxLsDp6M47HYFicw4TL\nL2INL2RqTXJ+ppe2L4VkXxyh+ZQB29+/wzDgFrgTeBmviANCZRVrsAz8okNd\njKPgQ9FrhQa5R2JagHtfMzwC5z2vqyFgVWQtX6ZT1lhuxlTiL+dD7v9wXO3N\nv+CAZwfG90gIFmNKTWgSRNLnMcIubLXh4dctwJmvMKVD0kOVWz5HgpBbj1NJ\nkh1FrLEOMseuhKW9lLbKWflMioC8vUL92yrHj0L1mttmkioZlStn/i6MsIcQ\niwWzIkVh/mf6yTXJ81WGvablyqYOTUHuga6fDMYMZ+WjTUdUzb0GArtgtMh+\ncZuhD1t06WQlzQFklJ6mEGqU/o3xUw/QkzxG/y3jHu6uc3vLALvjcI3hIQ4A\nV8ko\r\n=Oxv6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDG0KAk9mD1hXpP+4PWieJIAAgkxjYnsgCNyPuvN+RoRAIgapCNIQYiITsNHd0piA3/I+bCRES62gY2D/JuRkwdeJg="}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.12_1603261577966_0.28263418884928093"},"_hasShrinkwrap":false},"0.1.13":{"version":"0.1.13","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"72a2bb544db79fbacf7aec35fee5f17cba4158a3","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.13","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-Q63/ZExBDFfx64h4jrCA2s+zeuumWJiQEKkDsAr0sAf7FFQw1ZE6eWpaLg2pz0lJlNi5V3R+iksTkZ6orhW/8Q==","shasum":"6b63f6c9c179869c7789d8c8fbbe8cd24e3e2346","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.13.tgz","fileCount":46,"unpackedSize":287802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfkTaoCRA9TVsSAnZWagAAqggP/Rw1tEEgB8P5rj8JwDZ2\ncoDXrB8SkPEnWt40eDv5+L47j+HqYMLkIjUoOkHff5wJbt8ulerMfa+AtCM+\nhwvL8b9SM6DW8c0lcFbQBl9jQP7wpmVJYGXFuPZItoW6zHYAKOHafL7MBPV8\n2scn/GEXjWNoASu6P9hetZLEqefnrzBmY3DoA/VN9xRANUf5nvQnp5uk4RT6\n/W86hf5uKiVvArdLGVW9uKOGJqjHnZltQqqEyxgRciYSFZiEabQ7qfwESs27\niK17D7EXEiDf0RhnoFncQQhXMQITbUinfFq/GYcJJ4ZGuN9Cvla43gkASCap\nUBSGu7n8G7eiVBYN6ERw/YOa/1zsRvmIwaFY/lcVW1E7/MSV8GfdU/ayatQs\nd4ASOj6cal/iSydARQ699cLFBtKS03tNrf1GqZcY44Z0U+RmHAR5HPgMfmLC\nyTH/F1yG1mXc7WoTPktQUqzcFKUUij78DDVsWQeoV/+dpL4yt8n7lAUGw3jd\nXfCHBeU2SB/wZMPksfQtvucfKdLY9WAK0/OwYKDJj9CqrTiV3XvYsOUqHx2v\nRPseONwFspir0ZG/xN6cLiA+/6JmDx6Ho+eEcLDlpvIZQTAJgoXjERXUn7t+\n58k4rdPU5SFEku7ZTM0TCMqYPR51Qn+w//4f6ORDcbRjejRYCj+C1dqpYaY0\nSHgM\r\n=eQxd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFkgAsqrvFsfJGd6b96Ba/Q0+ufvNpOBVk8fdC9lEwncAiBH7ggx9tIuF6SukQj03V75omNtkWyNuY5EiIx9/pOSQA=="}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.13_1603352231525_0.801663038603182"},"_hasShrinkwrap":false},"0.1.14":{"version":"0.1.14","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"96cd1eb9ee02238a8cbca8fafb636042863adeeb","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.14","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-mI6W7HuZoeIT/kkTPFv13HhAf6VrgyFKH0fwZt9KLVmNcA46XzjH4L2v+pu23j62GSkbZa0Z/3d9SNJtfvFRYg==","shasum":"c8a3fec36c993a3c21ed07f1c6c28b6d1c0b58fd","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.14.tgz","fileCount":46,"unpackedSize":289127,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfkTkaCRA9TVsSAnZWagAAjR0P/jrTYKQFGTnUQtkmfyWf\nof/hnrdphpJ3G2Lkq3/89RSqevVLYy2T5lCVKSiOqfwSXmKcrL9y0eac3/bt\nheU0kR//5PU8D+b8ukQwHl0Ms/Z80pOheHyXsYODw57H/tZU3+FArLI2pirp\nD7Yv7lmb8xboo4PmqYjjwPMp4exzBv4yTeFXbPdcSvxkOtj3ofLJkkircuv6\nYg+YsWfVirjO1FTMwAzf89Q9/a/gdhQ1/US6TjhlvmC6bT0yfbQEP0Vcczxq\nvzUzRenoOB/87ag9dw0qVe3it+kYW/tovdNQPUmVeT61gbzfWLlqcToyR6Mu\nCtxXmfr4jcrV66MkkKVWd9W7kLfetpugoWnAw4tBQf6Y573SWTHEhEhUPTdM\n05EfpEMl36TGUbmrDoKNYYw/qZ5kTuIOo1Bc3lWYZ6FZBDcJHlN2zrx8Cjto\nhXg+31bF/toG3ZMdiSpm9zfULsZ2VsTfE0zloCyAtX9pOz59OViXn3Zt8XpH\nPr74H8KgRSkZwGBK2/Xe5+QzpE1v+qtozEKN/wlAKV8Co+wYYMHOwNfKQbo7\nlexz1qkrARP6ckvwmdS7uAj/rRN8JS9iACB22J4rDPqzw8vq33nRGwUoVvkM\nbuCtg9hn5hpIQ0g+SuG5xmC3Iyz3pdOLGz4qnYTo6qsExHdYDxV+exRftAJo\nsNFA\r\n=+4CY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAejA3Tq7E+QtFhjcIRcnl8B/ZkBsbw66pXvbI4ln2/FAiEAxl5N7p6RuEc4hlvRh79K6N3qo5lqeO79EY3XlqhafXA="}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.14_1603352858292_0.9251787694368632"},"_hasShrinkwrap":false},"0.1.15":{"version":"0.1.15","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsdx watch","build":"tsdx build","test":"tsdx test --passWithNoTests","lint":"tsdx lint","prepare":"tsdx build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tsdx":"^0.13.2","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"87074247ad2c8d3defae96bc9b25f91955bfe6e1","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.15","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-TpqR9Qq7038LT2YcKbyfPnHKH61qjkHz20bpAD90h6cfbULjlHoshqVKWzAmLcSnbgqZ4SntnCRjEtLWaOLW/A==","shasum":"358b5ac2f99cdfd2b676b0112a0a6144719e0b4e","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.15.tgz","fileCount":46,"unpackedSize":291993,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmHEkCRA9TVsSAnZWagAAQBIQAJW9i0H631cIrxF6wLAx\ngn28LY2kRFR14OKfjItKTzLKEpWMgbtdK2BglO79F6MpGaiA/3IDaC7qEGMg\nQAJ0J+uFLnmC3rl8TNUzMc9thOJOnBZa9SDahOhmIs3YZXXzwI4EduJQPdlw\ny7lDLSI2Mi0X6ccsZXBpFluSYlceGAvRt4kZrgsGVHgsu5NPJYJoUfeSL9F+\nXBaOQLwTATZcVKndcNN4JWsQZXmIYrBX/tel+oQetvpxzzbkmJXNa3mCL5tL\n3X3aagpksZSX3ak2QLzsjK55bk10ePez4kgnJ6uYyfYabOj6+DszBKm8guRH\nisE40W74WlsV0H+2dqbzJQFCHppwR+d9y+Ghkxu2KjY7RGAGLJgI0foRoUrW\nPRUDM9wWj+Xjc31SvD8bE9NavCevrq6xnQWhceLomO4rUc9YTK7yDvUUP1ID\nWGj0hoZJ/8bkKp/xTOri0SyUJoCBIxHhA92jWtQzYxXIDJL5Z5MoDlyCRkao\nQ9ELOlyGhAOvw4IAHE6BcedXHFvKcjV3uwEl9bYQDz+w3BzDdahhP7elIiOv\nAkR8s1FwwjlTDSI5Oa7GgBWm1rGdYIbwE0tXs1odhU5crxlii/fDKr9fbjW7\nXdTD/dfdJzriw/epmi3iAfQfGS+dq+NlTbxeFsz4grilhp37BgCmvXy+q3u/\ny/lc\r\n=fOVG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE1EeanZNviEEIDbsda/I3PCom/cDER7waZTisfGeMOyAiBQcq61Hg8NQj4XMc4/3dWFO1EjKVZE5oNHOvN//aMNpg=="}]},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.15_1603825955469_0.6855440751109776"},"_hasShrinkwrap":false},"0.1.16":{"version":"0.1.16","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","build":"tsc","prepare":"tsc"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","tslib":"^2.0.0","typescript":"^3.9.3"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"9bb14300454451b1b53b05e20a38ee5ba0699f46","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.16","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-ZYpsSSdb62mXu2c+biSIn+FwsQMwbyr4/zbQA7TjaSLsweYTJqzLJsZSn0q+BvM2A8zDFNfSZv+knNFO/or8Sg==","shasum":"051346bcf6d70f847dc6359f887887a34ae1231e","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.16.tgz","fileCount":75,"unpackedSize":92276,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqniaCRA9TVsSAnZWagAAYIsP/RpMsly5NoCzkmF3Sg7N\nnBL5UtCMr2UY2XtmXiYpJz8u6LyLoZV7Gj+BSJSuyMLKUZgNRMdlel/FvCSe\nW8lNp540uP3EUmWMqwa1FMbNHXmhd8Zmrr0wlSoGgL3bj653rsArkkXCEyrl\nsQ40rGsQr8qOnh31M0qt2u5ORLF7cYMwWQanUqBLTKqCgf0k7rYFCXrmS+4g\nHgj21mALC1rJuanGJ7IpBd6UhY8Kpe+lPKCGtP470eQ0CyksAhwwkx4jupmQ\njqYsmDG7OM7xL80Rcqn6fHTr/uW59ltRL6NFyg0BjQMR51zTRkKqFa1HmA30\n272KGWyTazmcPKKBeY8cCXUl7w+qWan4vL1s04gKafy5hnUwC3SSIfnvu5FC\nys89weEhPXV4Me4S65A5mPoe9nUs7BVQIotYan0yU3DCjhZVSl1AbhdaXdjX\n3kZU3e90mOP2hD1wGxH8XWdSYK3YmXhAV2NPSPmnQ+e50NSk7tpKDgLZvQgk\nCN8NJz4upVAanlbmKA+YcfxDxJKdsBtXtOQRvncfbxqMcTdftrgt5LKi6OG1\nV4jHfVZyS/hE2XnX0wmbb0ARM3icJWzfxobOACRj34PaaJjZlMYBbRdbIuaS\nH5J2R5yenyhMxson9lvv48uIEykH+OCItU4wrlbAYqgvMIx3qjb0KGpTJpfJ\nmHSK\r\n=pW1z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+EmjiO3A4hfU09al40HyVq1/oxJFJWcSH6690seKj9gIhANS6qiLHXGC6IKTgIgRke2jCmNtYZHeI6N3UqfXe3TZ3"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.16_1605007514366_0.7169712789311931"},"_hasShrinkwrap":false},"0.1.17":{"version":"0.1.17","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","build":"tsc","prepare":"tsc"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"9bb14300454451b1b53b05e20a38ee5ba0699f46","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.17","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-XcF8BjRevVtrvUpisyIh6F7IEiKe352KmSd+4gIjsPNJWYlMfyGYVKy/dk2L46JhmQxMq3+1ZQyFs/yHYf6y4Q==","shasum":"04742129065fa5043f0c73b1d2a14da36ffd8512","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.17.tgz","fileCount":75,"unpackedSize":96192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqnpsCRA9TVsSAnZWagAA7F8P/iEPlzoxIFSsnY85Fuif\nDO0sLVOVJUl2RRQFaMS99rTMi/fK6BlNHVkUa7EHx5hf80BwQvriA246R0sD\n3egl97ey665Wkd+a43ORKF9uplpMqFk97HB0atohCJ6ULRNMzyw0w7le1nxh\nEwJJxT3e69XCSdNsmmOBY6yGaLtJqE1BU5ACXvbe6TTogowk49+PTZvN8ZWa\nM6S9UsInj1AgDESqkjmvW7YJF9c2Jlw2asIgU+mNdXO+ILb7c5Vzn2B7fVFu\nWo8Hcm7o8I2ikSxblex6XeWSjSO+u0sgMlYnl4XUZVwA9cmoHzzi0DW5xpHW\nehQeHUomwc+vrWSC9zhgWALL/+oyunquFmyjC+Ej6f0BXQG9bvnXb+ydZMvC\nZJJVNz43OKbzAknac/7gcctrH81mqRsDAtIuWlEr0GBTL0J2ayoOpNn8IP+G\noiHyIc5dkFzhIN6OVQ+AHYag6Q351DuSfmmdmDTrWQWt3P6A6lmcYciLDBXF\nQXYv/4pyFVxMfHKwO5R0SYHBlG10vtE0UytFxnAaUIUdMOZxO5NP9mU3Ftyu\n2Jq1ppZ8TYjmI4rbrC1EaG/mcojuYRI+0JYoB+olmPPfsE1z4E0Z7m3DxN+i\nLTIRIlrDrc5n/19pVtlZGKiTOXsRbyOFv62KCPxfmijoNhkwafxfjQGeAWKf\n6Rcy\r\n=MD+B\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxJQz5wPBXp5DKbsv/DqlgaruynDMm8DuZvZLh8tZh9wIgAQBrYnymuY7gyiHkV5XkxhlXpZRgVUOnuPhmv6ILkKI="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.17_1605007979541_0.6166809556398731"},"_hasShrinkwrap":false},"0.1.18":{"version":"0.1.18","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","build":"tsc","prepare":"tsc"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"9bb14300454451b1b53b05e20a38ee5ba0699f46","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.18","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-6eW4UtBMGg+6EZIYGAzRu8a4blwruyPxkjbHO+BDyJkCJXRsN53kIektWmquJk+8Muw0XVYEbX7nd4GAGO8RNw==","shasum":"4e180aba20d8b37da48af77d9a460dd34db144f4","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.18.tgz","fileCount":75,"unpackedSize":96192,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqol+CRA9TVsSAnZWagAAZ4MP/2M4SyDg0fToYZYwk2uH\nbnIAvX+vzsHyl3uJGnDnCPbNycWKrDCBGQmkcyPewRqYmTwMmtXcIND8+S6l\nLYJloix7ORiHhNQJ1Tp59Ay16brZAgrSSFjcmiellrV2BF6tICjZrqy4NZOT\nWpxi3xRdCrOLgfYPIRVCJHT3lOYFuatQg51IMqpjBcvs90u4ox7FXk+TsrZl\nBPF9/IwCy8TsKAAJt2jLXfIzQSjhccCmMUCkJZzwe/w4V5B8txAMfjHS0/if\nRr009t9Mq9zdrKwIX6DMaezxLDhn95bz3Z7g8gVpsB4esIMU+beg/golpIV+\nVef6nXFd08w5eXsE4TAULdvKKLYUhuHeva+gdjeVbdZV1lRbv8+hhjYicELe\nB50VsMLkvtl3wat+Z8Ld/GbLq2x0371ist6hpn/fD0TQ+6KxAoNyX7v3FCjv\nvpPTPc3/Bj8W5sR67Dkf1S+gr+uv2uCDihIuY2p0OUnKWxzkI6HAnOn4V/So\nehAxKf9Dp9OErfsmqukiKnZ8eVqgj3VjT9phYpCZ8iDwwwUzNiRIUV54ynur\n+2k6WAWmQftw1IeOyjbnDAPUhxDlcMGlnH49smpR+7kN1n3bxYWJNqaKGyTf\nx95vYUhTCn9NXWtylY2AMkzkvB/41oDwm4KVsZ/oD0Ur0+dLG9/5sUoqBXaZ\n473d\r\n=1y5U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZy2AkpT8KLWwt41n61rEqqRFryWTY+4/YL0s5mwKz4AiEA9aKAJyXjVZ0MIERwPiKYJWAP8ow+3fU88TdhNevR+4s="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.18_1605011838151_0.8531179816074279"},"_hasShrinkwrap":false},"0.1.19":{"version":"0.1.19","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","build":"rm -rf dist && tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"f95978a883a624387d92f2634b201ad7eedf5d32","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.19","_nodeVersion":"12.18.2","_npmVersion":"6.14.8","dist":{"integrity":"sha512-uxr/Oy1n/m573tM94iOpr/39euYJ/IprQrWMiy23wL9QIbrNPqDwSQPC+Ns2JN1Oj/B6CgbOVvIn3hvw4KLELg==","shasum":"565613afe5183c2f880610103c5d7ac4875a2708","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.19.tgz","fileCount":79,"unpackedSize":97311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJftNTgCRA9TVsSAnZWagAAqeYQAJqG7eLNmDsm1sz8B43i\nmC+6ylE68jyPcJgU6cEjIeZAvlor82dVGnlgAj5W7/yUaJbg7EPjnnRXabXy\n3/x2O12cNwtHCxYkDlSW+YBpvCzfSwVGCCVGAkpXrPkYwAZV4I86sk2pQTWh\nGxOGKijNdQTyxYbEbW11yjq0ZJOtg3sIjtuahjYjGXjqO2nSWf20NFYJUM6U\nYT5/1otRurREKlLmtGUh8px8tXKywIyaV+2QWFBtGW094Uig7aUbkxqN9jc4\n4jPgJ5xYC/eBizziSbhta9NizC+S4suWOW07rZQLNylipdH4TyTrcP15PtQ6\nzRz2W/oKIgNWA8+ev9YbBycwdytIFmnEPDIei/MTKDB8fI3pkRPxhnCofTXi\nxk+ZzKc5fo05l/AGk6fZtvO8EfJ2hpilFBUrFNp+WHfV7lxMUxV9bIcZGRVT\nACW/qifCCMZhgrqn/Igo+n7NMAlAKcj+lE6xhc6KSZEZAX7jyE0TZBcu7WbT\nWZznQBLTpYBwZTMSYmqn2+cANqUxSkIsr4qhX4hesFOsGqA8jEZlwbMYirki\nmsjMyavYE2SAVPCA24KNxBgG+nUUN9byDtewRj++MmuXQDnkNAGDlqAxo7mm\nsi0Y0xEjhf2fqGcX40G8mk1+PdnwoQr2cGybJzbGZoXl161z2DhboGXokRoN\nl+3c\r\n=s4NE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDETldTHdo1xLAdznGIfuRyZK+VtCCmT457LxuY0B5vnAIhALQ2dv0hsmkY5vOdPOCKkfctqBk/lNo6qJ9fdfXM3w0N"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"},{"name":"hilma","email":"carmel6000dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.19_1605686496200_0.9399073198410635"},"_hasShrinkwrap":false},"0.1.20":{"version":"0.1.20","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","build":"rm -rf dist && tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"88a13796d62aec1c62217057f5826680f827ae05","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.20","_nodeVersion":"12.18.2","_npmVersion":"6.14.10","dist":{"integrity":"sha512-krYgH2XM+LF3EnibcQ2T+HalduH7jqUgiHA/7fxrUd7tcqjf4SnRHFx1qYeYHe2F72XfuSkKtYIgMZRUKwKzCw==","shasum":"fef1b4a4f41ffd44d72a70768d827e392fa78e0b","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.20.tgz","fileCount":79,"unpackedSize":98653,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf8Z0QCRA9TVsSAnZWagAAPzQP/imKnxUsOdSmN7mMave7\ndDCxFP8DLOmWTMsFfkVyGipXDGyWDb8ZtwodUeyVZS1Z5NqfvwgAv5wtr8j1\npFvtpldWqrL3ChR/cCPHyX2pIXt3EewK73nYegECQf/6v4/ykq5Zfsylgz1p\n1dzllQQTuEP/QA6FQr4fWnVvNt4d7SmNi/SxNM3T5NVW7wY1L8fqn4BSw8Ve\nqBp7iTgLhjB5P2fxgdxJJyc6UBU1IhvaR9Zm8bfF+OIyJvU97xocOgNSCls3\n5od6vuSJ2KjXzyn+A/fInAYekzXUu1c4tGmRWcabAJaEE8wDQv6C9RdFzvsw\ncpcM7zYaNFJ56EfjhPN6c2h7M64UxMvGJJTY4E36yY+0+HAefDQaeinKo3P7\nZ4KFac1w+eAUajWkhUjbbdJe8RABHzE71S0S4jdQcwd/Zg5JoelLo0rHaVV+\nYLbchneToPykkdv5rb9vFWijuUVgeUZX8eUJK8OUCuEg396mYouBbesKXQHl\nKqSAXaJVrQU4zGupc/ycCb5TLNyVmrhOu7UdCxdTumqBkM/RIOQ6F8K+EWvV\nUdlxaXSDqxlXVUokY6lXMWB84RmYgrTQjinzOkaykzmi6jt/Eov/NurhVTLd\nmMY6HteOxh8Ql0B512lWTkBAwitrtArOX8+JjRlTWa3o32OffgRMUEgQK/A4\nCoFU\r\n=6YnB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDqyu+rnP75Cq+8N+EaIgnO7UjXmhkj3ioxgpIEqHe9HAiEA2cH2pOyenDUeOM2w6NyTeuEvigxKOQojw4A0XseQUfU="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.20_1609669904112_0.8559181250255576"},"_hasShrinkwrap":false},"0.1.21-beta.0":{"version":"0.1.21-beta.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"module":"dist/tools.esm.js","repository":{"url":"git://github.com/yonabenreuven/tools.git..git"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"fec61fa40e3aae41c70ae71c2fcf1dd17b001b5c","description":"Tools is a package that has some useful client side tools.","bugs":{"url":"https://github.com/yonabenreuven/tools.git./issues"},"homepage":"https://github.com/yonabenreuven/tools.git.#readme","_id":"@hilma/tools@0.1.21-beta.0","_nodeVersion":"12.18.2","_npmVersion":"6.14.0","dist":{"integrity":"sha512-RkWuqTNJyRhSV3wfyBzediJ3jEnmu8VtsiuztupQVECv0VTuTkf9uMv6TH6mPoSGZ5VFxvT11NcuTJATjtdbbg==","shasum":"212763c77a2ab25cc01c3bccbb10b91e63e68eb6","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.21-beta.0.tgz","fileCount":91,"unpackedSize":101710,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgU0G6CRA9TVsSAnZWagAAmMMP/2ypg+rCZ3ZPGgxhAciI\nApQLFY9/uA6eC8wqzk4+UQvxjqyMEYBtIOPYcPoRai0DDswhXTQmZ8X14tSF\nquUJGRBRKwrWVcfpsQL4f8W+SnApW3reiH8PBxr3PrPVqWqywmd39vfs3F21\nx9J8NM0omTe8Kvqy+Hpk31SyyQxzc4zoiUzcYcNFFUWSXStd8n4xGYkqa3qx\nWIRwowt0UZZVoXuSuApXR2BeSBqfj18mPe06lQ4T6saAOSqMge7V8gsqw2va\ntICIIBlar+8BROp1sCiXpXOEU9vYbIjhS4esECZ3IOvu767KWkyKU2GS1288\nAopN6+XoA6qOtC1ScsuzgdrzOck1yg7GFlrnduuCRu7G6Qx3YAoBegd7+aot\naPemmZgVNLJO0rt2alTeUt6VuLag2B7wDckjgaQg9tykkr7AuGp3NsGcD9/s\nxUrOCEs1r7HtdavuRVzJW+VByGyeCKERKNZS2QO4JOxmpric0pfGyFTJJpsV\n/mAKSG6oJyn4mwp1qvgENFehgEOy324lmWCzjnQQES+/fjfJNrYDUh3ub0DG\nLEWQe0hn40OPXw8UNhLkERCihF/NWgMIIzLtpwDFTbykTVr+geNdUPvdGb27\nc5iNQT6Zk/VDMCA1IbXtEq998h6aNoUeoyGnOpXQUIrZl69U9s4vveL/ZK+V\nA9p2\r\n=fOcL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCToQvhgFxcgk+cURw6SVuiKX9dUSJRVYOjuSwk6oaMawIgDrOFZUllbO6oX1Wm1wE0e1/uz+Q6AMmEtPK5Z9RrGcA="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.21-beta.0_1616069050313_0.3953666256520312"},"_hasShrinkwrap":false},"0.1.21":{"version":"0.1.21","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"fec61fa40e3aae41c70ae71c2fcf1dd17b001b5c","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.1.21","_nodeVersion":"12.18.2","_npmVersion":"6.14.0","dist":{"integrity":"sha512-8Pswbw9u8bpWGvzl8qiixC8GNrE6DVhaeuRwrbgi+CbHyVIl40sOewpIj1IM1ff1lsl5YZwcB1Z3ulreD1Ni+w==","shasum":"88fbca8db4cd209afce8e171b4df6fef5672497a","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.21.tgz","fileCount":91,"unpackedSize":101592,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgU0NwCRA9TVsSAnZWagAARP0P/1rOb4XH2UzMR9LutTSL\nzUibdwqIGjZd7R18w3+kHFUmohkuyoxberIxlAehs9jNPtlMr3/ojGXlYOJQ\nmyP1RtGS4ZW03P3KMIh9Psc2yL49PAajtmYscU87k/R2i73e8+cVN5kDsbaT\n0PrYS+fYObVeXfLjh65FHP+eJWtqfgOnaG6VBYR0izn6FkWvWFnNrQsTJpLM\nbPwn0SQ/6YRdCIK/SAAptoP8J/TB8ZBeZ9378H19QdkP8SssHdbB4GA313qd\nHhTkMtJ0Sc0WbhHPvaWkj6a5lFFVsaL0Ca5tHdc9ne2iduqMKe86H6FIyWkk\nxIJTmQkTJedIkNwbyUnaCgdeJrkUcy8b8leQqf4qRGum4OHe/bQW8dLRtPC0\nilKpB+p35mrlykvYOztWEwYcMEcvo8zwTjoEptEs97DlcK/ARf2Cvtp2pYnI\npMaILmiBnteB8DVe+O6Z29CZT6C+xBtNAnCnww7UsUFyUuSDGLaoiM9JJAeV\nGx30CxK6BvPfkXiIr4/NfNhyQywxyxBRdKY2IyAnAPZBkWCN4RV95Rcis9i+\nN3tXV+4wc00+uLm2f12TLuzVzUqyc37RKVFPqB0pWl+H1uMNa57XoMtsetDz\nH+jxe42d5S7Erq8f9iCFvEd11qNdQT2TWZAdfd7ol4YAhNqRD+3JWXoHqsBx\nu3/q\r\n=9wKw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCG0XjLjnzkjwyjF5+I/eztxeTseNOcLBGaEBhzZc6LpQIgCYAyjx6nMZQlJqEk4g/pmPNRjxwzkJ0RiJi0Jcu4A0E="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.21_1616069488276_0.45927492183148555"},"_hasShrinkwrap":false},"0.1.22-beta.0":{"version":"0.1.22-beta.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"fec61fa40e3aae41c70ae71c2fcf1dd17b001b5c","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.1.22-beta.0","_nodeVersion":"12.18.2","_npmVersion":"6.14.0","dist":{"integrity":"sha512-h/ejMbXR8SNkOZSvVEdo976A8c2hkGacrD7ujdC05VA2k1DZAEuW02g88P/Zpd22BMBHuVpZVecuuYVgKexDVQ==","shasum":"f5b810a866170ad7b318bac25b8e4b2696216f9b","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.22-beta.0.tgz","fileCount":91,"unpackedSize":100931,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgVwFoCRA9TVsSAnZWagAAxpsP/0eVZdXtIkFl9HU1vL90\nZQk+0K+T+PXFoHxbJs/v1lUpHK/w0ZqQc7V1wkj03V6Jxy9FoMexJpj3s2+2\nudNe/EsBaP1bAoz1v16ZO7DqYGzWDU9rQW3YgWY8FPufwKJDq1jctmiKkuSS\neahuY4CIdCqYMpvFpoABrKt963tbjNbgBAdQrWx3lOYtHmPhQo+ERblLd0e8\na0ECYLBDGpYNfA9nLqQ4H7213lIFm2HUvo/thOWzRxFPwPn9sxZPloqAIcRY\n3RbW2uwC1cC1R5u3YM80yu9xZHnDxLvPmnImWLNk1iy3HEzi2+skJoOUejwS\nhHNUYkfvmEApcMkrCKtl8ox/IpdXMPPqCUb4Hy9iOxd3BtcJZsXsTzM2eqrU\n0yHvf+igoTQBN0PZlyq5pajNnmxxilzqb3ikbarSaI4K2fbjwn2zvT2+RX4W\nAIKQZ8Q+GwNtMJmurxazDeIsMvIGrwks5uC9M19SRksTjENIvOiPbwOei75N\n0wAYQsEUulJPA9hyf9B3/gTa1GB7bWwYRpboHRfMBLvqkxvykyXun9wOY4ON\n/NECH4+9QlRsYKOG6sX/9Y4/3Kny46SvNm1Zx/ThkIoqDZ4Jc3F6PwipPxot\nUNXJYnxzS25WuFqipx+HatjE5cGZ8LLF90mB3Cyoi9MNz5LWR/rCWPimtZKP\nIZxw\r\n=p9Al\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICeCkr/cYVSfIBvGilCNVCNZ0nFT3gGxQm5FaGyMw+3XAiAtrDBg0yTOKUlbU+NhwdtRrf3Q4nUmemmdpoQEuatmAg=="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.22-beta.0_1616314727360_0.9970362785456901"},"_hasShrinkwrap":false},"0.1.22":{"version":"0.1.22","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"fec61fa40e3aae41c70ae71c2fcf1dd17b001b5c","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.1.22","_nodeVersion":"12.18.2","_npmVersion":"6.14.0","dist":{"integrity":"sha512-WOYDJHJjAgCywxc3462TDk+hPyapS1fqeGfwqMyIuHcGpi5trksUoq+sOVmKs86d9mjkuXnirvff4/vGHnJyuw==","shasum":"ec59a8e1b24b6e53cd239064491f28b907878107","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.22.tgz","fileCount":91,"unpackedSize":100924,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgVwJtCRA9TVsSAnZWagAAi74P/RZlapNDJYay5OtGQYWE\nMIsTIKnKLz3nVC7ujWkh+dkXPpsI3Wl2izyzpzDfFk4bcL9sPyPP56yiHE9M\n1ttjcKKJTPWgMANezp0LU3e0qVroilzd3MNvqkpxuVAkj0A1UrPUTVsRlWr6\nQy+d4Lo6aTIcv0yRXcYlhyIh8vlJQa/jYc/ROo1yc4T1WsyNskW3DY5Cug0F\nqnp7y8uWzL6yfRieT6wf21nIOlVUPtcZmxWmpqwK6d02a8rtvd3T+xk+OQmU\nOrof9oaLYDDzQR00GFKv+BJFGs5Qht8XX3hHc8XZek3xNrcV9hygQA+tORXv\nyMKMz2ZYt6rY+jDt0XlNfxWAirytew0T9EPvmSe6ewXa4QDNX5tJkmMXtSxt\nb4ex0jSDiMj0QPxq4Uefr7K9L+YVSrXkgVqHrjxjCc2u5DQPNiIBpQQHBcb5\nWWTZfROfhlUebgCUM44e72/BPSu0PFVs8KP+us5/SkB1+7NmMIi7P1gzdkcf\ns7TmmD9rt6j2kpjWuDE/8m84/hmh3854oirB90Pk4ZjR93CxFmx+//NPM2ym\nAn93qGGMolSds1eXtjsDXKRbqtQD/aSGoR/9t9Ej1jep6ENU7N4npmrwPE3L\nrQuTBmyBgqnMJxLHFEmMQsVRvpZbbTiBDKbGO2C/HbX/dpOs7k/tp3nXmHAI\nZSE2\r\n=pONS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCwiqS222yOTR8frPFTtlqBhSd3Xe+TRA5bl65xctsetgIhAItZ+3QdA4PaYB2MCWnV6IU4qme47I+4Tl+CUndbt7MV"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.22_1616314988939_0.573675365842276"},"_hasShrinkwrap":false},"0.1.23-beta.0":{"version":"0.1.23-beta.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"45b2a6d1795c532a6890295edb97a0342428aeb1","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.1.23-beta.0","_nodeVersion":"12.19.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-nXfbD0M6UFmRYKeGrE29EaFOHyUbCCOJCvqTcFdHs+780afllrGbzaGfwcWwljlbDFGy1citxskbGDERD8pLNw==","shasum":"9456a84c1bf19ed7dacf83ef95b66f4641b7d88a","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.23-beta.0.tgz","fileCount":91,"unpackedSize":101066,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhyD7cCRA9TVsSAnZWagAAYnsQAIyhJUTjZosUzz3/JvAN\nAZHtDnon3v1sUZ35Le+KiBPBDHRj2WoSvn2w3Cy4d6H3ZLdiBWD0AiH+zVhV\nTN/gF/HLKaJ2g0oFAOHOXQXwg5X5EMPoXTHaHYo6GwHdVpBZSizURqzlTwSC\nag9npshu0ToXndVG8yuOIkVskh13hZbkZk0BppMvLpX8yi0wNqpnH3F8YJXy\nR9w1yW4tBfEAin+yU0c+i2sRwFzc+cy3g0wZe/3Ld98zhHlAkCXtGKJLff1G\niyfU8lUYykdQf4wh1lVLz6fvNLdv+CZ90Kzbe5me4VenwO+i6KKuONoL3fC3\n9fDK6WwQrrAwBtymT8Q7SH1SFYXLC5FazhcPRJAiveHzIZ9ndAvLNNlkBwRY\neEqjH2LAgKROPO/MC0hmg+IRmI1gKYM0FcxJQuUvhAcn1j4rISvCqfsyIr/7\nMPRdue3mlAfXSr4tYcffDxH352JMbKH3HYDeJ6PtaITl/vNwc+c62ORt6CJM\nxhEs+KkVLzV4zWviOpUTaYjlI6vfF7OoI8Ta/wXsZ/TD8HCbWGnba5GOr770\nz1v1rPTUNDJjWkCsJXOPtYpff7N1pzEJGSkco/C9/C8MCm9Vv3x5aaCxtbu8\nDdyj3u/taBbGmGXaF6gsZEfozjJpmx7guft8ztq+LfTk2MX+Fs0iRx4aY4OY\n/PCH\r\n=pgSt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgDxKyy/B/M+lDi125jPvoXGywKJEZFcxjzHaB34VDiwIhAJztB/Fy0kFSU3NcB9faKS+mpHRo6o1AuASlHzInPz9A"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.23-beta.0_1640513244394_0.740637729399866"},"_hasShrinkwrap":false},"0.1.23":{"version":"0.1.23","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"45b2a6d1795c532a6890295edb97a0342428aeb1","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.1.23","_nodeVersion":"12.19.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-Vrejt6f1LqSLyqAOpSmIcsvSMgsXZAMQXa+TrThNKaM9DODAfFlHNodQfEVOfHLFnYaq/zwoNgEBBcdf+b7F2w==","shasum":"2b5dc28ecdcb55dd9fad37e79d1f60aa077733fa","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.1.23.tgz","fileCount":91,"unpackedSize":101059,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhyECoCRA9TVsSAnZWagAAkSIP/3dA6qN91Pbdb1/42EXg\nVNqC4ESb3WL3sMCuixWlHFtfxbNYfsK0AxHuJyrfxLBByoBkG0G3gLlWaKOc\nbyGz2XRq3n+2JaoNaLeu3R0dHXBnyaYm3BruvVMVUMB7HE5u1rFPLYs6hkLX\nDt80sVnYcbSwl+onx/3PAEI3fKc6JsGRBNz+IDo7Y8dDqGARtdjKbJ/ZxxCj\nwZ9+Cem+ryM0hKlv6kgpH62TxyLRijuYKyzr+6NT0sh2Q+ZFyloQ1Vo7juyK\ni0dDObcca+Uo50qILLsJjOYVVzy/n0jfTeTkLOJSVo0MfjgSiYQ3XU6Z+IWB\nsIC65J315tIQdPpOHuN0Gr6g4LrfaVzdDH/7CAzgF5y7L4Yyal8XatSN47Ak\nfhnlw8r3IVz9Qkl2UbQXIvz59aX6JhvezLbaaykvd8ufQEBOUNSP8BVOsOIT\ntMnxARarnCXeYC9iRVM87NX9dWeMSW3uvAwFaiFBmepof82pUzPJjNFnGSMa\nhS6CS4rOQFlVZbA+Ob5hnvZe8ngLiAk8EaqqNoEJ34TYtKnxFwO8SrVgo4k9\nUOziBXZoG1XCCCEoLmMhydjiXtokp4D61lcHiAMODSDv0VPEcspUh5Ev3wMr\nCrcU5tEobidF+5zU1rrRaJwnoqMKEo3SzBPFd+iwdRzcPpdZX2hyu43niVmN\nKhtc\r\n=6K5t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEJuiiGHQULXRUTy1B1n8pMcJZhvns8/9BC5Bbc3icm7AiB4Q2BKvmp2yfXP5dLVU1iehbrOeuoG6eChOHQEo6R01g=="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.1.23_1640513704597_0.1276164962612194"},"_hasShrinkwrap":false},"0.2.0-beta.0":{"version":"0.2.0-beta.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"a2d2e509542ac496feccd3c0598d13991823a6c5","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.2.0-beta.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-9KqOiK9RNAsxk65MGiE5kL2ejMAGa5ZBYnBgUrF7/nCtLKze3F6/0sm2UiBCdnZioQLh8Mm0nb8pxo1hEDEZ/Q==","shasum":"deda6d8d2afea84e78ee75de60d514c3ff186f22","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.2.0-beta.0.tgz","fileCount":103,"unpackedSize":103455,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMBf1+AtBjijsCGEhG84qDAuHRaihC1xCU9uHkKOn8TQIgMiBLXdYfkCiksCvDYqBM06tp5KfwFNg4ZcKd4jEfQaY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjmx1DACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpSSRAAl073GvJR3mxXf/7iORp6OJFfebSFqpKUzxKJ//3JVXHacRtG\r\ndpj9p455hWvXfRpXJha+k9qqnmJjxWPUn8gV2NVekqTQva7tgvKi+qmrloPB\r\nYtCxoJUN3bJ3dopFFpTvJO7qhmRvCgQc4/HiA140PISkAMNuHEHh8F3nCufD\r\npBRWKT+YtjXQsPHGvMtPH+6ZtT9pyEg/Md/9I4TEXP62rsYa+kZGRRDOIVYv\r\nxyiVFdrIrGjww0KH44rfP/FWyPUHC58vxib47OktHIzAVcLaWKjr8axKFe+R\r\ni4TQRRffgMKNlFWcD7/IJ+GV0yapPQ9Zr1GhKc5PjLZ4PwE5whD4ByDynMvi\r\nCImNpZ2SQw6ydEyq5+HAjC3tIEzY8CfcrxNZCCyjJIooQNZABYPLJfX+6osg\r\nR0m4je2+uQLqKvhBNafHDkqAeSkrsSAyHRKpcp8prXp1eT2XCfzv7UFhONHG\r\nKwjdDsjVeO3zMHTChMexFNauJ5mgfgRh5sE36UROu4fCLqPp71DBUHSL0fYK\r\nXDbfxsNqbW3CPVyPA67qK88g/C3Y9oJuJp4Rrdle0rP89Yh1dZgmeDJA56AZ\r\n0HqUfqld35k7s3aZSpFCY5t1vRqHNapDSsHMFb3AMYWHdrvdE6AxyUsgNIw/\r\nC47e7KzV+o3M4Q6coepqavh95NxczV38AmA=\r\n=7JyV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.2.0-beta.0_1671109955023_0.18603271466289195"},"_hasShrinkwrap":false},"0.2.0-beta.1":{"version":"0.2.0-beta.1","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"a2d2e509542ac496feccd3c0598d13991823a6c5","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.2.0-beta.1","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-xSq1/3U6AfPEmSWxg3wsK5B2g86ywRS6Cz4Dzk7Km8xbi4eeT/XCPGAVBhumEjXzDC8ojnZ1g4Hssc3FqPE+8Q==","shasum":"3f64c300b53303d399594bf77e1a9734131f4234","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.2.0-beta.1.tgz","fileCount":115,"unpackedSize":108743,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB3DSvY847/wTv7TWB0Mo9KykfIIK+xYGRnlO/Ksdj1/AiAJ5OS/QEzxW9V3xGJeZYofN5Fi74Q/AOZ1/0tKHvdRXA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjnuhnACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrvAw//Zo6ENiwP7oQGxjPh9kaLG1PzBvCNokDdR6FFsks/jQNmpTgu\r\nMDI/ZrN1sQfyib0wbowB/VUqZtAwj8s6J4d40FNz47UcNjVDcxOcmoPzubLP\r\nxPh3L0smBeZV5wCARUTpkhzEFIIcw6yaBlrd/Ffek0du5X1a8+bqKQSdjim3\r\nzh6ih3+rsHHZM+RJSEynwWxkyIhTnfZ5k9rDgAgrZqBfUivyQ/IVfZIRgMIQ\r\ndRLBUfskXbmiviB2lpVRjYkSZYmOshcdhS1OsKo2DJuQNYJ5X+kSZfmw9d7H\r\n3a4x/F1I0EgIasurvp1EEF2a/CUi68XD9h3ExrksqsDEqFhukmbEgUC7EM3K\r\nvHo5dHYewo8IfoMsc2omcs+akMJ2JkNo3EdJTKWQQDvjd+/mOUZnHuzkRTvh\r\nCrM7qeWx/bg7QXiRxP4J3EdWAJaupAzDgauVIBF3OIRfwZdC+gbPw3WvYDVp\r\n58P/7m2ZRQJsitAEOXk/QvlKvRNrBVG4lHV4yoe4xLMRUDGRhjbqiN+muhnJ\r\nUwSAWGvQht6XXuZ0ywMFjUC6wfxUdtYuQQnkFj55t5JvsId/V4kbvaV223yk\r\nx5V+hSzfK3VtH/hrCvN6mQzJXFGDVnTlDucKNQw4dRz6cu2D3b3Ahj+xCZsp\r\nbpSzpiDgJbNty1bS4PeHkOAjDtS+n1mPvEs=\r\n=z6Hh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.2.0-beta.1_1671358567323_0.3536615000305092"},"_hasShrinkwrap":false},"0.2.0":{"version":"0.2.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"a2d2e509542ac496feccd3c0598d13991823a6c5","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.2.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-E9eZRkBRyYUOQgJstrLCKPzZ/m3uTeZhXfIkeh8tU5Atv7ROsZHsXZHxBoWz5GoVCBRJNxckZoiPD6VYFMvOKw==","shasum":"74fdd52779ca66865c55571669a72028540a4f17","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.2.0.tgz","fileCount":115,"unpackedSize":108736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDGpTyEv97wn5KiSdSaY7Q+I4pce0rn/TwFiQdQ+wlAcwIhAPmtd8jpEzDDi/x80XF5EVBYFGRk2ARgW69bn34aq9o6"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjnunMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmputA/+N0XfMOCzl6o/nbEs3oxt6u/KQX4KxcxnJSmB/oNfjNQ+R7kD\r\nP4VwoNXbZ+XmCqShu0kNVsAJzPv5shNZCBa2O6I/Tzr06/kS1L/zNW3iKepA\r\niP10OsPgyKPyAjpDS2qsOE3PENluUsUZ3vRCAyQmkyn830tls17hpVEqI3Ot\r\nOmUDwiKvLOcZry8DFoCd5pn+oJuAr690OsTBKfO3uPxG0o+ub+ussRJqejSN\r\nifkUg3t6Oe+jGhJmR9ouSZ76TyE/fjn81YE2+Q4vVgyUxayqQ9wcHdr6IViC\r\nq2i9KcHebNBwh7XC6WcIkd38oSQVcZqRosQlTPmbZojZp3c7SZxF1p/FCygV\r\nqR5EYCThjPH2XekCraYUmcl2KuXrDnF2N0OzatuPFll8njuEVGMJ0Zi9nESz\r\nViK+xKJwBzUrcgmAIfKqLW1d3E0uciQNV2rWI5042iy2zf6NiCNGzXkPBsNO\r\n3OHygpyg5qQ3lBkuSlFlBiVqHsrv/EkB+83Hfa2xHQXGxMe/dmKH331v1s9x\r\nmMIUxBdCTIs9+KCPIhiZgvQfL5a5Zd0wnO8qrLXBquyMxxKgfmlAmJc+i4AJ\r\nf1xWu+4TjqW5d4gWQBB4VnBWr+YYvcEc3C2ikUxcacXWHZCYyz7f15bOEhPO\r\nbb7gSEBzsheWAik6OXR04I4e0JZ8sPdueUc=\r\n=R+bG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.2.0_1671358923810_0.32552027206316314"},"_hasShrinkwrap":false},"0.2.1-beta.1":{"version":"0.2.1-beta.1","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"7ff2511045725409c2d9e02cd308b1edf0ea040e","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.2.1-beta.1","_nodeVersion":"16.18.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-HLcxiF1Bxa/KSj1W0roF5pJGGxcummW7wSCK6NU2YbMlO1QB/OHHDRG+JJvOmKRaJZRZiiAJIgGyBue9fUcLWA==","shasum":"422df686498ed9ac62928961aff23215e5f0241f","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.2.1-beta.1.tgz","fileCount":111,"unpackedSize":109366,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDpntSnU2CEPERteQtMH2B4HxCPIxyhi+Mm9xoMxMdLpAiB1xFID6ZSR0t/bXY0Jpcsy1uwnVk2LtUGFahxHmwwEgQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGaBiACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmosWBAAn7Ey4MtOJIc2OPOgW1VfAoIYAKiQAdRZkYX+Pb6OuO6zgehE\r\nGAnNUWOPMCJf9Sp1R0AaFUGGXSb4FMNr5pQ6pmdwyoQL5rElj/OXYx6ExJpC\r\niY8nKKkYj5+NYSfdoO9YqyMPh+OLKK1xiz2jUSauKQJtrJKqNlix531TftnY\r\n7mgXwgVh4B6HWovllWaL2GH0/Na08PJwr4QinW9vmN8U9aKshavLuAwKKb15\r\ndwIdwaSKbvw0WTMRoKKGbAZQk3xAWXd7Omr5sDTXU/EsigBLqrERGMvPT94n\r\nggHoxC2x2zIF1M6gcuQ84676yhfRveH1dxKFT17JAMnOzOy5cxctbzmAgv6s\r\ng0GG8szMNZ9qSs1VCrfkLMmko377pBnnYjqLdhiVkfN1RQdPVArnO64K8cSs\r\nRee5dH79baZrYwvIMhCvYJS6ELFX24P+/ip79Lef4jR8A51y7+Cm10o0c/Kv\r\neG3yXeMaqz6azy7txK70SURLVMO/wKLkpV7sXF7sLo4D2ak+4MUeaOcW7Iyq\r\ntaCgPWJvrTW81K0hlgcjKG1147JGWkHXt76qao2KQitM2p2mRkogOr1mFexB\r\npErf7ozO8Pr9LUOjjgDAaU4AqCCssLyTEM3QgDQ5kwvmhmJuM49qs0XmpMQ3\r\nBG+TBzakTlpO6fb5o7r4xStPchBpSIONTGk=\r\n=kHsC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.2.1-beta.1_1679401057848_0.7254626724201356"},"_hasShrinkwrap":false},"0.2.1-beta.2-debounce":{"version":"0.2.1-beta.2-debounce","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^16.13.1","react-dom":"^16.13.1","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"dc6f1850b992a17c6a49fe7196ae9feb05d807df","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.2.1-beta.2-debounce","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-aVV+BUClV+hld8oV5MGtE+UjGRiMXW1WEQQKGpEXB/2XtBwVE5Q0MKxksCoVBWgGWP1PubIF9Vbyiil20Peaaw==","shasum":"1b37a1c27de09504ba6ea41215bd0b6a9a2ecf9c","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.2.1-beta.2-debounce.tgz","fileCount":119,"unpackedSize":112212,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEZ6txyPRw2ISPQ6IeplDNfj1BVCA2cdadXad4UyoNipAiAu0hboGyX0sMce6qW+Euv4Fpr55aPrQJf/6zBzEycNXQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkRRSGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp1mA/+IlwDWkTWdegxdYaW1t8TTcywS8mwdVGsc7z6hM5QMrr8BeTB\r\nGSx1Mc/gc8FuUMyPpcLIzdpFSKXs5g77JPDAvbdpy1q1bJAbqVip12MW4c8u\r\n89LrQW+oC6ViQ5UYz10nxl5J3NrTL8kFFqjqhqRDnv+qzvmB+1+ANLr60eX9\r\nH64rytVqekAqD2FcFYAzfBImyf/jgCuvcspYt3nz5F5Dx8+7qc431DuV44JG\r\ntYfRd/QOj31bDgY8utd9Fwqg5jFodV0gDyM/IfI43t3RHEBor/gV+r5VR1zc\r\neAdN4IB+oYlhp8Y6Ch+CFHApP7B2hQbR+UnOdP6KUuMXe3po0i6lWE7vDpBd\r\n5pmlxRJK26I5aZcl5801a6tjpyVF46yc2/KPpCk4F7pRKXEA4hVID3CY+Xcu\r\n1oqBK40lkbcrJncCmcxMLlnb/MR1kGabnMGe3bfMoQ77VJCI5c50UFiQ8P0o\r\np3i3nmZsFIpduz3v1AXltnsR3leTda2oYxVyNCUGyxhwb5QJv/DCixyLhr6I\r\nB2VEzoZO1NG/jULKZpQ632zlcyQyDWRJKHlNZAxB+1uRAmJ7V93BzOvDu6nj\r\nNjbEzlwcEd8SFrhG2iPlhEhcn6wCmALbo4vvPBAIzQe3Kfb55VjGIEalC9HF\r\nC/82qg3Sj7wnMq7M/BYTLutAP7G9JZfy7h0=\r\n=FKHE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.2.1-beta.2-debounce_1682248838360_0.9138241415696722"},"_hasShrinkwrap":false},"0.0.0-beta0":{"version":"0.0.0-beta0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^18.2.0","react-dom":"^18.2.0","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n      - [Installation](#installation)\n  - [Main exports:](#main-exports)\n    - [provide - function](#provide---function)\n    - [withContext - function](#withcontext---function)\n    - [createMobXContext - function](#createmobxcontext---function)\n    - [useAsyncState - hook](#useasyncstate---hook)\n    - [useAsyncEffect - hook](#useasynceffect---hook)\n    - [isCapacitor - function](#iscapacitor---function)\n    - [useMemoOnce - hook](#usememoonce---hook)\n    - [useCallbackOnce - hook](#usecallbackonce---hook)\n    - [getDisplayName - function](#getdisplayname---function)\n    - [AsyncTools - object](#asynctools---object)\n      - [to](#to)\n      - [parseJSON](#parsejson)\n      - [fetch](#fetch)\n      - [superFetch](#superfetch)\n    - [ValidateFields - object](#validatefields---object)\n\n#### Installation\n\n``` bash\nnpm install --save @hilma/tools\n```\n\n## Main exports:\n\n### provide - function\n\n`provide` is a function that returns a HOC (Higher Order Component) that is used to eliminate nested providers in `React`.\n\n__without provide:__\n```jsx\nimpoer React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/** .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\n__with provide:__\n```jsx\nimpoer React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\nWhat `provide` does is wrap your component recursively for each component you pass to is. What this actually does looks something like this:\n\n```jsx\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nconst Provided1 = () => (\n    <StylesProvider>\n        <App />\n    </StylesProvider>\n);\n\nconst Provided2 = () => (\n    <ThemeProvider>\n        <Provided1 />\n    </ThemeProvider>\n);\n\nconst Provided3 = () => (\n    <AuthProvider>\n        <Provided2 />\n    </AuthProvider>\n);\n\nexport default Provided3;\n```\n\nIf you want to pass props to your provider, then you can pass an array where the first item is the provider and the second is an object that is the props of the provider:\n\n```jsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/** .... */}\n        </div>\n    );\n}\n\nexport default provide([AuthProvider, { basename: \"/\" }], ThemeProvider, [StylesProvider, { style: \"dark\" }])(App);\n```\n\n### withContext - function\n\n`withContext` is a function that returns a HOC (Higher Order Component) that is used to consume multiple context objects via props in a class based component in `React` (can also be used with functional components but not necessary with `useContext`).\n\n__example__:\n\n```jsx\nimport React, { Component } from 'react';\nimport { withContext } from '@hilma/tools';\n\nclass MyComponent extends Component {\n    componentDidMount() {\n        this.props.api...........\n    }\n    \n    render() {\n        return (\n            <div>{this.props.theme........}</div>\n        );\n    }\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nLet's look at what's going on here. First of all we're passing an object to `withContext`. this object represents how you want context objects to be passed via props: The key is the name of the prop you want and the value is the context object you want to pass down via the key.\n\nIn the example, we pass a key of 'theme' and value of 'ThemeContext'. This means that the 'ThemeContext' value will be passed down via the 'theme' prop. This is the same with 'api' and 'ApiContext'.\n\n### createMobXContext - function\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`.\n\n```jsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n```\n\nIn this instance, we need a way to pass around `theme` between our components. The best way to do this is to use `React`'s context api. The problem with that is there is a lot of boilerplate needed to make it all happen. That's where `createMobXContext` comes in. Let's see how to use it:\n\n```jsx\nclass ThemeStore {\n    ....\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\nHere we pass to  `createMobXContext` our store instance and get back an array with three items: The first being a context object that will hold our store for us, the second is a provider that we wrap our application with to provide the store, and the third is a hook that returns the store.\n\nLet's look at an example of useing those items:\n```jsx\nimport { ThemeContext, ThemeProvider, useTheme } from '......';\n\nconst App = () => (\n    <ThemeProvider>\n        <ClassComp />\n        <FuncComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n```\n\n### useAsyncState - hook\n\n`useAsyncState` is a hook based on the `useState` but with some extra useful asynchronous functionality:\n\n```jsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n`useAsyncState` is very similar to `useState`. it returns a tuple with three items: `state`, `setState` and `getState`. `state` is your state, `setState` is your setter, and `getState` is a getter.\n\nWith `useAsyncState`, now the `setState` function returns a promise with the resloved value being the new state. You can also pass a callback to the `setState` function that receives the new state.\n\nThe `getState` function returns a promise with the resolved value being the current state. The reason this is needed is because with the regular `state` variable, you won't always have the current state, for example, if you use a piece of state in an effect and its not one of the dependencies of `useEffect`.\n\n### useAsyncEffect - hook\n\n`useAsyncEffect` is a hook based on the `useEff ect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```jsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or an `async` cleanup function, you can do both, either one, or neither of them.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup can be called after the next effect (if you don't send an empty dependency array).\n\n### isCapacitor - function\n\nreturns a boolean value. If true, your'e working in a `Capacitor` environment:\n\n```jsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### useMemoOnce - hook\n\n`useMemoOnce` is a hook that calls `useMemo` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized value calculated once:\n\n```jsx\nimport { useMemoOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const value = useMemoOnce(() => {\n        return {\n            theme: \"dark\"\n        }\n    });\n\n    return <div>{value.theme}</div>;\n}\n```\n\n### useCallbackOnce - hook\n\n`useCallbackOnce` is a hook that calls `useCallback` with an empty dependency array. Not many use cases but when used, it's very explicit that you only want a memoized function calculated once:\n\n```jsx\nimport { useCallbackOnce } from '@hilma/tools';\n\nconst Comp = () => {\n\n    const func = useCallbackOnce(async () => {\n        await login();\n    });\n\n    return <button onClick={func}>click</button>;\n}\n```\n\n### getDisplayName - function\n\nA function that accepts a `React` component and returns its name. (don't use in production):\n\n```jsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n```\n\n### AsyncTools - object\n\n`AsyncTools` is an object that inlcudes some useful asynchronous functions:\n\n#### to\n\n`to` is a function that accepts an promise, and returns a promise with the resloved value being an array with two items, the first one being the rejected error (if there was one) and the seconde item being the resolved value (it there was one):\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [error, response] = await AsyncTools.to(fetch('/api/user/1'));\n    if (error) return console.error(error);\n    const data = await response.json();\n    return data;\n}\n```\n\n#### parseJSON\n\n`parseJSON` is a function that accepts a response from a fetch request (specifically from the `fetch` function of the browser) and returns a promise with the resolve value being an object with some info about the response:\n\n- __status:__ the response status.\n- __ok:__ if the request was made successfully\n- __json:__ the json response. if there's no response this will hold an object with a key value pair like `ok`\n  \n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const { status, ok, json } = await AsyncTools.parseJSON(await fetch('/api/user/1'));\n    if (!ok) return console.error(json);\n    return json;\n}\n```\n\n#### fetch\n\n`fetch` calls the browser's `fetch` function but also parses the json response:\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const data = await AsyncTools.fetch('/api/users/1');\n    return data;\n}\n```\n\n#### superFetch\n\n`superFetch` calls `AsyncTools.fetch` but returns an promise with the resolved value being an array with two items. the first item is the json response (if there was one) and the second item, the rejected value (if there was one)\n\n```jsx\nimport { AsyncTools } from '@hilma/tools';\n\nconst getstuff = async () => {\n    const [data, error] = await AsyncTools.superFetch('/api/users/1');\n    if (error) return console.error(error);\n    return data;\n}\n```\n\n### ValidateFields - object\n\nAn object that includes functions that validate inputs based on different types of information, like usernames, phonenumbers, names, email, and so on. Each function returns a string. If the value is valid, the string will be empty, if not, the string will be an error message in hebrew that describes what's not valid about the input. Let's look at one of these functions: \n\n```jsx\nimport { ValidateFields } from '@hilma/tools';\n\nconst isValid = ValidateFields.validateFullNameInput('הילמה הילמה');\n\nconsole.log(isValid); // ''\n\nconst isValid = ValidateFields.validateFullNameInput('שדגכשדגכשגדכשדגכשדגכשדגכשדגכשדגכשדגכשדגכשדגכ');\n\nconsole.log(isValid); // 'השם חייב להכיל פחות מ30 תווים'\n```","readmeFilename":"README.md","gitHead":"08a4941d9c84653af4f84d9224ff852fda91a538","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.0.0-beta0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-K5FtUfz43eJwHqZxjsvW5TUWPfsg48juUeyxsO8ECH92avVISIIBzwqwXOUfo0Y7+2Aj36emYuhMNltilxQ6kw==","shasum":"eedbaf8908996ae5b305ec1a7047ec5540ca7b1d","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.0.0-beta0.tgz","fileCount":115,"unpackedSize":108740,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF6o5FQCw18duCL9bKVskuXhiKvOAAxsKE3NnvT48wtsAiEAk1wLS/Lqf7+mS4dNe8rYPQ6cABfZa9zhRmVnaSgfR+g="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.0.0-beta0_1683703085527_0.22808449884598048"},"_hasShrinkwrap":false},"0.3.0":{"version":"0.3.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build"},"peerDependencies":{"react":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@capacitor/core":"^2.4.2","@types/node":"^14.0.5","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^4.2.5","react":"^18.2.0","react-dom":"^18.2.0","rimraf":"^3.0.2","typescript":"^4.0.5"},"dependencies":{"dotenv":"^8.2.0","validate.js":"^0.13.1"},"gitHead":"08a4941d9c84653af4f84d9224ff852fda91a538","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.3.0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-B2Cz1nkm/wnCPqLu83mpq/56auGcoJgIOGtu6S/7Zkt82FW0WNLl82ria0ulsek8rUlEGACB2Scfbl1JG6BZoQ==","shasum":"eff4a30ba95872eb6d84355226603541d91add12","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.3.0.tgz","fileCount":115,"unpackedSize":108733,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC9JnXC6fgQbq89iuyBFTzRBZ+C+4leY3j+XmS8H19X0AIhAPlwm+rfsVlIp/bShiZ0DskgEkZQSbiJDGDHue68JeVH"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.3.0_1683784949889_0.8675308513404694"},"_hasShrinkwrap":false},"0.4.0":{"version":"0.4.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npx husky install && npm run build","test":"jest","test:watch":"jest --watchAll"},"peerDependencies":{"react":">=16","react-dom":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@swc/jest":"^0.2.26","@testing-library/react":"^14.0.0","@types/jest":"^29.5.1","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","husky":"^8.0.3","jest":"^29.5.0","jest-environment-jsdom":"^29.5.0","rimraf":"^5.0.1","ts-jest":"^29.1.0","typescript":"^4.0.5"},"dependencies":{"validate.js":"^0.13.1"},"gitHead":"10305eb480e6a611d09e12d75c34f5af32dda9eb","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.4.0","_nodeVersion":"18.16.0","_npmVersion":"9.5.1","dist":{"integrity":"sha512-ac/gaOkRCpUYzF9U+u4GtS9cNuU/IuDCZ0m/t3IZX0A26r+rVC6FI+Bh/o0W1DG+z3W93T3q4wHmZxhnqPYxWg==","shasum":"ba6588f5ff8654e863c3f6985f418951e8bba20b","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.4.0.tgz","fileCount":87,"unpackedSize":120154,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE2oih968tTXc+7kPdMervtsgLk2OpSA5u2ufH7KqFZ4AiEA2z95S45ZuIZ871L/uPD/lalODqMoZb8XhXUp/GA7zco="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.4.0_1686821542669_0.8119924625370878"},"_hasShrinkwrap":false},"0.0.0-XhUgS5tz":{"version":"0.0.0-XhUgS5tz","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build","test":"jest","test:watch":"jest --watchAll","test:co":"jest --coverage","get-command":"echo \"npm install @hilma/forms@$(npm pkg get version | sed \"s/\\\"//g\")\"","randomize-version":"npm pkg set version=\"0.0.0-$(openssl rand -base64 6)\" ","beta":"npm run randomize-version && npm publish --tag beta && npm run get-command"},"peerDependencies":{"react":">=16","react-dom":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@swc/jest":"^0.2.26","@testing-library/react":"^14.0.0","@types/jest":"^29.5.1","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","jest":"^29.5.0","jest-environment-jsdom":"^29.5.0","rimraf":"^5.0.1","ts-jest":"^29.1.0","typescript":"^4.0.5"},"dependencies":{"validate.js":"^0.13.1"},"readme":"# Tools\n\nTools is a package that has some useful client side tools.\n\n- [Tools](#tools)\n    - [Installation](#installation)\n    - [Usage](#usage)\n\t    - [`provide` and `wrap`](#provide-and-wrap)\n\t    - [`withContext`](#withcontext)\n\t    - [`createContextHook`](#createcontexthook)\n\t    - [`createMobXContext`](#createmobxcontext)\n\t    - [`useAsyncState`](#useasyncstate)\n\t    - [`useAsyncEffect`](#useasynceffect)\n        - [`useLocalStorage` and `useSessionStorage`](#uselocalstorage-and-usesessionstorage)\n\t    - [`isCapacitor`](#iscapacitor)\n\t    - [`getDisplayName`](#getdisplayname)\n    -  [API](#api)\n\t    - [`provide`](#provide)\n            - [`wrap`](#wrap)\n\t    - [`withContext`](#withcontext-1)\n\t    - [`createContextHook`](#createcontexthook-1)\n\t    - [`createMobXContext`](#createmobxcontext-1)\n\t    - [`useAsyncState`](#useasyncstate-1)\n\t    - [`useAsyncEffect`](#useasynceffect-1)\n        - [`useLocalStorage`](#uselocalstorage)\n        - [`useSessionStorage`](#usesessionstorage)\n\t    - [`isCapacitor`](#iscapacitor-1)\n\t    - [`getDisplayName`](#getdisplayname-1)\n\n## Installation\n\n``` bash\nnpm install @hilma/tools\n```\n\n## Usage\n\n### `provide` (and `wrap`)\n\n`provide` is a function that is used to eliminate nested providers in React code.\n\nOften we have a component with tons of wrappers or providers, where all we care about is the component logic itself, like this:\n\n```tsx\nimport React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/* .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\nNot even taking into account that `App` might want to use the context provided by `AuthProvider`, `ThemeProvider`, and the like, this code is already looking much more complicated than it should be. `provide` aims to simplify code like this.\n\n__With `provide`:__\n\n```tsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/* .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\n\nThis allows us to access the context provided by `AuthProvider`, `ThemeProvider`, etc. from inside of `App`, and makes our code much simpler to read and understand.\n\nIf you want to pass props to a provider, you can use a tuple where the first item is the provider and the second is the props:\n\n```tsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/* .... */}\n        </div>\n    );\n}\n\nexport default provide(\n    [AuthProvider, { basename: \"/\" }],\n    ThemeProvider,\n    [StylesProvider, { style: \"dark\" }]\n)(App);\n```\n\n### `withContext`\n\n`withContext` is used to consume multiple contexts via props in some component.\n\n__Example__:\n\n```tsx\nimport React, { createContext } from 'react';\nimport { withContext } from '@hilma/tools';\n\nconst ThemeContext = createContext(\"black\");\nconst ApiContext = createContext(\"http://localhost:8080\"):\n\nconst MyComponent: React.FC<{ theme: string; api: string; }> = (props) => {\n\t// instead of doing\n\t// const theme = useContext(ThemeContext);\n\t// const api = useContext(ApiContext);\n\t// we can just get the context values from the props\n\tconst { theme, api } = props;\n\n\treturn (\n\t\t<div>\n\t\t\t{/* ... */}\n\t\t</div>\n\t);\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nOur component here takes a `theme` and `api` prop that correlate to the values provided by `ThemeContext` and `ApiContext`. We then define a `mapContextToProps` object that connects the contexts to the props.\n\n### `createContextHook`\n\nWe often can't populate our React contexts with values when we're creating them. A common solution to this problem is to define our context's type with `SomeType | null`, like this:\n\n```tsx\nconst UsernameContext = createContext<string | null>(null);\n```\n\nAnd then building our own custom `useMyContext` hook that can ignore this `null`, like so:\n\n```tsx\n// either\nconst useMyContext = () => useContext(UsernameContext)!;\n\n// or\nconst useMyContext = () => {\n\tconst value = useContext(UsernameContext);\n\tif (value === null) throw new Error(\"You called useUsername while not inside of the UsernameProvider\");\n\treturn value;\n}\n```\n\n`createContextHook` simplifies this process by automating the second approach. So the second version of `useMyContext` in the example above is the same as doing:\n\n```tsx\nimport { createContextHook } from '@hilma/tools';\n\nUsernameContext.displayName = \"Username\";\nconst useMyContext = createContextHook(UsernameContext);\n```\n\n### createMobXContext\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`. It works with `createContextHook`, and is based on the fact that when using `mobx`, we _do_ have a starting value (the store itself).\n\n```tsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\n\nHere we pass to  `createMobXContext` our store instance and get back a tuple with three items: \n1) A context for the `ThemeStore`\n2) A provider that we can wrap our application with\n3) A hook that uses that context\n\nLet's look at an example of using these items:\n\n```tsx\nimport { ThemeContext, ThemeProvider, useTheme } from './ThemeContext';\n\nconst App = () => (\n    <ThemeProvider>\n        <FuncComp />\n        <ClassComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n```\n\n### useAsyncState\n\n`useAsyncState` is a hook based on `useState` but with some extra useful asynchronous functionality. It returns a tuple with three items: \n1) `state`,  the actual state, just like with `useState`\n2) `setState`, which sets the value of the state and returns a promise with the new state\n3) `getState`, which returns a promise of the state's current value no matter when. This is needed because the `state` variable is not always up to date with the latest state inside of a `useEffect`.\n\n```tsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n### useAsyncEffect\n\n`useAsyncEffect` is a hook based on the `useEffect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```tsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or with an `async` cleanup function.\n\n__Note:__ Because the behavior of the cleanup can be asynchronous, the cleanup might be called after the next effect (if you don't have an empty dependency array). You shouldn't rely too heavily on state changes and the like occuring due to cleanup functions returned from a `useAsyncEffect`.\n\n### `useLocalStorage` and `useSessionStorage`\n\nThese functions wrap `useState` and create a simple API for working with JSON data stored in either `localStorage` or `sessionStorage`.\n\n```tsx\nconst MyComponent = () => {\n    // the first parameter is the key to store the data in\n    // the second parameter is the value to default to, in case the data\n    // doesn't yet exist or is corrupted somehow\n    const [theme, setTheme] = useLocalStorage<\"dark\" | \"light\">(\"theme\", \"dark\");\n    const [canSendHeart, setCanSendHeart] = useSessionStorage(\"has-seen-popup\", true);\n\n    return (\n        <div className={theme}>\n            <button \n                onClick={() => {\n                    // this will update both the state (causing a re-render) and `localStorage`\n                    setTheme(\"light\");\n                }}\n            >\n                Change Theme\n            </button>\n\n            {canSendHeart && (\n                <button \n                    onClick={() => {\n                        // this will update both the state (causing a re-render) and `sessionStorage`\n                        setCanSendHeart(false);\n                    }}\n                >\n                    Send Heart\n                </button>\n            )}\n        </div>\n    );\n}\n```\n\n### isCapacitor\n\nReturns a boolean value. If `true`, the code is running in a `Capacitor` environment.\n\n```tsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### getDisplayName\n\nA function that accepts a `React` component and returns its name. (This is mainly for testing and better error messages for developers; don't rely on this function in production).\n\n```tsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n\nconst OtherComp = () => {\n\treturn <div></div>;\n}\n\nOtherComp.displayName = 'MyComponent';\n\nconsole.log(getDisplayName(OtherComp)); // 'MyComponent';\n```\n\n### useMemoOnce\n\n**DEPRECATED** - if you need a `useMemo` that only happens once, call `useMemo` with an empty dependency array. Regardless, you should note that `useMemo` is often an anti-pattern and you should try to avoid it when it isn't needed. Read more [here](https://blog.logrocket.com/when-not-to-use-usememo-react-hook/).\n\n`useMemoOnce` will be removed from `@hilma/tools` by version `1.0.0`.\n\n### useCallbackOnce\n\n**DEPRECATED** - if you need a `useCallback` that only happens once, call `useCallback` with an empty dependency array.\n\n`useCallbackOnce` will be removed from `@hilma/tools` by version `1.0.0`.\n\n### AsyncTools\n\n**DEPRECATED** - use a package like `axios` for simple, well-typed data fetching with error handling, and packages like `@tanstack/react-query` to handle the state of that data, along with caching.\n\n`AsyncTools` will be removed from `@hilma/tools` by version `1.0.0`.\n\n### ValidateFields\n\n**DEPRECATED** - use a package like `yup` or `zod`. Those packages are far more in-depth, provide a TypeScript-supporting interface, and interop much better with other libraries. In particular, `yup` is the recommended solution for validation using `@hilma/forms`.\n\n`ValidateFields` will be removed from `@hilma/tools` by version `1.0.0`.\n\n## API\n\n### `provide`\n\n```typescript\nexport function provide<TParents extends { [key: string]: any }[]>(\n\t...parents: Providers<TParents>\n): <TProps>(\n\tchild: React.ComponentType<TProps>\n) => React.ComponentType<TProps>;\n```\n\nThe `Providers` type maps an array of prop types to an array of either `ComponentType` or `[ComponentType, Props]`, depending on which props are required and whether the props include `children`.\n\n- If a provider does not take the `children` prop, it cannot be used within `parents`\n- If a provider doesn't take any required props, it can either be passed as `Component` or as `[Component, Props]`\n- If a provider takes any required props, it _must_ be passed as `[Component, Props]`\n\n### `wrap`\n\n```typescript\nexport function wrap<TParents extends { [key: string]: any }[]>(\n\t...parents: Provider<TParents>\n): {\n\t(element: Element) => Element;\n\t<TProps>(\n\t\tcomponent: React.ComponentType<TProps>, props: TProps\n\t) => Element;\n}\n```\n\nThe `Providers` type here is the same as for `provide`. See [above](#provide).\n\n### `withContext`\n\n```typescript\nexport function withContext<T extends {}>(\n\tmapContextToProps: MapContextToProps<T>\n): <TProps extends T>(\n\tchild: React.ComponentType<TProps>\n) => React.ComponentType<Omit<TProps, keyof T>>;\n```\n\nThe `MapContextToProps` type takes a generic type `T` (some basic props object) and returns a type with that type's value, mapped to context types.\n\n###  `createContextHook`\n\n```typescript\nexport function createContextHook<T>(\n\tcontext: React.Context<T | null>\n): () => T\n```\n\n### `createMobXContext`\n\n```typescript\nexport function createMobXContext<T extends { [key: string]: any }>(\n\tstoreInstance: T\n): [React.Context<T>, React.FC<{ children?: React.ReactNode }>, () => T]\n```\n\n###  `useAsyncState`\n\n```typescript\nexport function useAsyncState<T>(\n\tinitialState: T | (() => T)\n): [T, (value: T | ((prev: T) => T)) => Promise<T>, () => Promise<T>]\n```\n\n### `useAsyncEffect`\n\n```typescript\nexport function useAsyncEffect(\n\teffect: () => void | (() => void) | Promise<void | (() => void)>,\n\tdeps: React.DependencyList\n): void;\n```\n\n### `useLocalStorage`\n\n```typescript\nexport function useLocalStorage<T>(\n    key: string,\n    fallback: T\n): [T, (value: T | ((prev: T) => T)) => void];\n```\n\n### `useSessionStorage`\n\n```typescript\nexport function useSessionStorage<T>(\n    key: string,\n    fallback: T\n): [T, (value: T | ((prev: T) => T)) => void];\n```\n\n### `isCapacitor`\n\n```typescript\nexport function isCapacitor(): boolean\n```\n\n### `getDisplayName`\n\n```typescript\nexport function getDisplayName(\n\tcomponent: React.ComponentType<unknown>\n): string;\n```\n","readmeFilename":"README.md","gitHead":"662fdf7db2ce455a390082b0d4b9b83967f2fb02","description":"Tools is a package that has some useful client side tools.","_id":"@hilma/tools@0.0.0-XhUgS5tz","_nodeVersion":"18.16.0","_npmVersion":"9.5.1","dist":{"integrity":"sha512-RvO8etd6e8kDMWsoifgJQCVJtzQTbvR7n9HSa8XsBVeDzmvUCtcEWzjftsfmGYyFAr5BMa1BKlqQBK/zmWWp3w==","shasum":"db684e5bef98598de865758d9508bc5c46e5d522","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-0.0.0-XhUgS5tz.tgz","fileCount":91,"unpackedSize":126362,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBoSRG4Dofb58Uk7S87zD9YEA9l6q02gjKrTscNLUiP2AiAFvQQPANtX4Qb383L+LjC6bOxhavqxXz3pQOFjfgKfiQ=="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_0.0.0-XhUgS5tz_1687268887783_0.20525900104557415"},"_hasShrinkwrap":false},"1.0.0":{"version":"1.0.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build","test":"jest","test:watch":"jest --watchAll","test:co":"jest --coverage"},"peerDependencies":{"react":">=16","react-dom":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@swc/jest":"^0.2.26","@testing-library/react":"^14.0.0","@types/jest":"^29.5.1","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","jest":"^29.5.0","jest-environment-jsdom":"^29.5.0","rimraf":"^5.0.1","ts-jest":"^29.1.0","typescript":"^4.0.5"},"gitHead":"afdfd117f3d8eeec719fe1ecf5a4c32db96f63f1","description":"Tools is a package that has some useful client side tools. It makes writing client side code (particularly React boilerplate) easier and simpler. You can see more code examples in [the CodeSandbox](https://codesandbox.io/p/github/ej-shafran/hilma-tools-sa","_id":"@hilma/tools@1.0.0","_nodeVersion":"18.16.0","_npmVersion":"9.5.1","dist":{"integrity":"sha512-ofK7mcYxhrJbOVA3x7KVU2WExSz+kl01x0Z0cXbHt/aM3H/VpJfNKi7shXE6XnvtYRyxDno6/u+6USe+1ztbzA==","shasum":"283d8042795478c317d74c2ee67cfaa86bbb42e7","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-1.0.0.tgz","fileCount":67,"unpackedSize":60688,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC6EIS5Hg9Ov6dfcTLunwaAvclfzYQhB+0Cu/hyVLRVKQIgGywW32+Zt2rULiODW6euMVqA/BmEZKboLWlfkq4OC9c="}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_1.0.0_1687366048694_0.6390930157474437"},"_hasShrinkwrap":false},"1.1.0":{"version":"1.1.0","license":"MIT","main":"dist/index.js","typings":"dist/index.d.ts","engines":{"node":">=10"},"scripts":{"start":"tsc --watch","prebuild":"rimraf dist","build":"tsc","prepare":"npm run build","test":"jest","test:watch":"jest --watchAll","test:co":"jest --coverage","get-command":"echo \"npm install @hilma/tools@$(npm pkg get version | sed \"s/\\\"//g\")\"","randomize-version":"npm pkg set version=\"0.0.0-$(openssl rand -base64 6)\" ","beta":"npm run randomize-version && npm publish --tag beta && npm run get-command"},"peerDependencies":{"react":">=16","react-dom":">=16"},"name":"@hilma/tools","author":{"name":"Yona Ben-Reuven"},"devDependencies":{"@swc/jest":"^0.2.26","@testing-library/react":"^14.0.0","@types/jest":"^29.5.1","@types/react":"^16.9.35","@types/react-dom":"^16.9.8","jest":"^29.5.0","jest-environment-jsdom":"^29.5.0","rimraf":"^5.0.1","ts-jest":"^29.1.0","typescript":"^4.0.5"},"gitHead":"3c3d61156c739c7f31762a719822f3762e74f1d3","description":"Tools is a package that has some useful client side tools. It makes writing client side code (particularly React boilerplate) easier and simpler. You can see more code examples in [the CodeSandbox](https://codesandbox.io/p/github/ej-shafran/hilma-tools-sa","_id":"@hilma/tools@1.1.0","_nodeVersion":"18.16.0","_npmVersion":"9.5.1","dist":{"integrity":"sha512-ZygCuL3GqQPHDX4OUZZkq5Yy9nEbkrwmxAzJS2ve2YGJCdZiFTtPCijDCdkRdLGPdy6mMKvTsJRCTz9DoGUksA==","shasum":"1ee78c4ab14a80d68b7bd2581314b85305610047","tarball":"https://registry.npmjs.org/@hilma/tools/-/tools-1.1.0.tgz","fileCount":75,"unpackedSize":85241,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCUu3hPDvIJqhtsqL1uxsxTJ/1PF8TA0fkbWQpPdWeJQIhAL/QZIn6FslEFdRx3SFRIN7nlJrMiH6j861xU9eVGuDL"}]},"_npmUser":{"name":"hilma","email":"carmel6000dev@gmail.com"},"directories":{},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tools_1.1.0_1689836902780_0.002980289976799888"},"_hasShrinkwrap":false}},"time":{"created":"2020-05-27T12:41:05.831Z","0.1.0":"2020-05-27T12:41:06.158Z","modified":"2023-07-20T07:08:23.074Z","0.1.1":"2020-05-27T12:44:39.414Z","0.1.2":"2020-05-27T12:47:51.303Z","0.1.3":"2020-06-07T16:51:01.120Z","0.1.4":"2020-06-08T09:26:12.739Z","0.1.5":"2020-06-09T12:10:39.592Z","0.1.6":"2020-06-14T08:37:04.691Z","0.1.7":"2020-07-01T11:55:04.469Z","0.1.8":"2020-08-05T09:02:08.479Z","0.1.9":"2020-09-24T06:01:28.348Z","0.1.10":"2020-09-24T08:42:28.377Z","0.1.11":"2020-10-01T08:18:41.384Z","0.1.12":"2020-10-21T06:26:18.136Z","0.1.13":"2020-10-22T07:37:11.707Z","0.1.14":"2020-10-22T07:47:38.446Z","0.1.15":"2020-10-27T19:12:35.747Z","0.1.16":"2020-11-10T11:25:14.487Z","0.1.17":"2020-11-10T11:32:59.654Z","0.1.18":"2020-11-10T12:37:18.310Z","0.1.19":"2020-11-18T08:01:36.312Z","0.1.20":"2021-01-03T10:31:44.314Z","0.1.21-beta.0":"2021-03-18T12:04:10.519Z","0.1.21":"2021-03-18T12:11:28.409Z","0.1.22-beta.0":"2021-03-21T08:18:47.524Z","0.1.22":"2021-03-21T08:23:09.098Z","0.1.23-beta.0":"2021-12-26T10:07:24.539Z","0.1.23":"2021-12-26T10:15:04.805Z","0.2.0-beta.0":"2022-12-15T13:12:35.198Z","0.2.0-beta.1":"2022-12-18T10:16:07.497Z","0.2.0":"2022-12-18T10:22:03.991Z","0.2.1-beta.1":"2023-03-21T12:17:38.010Z","0.2.1-beta.2-debounce":"2023-04-23T11:20:38.559Z","0.0.0-beta0":"2023-05-10T07:18:05.771Z","0.3.0":"2023-05-11T06:02:30.127Z","0.4.0":"2023-06-15T09:32:22.865Z","0.0.0-XhUgS5tz":"2023-06-20T13:48:08.094Z","1.0.0":"2023-06-21T16:47:28.890Z","1.1.0":"2023-07-20T07:08:22.905Z"},"maintainers":[{"name":"hilma","email":"carmel6000dev@gmail.com"},{"name":"elsasebagh","email":"elsa@carmel6000.amitnet.org"}],"author":{"name":"Yona Ben-Reuven"},"license":"MIT","readme":"# Tools\n\nTools is a package that has some useful client side tools. It makes writing client side code (particularly React boilerplate) easier and simpler. You can see more code examples in [the CodeSandbox](https://codesandbox.io/p/github/ej-shafran/hilma-tools-sandbox/draft/late-dew?workspaceId=a0b9b70f-df77-4288-bcf0-323a0ece81e3).\n\nThis documentation is also available in [the Hilma Confluence space](https://hilma.atlassian.net/wiki/spaces/TD/pages/698515457/Hilma+Tools).\n\n- [Tools](#tools)\n    - [Installation](#installation)\n    - [Usage](#usage)\n\t    - [`provide` and `wrap`](#provide-and-wrap)\n\t    - [`withContext`](#withcontext)\n\t    - [`createContextHook`](#createcontexthook)\n\t    - [`createMobXContext`](#createmobxcontext)\n\t    - [`useAsyncState`](#useasyncstate)\n\t    - [`useAsyncEffect`](#useasynceffect)\n        - [`useLocalStorage` and `useSessionStorage`](#uselocalstorage-and-usesessionstorage)\n        - [`ErrorBoundary`](#errorboundary)\n\t    - [`isCapacitor`](#iscapacitor)\n\t    - [`getDisplayName`](#getdisplayname)\n    -  [API](#api)\n\t    - [`provide`](#provide)\n            - [`wrap`](#wrap)\n\t    - [`withContext`](#withcontext-1)\n\t    - [`createContextHook`](#createcontexthook-1)\n\t    - [`createMobXContext`](#createmobxcontext-1)\n\t    - [`useAsyncState`](#useasyncstate-1)\n\t    - [`useAsyncEffect`](#useasynceffect-1)\n        - [`useLocalStorage`](#uselocalstorage)\n        - [`useSessionStorage`](#usesessionstorage)\n        - [`ErrorBoundary`](#errorboundary)\n\t    - [`isCapacitor`](#iscapacitor-1)\n\t    - [`getDisplayName`](#getdisplayname-1)\n\n## Installation\n\n``` bash\nnpm install @hilma/tools\n```\n\n## Usage\n\n### `provide` (and `wrap`)\n\n`provide` is a function that is used to eliminate nested providers in React code.\n\nOften we have a component with tons of wrappers or providers, where all we care about is the component logic itself, like this:\n\n```tsx\nimport React from 'react';\n\nconst App = () => {\n    return (\n        <AuthProvider>\n            <ThemeProvider>\n                <StylesProvider>\n                    <div className=\"App\">\n                        {/* .... */}\n                    </div>\n                </StylesProvider>\n            </ThemeProvider>\n        </AuthProvider>\n    );\n}\n\nexport default App;\n```\n\nNot even taking into account that `App` might want to use the context provided by `AuthProvider`, `ThemeProvider`, and the like, this code is already looking much more complicated than it should be. `provide` aims to simplify code like this.\n\n__With `provide`:__\n\n```tsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/* .... */}\n        </div>\n    );\n}\n\nexport default provide(AuthProvider, ThemeProvider, StylesProvider)(App);\n```\n\nThis allows us to access the context provided by `AuthProvider`, `ThemeProvider`, etc. from inside of `App`, and makes our code much simpler to read and understand.\n\nIf you want to pass props to a provider, you can use a tuple where the first item is the provider and the second is the props:\n\n```tsx\nimport React from 'react';\nimport { provide } from '@hilma/tools';\n\nconst App = () => {\n    return (\n        <div className=\"App\">\n            {/* .... */}\n        </div>\n    );\n}\n\nexport default provide(\n    [AuthProvider, { basename: \"/\" }],\n    ThemeProvider,\n    [StylesProvider, { style: \"dark\" }]\n)(App);\n```\n\n### `withContext`\n\n`withContext` is used to consume multiple contexts via props in some component.\n\n__Example__:\n\n```tsx\nimport React, { createContext } from 'react';\nimport { withContext } from '@hilma/tools';\n\nconst ThemeContext = createContext(\"black\");\nconst ApiContext = createContext(\"http://localhost:8080\"):\n\nconst MyComponent: React.FC<{ theme: string; api: string; }> = (props) => {\n\t// instead of doing\n\t// const theme = useContext(ThemeContext);\n\t// const api = useContext(ApiContext);\n\t// we can just get the context values from the props\n\tconst { theme, api } = props;\n\n\treturn (\n\t\t<div>\n\t\t\t{/* ... */}\n\t\t</div>\n\t);\n}\n\nconst mapContextToProps = {\n    theme: ThemeContext,\n    api: ApiContext\n}\n\nexport default withContext(mapContextToProps)(MyComponent);\n```\n\nOur component here takes a `theme` and `api` prop that correlate to the values provided by `ThemeContext` and `ApiContext`. We then define a `mapContextToProps` object that connects the contexts to the props.\n\n### `createContextHook`\n\nWe often can't populate our React contexts with values when we're creating them. A common solution to this problem is to define our context's type with `SomeType | null`, like this:\n\n```tsx\nconst UsernameContext = createContext<string | null>(null);\n```\n\nAnd then building our own custom `useMyContext` hook that can ignore this `null`, like so:\n\n```tsx\n// either\nconst useMyContext = () => useContext(UsernameContext)!;\n\n// or\nconst useMyContext = () => {\n\tconst value = useContext(UsernameContext);\n\tif (value === null) throw new Error(\"You called useUsername while not inside of the UsernameProvider\");\n\treturn value;\n}\n```\n\n`createContextHook` simplifies this process by automating the second approach. So the second version of `useMyContext` in the example above is the same as doing:\n\n```tsx\nimport { createContextHook } from '@hilma/tools';\n\nUsernameContext.displayName = \"Username\";\nconst useMyContext = createContextHook(UsernameContext);\n```\n\n### `createMobXContext`\n\n`createMobXContext` is a function that eliminates the boilerplate needed to use `mobx` with `React`. It works with `createContextHook`, and is based on the fact that when using `mobx`, we _do_ have a starting value (the store itself).\n\n```tsx\nimport { makeAutoObservable } from 'mobx';\n\nclass ThemeStore {\n    color = \"dark\";\n\n    constructor() {\n        makeAutoObservable(this);\n    }\n\n    setColor = color => {\n        this.color = color;\n    }\n}\n\nconst theme = new ThemeStore();\n\nexport const [ThemeContext, ThemeProvider, useTheme] = createMobXContext(theme);\n```\n\nHere we pass to  `createMobXContext` our store instance and get back a tuple with three items: \n1) A context for the `ThemeStore`\n2) A provider that we can wrap our application with\n3) A hook that uses that context\n\nLet's look at an example of using these items:\n\n```tsx\nimport { ThemeContext, ThemeProvider, useTheme } from './ThemeContext';\n\nconst App = () => (\n    <ThemeProvider>\n        <FuncComp />\n        <ClassComp />\n    </ThemeProvider>\n);\n\nexport default App;\n\nconst FuncComp = () => {\n    const theme = useTheme();\n    \n    return (\n        <div>{theme.color}</div>\n    );\n}\n\nclass ClassComp {\n    static contextType = ThemeContext;\n    \n    render() {\n        return (\n            <div>{this.context.color}</div>\n        );\n    }\n}\n```\n\n### `useAsyncState`\n\n`useAsyncState` is a hook based on `useState` but with some extra useful asynchronous functionality. It returns a tuple with three items: \n1) `state`,  the actual state, just like with `useState`\n2) `setState`, which sets the value of the state and returns a promise with the new state\n3) `getState`, which returns a promise of the state's current value no matter when. This is needed because the `state` variable is not always up to date with the latest state inside of a `useEffect`.\n\n```tsx\nimport { useAsyncState } from '@hilma/tools';\n\nconst Comp = () => {\n    const [color, setColor, getColor] = useAsyncState('black');\n    \n    const updateColorWithAwait = async (event) => {\n        const newColor = await setColor(event.target.value);\n        console.log(newColor);\n    }\n\n    const updateColorWithCallback = (event) => {\n        setColor(event.target.value, newColor => {\n            console.log(newColor);\n        });\n    }\n\n    const getColorAsync = async () => {\n        const color = await getColor();\n        console.log(color);\n    }\n    \n    return <div></div>;\n}\n```\n\n### `useAsyncEffect`\n\n`useAsyncEffect` is a hook based on the `useEffect` hook but with some extra useful asynchronous functionality. By default, `useEffect` doesn't accept an `async` function because the function returns a promise. It also doesn't accept an `async` cleanup function. The `useAsyncEffect`  allows you to do both:\n\n```tsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n\n    useAsyncEffect(async () => {\n        // stuff\n\n        return async () => {\n            // more stuff\n        }\n    }, []);\n\n    return <div></div>;\n}\n```\n\nYou don't have to call `useAsyncEffect` with an `async` function or with an `async` cleanup function.\n\nBecause the behavior of the cleanup can be asynchronous, the cleanup might be called after the next effect (if you don't have an empty dependency array) or after the component has unmounted.\n\nTo make sure you're not updating state on an unmounted component, or updating state after the next effect has run, you can use the `isMounted` parameter which is passed into the callback:\n\n```tsx\nimport { useAsyncEffect } from '@hilma/tools';\n\nconst Comp = () => {\n    // ...\n\n    useAsyncEffect(async (isMounted) => {\n        await someActionThatTakesAWhile();\n        if (isMounted.current) setSomeState();\n    }, [])\n\n    return <div></div>;\n}\n```\n\n### `useLocalStorage` and `useSessionStorage`\n\nThese functions wrap `useState` and create a simple API for working with JSON data stored in either `localStorage` or `sessionStorage`.\n\n```tsx\nconst MyComponent = () => {\n    // the first parameter is the key to store the data in\n    // the second parameter is the value to default to, in case the data\n    // doesn't yet exist or is corrupted somehow\n    const [theme, setTheme] = useLocalStorage<\"dark\" | \"light\">(\"theme\", \"dark\");\n    const [canSendHeart, setCanSendHeart] = useSessionStorage(\"has-seen-popup\", true);\n\n    return (\n        <div className={theme}>\n            <button \n                onClick={() => {\n                    // this will update both the state (causing a re-render) and `localStorage`\n                    setTheme(\"light\");\n                }}\n            >\n                Change Theme\n            </button>\n\n            {canSendHeart && (\n                <button \n                    onClick={() => {\n                        // this will update both the state (causing a re-render) and `sessionStorage`\n                        setCanSendHeart(false);\n                    }}\n                >\n                    Send Heart\n                </button>\n            )}\n        </div>\n    );\n}\n```\n\n### `ErrorBoundary`\n\nA component which can be used like a `catch` block for handling uncaught errors anywhere within it.\n\n__Note:__ React will still print console warnings when uncaught errors are thrown inside of an application. We recommend handling scenarios that are likely to produce errors more explicitly, and using `ErrorBoundary` to handle severe edge cases.\n\n```tsx\nconst Throws: React.FC = () => {\n  throw new Error(\"ERROR\");\n}\n\nconst App: React.FC = () => {\n    return (\n        <ErrorBoundary\n          fallback={<div>An Error Has Occured!</div>}\n          callback={(error, info) => { ... }}\n        >\n          <Throws />\n        </ErrorBoundary>\n    );\n}\n```\n\n### `isCapacitor`\n\nReturns a boolean value. If `true`, the code is running in a `Capacitor` environment.\n\n```tsx\nimport { isCapacitor } from '@hilma/tools';\n\nconsole.log(isCapacitor());\n```\n\n### `getDisplayName`\n\nA function that accepts a `React` component and returns its name. (This is mainly for testing and better error messages for developers; don't rely on this function in production).\n\n```tsx\nimport { getDisplayName } from '@hilma/tools';\n\nconst Comp = () => {\n    return <div></div>;\n}\n\nconsole.log(getDisplayName(Comp)); // 'Comp'\n\nconst OtherComp = () => {\n\treturn <div></div>;\n}\n\nOtherComp.displayName = 'MyComponent';\n\nconsole.log(getDisplayName(OtherComp)); // 'MyComponent';\n```\n\n## API\n\n### `provide`\n\n```typescript\nexport function provide<TParents extends { [key: string]: any }[]>(\n\t...parents: Providers<TParents>\n): <TProps>(\n\tchild: React.ComponentType<TProps>\n) => React.ComponentType<TProps>;\n```\n\nThe `Providers` type maps an array of prop types to an array of either `ComponentType` or `[ComponentType, Props]`, depending on which props are required and whether the props include `children`.\n\n- If a provider does not take the `children` prop, it cannot be used within `parents`\n- If a provider doesn't take any required props, it can either be passed as `Component` or as `[Component, Props]`\n- If a provider takes any required props, it _must_ be passed as `[Component, Props]`\n\n### `wrap`\n\n```typescript\nexport function wrap<TParents extends { [key: string]: any }[]>(\n\t...parents: Provider<TParents>\n): {\n\t(element: Element) => Element;\n\t<TProps>(\n\t\tcomponent: React.ComponentType<TProps>, props: TProps\n\t) => Element;\n}\n```\n\nThe `Providers` type here is the same as for `provide`. See [above](#provide).\n\n### `withContext`\n\n```typescript\nexport function withContext<T extends {}>(\n\tmapContextToProps: MapContextToProps<T>\n): <TProps extends T>(\n\tchild: React.ComponentType<TProps>\n) => React.ComponentType<Omit<TProps, keyof T>>;\n```\n\nThe `MapContextToProps` type takes a generic type `T` (some basic props object) and returns a type with that type's value, mapped to context types.\n\n###  `createContextHook`\n\n```typescript\nexport function createContextHook<T>(\n\tcontext: React.Context<T | null>\n): () => T\n```\n\n### `createMobXContext`\n\n```typescript\nexport function createMobXContext<T extends { [key: string]: any }>(\n\tstoreInstance: T\n): [React.Context<T>, React.FC<{ children?: React.ReactNode }>, () => T]\n```\n\n###  `useAsyncState`\n\n```typescript\nexport function useAsyncState<T>(\n\tinitialState: T | (() => T)\n): [T, (value: T | ((prev: T) => T)) => Promise<T>, () => Promise<T>]\n```\n\n### `useAsyncEffect`\n\n```typescript\nexport function useAsyncEffect(\n\teffect: (isMounted: { current: boolean }) => (void | (() => void) | Promise<void | (() => void)>),\n\tdeps: React.DependencyList\n): void;\n```\n\n### `useLocalStorage`\n\n```typescript\nexport function useLocalStorage<T>(\n    key: string,\n    fallback: T\n): [T, (value: T | ((prev: T) => T)) => void];\n```\n\n### `useSessionStorage`\n\n```typescript\nexport function useSessionStorage<T>(\n    key: string,\n    fallback: T\n): [T, (value: T | ((prev: T) => T)) => void];\n```\n\n### `ErrorBoundary`\n\n```typescript\nexport interface ErrorBoundaryProps {\n   children?: React.ReactNode; \n   fallback?: React.ReactNode;\n   onError?: (error: unknown, info: React.ErrorInfo) => void;\n};\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps> { ... };\n```\n\n### `isCapacitor`\n\n```typescript\nexport function isCapacitor(): boolean\n```\n\n### `getDisplayName`\n\n```typescript\nexport function getDisplayName(\n\tcomponent: React.ComponentType<unknown>\n): string;\n```\n","readmeFilename":"README.md","description":"Tools is a package that has some useful client side tools. It makes writing client side code (particularly React boilerplate) easier and simpler. You can see more code examples in [the CodeSandbox](https://codesandbox.io/p/github/ej-shafran/hilma-tools-sa"}