{"_id":"@asyncify-hq/react-native","_rev":"2-18fb436aa66e27bc8e533bc13ff7d73f","name":"@asyncify-hq/react-native","dist-tags":{"latest":"0.1.0"},"versions":{"0.0.0":{"name":"@asyncify-hq/react-native","version":"0.0.0","keywords":["notifications","push","react-native","fcm","firebase","asyncify"],"author":{"name":"Shubam Patil"},"license":"MIT","_id":"@asyncify-hq/react-native@0.0.0","maintainers":[{"name":"shubam14dec","email":"shubamp981@gmail.com"}],"homepage":"https://asyncify.org","bugs":{"url":"https://github.com/shubam14dec/Scalable-Notification-System/issues"},"dist":{"shasum":"a4192ed359795901bf55e0aa540f281bd8712a56","tarball":"https://registry.npmjs.org/@asyncify-hq/react-native/-/react-native-0.0.0.tgz","fileCount":7,"integrity":"sha512-1fGnvTglHsBFfjbzVM5KHadrtjA38j+TzF/ePwgopk6+UryVemZHJSEdWiJfLAPWsBMJmpVy95Xxt6dx3oLZkg==","signatures":[{"sig":"MEQCIG/pZjBbgID+FMUdyi56w1mwxkmp6sfc/6SKizMWRoLnAiByw7eQR/wVEMevmqYexXY8GXIRM+m6YyxATNU1el52ig==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30226},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"d8286da1fa55943d300165873973c7ee209a0ee7","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"shubam14dec","email":"shubamp981@gmail.com"},"repository":{"url":"git+https://github.com/shubam14dec/Scalable-Notification-System.git","type":"git","directory":"packages/react-native"},"_npmVersion":"11.6.2","description":"Native push registration for Asyncify — one hook that wires FCM device tokens, permissions and token rotation on Android and iOS","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","react-native":"./dist/index.js","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"18.2.0","typescript":"^5.7.2","@types/react":"^18.2.0","react-native":"^0.74.5","@react-native-firebase/app":"^21.6.1","@react-native-firebase/messaging":"^21.6.1","@react-native-async-storage/async-storage":"1.23.1"},"peerDependencies":{"react":">=18","react-native":">=0.72","@react-native-firebase/app":">=18","@react-native-firebase/messaging":">=18","@react-native-async-storage/async-storage":">=1.17.0"},"peerDependenciesMeta":{"@react-native-async-storage/async-storage":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/react-native_0.0.0_1784453712363_0.5687113532678738","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@asyncify-hq/react-native","version":"0.1.0","description":"Native push registration for Asyncify — one hook that wires FCM device tokens, permissions and token rotation on Android and iOS","keywords":["notifications","push","react-native","fcm","firebase","asyncify"],"homepage":"https://asyncify.org","repository":{"type":"git","url":"git+https://github.com/shubam14dec/Scalable-Notification-System.git","directory":"packages/react-native"},"license":"MIT","author":{"name":"Shubam Patil"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","react-native":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"publishConfig":{"access":"public"},"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","prepublishOnly":"npm run build"},"peerDependencies":{"@react-native-async-storage/async-storage":">=1.17.0","@react-native-firebase/app":">=18","@react-native-firebase/messaging":">=18","react":">=18","react-native":">=0.72"},"peerDependenciesMeta":{"@react-native-async-storage/async-storage":{"optional":true}},"devDependencies":{"@react-native-async-storage/async-storage":"1.23.1","@react-native-firebase/app":"^21.6.1","@react-native-firebase/messaging":"^21.6.1","@types/react":"^18.2.0","react":"18.2.0","react-native":"^0.74.5","tsup":"^8.3.5","typescript":"^5.7.2"},"gitHead":"7df1114f23678f4db498c0d6fca74dbf494f597b","_id":"@asyncify-hq/react-native@0.1.0","bugs":{"url":"https://github.com/shubam14dec/Scalable-Notification-System/issues"},"_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-NBl+2Px93CJ632dhuO3pX06OB4VOuoyg9Uq2I7D2fr5QS1w1zEu5xEtRRp/b1k9j6sajm5SMtnvTb+dq1PoqNQ==","shasum":"e606d88e3ba638d49c1cc02c8816854192dd186a","tarball":"https://registry.npmjs.org/@asyncify-hq/react-native/-/react-native-0.1.0.tgz","fileCount":7,"unpackedSize":30226,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@asyncify-hq%2freact-native@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFRDDqFo8qAQZvSeoeWPlQNgHLVw2SoZRHNVkhpX/odjAiEA3rfj6EiDMhlQXHyZ7AALF35uxlisJE0G21bW7fMy0lw="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:349c0f5b-4869-478b-a2cb-4ccb1bdde44a"}},"directories":{},"maintainers":[{"name":"shubam14dec","email":"shubamp981@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-native_0.1.0_1784454119166_0.6430390193584907"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-19T09:35:12.264Z","modified":"2026-07-19T09:41:59.620Z","0.0.0":"2026-07-19T09:35:12.507Z","0.1.0":"2026-07-19T09:41:59.282Z"},"bugs":{"url":"https://github.com/shubam14dec/Scalable-Notification-System/issues"},"author":{"name":"Shubam Patil"},"license":"MIT","homepage":"https://asyncify.org","keywords":["notifications","push","react-native","fcm","firebase","asyncify"],"repository":{"type":"git","url":"git+https://github.com/shubam14dec/Scalable-Notification-System.git","directory":"packages/react-native"},"description":"Native push registration for Asyncify — one hook that wires FCM device tokens, permissions and token rotation on Android and iOS","maintainers":[{"name":"shubam14dec","email":"shubamp981@gmail.com"}],"readme":"# @asyncify-hq/react-native\n\nNative push registration for [Asyncify](https://asyncify.org): one hook that\nwires a device's FCM token into your Asyncify subscriber, asks for the OS\nnotification permission, follows token rotation, and surfaces foreground\nmessages. Built on [React Native Firebase](https://rnfirebase.io) — the OS is\nthe push receiver, so there is no service worker to run.\n\n## Install\n\n```bash\nnpm install @asyncify-hq/react-native\n```\n\nThis package has required peers — install and configure them too:\n\n```bash\nnpm install @react-native-firebase/app @react-native-firebase/messaging\n```\n\nFollow the React Native Firebase\n[getting-started guide](https://rnfirebase.io/#installation) to add your\n`google-services.json` (Android) / APNs key (iOS) and the `@react-native-firebase/app`\nconfig plugin. `react` and `react-native` are peers you already have.\n\n## Usage\n\nYour backend mints a short-lived, single-subscriber token with\n[`@asyncify-hq/node`](https://www.npmjs.com/package/@asyncify-hq/node)\n(API keys never reach the device):\n\n```ts\n// backend\nconst { token } = await asyncify.subscriberToken(user.id);\n```\n\n```tsx\n// app\nimport { usePushRegistration } from '@asyncify-hq/react-native';\n\nfunction PushToggle({ token }: { token: string }) {\n  const push = usePushRegistration({\n    token,\n    apiUrl: 'https://api.your-deployment.com',\n    onForegroundMessage: (msg) => console.log('foreground push', msg),\n  });\n\n  if (!push.supported) return null;\n\n  return (\n    <Button\n      title={push.enabled ? 'Disable push' : 'Enable push'}\n      disabled={push.busy}\n      onPress={push.enabled ? push.disable : push.enable}\n    />\n  );\n}\n```\n\n`enable()` prompts for the notification permission, reads the FCM token, and\nregisters the device. The hook also re-registers silently after a token\nrotation (the server upsert is idempotent), so you call `enable()` once.\n\n### The `localhost` warning\n\n`apiUrl` is **required** and must be reachable **from the phone**. On a device,\n`localhost` / `127.0.0.1` is the phone itself — not your laptop. Point `apiUrl`\nat a LAN IP or a public tunnel (e.g. the cloudflare URL that `asyncify dev`\nprints), never `localhost`.\n\n## Hook API\n\n```ts\nconst {\n  supported,   // boolean — true on Android/iOS\n  permission,  // 'granted' | 'denied' | 'prompt'\n  enabled,     // boolean — true once the device is registered\n  busy,        // boolean — an enable()/disable() is in flight\n  error,       // string | null — last explicit-action error\n  enable,      // () => Promise<void>\n  disable,     // () => Promise<void>\n} = usePushRegistration({ token, apiUrl, onForegroundMessage });\n```\n\nBackground and quit-state notifications are displayed by the OS automatically;\n`onForegroundMessage` fires **only** while the app is open.\n\n## Tapping a notification\n\nOn native, the OS always launches the **app** when a notification is tapped —\nthere is no browser-opens-directly path like web push. When the tapped message\ncarries a `clickUrl` (set on the workflow's push step), the hook forwards it to\nthe system browser automatically, covering both a background tap and a tap that\ncold-started the app. Pass `openClickUrlOnTap: false` to receive taps yourself\nvia the React Native Firebase APIs instead — the URL also rides in the message\n`data` as `clickUrl`.\n\n## Sticky opt-out\n\n`disable()` must survive an app relaunch — otherwise, since the OS notification\npermission is still granted, the hook would silently re-register a fresh token\non the next launch and undo the user's opt-out. To make it stick, the hook\npersists an opt-out marker (`asyncify:push:opted-out`) via\n[`@react-native-async-storage/async-storage`](https://react-native-async-storage.github.io/async-storage/),\nwhich is an **optional peer**: `disable()` sets it, `enable()` clears it, and a\nlaunch that sees it skips the silent re-register. Install async-storage to get\nthis behavior:\n\n```bash\nnpm install @react-native-async-storage/async-storage\n```\n\nWithout async-storage the hook still works, but a `disable()` only lasts until\nthe next app launch (the marker can't be persisted). The marker stores an\nopt-**out**, so users who never call `disable()` keep the zero-config\nauto-register behavior with no storage library at all.\n\n## iOS note\n\nThe code is platform-neutral — the same hook drives Android and iOS. iOS\nadditionally requires an APNs key uploaded in the Firebase console and a Mac\nbuild (Xcode / an Apple Developer account). This package has been **verified\nlive on Android only**; iOS is wired but unverified.\n\nMIT © Shubam Patil\n","readmeFilename":"README.md"}