{"_id":"@bayonai/push-notifications","_rev":"3-71131efaa8c045a0ebeeb2ecdc768015","name":"@bayonai/push-notifications","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@bayonai/push-notifications","version":"0.1.0","keywords":["capacitor","firebase","notifications","push-notifications","fcm"],"author":{"name":"Bayon AI"},"license":"MIT","_id":"@bayonai/push-notifications@0.1.0","maintainers":[{"name":"toledoroy","email":"toledoroy@gmail.com"}],"homepage":"https://github.com/toledoroy/bounded/tree/main/packages/push-notifications#readme","bugs":{"url":"https://github.com/toledoroy/bounded/issues"},"dist":{"shasum":"42fe667a9b7c6b9bb962af366a87436a149fb6cd","tarball":"https://registry.npmjs.org/@bayonai/push-notifications/-/push-notifications-0.1.0.tgz","fileCount":56,"integrity":"sha512-4XkyTCx2tXE5ls2tsVSJ9mkZzsiIYb4qsvxUXykLprduon0YZByXOXNl0ikm5nCvw+fgyO9q7JneXggP+34ISw==","signatures":[{"sig":"MEQCICkey5RQBaBMwAUvW2ouYcrxuKFHg5JapnP9bGSo5rV+AiAySNRps/pE09HKWN4dnPNVMLgYFgzVLHo9MJ+j8C29cA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107052},"main":"./dist-cjs/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./capacitor":{"types":"./dist/capacitor/index.d.ts","import":"./dist/capacitor/index.js","require":"./dist-cjs/capacitor/index.js"},"./firebase-admin":{"types":"./dist/firebase-admin/index.d.ts","import":"./dist/firebase-admin/index.js","require":"./dist-cjs/firebase-admin/index.js"},"./capacitor-local":{"types":"./dist/capacitor-local/index.d.ts","import":"./dist/capacitor-local/index.js","require":"./dist-cjs/capacitor-local/index.js"},"./capacitor-firebase":{"types":"./dist/capacitor-firebase/index.d.ts","import":"./dist/capacitor-firebase/index.js","require":"./dist-cjs/capacitor-firebase/index.js"}},"gitHead":"559589ca2a7115c9460db7924bc7114fc1ae25c6","scripts":{"lint":"tsc --noEmit -p tsconfig.json","test":"vitest run","build":"tsc -p tsconfig.json && node ../firebase-auth/scripts/write-esm-extensions.mjs . && tsc -p tsconfig.cjs.json && node ../firebase-auth/scripts/write-cjs.mjs .","prepack":"corepack pnpm run build","pack:smoke":"corepack pnpm run build && npm pack --dry-run --access public","consumer:smoke":"node scripts/verify-consumer-package.mjs"},"_npmUser":{"name":"toledoroy","email":"toledoroy@gmail.com"},"repository":{"url":"git+https://github.com/toledoroy/bounded.git","type":"git","directory":"packages/push-notifications"},"_npmVersion":"10.9.8","description":"Provider-neutral notification contracts with Capacitor Firebase and Firebase Admin adapters.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/index.d.ts"],"capacitor":["./dist/capacitor/index.d.ts"],"firebase-admin":["./dist/firebase-admin/index.d.ts"],"capacitor-local":["./dist/capacitor-local/index.d.ts"],"capacitor-firebase":["./dist/capacitor-firebase/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","typescript":"^5.9.3","@types/node":"^22.19.1","firebase-admin":"^13.10.0","@capacitor/core":"^8.4.1","firebase-functions":"^7.2.5","@capacitor-firebase/messaging":"^8.3.0","@capacitor/local-notifications":"^8.2.0"},"peerDependencies":{"firebase-admin":"^13.0.0 || ^14.0.0","@capacitor/core":"^8.0.0","firebase-functions":"^7.0.0","@capacitor-firebase/messaging":"^8.0.0","@capacitor/local-notifications":"^8.2.0"},"peerDependenciesMeta":{"firebase-admin":{"optional":true},"@capacitor/core":{"optional":true},"firebase-functions":{"optional":true},"@capacitor-firebase/messaging":{"optional":true},"@capacitor/local-notifications":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/push-notifications_0.1.0_1784184929927_0.22262121600259221","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@bayonai/push-notifications","version":"0.1.1","keywords":["capacitor","firebase","notifications","push-notifications","fcm"],"author":{"name":"Bayon AI"},"license":"MIT","_id":"@bayonai/push-notifications@0.1.1","maintainers":[{"name":"toledoroy","email":"toledoroy@gmail.com"}],"homepage":"https://github.com/toledoroy/bounded/tree/main/packages/push-notifications#readme","bugs":{"url":"https://github.com/toledoroy/bounded/issues"},"dist":{"shasum":"f00ecc0759b36ab1afdb33feef667beccfefe6da","tarball":"https://registry.npmjs.org/@bayonai/push-notifications/-/push-notifications-0.1.1.tgz","fileCount":56,"integrity":"sha512-hGznVG0Cz+t53G9jd9mg5h4lDtk1xkcrfm+8fs1nhnZkrrzG4AL7rGRsxCNGUhIYhnAybtc+BtXwBWX5lrUipQ==","signatures":[{"sig":"MEUCIH/nhgwYCnQox/6QY1F3mG91aa8zYSSYNXuUitsNloEAAiEAklfpcEfzMlqHWPhLCnJRvB5zrk6S1P0Jl4I3yW+WS+c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109697},"main":"./dist-cjs/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./capacitor":{"types":"./dist/capacitor/index.d.ts","import":"./dist/capacitor/index.js","require":"./dist-cjs/capacitor/index.js"},"./firebase-admin":{"types":"./dist/firebase-admin/index.d.ts","import":"./dist/firebase-admin/index.js","require":"./dist-cjs/firebase-admin/index.js"},"./capacitor-local":{"types":"./dist/capacitor-local/index.d.ts","import":"./dist/capacitor-local/index.js","require":"./dist-cjs/capacitor-local/index.js"},"./capacitor-firebase":{"types":"./dist/capacitor-firebase/index.d.ts","import":"./dist/capacitor-firebase/index.js","require":"./dist-cjs/capacitor-firebase/index.js"}},"gitHead":"480d08d9ba8ddd0e2abedbba24f48e705efe1397","scripts":{"lint":"tsc --noEmit -p tsconfig.json","test":"vitest run","build":"tsc -p tsconfig.json && node ../firebase-auth/scripts/write-esm-extensions.mjs . && tsc -p tsconfig.cjs.json && node ../firebase-auth/scripts/write-cjs.mjs .","prepack":"corepack pnpm run build","pack:smoke":"corepack pnpm run build && npm pack --dry-run --access public","consumer:smoke":"node scripts/verify-consumer-package.mjs"},"_npmUser":{"name":"toledoroy","email":"toledoroy@gmail.com"},"repository":{"url":"git+https://github.com/toledoroy/bounded.git","type":"git","directory":"packages/push-notifications"},"_npmVersion":"10.9.8","description":"Provider-neutral notification contracts with Capacitor Firebase and Firebase Admin adapters.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/index.d.ts"],"capacitor":["./dist/capacitor/index.d.ts"],"firebase-admin":["./dist/firebase-admin/index.d.ts"],"capacitor-local":["./dist/capacitor-local/index.d.ts"],"capacitor-firebase":["./dist/capacitor-firebase/index.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","typescript":"^5.9.3","@types/node":"^22.19.1","firebase-admin":"^13.10.0","@capacitor/core":"^8.4.1","firebase-functions":"^7.2.5","@capacitor-firebase/messaging":"^8.3.0","@capacitor/local-notifications":"^8.2.0"},"peerDependencies":{"firebase-admin":"^13.0.0 || ^14.0.0","@capacitor/core":"^8.0.0","firebase-functions":"^7.0.0","@capacitor-firebase/messaging":"^8.0.0","@capacitor/local-notifications":"^8.2.0"},"peerDependenciesMeta":{"firebase-admin":{"optional":true},"@capacitor/core":{"optional":true},"firebase-functions":{"optional":true},"@capacitor-firebase/messaging":{"optional":true},"@capacitor/local-notifications":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/push-notifications_0.1.1_1784391853639_0.7697906190528143","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@bayonai/push-notifications","version":"0.1.2","description":"Provider-neutral notification contracts with Capacitor Firebase and Firebase Admin adapters.","license":"MIT","author":{"name":"Bayon AI"},"homepage":"https://github.com/toledoroy/bounded/tree/main/packages/push-notifications#readme","repository":{"type":"git","url":"git+https://github.com/toledoroy/bounded.git","directory":"packages/push-notifications"},"bugs":{"url":"https://github.com/toledoroy/bounded/issues"},"keywords":["capacitor","firebase","notifications","push-notifications","fcm"],"sideEffects":false,"type":"module","main":"./dist-cjs/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./capacitor":{"types":"./dist/capacitor/index.d.ts","import":"./dist/capacitor/index.js","require":"./dist-cjs/capacitor/index.js"},"./capacitor-firebase":{"types":"./dist/capacitor-firebase/index.d.ts","import":"./dist/capacitor-firebase/index.js","require":"./dist-cjs/capacitor-firebase/index.js"},"./capacitor-local":{"types":"./dist/capacitor-local/index.d.ts","import":"./dist/capacitor-local/index.js","require":"./dist-cjs/capacitor-local/index.js"},"./firebase-admin":{"types":"./dist/firebase-admin/index.d.ts","import":"./dist/firebase-admin/index.js","require":"./dist-cjs/firebase-admin/index.js"}},"typesVersions":{"*":{"capacitor":["./dist/capacitor/index.d.ts"],"capacitor-firebase":["./dist/capacitor-firebase/index.d.ts"],"capacitor-local":["./dist/capacitor-local/index.d.ts"],"firebase-admin":["./dist/firebase-admin/index.d.ts"],"*":["./dist/index.d.ts"]}},"publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.json && node ../firebase-auth/scripts/write-esm-extensions.mjs . && tsc -p tsconfig.cjs.json && node ../firebase-auth/scripts/write-cjs.mjs .","consumer:smoke":"node scripts/verify-consumer-package.mjs","lint":"tsc --noEmit -p tsconfig.json","pack:smoke":"corepack pnpm run build && npm pack --dry-run --access public","prepack":"corepack pnpm run build","test":"vitest run","test:coverage":"vitest run --coverage"},"peerDependencies":{"@capacitor-firebase/messaging":"^8.0.0","@capacitor/core":"^8.0.0","@capacitor/local-notifications":"^8.2.0","firebase-admin":"^13.0.0 || ^14.0.0","firebase-functions":"^7.0.0"},"peerDependenciesMeta":{"@capacitor-firebase/messaging":{"optional":true},"@capacitor/core":{"optional":true},"@capacitor/local-notifications":{"optional":true},"firebase-admin":{"optional":true},"firebase-functions":{"optional":true}},"devDependencies":{"@capacitor-firebase/messaging":"^8.3.0","@capacitor/core":"^8.4.1","@capacitor/local-notifications":"^8.2.0","@types/node":"^22.19.1","firebase-admin":"^13.10.0","firebase-functions":"^7.2.5","typescript":"^5.9.3","vitest":"^4.1.7"},"_id":"@bayonai/push-notifications@0.1.2","gitHead":"5387dc62bb4983d8a0294251d2d2cfdb34793061","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-C7ipn5h6+tamJS0J7YcrmIY4ZU66jlSQK6xNT1fpTmaD02uRMGcXtlpxuUrXuFCbV7rAgcJ+yvVz2b9YIsvAbQ==","shasum":"c33537a8589ae55d75e7eaed53e939e02461c342","tarball":"https://registry.npmjs.org/@bayonai/push-notifications/-/push-notifications-0.1.2.tgz","fileCount":62,"unpackedSize":120738,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGPKRlw2g/c+hrDKM6vIk8dI5jAipx95BVt2btousinKAiEAg2SQkvZQpuoOz6PwTH+kg5kCjIYWSCvMMH8/oxtrurE="}]},"_npmUser":{"name":"toledoroy","email":"toledoroy@gmail.com"},"directories":{},"maintainers":[{"name":"toledoroy","email":"toledoroy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/push-notifications_0.1.2_1787805209027_0.30959618868449"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-16T06:55:29.748Z","modified":"2026-08-27T04:33:29.379Z","0.1.0":"2026-07-16T06:55:30.059Z","0.1.1":"2026-07-18T16:24:13.773Z","0.1.2":"2026-08-27T04:33:29.169Z"},"bugs":{"url":"https://github.com/toledoroy/bounded/issues"},"author":{"name":"Bayon AI"},"license":"MIT","homepage":"https://github.com/toledoroy/bounded/tree/main/packages/push-notifications#readme","keywords":["capacitor","firebase","notifications","push-notifications","fcm"],"repository":{"type":"git","url":"git+https://github.com/toledoroy/bounded.git","directory":"packages/push-notifications"},"description":"Provider-neutral notification contracts with Capacitor Firebase and Firebase Admin adapters.","maintainers":[{"name":"toledoroy","email":"toledoroy@gmail.com"}],"readme":"# `@bayonai/push-notifications`\n\nProvider-neutral notification contracts with optional Capacitor Firebase\nMessaging and Firebase Admin adapters.\n\n## Install\n\nInstall the package and only the peers used by the consuming runtime:\n\n```bash\npnpm add @bayonai/push-notifications\npnpm add @capacitor/core @capacitor-firebase/messaging\npnpm add firebase-admin firebase-functions\n```\n\nDo not install `@capacitor/push-notifications` beside the Firebase Messaging\nadapter. Both plugins compete for native push registration callbacks.\n\n## Entry points\n\n- `@bayonai/push-notifications`: messages, audiences, validation, providers,\n  installation registries, job queues, and dispatcher.\n- `@bayonai/push-notifications/capacitor`: framework-independent lifecycle controller.\n- `@bayonai/push-notifications/capacitor-firebase`: dynamically loaded Capacitor FCM adapter.\n- `@bayonai/push-notifications/capacitor-local`: dynamically loaded offline\n  device scheduler using Capacitor Local Notifications.\n- `@bayonai/push-notifications/firebase-admin`: Firestore registry, authenticated\n  callable factories, and FCM provider.\n\nThe Firebase adapter also supports web browsers. Supply the Firebase Web Push\nVAPID public key and a host-owned service worker path; the adapter registers the\nworker only when a browser explicitly requests permission.\n\n```ts\nimport { createFirebaseMessagingAdapter } from \"@bayonai/push-notifications/capacitor-firebase\";\n\nconst adapter = createFirebaseMessagingAdapter({\n  serviceWorkerPath: \"/firebase-messaging-sw.js\",\n  vapidKey: \"your-public-vapid-key\",\n});\n```\n\nNative code is dynamically imported only by the Capacitor Firebase entrypoint,\nso importing core or server contracts during SSR does not initialize Capacitor.\n\n## Data storage boundary\n\nThe core, Capacitor, Capacitor Firebase, and Capacitor Local entrypoints do not\nrequire a database. The client lifecycle accepts host-provided registration and\nrevocation callbacks, so an application can store installations through its own\nauthenticated API or another persistence layer.\n\nThe optional `firebase-admin` entrypoint includes a Firestore implementation of\nthat storage contract. Use `createFirestoreInstallationRegistry(firestore)`\nwhen server-side FCM delivery needs to look up active device targets. The\npackage does not create a database or choose a collection for hosts using a\ncustom `InstallationRegistry`.\n\n## Offline device scheduling\n\nInstall `@capacitor/local-notifications` only in apps that schedule reminders on\nthe device. This adapter is independent from the selected remote push provider.\n\n```ts\nimport { createLocalNotificationScheduler } from \"@bayonai/push-notifications/capacitor-local\";\n\nconst scheduler = createLocalNotificationScheduler();\nawait scheduler.schedule([\n  {\n    body: \"You have a Bounded reminder.\",\n    data: { openPath: \"/notifications/open\", schemaVersion: \"1\" },\n    id: 42,\n    scheduleAt: new Date(Date.now() + 60_000).toISOString(),\n    title: \"Bounded\",\n  },\n]);\n```\n\nOneSignal is intentionally not part of this package's active Bounded\nimplementation. Do not install its SDK or adapters alongside Firebase Messaging;\na future provider migration must preserve existing FCM registrations and be\nplanned as a separate release.\n\n## Client lifecycle\n\n```ts\nimport { createNotificationLifecycleController } from \"@bayonai/push-notifications/capacitor\";\nimport { createFirebaseMessagingAdapter } from \"@bayonai/push-notifications/capacitor-firebase\";\n\nconst controller = createNotificationLifecycleController({\n  adapter: createFirebaseMessagingAdapter(),\n  appId: \"com.example.app\",\n  provider: \"fcm\",\n  registerInstallation: async (installation) => api.register(installation),\n  revokeInstallation: async (installation) => api.revoke(installation),\n});\n\nawait controller.start();\nawait controller.sync({\n  enabled: true,\n  identity: { ownerUserId: \"authenticated-user-id\" },\n});\n```\n\nCall `requestPermissionAndSync` only after an explicit user action. Call\n`disable` before sign-out and `stop` when the host lifecycle is disposed.\nLifecycle transitions are serialized internally, so hosts may safely call\n`sync`, `disable`, `stop`, and token-refresh handlers from overlapping effects.\nInjected loggers must redact provider errors and must never serialize target\nvalues; the package never intentionally emits a target as a standalone log\nfield.\n\n## Server delivery\n\n```ts\nimport { createNotificationDispatcher } from \"@bayonai/push-notifications\";\nimport {\n  createFcmNotificationProvider,\n  createFirestoreInstallationRegistry,\n} from \"@bayonai/push-notifications/firebase-admin\";\n\nconst registry = createFirestoreInstallationRegistry(firestore);\nconst dispatcher = createNotificationDispatcher({\n  appId: \"com.example.app\",\n  provider: createFcmNotificationProvider(messaging),\n  registry,\n});\n\nawait dispatcher.send({\n  audience: { kind: \"users\", userIds: [\"user-id\"] },\n  message: {\n    title: \"New notification\",\n    body: \"Open the app to review it.\",\n    data: { schemaVersion: \"1\", notificationId: \"notification-id\" },\n  },\n});\n```\n\nDirect FCM delivery preserves successful multicast chunks when another chunk's\nrequest fails. The returned `failures` identify only the affected targets and\nmark them retryable, allowing a host queue to avoid replaying already accepted\ndevices.\n\nTopics and provider conditions are broadcast mechanisms, not authorization.\nNever place private content in topic messages. Scheduling requires an injected\n`NotificationJobQueue` and deliberately owns no campaign database or UI.\n\n## Reliable delivery lifecycle\n\nThe core entrypoint also exposes a storage-neutral outbox lifecycle for hosts\nthat must retry notification channels such as email and push together.\n`claimNotificationDelivery` transaction-compatibly computes a lease for pending,\nready-to-retry, or expired work; `failNotificationDelivery` applies the shared\nbounded exponential retry policy. Hosts persist `NotificationDeliveryRecord`\nand supply their own database transactions and channel executors, keeping\npayloads and product-specific stale-content rules outside this package.\n\n## Firestore contract\n\nOnly the optional Firebase registry uses Firestore. It stores\n`pushInstallations/{sha256}` with server-only raw targets and ownership\nmetadata. Host rules must deny all client access. The callable factories\nvalidate authentication, app ID, provider, platform, and target bounds before\ncalling the registry.\n\nRefresh registrations when an authenticated native app starts and when the\nprovider emits a new token. Remove invalid targets after delivery and schedule\n`pruneStale` with an app-appropriate retention window.\n\n## Publishing\n\n```bash\npnpm test\npnpm lint\npnpm build\npnpm consumer:smoke\npnpm pack:smoke\n```\n\nPublishing is intentionally separate from implementation. Bump the version and\nchangelog, verify npm scope authorization, publish with public access, and test\nthe registry artifact in a fresh Capacitor consumer before changing apps from\nworkspace consumption.\n","readmeFilename":"README.md"}