{"_id":"harpoon-package","_rev":"3-a1e2b61d5fd3ffda203cbb4515ab4385","name":"harpoon-package","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"harpoon-package","version":"1.0.0","keywords":["harpoon","game-protocol"],"license":"ISC","_id":"harpoon-package@1.0.0","maintainers":[{"name":"nozomi01","email":"fulldeveloper777@gmail.com"}],"dist":{"shasum":"51c5791c3036fb546b634d1903b2b4a4d536483f","tarball":"https://registry.npmjs.org/harpoon-package/-/harpoon-package-1.0.0.tgz","fileCount":24,"integrity":"sha512-qjTghoM2ZnmWiXj/7TchvFVADpmrjivE4UDpnt5Zk7vhGlho9r+HgxE4qbq79kbdY8+BgpO3kZpBauhMRasHOQ==","signatures":[{"sig":"MEUCIQCgHwGakXCIOwo2B8cJlkliESgSK9i5sIRGNd1zSEUnOQIgcpsKRRaIDS6WfxBjjsoEYFn//lnYjwNFlXICXPfxgD4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27652},"main":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"60e06e172e4cccd0f389a6cfe7a4e51e8a3cdb89","scripts":{"test":"npx vitest run","build":"npx tsc -p tsconfig.json","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"npx vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"nozomi01","email":"fulldeveloper777@gmail.com"},"_npmVersion":"10.8.2","description":"Server runtime helpers: graceful shutdown hooks, health report JSON, and tick profiling (used by harpoon-be). Wire protocol lives in harpoon-be/src/protocol (shared with harpoon-fe via @arena/protocol).","directories":{},"sideEffects":false,"_nodeVersion":"20.18.3","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","typescript":"^6.0.3","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/harpoon-package_1.0.0_1781516158964_0.4369477571768656","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"harpoon-package","version":"1.1.0","keywords":["harpoon","game-protocol"],"license":"ISC","_id":"harpoon-package@1.1.0","maintainers":[{"name":"nozomi01","email":"fulldeveloper777@gmail.com"}],"dist":{"shasum":"363844eb224803f4a218e8afa88393903f3ca19b","tarball":"https://registry.npmjs.org/harpoon-package/-/harpoon-package-1.1.0.tgz","fileCount":24,"integrity":"sha512-yI4MnnmKrsMOaG7vnPHZA3fXFgKb0Wc6+JK93OR45yPD77zJk4UBmg777j2SMul3Gx9D7//yz7mXGWJJ/ec6cg==","signatures":[{"sig":"MEUCID4iLxh9SgBOgFwiZViNsaIGjmifQKu0IKgH56heXjaRAiEA+ERQ9wlpLfJerb7IorFQT6ekfpLe5ABLC98cs5yfDmU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31338},"main":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"09762c264045b03c047b63208401aaaacb1b785d","scripts":{"test":"npx vitest run","build":"npx tsc -p tsconfig.json","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"npx vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"nozomi01","email":"fulldeveloper777@gmail.com"},"_npmVersion":"10.8.2","description":"Server runtime helpers: graceful shutdown hooks, health report JSON, and tick profiling (used by harpoon-be). Wire protocol lives in harpoon-be/src/protocol (shared with harpoon-fe via @arena/protocol).","directories":{},"sideEffects":false,"_nodeVersion":"20.18.3","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","typescript":"^6.0.3","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/harpoon-package_1.1.0_1781643513866_0.7434436992711397","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"harpoon-package","version":"1.2.0","description":"Server runtime helpers: graceful shutdown hooks, health report JSON, and tick profiling (used by harpoon-be). Wire protocol lives in harpoon-be/src/protocol (shared with harpoon-fe via @arena/protocol).","license":"ISC","engines":{"node":">=18"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js","default":"./dist/index.js"}},"sideEffects":false,"scripts":{"prepublishOnly":"npm run build","build":"npx tsc -p tsconfig.json","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test":"npx vitest run","test:watch":"npx vitest"},"keywords":["harpoon","game-protocol"],"devDependencies":{"@types/node":"^22.10.0","typescript":"^6.0.3","vitest":"^3.2.4"},"_id":"harpoon-package@1.2.0","gitHead":"4d79528033d1cee1cedf649d74f368d4a383bbef","_nodeVersion":"20.18.3","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Gf8i9n4mfZ0QhREknr7Rc793K0UVol/gKRZprT94rqUmwv4GJAeTgu2ohhU2yYVq2iPj41wIEd8cNjsXh+PXRg==","shasum":"2f7c71f068b67f3211f44892e9c5fba0f181eadc","tarball":"https://registry.npmjs.org/harpoon-package/-/harpoon-package-1.2.0.tgz","fileCount":24,"unpackedSize":31338,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIF8FT4FKzcoZoaJG1IwE4N0wQ66ohrDgBD0GB70Gn5cGAiEA6jLsqQ+DtcSr2Hb3TuUyyhEWstBH2WR87iKAXnKvMCU="}]},"_npmUser":{"name":"nozomi01","email":"fulldeveloper777@gmail.com"},"directories":{},"maintainers":[{"name":"nozomi01","email":"fulldeveloper777@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/harpoon-package_1.2.0_1782996737475_0.6843100933593607"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-15T09:35:58.916Z","modified":"2026-07-02T12:52:17.743Z","1.0.0":"2026-06-15T09:35:59.125Z","1.1.0":"2026-06-16T20:58:34.017Z","1.2.0":"2026-07-02T12:52:17.628Z"},"license":"ISC","keywords":["harpoon","game-protocol"],"description":"Server runtime helpers: graceful shutdown hooks, health report JSON, and tick profiling (used by harpoon-be). Wire protocol lives in harpoon-be/src/protocol (shared with harpoon-fe via @arena/protocol).","maintainers":[{"name":"nozomi01","email":"fulldeveloper777@gmail.com"}],"readme":"# `harpoon-package`\r\n\r\nSmall **Node server** helpers for Harpoon Arena:\r\n\r\n- **Graceful shutdown** — `registerGracefulShutdown` (SIGINT / SIGTERM / SIGBREAK on Windows).\r\n- **Health probes** — `createProcessClock`, `buildHealthReport` (pass `wireProtocolMajor` from your wire module, e.g. `harpoon-be/src/protocol`).\r\n- **Tick profiling** — `TickProfiler`, `createSlowTickReporter`, `monotonicNowMs` (usable in Node or browser; the server imports these from here).\r\n\r\n**Wire protocol** (`MessageType`, guards, `GameConfig`, fraud helpers, etc.) lives in **`harpoon-be/src/protocol`** and is consumed by the Phaser client via the **`@arena/protocol`** webpack alias (see `harpoon-fe/webpack.config.js`).\r\n\r\n> **npm name:** `harpoon-package`  \r\n> **Folder:** `packages/harpoon-package` — depend from the server with `\"harpoon-package\": \"file:../packages/harpoon-package\"`.\r\n\r\n## Server: health + shutdown\r\n\r\n```ts\r\nimport { WIRE_PROTOCOL_MAJOR } from \"./protocol\"; // or your protocol entry\r\nimport {\r\n  buildHealthReport,\r\n  createProcessClock,\r\n  registerGracefulShutdown,\r\n} from \"harpoon-package\";\r\n\r\nconst clock = createProcessClock();\r\n\r\nregisterGracefulShutdown(async () => {\r\n  await closeServers();\r\n  process.exit(0);\r\n});\r\n\r\n// GET /health\r\nJSON.stringify(\r\n  buildHealthReport({\r\n    wireProtocolMajor: WIRE_PROTOCOL_MAJOR,\r\n    uptimeSeconds: clock.uptimeSeconds(),\r\n    tickBudgetMs: 33, // frame budget (ms); ok:false when p95Ms exceeds this\r\n    tickPerformance: profiler.getSnapshot({ budgetMs: 33 }),\r\n    // ...\r\n  })\r\n);\r\n```\r\n\r\n## Tick budget + health `ok`\r\n\r\nPass **`tickBudgetMs`** with **`tickPerformance`** from `TickProfiler.getSnapshot({ budgetMs })`. When the rolling **p95** tick duration exceeds the budget, **`buildHealthReport`** returns **`ok: false`** (unless you also pass `ok: false` explicitly — both must pass).\r\n\r\n```ts\r\nconst budgetMs = 1000 / 30; // ~33ms at 30 Hz\r\nconst perf = profiler.getSnapshot({ budgetMs });\r\n// perf.withinBudget, perf.overBudgetPct, perf.overBudgetSamples\r\n```\r\n\r\n## Performance (game loop)\r\n\r\n```ts\r\nimport { TickProfiler, createSlowTickReporter, monotonicNowMs } from \"harpoon-package\";\r\n\r\nconst profiler = new TickProfiler(180);\r\nconst warnSlow = createSlowTickReporter({ thresholdMs: 48, label: \"tick\" });\r\n\r\nconst end = profiler.begin();\r\n// ... work ...\r\nend();\r\nwarnSlow(profiler.getSnapshot().lastMs);\r\n```\r\n\r\n## Install\r\n\r\nIn this monorepo, use the workspace dependency on **`harpoon-package`** from **`harpoon-be`** only (the browser bundles protocol sources from `harpoon-be/src/protocol`).\r\n","readmeFilename":"README.md"}