{"_id":"@addilytics/hono","name":"@addilytics/hono","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@addilytics/hono","version":"0.0.1","description":"Hono server analytics and bundled browser relay.","type":"module","license":"MIT","publishConfig":{"access":"public"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./browser":{"types":"./dist/browser.d.ts","default":"./dist/browser.js"}},"dependencies":{"addilytics":"0.0.1"},"peerDependencies":{"hono":"^4.0.0"},"devDependencies":{"@types/node":"^24.0.0","hono":"^4.13.7","tsx":"^4.20.0","typescript":"^6.0.3"},"scripts":{"build":"tsc -p tsconfig.json","check":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json","test":"pnpm build && tsx --test test/*.test.ts test/*.test.mjs","test:compat":"pnpm build && node test/compat.mjs"},"_nodeVersion":"26.0.0","_id":"@addilytics/hono@0.0.1","dist":{"integrity":"sha512-fZCY3NCiakFQHXDB23g1+HC+a92YYs21nYrDV+XcOAaEpjdTRC9TVXF1IJch/WvgdQIFVjupb+C1aN0xQ2S1dw==","shasum":"57f04d8f8e0089b1cef8707f9c8618bf23c048c1","tarball":"https://registry.npmjs.org/@addilytics/hono/-/hono-0.0.1.tgz","fileCount":6,"unpackedSize":10804,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGtJlrs15xSBtn9itGKpp5q+hgoyRoZTZSL1bjYdfQYzAiBYmbVr+54kwacrDkyS9O7wBLywCMUAq8+LJB27z3EY6Q=="}]},"_npmUser":{"name":"embedvr","email":"npm@helium.email"},"directories":{},"maintainers":[{"name":"embedvr","email":"npm@helium.email"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hono_0.0.1_1789127073658_0.31118936413847087"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-11T11:44:33.390Z","0.0.1":"2026-09-11T11:44:33.795Z","modified":"2026-09-11T11:44:34.058Z"},"maintainers":[{"name":"embedvr","email":"npm@helium.email"}],"description":"Hono server analytics and bundled browser relay.","license":"MIT","readme":"# @addilytics/hono\n\nHono middleware that records pageviews from the final `Context.res`. It does not read, clone, or\nreplace the response body.\n\n```ts\nimport { addilytics } from '@addilytics/hono';\nimport { Hono } from 'hono';\n\nconst app = new Hono();\nconst analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: 'ak_...'\n});\n\napp.use('*', analytics);\n```\n\nRegister authentication or context initialization first, Addilytics second, and routes or\nresponse-mutating middleware after it. Hono runs Addilytics as an outer layer around later handlers,\nso it sees the final response after they finish. Relay requests return from Addilytics without\nrunning later middleware. Redirects, JSON responses, and server errors are skipped by default.\n\nOnly requests dispatched through this Hono app count. A CDN response, prerendered file, client-side\nroute change without an HTML request, or browser back-forward cache restore bypasses the middleware.\n\n## Custom events\n\nThe middleware carries a typed `track()` method.\n\n```ts\napp.post('/signup', async (context) => {\n\tawait analytics.track(context, 'signup', {\n\t\tprops: { source: 'pricing' }\n\t});\n\treturn context.body(null, 204);\n});\n```\n\n`track()` uses the same bot filtering and identity rules as the core client.\n\n## Identity and background delivery\n\nUse `user` when identity lives in a Hono variable or binding.\n\n```ts\nconst analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: 'ak_...',\n\tuser: (context) => context.get('userId')\n});\n\napp.use('*', authMiddleware);\napp.use('*', analytics);\n```\n\nThe `user` resolver can read `context.get()` only when an earlier middleware sets that value. A\nresolver that reads the raw request can stay inside the Addilytics options.\n\nHono does not expose a portable client-address API. Supply `ip` when the deployment runtime keeps\nthe address on a binding, request property, or trusted context value:\n\n```ts\nconst analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: 'ak_...',\n\tip: (context) => context.env.incomingRequestIp\n});\n```\n\nThe resolver may be async. If it throws, the adapter reports an `ip` error and records the event\nwithout an address. It does not fall back to forwarded headers after a resolver failure. Without an\n`ip` resolver, `trustProxy: true` enables the core client's forwarded-header fallback.\n\nThe adapter uses `context.executionCtx.waitUntil()` on runtimes that provide it. Elsewhere it waits\nfor delivery before the request completes. You can supply `waitUntil` when a platform exposes its\nbackground-task hook somewhere else.\n\nAnalytics failures never replace or reject an otherwise successful application response.\n\n## Browser navigation modes\n\nServer tracking remains the default. Use `hybrid` when Hono records the initial document and your\nclient router reports later navigations. Use `client` when the browser owns every pageview. Client\nmode keeps custom server events enabled but skips automatic server document capture.\n\nConfigure authentication before the analytics middleware, then put routes after it so the relay can\nuse established identity without reaching application handlers:\n\n```ts\nconst analytics = addilytics({\n\tendpoint: process.env.ADDILYTICS_ENDPOINT!,\n\tmode: 'hybrid',\n\trelayPath: '/internal/analytics',\n\tsiteKey: process.env.ADDILYTICS_SITE_KEY!\n});\n\napp.use('*', authMiddleware);\napp.use('*', analytics);\n```\n\nHono has no client router, so its browser entry re-exports the generic tracker. Call `pageview()`\nafter your router commits a navigation, including the initial page:\n\n```ts\nimport { createBrowserTracker } from '@addilytics/hono/browser';\n\nconst tracker = createBrowserTracker({\n\tendpoint: '/internal/analytics',\n\tmode: 'hybrid'\n});\n\nrouter.afterEach((url) => tracker.pageview(url));\n```\n\nHybrid mode skips the first browser call because the server owns it. Client mode sends that call.\nThe core tracker deduplicates repeated URLs and ignores hash-only changes unless you set\n`trackHashChanges: true`. Applications should also call `pageview()` with `force: true` for a\npersisted `pageshow` event if back-forward cache restores count as new visits.\n\nThe browser sends only a generated event ID, timestamp, pathname, allowlisted campaign query, and\nreferrer. The relay adds trusted server metadata and user identity. It accepts only its exact path\nand rejects cross-origin or malformed requests. The site key and ingest endpoint stay in server\ncode, and this package does not inject or load an external script.\n","readmeFilename":"","_rev":"1-5f8501dbb61bae61c3b66ea52cffdc83"}