{"_id":"@anamico/4ars-reporter","_rev":"4-f7995fd12c441f7a66ee603083fa4b94","name":"@anamico/4ars-reporter","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@anamico/4ars-reporter","version":"0.1.0","keywords":["4ars","anamico","monitoring","analytics","arr","mrr","saas","reporter","events","webhook"],"author":{"name":"anamico"},"license":"MIT","_id":"@anamico/4ars-reporter@0.1.0","maintainers":[{"name":"imagineit","email":"manager@ImagineIT.com.au"},{"name":"macinspak","email":"npm@imagineit.com.au"}],"homepage":"https://github.com/Anamico/4ars-packages/tree/main/4ars-reporter#readme","bugs":{"url":"https://github.com/Anamico/4ars-packages/issues"},"dist":{"shasum":"e323d4a3cf80b2f559f507c7dcdede3ca8fa7699","tarball":"https://registry.npmjs.org/@anamico/4ars-reporter/-/4ars-reporter-0.1.0.tgz","fileCount":8,"integrity":"sha512-XK0DszsCM36Xce2MY3awDCHl5TJt/13f520WSPCxY9K59/0SbiHK0x3/8OqrURwCvWsEF0bb1Gnq/UHBmQTX/g==","signatures":[{"sig":"MEYCIQCPhYkEdY7ITvqky2Z6MFBs8AKM+jHRm4XhYLdunPetMAIhAJ5uLsqrd9rn12bEhTAthW2Msha3Zhbf9yRf1Z8QjUK/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77971},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"e7c502a23da71b66019cc64675617a9ce1474b12","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run test && npm run build"},"_npmUser":{"name":"macinspak","email":"npm@imagineit.com.au"},"repository":{"url":"git+https://github.com/Anamico/4ars-packages.git","type":"git","directory":"4ars-reporter"},"_npmVersion":"11.6.2","description":"Fire-and-forget event reporter for the 4ARS monitoring platform — typed signup/login/subscription/purchase emitters with HMAC-signed delivery and a custom-metric API.","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/4ars-reporter_0.1.0_1779018543778_0.9366256274815714","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@anamico/4ars-reporter","version":"0.1.1","keywords":["4ars","anamico","monitoring","analytics","arr","mrr","saas","reporter","events","webhook"],"author":{"name":"anamico"},"license":"MIT","_id":"@anamico/4ars-reporter@0.1.1","maintainers":[{"name":"imagineit","email":"manager@ImagineIT.com.au"},{"name":"macinspak","email":"npm@imagineit.com.au"}],"homepage":"https://github.com/Anamico/4ars-packages/tree/main/4ars-reporter#readme","bugs":{"url":"https://github.com/Anamico/4ars-packages/issues"},"dist":{"shasum":"e3a10503ed544c262d6864743f58fcf94b63a4c9","tarball":"https://registry.npmjs.org/@anamico/4ars-reporter/-/4ars-reporter-0.1.1.tgz","fileCount":8,"integrity":"sha512-G20+27eFe62vTvMTYAnOWhsWwh5gw2C48dvKMYGvLJtSSxWCeCqg7yNHZANj+ONan/NqRg8fNcYmdAd1YrKZLg==","signatures":[{"sig":"MEUCIQC5XwumgNhWAN9LXjIIwOvEl+6m78D5Tj3X8Rd5m4rPRAIgB05oP+Ncc6jtWzQLeuJF3AJ5tqzPBZyusN5NqRtV3SA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78013},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"a24d0074261d475237cfdcbdaf30a6ac325d0142","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","release":"node scripts/release.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run test && npm run build"},"_npmUser":{"name":"macinspak","email":"npm@imagineit.com.au"},"repository":{"url":"git+https://github.com/Anamico/4ars-packages.git","type":"git","directory":"4ars-reporter"},"_npmVersion":"11.6.2","description":"Fire-and-forget event reporter for the 4ARS monitoring platform — typed signup/login/subscription/purchase emitters with HMAC-signed delivery and a custom-metric API.","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/4ars-reporter_0.1.1_1779095855032_0.2630853670949247","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@anamico/4ars-reporter","version":"0.1.5","keywords":["4ars","anamico","monitoring","analytics","arr","mrr","saas","reporter","events","webhook"],"author":{"name":"anamico"},"license":"MIT","_id":"@anamico/4ars-reporter@0.1.5","maintainers":[{"name":"imagineit","email":"manager@ImagineIT.com.au"},{"name":"macinspak","email":"npm@imagineit.com.au"}],"homepage":"https://github.com/Anamico/4ars-packages/tree/main/4ars-reporter#readme","bugs":{"url":"https://github.com/Anamico/4ars-packages/issues"},"dist":{"shasum":"0b6647f6b9105f175aa9bc9f8a24f38bc24ac867","tarball":"https://registry.npmjs.org/@anamico/4ars-reporter/-/4ars-reporter-0.1.5.tgz","fileCount":8,"integrity":"sha512-4FF/VzyCennbPSy6pA3/+NXhFEMdhjVrtReKpBBVeyML3ThbARiXjTM2mbJuHzqQLn0l1K/x+aH5BxF4nFgM3w==","signatures":[{"sig":"MEUCIQDHdQXobF9J/Cxl/cO8+ozm9HSljXNpDCsaAR4rf3701AIgJX/GRYkZ1dEm2oyOz4MdrDTKHSQAbO+izR9JtsbK3n0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@anamico%2f4ars-reporter@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":78013},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"21c73a3c26ffc397d55f82fa1ec3304bf3211c06","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","release":"node scripts/release.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run test && npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4b5ffa3b-37ac-48cb-8390-314d1447b069"}},"repository":{"url":"git+https://github.com/Anamico/4ars-packages.git","type":"git","directory":"4ars-reporter"},"_npmVersion":"11.12.1","description":"Fire-and-forget event reporter for the 4ARS monitoring platform — typed signup/login/subscription/purchase emitters with HMAC-signed delivery and a custom-metric API.","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/4ars-reporter_0.1.5_1779102249973_0.6296766924238815","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@anamico/4ars-reporter","version":"0.2.1","description":"Fire-and-forget event reporter for the 4ARS monitoring platform — typed signup/login/subscription/purchase emitters with HMAC-signed delivery and a custom-metric API.","keywords":["4ars","anamico","monitoring","analytics","arr","mrr","saas","reporter","events","webhook"],"homepage":"https://github.com/Anamico/4ars-packages/tree/main/4ars-reporter#readme","repository":{"type":"git","url":"git+https://github.com/Anamico/4ars-packages.git","directory":"4ars-reporter"},"bugs":{"url":"https://github.com/Anamico/4ars-packages/issues"},"type":"module","license":"MIT","author":{"name":"anamico"},"engines":{"node":">=18"},"publishConfig":{"access":"public"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck && npm run test && npm run build","release":"node scripts/release.js"},"devDependencies":{"@types/node":"^22.0.0","tsup":"^8.0.0","typescript":"^5.5.0","vitest":"^2.0.0"},"gitHead":"2c4e37ad8466770902865fc59c2a2d028ce7e415","_id":"@anamico/4ars-reporter@0.2.1","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-L6lLj4tEZmpr5pYSoC2yj5aVvDmZbbwT0+YsxnisuIiU7KTwALKxbeHYoiIeZzmJlAad04CfILB+6WCkcMAmzg==","shasum":"d4047fba6866d89b6286e32da9a662b1beb861b6","tarball":"https://registry.npmjs.org/@anamico/4ars-reporter/-/4ars-reporter-0.2.1.tgz","fileCount":8,"unpackedSize":98327,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@anamico%2f4ars-reporter@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHhL30cXpZj2M1flgLiyAE4Bqr+2tFktd87Yefu8PP1mAiEA1DyqpTtAGB3jAtHKJ/Dpp1vxptPEUEezlu+Sm1PufPk="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4b5ffa3b-37ac-48cb-8390-314d1447b069"}},"directories":{},"maintainers":[{"name":"imagineit","email":"manager@ImagineIT.com.au"},{"name":"macinspak","email":"npm@imagineit.com.au"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/4ars-reporter_0.2.1_1780530734106_0.7649024305815053"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-17T11:49:03.664Z","modified":"2026-06-03T23:52:14.569Z","0.1.0":"2026-05-17T11:49:03.928Z","0.1.1":"2026-05-18T09:17:35.196Z","0.1.5":"2026-05-18T11:04:10.129Z","0.2.1":"2026-06-03T23:52:14.240Z"},"bugs":{"url":"https://github.com/Anamico/4ars-packages/issues"},"author":{"name":"anamico"},"license":"MIT","homepage":"https://github.com/Anamico/4ars-packages/tree/main/4ars-reporter#readme","keywords":["4ars","anamico","monitoring","analytics","arr","mrr","saas","reporter","events","webhook"],"repository":{"type":"git","url":"git+https://github.com/Anamico/4ars-packages.git","directory":"4ars-reporter"},"description":"Fire-and-forget event reporter for the 4ARS monitoring platform — typed signup/login/subscription/purchase emitters with HMAC-signed delivery and a custom-metric API.","maintainers":[{"name":"imagineit","email":"manager@ImagineIT.com.au"},{"name":"macinspak","email":"npm@imagineit.com.au"}],"readme":"# @anamico/4ars-reporter\n\nFire-and-forget event reporter for the [4ARS](https://github.com/anamico/4ars) monitoring platform. Drops into any Node.js SaaS project to stream typed events to the 4ARS Hub with zero runtime dependencies.\n\n## Installation\n\n```bash\nnpm install @anamico/4ars-reporter\n```\n\n## Quick start\n\n```ts\nimport { Reporter } from \"@anamico/4ars-reporter\";\n\nconst reporter = new Reporter({\n  hubUrl:      process.env.HUB_URL!,\n  projectId:   process.env.PROJECT_ID!,\n  secret:      process.env.HUB_SECRET!,\n  displayName: \"My SaaS\",\n  environment: \"production\",\n  adminUrl:    \"https://myapp.com/admin\",\n  icon:        \"creditcard.fill\",\n  color:       \"#FF6B35\",\n  customMetrics: [\n    { id: \"credits_remaining\", label: \"Credits\", format: \"number\",\n      showInList: true, listPriority: 1, trend: \"lower-is-bad\", alertBelow: 100 },\n  ],\n});\n\n// Typed helpers\nreporter.userSignup({ user: { id: \"usr_123\", email: \"j***@gmail.com\" }, source: \"web\" });\nreporter.subscriptionCreated({ user: { id: \"usr_123\" }, plan: \"pro\", mrr: 99 });\nreporter.purchaseCompleted({ user: { id: \"usr_123\" }, amount: 29, sku: \"credits-100\" });\nreporter.metric(\"credits_remaining\", 2450);\nreporter.custom(\"ai.tokens.used\", { model: \"gpt-4o\", tokens: 1234 });\n\n// Before process exit (optional)\nawait reporter.flush();\n```\n\n## Authoritative state\n\nEvents drive notifications and the activity feed (lossy OK). Your SaaS's authoritative current numbers — ARR, MRR, total users, custom metric current values — flow through `reporter.state(...)`. The Hub stores last-write-wins; iOS renders from this when present, falling back to event-derived counts otherwise.\n\n```ts\n// Push on startup, after meaningful changes, and on a safety-net cron.\nreporter.state({\n  totalUsers:           1247,\n  totalSubscribers:     89,\n  totalRevenueLifetime: 18420.00,\n  mrr:                  2580.00,\n  arr:                  30960.00,        // omit and Hub computes mrr * 12\n  activeUsers24h:       412,\n  activeUsers30d:       937,\n  customMetrics: {\n    credits_remaining: 2450,\n    ai_spend_today:    4.20,\n  },\n});\n\n// Convenience cron: calls fn immediately, then every N seconds.\n// Fires unref'd; returned function cancels.\nimport { enableAutoStateCron } from \"@anamico/4ars-reporter\";\n\nconst stop = enableAutoStateCron(reporter, 300, async () => ({\n  totalUsers:       await db.users.count(),\n  totalSubscribers: await db.subs.count({ active: true }),\n  mrr:              await db.subs.sumMrr({ active: true }),\n}));\n```\n\n`snapshotAt` defaults to `new Date().toISOString()`; pass a `Date` or ISO string to override. Same HMAC-signed pathway as event ingest — fire-and-forget, one auto-retry on transient failure, shared circuit breaker.\n\n## Environment variables\n\n| Variable | Description |\n|---|---|\n| `HUB_URL` | Base URL of the 4ARS Hub, e.g. `https://4ars-hub.yourdomain.com` |\n| `HUB_SECRET` | Pre-shared HMAC secret provisioned on the Hub |\n| `PROJECT_ID` | Unique project identifier, e.g. `pass-app` |\n\n## Method signatures\n\n```ts\nclass Reporter {\n  constructor(options: ReporterOptions)\n\n  userSignup(args: { user: { id: string; email?: string }; source?: string }): void\n  userLogin(args: { user: { id: string } }): void\n  sessionStarted(args: { user: { id: string }; device?: object }): void\n  subscriptionCreated(args: { user: { id: string }; plan: string; mrr: number }): void\n  subscriptionUpgraded(args: { user: { id: string }; plan: string; mrr: number; mrrDelta: number }): void\n  subscriptionDowngraded(args: { user: { id: string }; plan: string; mrr: number; mrrDelta: number }): void\n  subscriptionCancelled(args: { user: { id: string }; reason?: string; mrrLost: number }): void\n  purchaseCompleted(args: { user: { id: string }; amount: number; sku: string }): void\n  refundIssued(args: { user: { id: string }; amount: number; sku?: string }): void\n  paymentFailed(args: { user: { id: string }; amount?: number; reason?: string }): void\n  metric(metricId: string, value: number): void\n  custom(type: string, data: Record<string, unknown>): void\n\n  state(snapshot: StateSnapshot): void\n\n  flush(): Promise<void>\n}\n```\n\nAll currency values are USD (not parametrisable in v1).\n\n## Behaviour & failure semantics\n\n**Fire-and-forget.** Every method returns immediately. HTTP POSTs to the Hub happen in the background via `Promise.resolve().then(...)`.\n\n**No persistent queue.** No SQLite, no disk state, no background worker. In-memory only.\n\n**What gets stored.** Nothing client-side. Events are shipped to the Hub and forgotten.\n\n**Events during outage are lost.** If the Hub is unreachable, events that occur during the outage are not recoverable from the reporter. The `adminUrl` you configure at enrolment is the escape hatch — the iOS detail view renders it as a primary \"Open Admin\" button for one-tap access to ground-truth historical data.\n\n**Retry.** One automatic retry after 1 second on transient failure (network error, HTTP 5xx, 429).\n\n**Circuit breaker.** After 10 consecutive failures the circuit opens for 60 seconds. Events emitted during that window are dropped immediately with a `process.stderr` log line. The circuit resets on the next successful delivery.\n\n**Self-enrolment.** The Reporter POSTs `/enroll` in the background on construction, and re-enrols automatically whenever `displayName`, `adminUrl`, `capabilities`, or `customMetrics` change (fingerprint comparison). Enrolment is idempotent on the Hub.\n\n**HMAC signing.** Every request carries:\n- `X-Project-Id` — your project ID\n- `X-Timestamp` — Unix seconds\n- `X-Signature: sha256=<hmac-sha256 of \"${timestamp}.${body}\">` — computed with `crypto.subtle`\n\nThe Hub enforces a 5-minute replay window.\n\n**Event IDs.** Client-generated UUIDv7 (timestamp-ordered). The Hub deduplicates on `(projectId, id)` — safe to retry without double-counting.\n\n**Batching.** Events emitted within a 10ms window are coalesced into a single `/ingest` POST (up to 1000 events per batch).\n\n**`flush()`** — best-effort drain before process exit. Immediately dispatches any queued events, then awaits all in-flight POSTs. Does not guarantee delivery if the Hub is down.\n","readmeFilename":"README.md"}