{"_id":"tasktimer","_rev":"10-d6ed1a68e91a5383f59b9b362ad97497","name":"tasktimer","dist-tags":{"latest":"4.0.0"},"versions":{"1.0.0":{"name":"tasktimer","version":"1.0.0","keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","_id":"tasktimer@1.0.0","maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"homepage":"https://github.com/onury/tasktimer#readme","bugs":{"url":"https://github.com/onury/tasktimer/issues"},"dist":{"shasum":"54478e943afe0c7834aa9e1d6491655e3b9dbed3","tarball":"https://registry.npmjs.org/tasktimer/-/tasktimer-1.0.0.tgz","integrity":"sha512-8bec3NnfQBtHOhLGZ0XaKQrKzYQF/RYfiTfql1AkAFVcXbu2AQV4CMuCnWTOfa6vROVCfbYzBtjnpHrHjf+2kQ==","signatures":[{"sig":"MEYCIQCNgn/a88q4xtS2vBdMZ0iQF/wlw9InNEHtJh+BkZ+VYQIhAJm8NTqEyR25vXbPGHPXVLrCif+Kj6UtrXT9GYRDQjHr","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"main":"dist/tasktimer.min.js","_from":".","_shasum":"54478e943afe0c7834aa9e1d6491655e3b9dbed3","gitHead":"6100f508f502e3ffb0b3aab5bbaea1db871d09ea","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"onury","email":"onur@cutepilot.com"},"repository":{"url":"git+https://github.com/onury/tasktimer.git","type":"git"},"_npmVersion":"3.10.5","description":"A timer utility for running/scheduling periodic tasks on the given interval ticks. (Node and Browser)","directories":{},"_nodeVersion":"4.4.7","dependencies":{"eventemitter3":"^1.2.0"},"devDependencies":{"grunt":"^1.0.1","eslint":"^3.3.1","webpack":"^1.13.1","matchdep":"^1.0.1","babel-core":"^6.13.2","grunt-docma":"^0.6.4","babel-eslint":"^6.1.2","babel-loader":"^6.2.4","grunt-webpack":"^1.0.14","eslint-config-xo":"^0.15.3","webpack-dev-server":"^1.14.1","babel-preset-es2015":"^6.13.2","grunt-contrib-watch":"^1.0.0","grunt-jasmine-nodejs":"^1.5.2","grunt-contrib-jasmine":"^1.0.3"},"_npmOperationalInternal":{"tmp":"tmp/tasktimer-1.0.0.tgz_1471372142555_0.6473216405138373","host":"packages-16-east.internal.npmjs.com"}},"2.0.0":{"name":"tasktimer","version":"2.0.0","keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","_id":"tasktimer@2.0.0","maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"homepage":"https://github.com/onury/tasktimer#readme","bugs":{"url":"https://github.com/onury/tasktimer/issues"},"dist":{"shasum":"b63764c78313c7908a5657dde6afa0d0c35c7e80","tarball":"https://registry.npmjs.org/tasktimer/-/tasktimer-2.0.0.tgz","fileCount":16,"integrity":"sha512-zxlqMb+B/YGOANF/aTM1lfhmmMARmAmnHh0Eq2H+IzMVg+qi0xox2QUE+yhTRK0iv00T0szQ/5doWg/+W00m4A==","signatures":[{"sig":"MEUCIQCsbMG9bwR3jBnky16CbxhQZPW6ZLHX3eyK+zXFenaulQIgFK22l+LSblr+zieu3uKeyptMMO07oNoNWfat5gciTFU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":350424,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRRPcCRA9TVsSAnZWagAAPzkQAKGbRzmkykutp7sRqFEs\nMaxhIH0JET93OlxCxcuUiGKliLkQ7cUV69QqIWdrTKhSH6sSyQ34ponaLrwV\n0Kc3jZSfmixw1/PsPVGALiD5eK8uRwWT4j8cfQocyfnw6a4tolSluaEbXgP/\nowbmj3qOmW0RMNy8hFOY+ZDrPt+KTYJP1GMHtDjolKFQELE7Y+WKa3+/t/tA\n009puaIObt/S98l9uHoJ4RYJUt4jEMiCjREEcxh8JsGUXXKYnmmAH70Tg7UW\n0cybzHOKNUJvb217Oe+/xthLR+7nSIpLricjrki6JQ0ju/mKV5cupTbu3rSC\nKOxTLIzMYoIlDFVcNd0II2AlgOvw20YfH4Ha3DN9d/BFD2Td58bTj6KWkVNk\nrnbns5TvOHi93HvFIn/h0taYB/TAMmhQJnkg0JNY+CT6ihwmzXNJA7nh30u9\nQh+bcve+5iy1bQT2KqIIGSZI10t6yBPVCXNtT3RGpxc7mtw7dbnkhbZz9gSu\nRTPtGHJY6x/whlc45WsvFUCU7bokifHSibUgteq84YoiH0pTETR1LaOffMPN\nfDohwb/6plccBcKgG3OpbOqpN60pgFERi5FY8yulDQA7bW2uvF3IumffGH/i\nbrSIn5Y0dQcaUSMiNk6KbUrXi72Q5CFTnLP0hEvj9LJ8LmrNYvo42AdgCeZb\nEtv0\r\n=xR3D\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/tasktimer.min.js","types":"lib/index.d.ts","gitHead":"d57d92b24067211c3081e09952fa951895ad8a09","scripts":{"docs":"npm run build:dev && docma","test":"jest --coverage --verbose --no-cache --runInBand -c ./jest.json","build":"npm run clean && npm run build:dev && npm run build:prod","clean":"rimraf ./lib","build:dev":"webpack --mode=development --env.WEBPACK_OUT=development --progress --colors","coveralls":"cat ./test/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js -v","build:prod":"webpack --mode=production --env.WEBPACK_OUT=production --progress --colors","test:serve":"node ./test/_server","test:browser":"npm run clean && npm run build:dev && jest --verbose --no-cache --runInBand -c ./jest-puppeteer.json"},"_npmUser":{"name":"onury","email":"onur@cutepilot.com"},"repository":{"url":"git+https://github.com/onury/tasktimer.git","type":"git"},"_npmVersion":"6.4.1","description":"An accurate timer utility for running periodic tasks on the given interval ticks or dates. (Node and Browser)","directories":{},"_nodeVersion":"8.12.0","dependencies":{"eventemitter3":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","docma":"^3.2.2","table":"^5.2.1","rimraf":"^2.6.3","express":"^4.16.4","ts-jest":"^23.10.5","webpack":"^4.29.0","jest-cli":"^23.6.0","coveralls":"^3.0.2","puppeteer":"^1.11.0","ts-loader":"^5.3.3","typescript":"^3.2.4","@types/jest":"^23.3.13","webpack-cli":"^3.2.1","jest-puppeteer":"^3.8.0","@types/puppeteer":"^1.11.1","jest-environment-node":"^23.4.0","@types/expect-puppeteer":"^3.3.0","uglifyjs-webpack-plugin":"^2.1.1","fork-ts-checker-webpack-plugin":"^0.5.2","@types/jest-environment-puppeteer":"^2.2.1"},"_npmOperationalInternal":{"tmp":"tmp/tasktimer_2.0.0_1548030939433_0.02733523642383795","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"tasktimer","version":"2.0.1","keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","_id":"tasktimer@2.0.1","maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"homepage":"https://github.com/onury/tasktimer#readme","bugs":{"url":"https://github.com/onury/tasktimer/issues"},"dist":{"shasum":"9e495d9dd8a2cf2498e426fdeb19960cca9b4088","tarball":"https://registry.npmjs.org/tasktimer/-/tasktimer-2.0.1.tgz","fileCount":16,"integrity":"sha512-bJ/0M6JUmSAxbYyKhF4v8ngH28CtQuiVfNVIhFQjlgJ6YzvLPPNj8VGleRFQfSjiH4weRvd/JSYIb0X4utkbNg==","signatures":[{"sig":"MEUCIQD/L6RGfhRCZI2wJxHDGvvF9yewiBJfloDfSuda1Fh5TAIgbZVVszOREjzRKWu/Nb4StlVdIMJrS/q0Nu/7ZgrVVSU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":285212,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcRSX0CRA9TVsSAnZWagAA85wP/is/RoRNiz3E4xV1fIJ3\nUx0pkWDkHerN5anoCCubLztPVtPyyRZ7M5KGt7YTql0tgwMGwV/vUiU+WHFp\n3hH45eEBNmZXKT8bxdscd+tySit9XIAZvNYTBvubxTE1hf97hrDDhHwi9HKv\nypgyJ9xcWtlXrUOxyZ0ECxyhGAtu/RefKmn9eL0mn5g9jy1GNM6lXQ+kxKKk\nb7HOuP+/W7VlgMXSG4++TtZJK/phtiewc6Uqkd+vHs3q8+foK7qo8Jlo36hk\n5lacnNmbhBEfb1OsbznPVpIWHavxM6kuly6HWqXf9O60hlBEUo9H7yDcB4gU\nPE5b9/mbVFJlPCAOr9mHkOnfngcHYpWxgfkUpTmeIEmg52BisHfyWCs0uZQm\ni+k6eD5UvPsoU4HbamgiTbNFKFCIVOdzdI7L3MOoBc1eDVtmgQNqHdLYtopK\n+g2KktdQn4ITBT0BAkKp8IO2BYrGHX54+CXdmHLL4h6L+k+EZ1XsM8qjqiOw\nvlaAYzTPZ6ELEa9HCDPjH6GlWGlWlHceqeB9umX/TxMCjU5Q1v3zXd8vJz8p\nOZfM3Y6ic5KoIiiIjZFYtxH0gPA0wPEbLi+YwvIgz6DvKW4ZhPu6iajTjM19\n6W8kNpPuYnNxg8OdTMd0b5C2ql9oPZPxVMSox/gsjl8b/So3aKHjfuGFzCii\ny1EG\r\n=KPO5\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/tasktimer.min.js","types":"lib/index.d.ts","gitHead":"9d246e01c96e3b607842aa0bf4e40adf163c5eb5","scripts":{"docs":"npm run build:dev && docma","test":"jest --coverage --verbose --no-cache --runInBand -c ./jest.json","build":"npm run clean && npm run build:dev && npm run build:prod","clean":"rimraf ./lib","build:dev":"webpack --mode=development --env.WEBPACK_OUT=development --progress --colors","coveralls":"cat ./test/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js -v","build:prod":"webpack --mode=production --env.WEBPACK_OUT=production --progress --colors","test:serve":"node ./test/_server","test:browser":"npm run clean && npm run build:dev && jest --verbose --no-cache --runInBand -c ./jest-puppeteer.json"},"_npmUser":{"name":"onury","email":"onur@cutepilot.com"},"repository":{"url":"git+https://github.com/onury/tasktimer.git","type":"git"},"_npmVersion":"6.4.1","description":"An accurate timer utility for running periodic tasks on the given interval ticks or dates. (Node and Browser)","directories":{},"_nodeVersion":"8.12.0","dependencies":{"eventemitter3":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","docma":"^3.2.2","table":"^5.2.1","rimraf":"^2.6.3","express":"^4.16.4","ts-jest":"^23.10.5","webpack":"^4.29.0","jest-cli":"^23.6.0","coveralls":"^3.0.2","puppeteer":"^1.11.0","ts-loader":"^5.3.3","typescript":"^3.2.4","@types/jest":"^23.3.13","webpack-cli":"^3.2.1","jest-puppeteer":"^3.8.0","@types/puppeteer":"^1.11.1","jest-environment-node":"^23.4.0","@types/expect-puppeteer":"^3.3.0","uglifyjs-webpack-plugin":"^2.1.1","fork-ts-checker-webpack-plugin":"^0.5.2","@types/jest-environment-puppeteer":"^2.2.1"},"_npmOperationalInternal":{"tmp":"tmp/tasktimer_2.0.1_1548035571848_0.41529818115766726","host":"s3://npm-registry-packages"}},"3.0.0":{"name":"tasktimer","version":"3.0.0","keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","_id":"tasktimer@3.0.0","maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"homepage":"https://github.com/onury/tasktimer#readme","bugs":{"url":"https://github.com/onury/tasktimer/issues"},"dist":{"shasum":"bede9a1edde30317b5b38eb6392eb7eb42560c97","tarball":"https://registry.npmjs.org/tasktimer/-/tasktimer-3.0.0.tgz","fileCount":16,"integrity":"sha512-Fx2Zw4FFM/gc9cY4Iodo9UwC9yFl7fIU3ay/wqq0+E5WT587aZlmjCW2yLCHRVIwzcSig4tMqIh4vqxOcyXr9A==","signatures":[{"sig":"MEUCIQDZ0xpP/YGn40HZDnbpv3u7lQNjMTQ3p8DmJE3R1KnELwIgSNokadGocpqnsH+rGn3B4SlSas/m539w0HYbkUbdACw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":294845,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQ4LKCRA9TVsSAnZWagAAN5wP/3IfJTmNm/3/NgSNqmvM\n9lDBYR/7jFy9X1SawM/Y+lgU1/aiIF7jsBbS1NMIxoC+GGVf48SX4j0Sm79s\nAOtLwVom8JDqrWQwwgOW2CUlPEYgAYbgSmrheWzsHJUeL0s7O2C2tEQAGSOi\nOqXIsle4YKb8i64ryI2SyTCzdCKvU0Ag2UocPPFoDe/4ls9MXrzojA0hlEw6\nvQVA3HUKNGpxjSOMw5If1n7jTlvDZjWFokpLjgydfCMB2XG3JNkPmf6gzHL5\n+u//0CAnNJhjoRiT8PrGJrC9QMe5HbmgLgBBEUr7K/8r2/foBGMHeyvpWYJe\n/dFTCjinX+DS+t5FhP80KhC3aa/qqTH8g6K4aaPjVJf89ji0nyV2Gb6sO5S1\nd/Oc4vGpSVFoSa6f2w6JXwe8aaoHHMNqVTWlClK6cABFTQ8sV7H4SxGGgEIS\nU9313GX0/61RopOrO7ADv/7mb9ZK+DmlCQIkGAEljLq9Xx6xJHLJlEDJTw35\nK+h6BS+kkZQSFAaEyO3NU3b0lGGQn46Ptf1lzFP0pEINgLWMeC62d9rAoQFU\nu8jbj0VWxDG7nGbGeDlpeBWBqm5xGLjPjx33FgrZ9RKxHZZ3pPYpyf04ntmD\nDDH9EWAlIKD+l0+4XvNzBDsm7UZk39MHVAwlO2rPF4ZInMmegWMQ9E5kYNxB\nnxIA\r\n=0p8P\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/tasktimer.min.js","types":"lib/index.d.ts","gitHead":"08072af74ef8638df3a81757ad515f1ffdeb022b","scripts":{"docs":"npm run build:dev && docma","size":"gzip-size ./lib/tasktimer.min.js","test":"jest --coverage --verbose --no-cache --runInBand -c ./jest.json","audit":"npm audit --production","build":"npm run clean && npm run build:dev && npm run build:prod","clean":"rimraf ./lib","build:dev":"webpack --mode=development --env.WEBPACK_OUT=development --progress --colors","coveralls":"cat ./test/coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js -v","build:prod":"webpack --mode=production --env.WEBPACK_OUT=production --progress --colors","test:serve":"node ./test/_server","test:browser":"npm run clean && npm run build:dev && jest --verbose --no-cache --runInBand -c ./jest-puppeteer.json"},"_npmUser":{"name":"onury","email":"onur@cutepilot.com"},"repository":{"url":"git+https://github.com/onury/tasktimer.git","type":"git"},"_npmVersion":"6.10.2","description":"An accurate timer utility for running periodic tasks on the given interval ticks or dates. (Node and Browser)","directories":{},"_nodeVersion":"10.15.1","dependencies":{"eventemitter3":"^4.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^24.8.0","docma":"^3.2.2","is-ci":"^2.0.0","table":"^5.4.5","rimraf":"^2.6.3","express":"^4.17.1","ts-jest":"^24.0.2","webpack":"^4.39.0","jest-cli":"^24.8.0","coveralls":"^3.0.5","puppeteer":"^1.19.0","ts-loader":"^6.0.4","typescript":"^3.5.3","@types/jest":"^24.0.16","webpack-cli":"^3.3.6","jest-puppeteer":"^4.3.0","@types/puppeteer":"^1.19.0","jest-environment-node":"^24.8.0","@types/expect-puppeteer":"^3.3.1","uglifyjs-webpack-plugin":"^2.2.0","fork-ts-checker-webpack-plugin":"^1.4.3","@types/jest-environment-puppeteer":"^4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tasktimer_3.0.0_1564705481717_0.9315299664989267","host":"s3://npm-registry-packages"}},"4.0.0":{"name":"tasktimer","version":"4.0.0","description":"An accurate timer utility for running periodic tasks on the given interval ticks or dates.","author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","type":"module","main":"./lib/index.js","module":"./lib/index.js","types":"./lib/index.d.ts","exports":{".":{"types":"./lib/index.d.ts","default":"./lib/index.js"},"./package.json":"./package.json"},"sideEffects":false,"engines":{"node":">=22"},"scripts":{"lint":"biome check src test","format":"biome check --write src test","build":"tsc -p tsconfig.build.json","typecheck":"tsc --noEmit -p tsconfig.json","pretest":"npm run lint && npm run typecheck","test":"vitest run","cover":"vitest run --coverage","mutation":"stryker run","docs":"npm --prefix site run build","docs:dev":"npm --prefix site run dev","docs:host":"npm --prefix site run dev:host","prepublishOnly":"npm run build"},"repository":{"type":"git","url":"git+https://github.com/onury/tasktimer.git"},"keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"bugs":{"url":"https://github.com/onury/tasktimer/issues"},"homepage":"https://onury.io/tasktimer","devDependencies":{"@biomejs/biome":"^2.5.1","@stryker-mutator/core":"^9.6.1","@stryker-mutator/vitest-runner":"^9.6.1","@types/node":"^26.0.1","@vitest/coverage-istanbul":"^4.1.9","biome-config-oy":"^1.1.0","tsconfig-oy":"^2.0.1","typescript":"^6.0.3","vitest":"^4.1.9"},"_id":"tasktimer@4.0.0","gitHead":"cad0f5eac4107d7073d7128bb507f1dd62afb012","_nodeVersion":"22.22.3","_npmVersion":"10.9.8","dist":{"integrity":"sha512-/HdB1YoX6j3TplDyitdxSMLYsLetnPBX7HeTsb5McvQxiDPfqsBGGb8JgixFwmnPsHXDpr6UujbNUzTBcN7FqA==","shasum":"7a1477076e98a6000f6c4e03d05d143e67b1f7bb","tarball":"https://registry.npmjs.org/tasktimer/-/tasktimer-4.0.0.tgz","fileCount":75,"unpackedSize":126838,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBRmATk2dLchnPKzSyOe5C5S++t3tcb96rTZ5wz3tY2lAiEAqwQUWIKnMaI/qT2Y9YLOmhv2CsntsSUESjSheUSGFRI="}]},"_npmUser":{"name":"onury","email":"onur@cutepilot.com"},"directories":{},"maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tasktimer_4.0.0_1782787725867_0.33291404083868836"},"_hasShrinkwrap":false}},"time":{"created":"2016-08-16T18:29:05.160Z","modified":"2026-06-30T02:48:46.117Z","1.0.0":"2016-08-16T18:29:05.160Z","2.0.0":"2019-01-21T00:35:39.528Z","2.0.1":"2019-01-21T01:52:52.016Z","3.0.0":"2019-08-02T00:24:41.923Z","4.0.0":"2026-06-30T02:48:45.997Z"},"bugs":{"url":"https://github.com/onury/tasktimer/issues"},"author":{"name":"Onur Yıldırım","email":"onur@cutepilot.com"},"license":"MIT","homepage":"https://onury.io/tasktimer","keywords":["timer","interval","tick","task","schedule","timeout","alarm","clock","time","job","work","run"],"repository":{"type":"git","url":"git+https://github.com/onury/tasktimer.git"},"description":"An accurate timer utility for running periodic tasks on the given interval ticks or dates.","maintainers":[{"name":"onury","email":"onur@cutepilot.com"}],"readme":"<p align=\"center\">\n    <a href=\"https://onury.io/tasktimer\">\n        <picture>\n            <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/onury/tasktimer/master/tasktimer-white.svg\" />\n            <img width=\"420\" src=\"https://raw.githubusercontent.com/onury/tasktimer/master/tasktimer-black.svg\" alt=\"TaskTimer\" />\n        </picture>\n    </a>\n</p>\n<p align=\"center\">\n  <a href=\"https://github.com/onury/tasktimer/actions/workflows/ci.yml\"><img src=\"https://github.com/onury/tasktimer/actions/workflows/ci.yml/badge.svg\" alt=\"build\" /></a>\n  <a href=\"#\"><img src=\"https://img.shields.io/badge/coverage-100%25-2BB150?logo=vitest&logoColor=%23FDC72B&style=flat\" alt=\"coverage\" /></a>\n  <a href=\"https://stryker-mutator.io/docs/\"><img src=\"https://img.shields.io/badge/mutation-100%25-2BB150?style=flat\" alt=\"mutation score\" /></a>\n  <a href=\"https://www.npmjs.com/package/tasktimer\"><img src=\"https://img.shields.io/npm/v/tasktimer.svg?style=flat&label=&color=%23C6234B&logo=npm\" alt=\"version\" /></a>\n  <a href=\"https://www.npmjs.com/package/tasktimer\"><img src=\"https://img.shields.io/npm/dt/tasktimer.svg?style=flat&color=2BB150\" alt=\"downloads\" /></a>\n  <a href=\"#\"><img src=\"https://img.shields.io/badge/deps-zero-2BB150?style=flat\" alt=\"zero dependencies\" /></a>\n  <a href=\"https://gist.github.com/onury/d3f3d765d7db2e8b2d050d14315f2ac7\"><img src=\"https://img.shields.io/badge/ESM-F7DF1E?style=flat\" alt=\"ESM\" /></a>\n  <a href=\"https://www.typescriptlang.org/\"><img src=\"https://img.shields.io/badge/TS-3260C7?style=flat\" alt=\"TS\" /></a>\n  <a href=\"https://github.com/onury/tasktimer/blob/master/LICENSE\"><img src=\"https://img.shields.io/npm/l/tasktimer.svg?style=flat&color=blue\" alt=\"license\" /></a>\n  <a href=\"https://onury.io/tasktimer\"><img src=\"https://img.shields.io/badge/docs-onury.io-c27cf4?style=flat\" alt=\"documentation\" /></a>\n</p>\n\n> This module is **ESM** 🔆. Please [**read this**](https://gist.github.com/onury/d3f3d765d7db2e8b2d050d14315f2ac7).\n\nAn accurate timer utility for running periodic tasks on the given interval ticks or dates — with a single timer instance, zero runtime dependencies, and full TypeScript types.\n\n📖 &nbsp;**Full documentation & guides:** &nbsp;**[onury.io/tasktimer](https://onury.io/tasktimer)**\n\n> [!TIP]\n> **v4** is a 2026 modernization — ESM-only, zero-dependency, browser-safe, drift-free precision — that also **squashed some long-standing bugs** and made **API improvements**, plus new sugar: leading-edge runs (`lead`), typed task `data`, typed events, coded errors (`TaskTimerError`), and `silentErrors`. &nbsp;**[What's changed →](CHANGELOG.md#migrating-from-3x)**\n\n## Why TaskTimer?\n\nBecause of the single-threaded, asynchronous [nature of JavaScript][how-timers-work], each execution takes a slice of CPU time, and the wait before the next one varies with the load. This creates a cumulative latency in naive timers that gradually drifts away from the intended schedule. TaskTimer corrects this drift on every tick, and it lets you run many tasks — each on its own interval, run limit, or date window — from a single timer.\n\n## Features\n\n- **Precision** (on by default): the delay between ticks is auto-adjusted when it drifts due to task/CPU load or [clock drift][clock-drift]. It uses the monotonic [`performance.now()`][perf-now] (drift-free, in Node **and** the browser) and auto-recovers via immediate ticks after a blocking task.\n- Run or schedule **multiple tasks** on a single timer instance.\n- **Sync or async** tasks — return a `Promise` or use the `done()` callback.\n- **Limit runs** per task (`totalRuns`), add an initial **delay** (`tickDelay`), run on the **leading edge** (`lead`), or bind a task to a **date window** (`startDate` / `stopDate`).\n- Attach arbitrary **`data`** to a task — typed via `Task<TData>`.\n- Add, remove, reset, enable/disable, **pause and resume** tasks at any time — without recreating the timer.\n- **Stateful**: auto-stop when all tasks complete (`stopOnCompleted`); free memory when a task finishes (`removeOnCompleted`).\n- A familiar, **typed `EventEmitter`** surface (`on` / `once` / `off` / `emit` …) — listeners get a typed event.\n- **Coded errors** — every throw is a `TaskTimerError` with a stable `err.code`; opt out of swallowing task errors with `silentErrors`.\n- **ESM-only**, **zero runtime dependencies**, runs in Node and the browser, written in **TypeScript**.\n\n## Installation\n\n```sh\nnpm i tasktimer\n```\n\n```js\nimport { TaskTimer, Event, State } from 'tasktimer';\n```\n\n`Event`, `State`, `Task`, `TaskTimerError` and `ErrorCode` are all named exports (there is no `TaskTimer.Event` namespace).\n\n> [!NOTE]\n> TaskTimer is **ESM-only**. It runs in Node **and** the browser via native ESM or a bundler (Vite, esbuild, Rollup, webpack …) — precision uses the universal `performance.now()`, and `setImmediate` falls back to `setTimeout` off-Node.\n\n## Usage\n\n### Simplest example\n\n```js\nconst timer = new TaskTimer(1000); // base interval: 1000 ms\ntimer.add(task => console.log(`Run #${task.currentRuns}`)).start();\n```\n\n### A plain timer (events only, no tasks)\n\n```js\nconst timer = new TaskTimer(5000);\ntimer.on(Event.TICK, () => console.log(`Tick #${timer.tickCount}`));\ntimer.start();\n```\n\n### Multiple tasks on a single timer\n\n```js\nconst timer = new TaskTimer(1000); // 1s base resolution\n\ntimer.add([\n    {\n        id: 'task-1',\n        tickInterval: 5,  // every 5 ticks → 5s\n        totalRuns: 10,    // run 10 times only (0 = unlimited)\n        callback(task) {\n            console.log(`${task.id} ran ${task.currentRuns} times`);\n        }\n    },\n    {\n        id: 'task-2',\n        tickDelay: 1,     // wait 1 tick before the first run\n        tickInterval: 10, // every 10 ticks → 10s\n        totalRuns: 2,\n        callback(task) {\n            console.log(`${task.id} ran ${task.currentRuns} times`);\n        }\n    }\n]);\n\ntimer.on(Event.TICK, () => {\n    console.log(`tick ${timer.tickCount} · elapsed ${timer.time.elapsed} ms`);\n});\n\ntimer.start();\n```\n\n### Async tasks\n\n```js\n// return a Promise\ntimer.add(task => fetch(url).then(handle));\n\n// or call done() when finished\ntimer.add((task, done) => {\n    fs.readFile(path, () => done());\n});\n```\n\n> [!TIP]\n> Set `defer: true` on a task to defer its callback to the next event-loop turn (via `setImmediate`) — useful when the task synchronously blocks the event loop without doing I/O. Set `lead: true` to run a task once immediately on `start()` (the leading edge), instead of waiting a full interval.\n\n### Auto-stop when everything completes\n\n```js\nconst timer = new TaskTimer({ interval: 1000, stopOnCompleted: true });\n\ntimer.add({ totalRuns: 3, callback: doWork });\ntimer.add({ totalRuns: 5, callback: doOtherWork });\n\ntimer.on(Event.COMPLETED, () => console.log('all tasks done'));\ntimer.start();\n```\n\n### Pause and resume\n\n```js\ntimer.start();\ntimer.pause();   // holds all tasks\ntimer.resume();  // continues where it left off\ntimer.stop();    // stops; tasks and counters are retained\ntimer.reset();   // back to idle; tasks removed silently\n```\n\n## How it works\n\n- You create a timer with a **base interval** (e.g. `1000` ms) — the **tick** resolution shared by all tasks.\n- You add tasks that run on **tick intervals** (e.g. every 5th tick), optionally with a run limit, an initial delay, or a start/stop date.\n- Beyond task callbacks, you can listen for lifecycle **events** (`tick`, `task`, `completed`, …).\n- Tasks can be added, removed, reset, enabled or disabled at any time; the timer can be paused and resumed — all without recreating it.\n\n## API\n\n### `new TaskTimer(options?)`\n\n`options` is either an [`ITaskTimerOptions`](#itasktimeroptions) object or a `number` (the base interval in ms).\n\n#### Timer properties\n\n| Property | Type | Description |\n| --- | --- | --- |\n| `interval` | `number` | Base tick interval in ms (read/write). |\n| `precision` | `boolean` | Whether drift auto-correction is enabled (read/write). |\n| `stopOnCompleted` | `boolean` | Auto-stop once all tasks complete (read/write). |\n| `silentErrors` | `boolean` | Swallow task errors with no `taskError` listener; `false` surfaces them (read/write). |\n| `state` | [`State`](#enumerations) | Current timer state (read-only). |\n| `time` | [`ITimeInfo`](#itimeinfo) | `{ started, stopped, elapsed }` for the current run (read-only). |\n| `tickCount` | `number` | Ticks elapsed in the current run (read-only). |\n| `taskCount` | `number` | Number of tasks (read-only). |\n| `tasks` | `Task[]` | All tasks, in insertion order (read-only). |\n| `taskRunCount` | `number` | Total task executions (read-only). |\n| `runCount` | `number` | Total timer runs, including resumes (read-only). |\n\n#### Timer methods\n\n| Method | Returns | Description |\n| --- | --- | --- |\n| `add(task)` | `TaskTimer` | Add a task, options, callback, or an array of these. |\n| `get(id)` | `Task \\| undefined` | Get a task by id (`undefined` if absent). |\n| `remove(task)` | `TaskTimer` | Remove a task by id or instance. |\n| `start()` | `TaskTimer` | Start (or restart) the timer. |\n| `pause()` | `TaskTimer` | Pause the timer and all tasks. |\n| `resume()` | `TaskTimer` | Resume a paused timer (starts it if idle). |\n| `stop()` | `TaskTimer` | Stop the timer, retaining tasks and counters. |\n| `reset()` | `TaskTimer` | Stop and reset to idle, removing all tasks silently. |\n\n`TaskTimer` also exposes the `EventEmitter` surface: `on` / `addListener`, `once`, `off` / `removeListener`, `removeAllListeners`, `emit`, `listeners`, `listenerCount`, `eventNames`.\n\n### `new Task(options)`\n\nA `Task` is created implicitly via `timer.add(...)`, or explicitly with the constructor (an [`ITaskOptions`](#itaskoptions) with a required `id` and `callback`).\n\n| Member | Type | Description |\n| --- | --- | --- |\n| `id` | `string` | Unique task id (read-only). |\n| `enabled` | `boolean` | While `false`, the task bypasses its callback (read/write). |\n| `tickDelay` | `number` | Ticks to wait before the first run (read/write). |\n| `tickInterval` | `number` | Tick interval the task runs on (read/write). |\n| `totalRuns` | `number \\| null` | Run limit; `0`/`null` = unlimited (read/write). |\n| `defer` | `boolean` | Defer the callback to the next event-loop turn via `setImmediate` (read/write). |\n| `lead` | `boolean` | Run once immediately on `start()` (the leading edge) (read/write). |\n| `removeOnCompleted` | `boolean` | Remove the task once completed (read/write). |\n| `data` | `TData` | Arbitrary user data attached to the task (read/write). |\n| `currentRuns` | `number` | Number of times run so far (read-only). |\n| `completed` | `boolean` | Whether the task is completed (read-only). |\n| `time` | [`ITimeInfo`](#itimeinfo) | The task's lifetime `{ started, stopped, elapsed }` (read-only). |\n| `callback` | `TaskCallback` | The callback executed on each run (read-only). |\n| `reset(options?)` | `Task` | Reset the run count, optionally re-configuring (id can't change). |\n\n### Enumerations\n\nAll are named exports: `import { State, Event, ErrorCode } from 'tasktimer'`.\n\n`State` — `IDLE` · `RUNNING` · `PAUSED` · `STOPPED`.\n\n`ErrorCode` — the `code` on a thrown [`TaskTimerError`](https://onury.io/tasktimer): `NO_TASK_PROVIDED` · `TASK_ID_REQUIRED` · `CALLBACK_REQUIRED` · `DUPLICATE_TASK_ID` · `NO_SUCH_TASK` · `INVALID_DATE_RANGE` · `CANNOT_CHANGE_ID` · `TASK_ERROR`.\n\n`Event` — the events emitted by the timer:\n\n| Event | Value | Emitted when |\n| --- | --- | --- |\n| `TICK` | `tick` | Each tick of the timer. |\n| `STARTED` | `started` | The timer is started. |\n| `RESUMED` | `resumed` | The timer is resumed. |\n| `PAUSED` | `paused` | The timer is paused. |\n| `STOPPED` | `stopped` | The timer is stopped. |\n| `RESET` | `reset` | The timer is reset. |\n| `TASK` | `task` | A task is executed. |\n| `TASK_ADDED` | `taskAdded` | A task is added. |\n| `TASK_REMOVED` | `taskRemoved` | A task is removed. |\n| `TASK_COMPLETED` | `taskCompleted` | A task completes its runs / reaches its `stopDate`. |\n| `TASK_ERROR` | `taskError` | A task throws or rejects. |\n| `COMPLETED` | `completed` | Every task has completed. |\n\nEvent listeners receive a typed [`ITaskTimerEvent`](#itasktimerevent): `{ name, timer, task?, error? }`. The related task is `event.task` and the timer is `event.timer` — on every event, including `taskError`.\n\n### Types\n\n###### `ITaskTimerOptions`\n`{ interval?, precision?, stopOnCompleted?, silentErrors? }`\n\n###### `ITaskOptions<TData>`\n`{ id?, enabled?, tickDelay?, tickInterval?, totalRuns?, startDate?, stopDate?, defer?, lead?, removeOnCompleted?, data?, callback }`\n\n###### `ITimeInfo`\n`{ started, stopped, elapsed }` — timestamps and elapsed time in ms.\n\n###### `ITaskTimerEvent`\n`{ name, timer, task?, error? }`\n\n###### `TaskCallback<TData>`\n`(task: Task<TData>, done?: () => void) => void | Promise<unknown>`\n\nFull reference: **[onury.io/tasktimer](https://onury.io/tasktimer)**.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md). Migrating from v3? See the [migration notes](CHANGELOG.md#migrating-from-3x) — v4 is **ESM-only**, drops the `TaskTimer.Event` namespace for named exports, and reshapes the event payload.\n\n## Other Projects\n\n- [**AccessControl**](https://github.com/onury/accesscontrol) — Role and Attribute based Access Control for Node.js.\n- [**Configuard**](https://github.com/onury/configuard) — Turn flat config rows from a database table into a nested, typed configuration object — with `${...}` templating and accessor-based (ABAC) filtering.\n- [**Notation**](https://github.com/onury/notation) — Read, modify, and filter the contents of objects and arrays via dot/bracket notation strings or glob patterns.\n\n## License\n\n© 2026, Onur Yıldırım. [**MIT**](LICENSE) License.\n\n[how-timers-work]: https://johnresig.com/blog/how-javascript-timers-work/\n[clock-drift]: https://en.wikipedia.org/wiki/Clock_drift\n[perf-now]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now\n","readmeFilename":"README.md","users":{"letsbora":true}}