expo-pusher-push-notifications 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -103,6 +103,14 @@ Custom sounds go in the plugin's `sounds` option. Details in [Extras](docs/extra
103
103
  - [Full API](docs/api.md)
104
104
  - [Migrating from react-native-pusher-push-notifications](docs/migrating.md)
105
105
 
106
+ ## Agent migration
107
+
108
+ Migrating from `react-native-pusher-push-notifications` (b8ne / forks) with Cursor, Claude, Grok or another coding agent? Tell it:
109
+
110
+ > Follow `node_modules/expo-pusher-push-notifications/skills/migrate-from-b8ne/SKILL.md` to migrate this app.
111
+
112
+ The skill has the inventory commands, search/replace table, native cleanup steps and a checklist. Human version: [Migrating](docs/migrating.md). Copy it into `.cursor/skills/` or `.claude/skills/` to make it auto-discoverable.
113
+
106
114
  ## Good to know
107
115
 
108
116
  - This module owns the iOS notification delegate and the Android FCM service, so don't run it alongside `expo-notifications` or `@react-native-firebase/messaging`.
package/docs/migrating.md CHANGED
@@ -1,32 +1,97 @@
1
1
  # Migrating from react-native-pusher-push-notifications
2
2
 
3
- This is a rewrite of [ZeptInc/react-native-pusher-push-notifications](https://github.com/ZeptInc/react-native-pusher-push-notifications) (itself a fork of [b8ne's](https://github.com/b8ne/react-native-pusher-push-notifications)).
3
+ Covers [`b8ne/react-native-pusher-push-notifications`](https://github.com/b8ne/react-native-pusher-push-notifications) (and its forks such as ZeptInc / pusher-community) → `expo-pusher-push-notifications` **0.5.x**.
4
4
 
5
- Here is what the ZeptInc and b8ne packages had, and where it lives now:
5
+ > **This is not a drop-in replacement.** The API is promise-based, start-up is a single `start()`/`Interests.start()` call, and native setup moves from hand-edited AppDelegate/MainApplication code to an Expo config plugin. Budget a small refactor, not a package swap.
6
6
 
7
- | Original | Here |
7
+ Using an AI agent? Point it at [`skills/migrate-from-b8ne/SKILL.md`](../skills/migrate-from-b8ne/SKILL.md) (shipped in the npm package).
8
+
9
+ ## 1. Install / remove
10
+
11
+ ```sh
12
+ npm uninstall react-native-pusher-push-notifications
13
+ npx expo install expo-pusher-push-notifications
14
+ ```
15
+
16
+ Requires an Expo dev build / prebuild (not Expo Go). Bare RN apps need `expo` modules installed (`npx install-expo-modules`).
17
+
18
+ ## 2. Native setup: config plugin instead of AppDelegate edits
19
+
20
+ | Old (manual) | New |
8
21
  |---|---|
9
- | `setInstanceId` / `setAppKey` | `start({ instanceId })` |
10
- | `subscribe` / `unsubscribe` with callbacks | Promise-based. |
11
- | `setSubscriptions` (iOS only), `getSubscriptions` (Android only) | Both on both platforms. |
12
- | `setOnSubscriptionsChangedListener` (Android only) | `subscriptionsChanged` event on both platforms. |
13
- | `setUserId(userId, token, onError, onSuccess)` (b8ne, static token) | `setUserId(userId, token)`. A remote token provider is also supported. |
14
- | `clearAllState` (b8ne) | `clearAllState()` |
15
- | `on('registered' \| 'notification')` | Same, plus `error`, and it returns a removable subscription. |
16
- | iOS foreground / background / opened states | `appState` on every notification. |
17
- | `aps.data.incrementBadge` (b8ne, iOS) | Supported on iOS and Android, plus full badge APIs. |
18
- | Android launch-intent notification delivery (b8ne) | `getInitialNotification()` and an `opened` event on tap. |
19
-
20
- Neither original had custom sounds, notification channels, or local and scheduled notifications. Those are new here.
22
+ | Carthage/CocoaPods `PushNotifications` framework, `RNPusherPushNotifications` imports | Autolinking (pods pulled automatically) |
23
+ | AppDelegate: `didRegisterForRemoteNotificationsWithDeviceToken` → `[[RNPusherPushNotifications alloc] setDeviceToken:]`, `didReceiveRemoteNotification` forwarding | Expo AppDelegate subscriber in this module – **delete** those lines |
24
+ | Android: `google-services.json` + gradle plugin lines, `MainApplication` / manifest service edits | Plugin config + `android.googleServicesFile` in app.json |
25
+ | Push capability / background modes toggled in Xcode | Added by the plugin on prebuild |
21
26
 
22
- ## Coming from 0.4
27
+ ```json
28
+ {
29
+ "expo": {
30
+ "android": { "googleServicesFile": "./google-services.json" },
31
+ "plugins": [["expo-pusher-push-notifications", { "instanceId": "YOUR_BEAMS_INSTANCE_ID" }]]
32
+ }
33
+ }
34
+ ```
23
35
 
24
- 0.5 brings back device-token support (`DeviceToken`, `registerForDeviceToken`, `getDevicePushToken`, `deleteDevicePushToken`, and `mode: 'device'`), same API as 0.3. Beams code from 0.4 keeps working unchanged.
36
+ Then `npx expo prebuild --clean`. See [Setup](setup.md).
25
37
 
26
- ## Steps
38
+ ## 3. API mapping
39
+
40
+ | b8ne / forks | expo-pusher-push-notifications 0.5 |
41
+ |---|---|
42
+ | `import RNPusherPushNotifications from 'react-native-pusher-push-notifications'` | `import { Interests, Users, on } from 'expo-pusher-push-notifications'` |
43
+ | `setInstanceId(id)` (+ `setAppKey` on some forks) | `await Interests.start(id)` or `await start({ instanceId: id })` |
44
+ | `subscribe(interest, onError, onSuccess)` | `await Interests.subscribe(interest)` (try/catch) |
45
+ | `unsubscribe(interest, onError, onSuccess)` | `await Interests.unsubscribe(interest)` |
46
+ | `setSubscriptions(arr)` (iOS only) | `await Interests.set(arr)` (both platforms) |
47
+ | `getSubscriptions(cb)` (Android only) | `const list = await Interests.get()` |
48
+ | `setOnSubscriptionsChangedListener(cb)` | `on('subscriptionsChanged', cb)` |
49
+ | `setUserId(userId, token, onError, onSuccess)` | `await Users.start(id)` then `await Users.login(userId, token)` — or pass `{ url, headers }` token provider instead of a static token |
50
+ | `clearAllState()` | `await Users.logout()` / `Interests.reset()` / `clearAllState()` |
51
+ | `on('registered', cb)` | `const sub = on('registered', cb)`; later `sub.remove()` |
52
+ | `on('notification', cb)` with iOS `appState` | Same; `appState` on both platforms; also `opened` and `error` events |
53
+ | Android launch-intent delivery | `await getInitialNotification()` + `on('opened', …)` |
54
+ | `aps.data.incrementBadge` | Supported both platforms + `setBadgeCount` / `incrementBadgeCount` |
55
+ | _(none)_ | Sounds, Android channels, local/scheduled notifications, raw device tokens (`DeviceToken`) |
27
56
 
28
- Remove the old package, its Carthage framework, and any `RNPusherPushNotifications` code in your AppDelegate and MainApplication. Autolinking, the config plugin, and the Expo AppDelegate subscriber replace them.
57
+ ### Before / after
58
+
59
+ ```ts
60
+ // before
61
+ RNPusherPushNotifications.setInstanceId(INSTANCE_ID);
62
+ RNPusherPushNotifications.on('registered', () => {
63
+ RNPusherPushNotifications.subscribe('news', err => console.warn(err), () => console.log('ok'));
64
+ });
65
+ RNPusherPushNotifications.on('notification', n => handle(n));
66
+
67
+ // after
68
+ import { Interests, on } from 'expo-pusher-push-notifications';
69
+ const sub = on('notification', n => handle(n));
70
+ await Interests.start(INSTANCE_ID); // no need to wait for 'registered'
71
+ await Interests.subscribe('news');
72
+ // cleanup: sub.remove();
73
+ ```
74
+
75
+ ```ts
76
+ // users — before
77
+ RNPusherPushNotifications.setUserId(userId, beamsToken, onError, onSuccess);
78
+ // after
79
+ await Users.start(INSTANCE_ID);
80
+ await Users.login(userId, { url: 'https://api.example.com/beams-token', headers: { Authorization: `Bearer ${jwt}` } });
81
+ // sign-out
82
+ await Users.logout();
83
+ ```
84
+
85
+ ## 4. Gotchas
86
+
87
+ - Notification payload shape may differ slightly; log one and update field access (`n.title`, `n.body`, `n.data`).
88
+ - Don't run alongside `expo-notifications` or `@react-native-firebase/messaging` (this module owns the delegate/FCM service).
89
+ - `start()` requests notification permission by default; pass `{ requestPermission: false }` to control it yourself.
90
+ - Calling Beams APIs before `start()` throws.
91
+
92
+ ## Coming from 0.4
29
93
 
94
+ 0.5 brings back device-token support (`DeviceToken`, `registerForDeviceToken`, `getDevicePushToken`, `deleteDevicePushToken`, `mode: 'device'`). Beams code from 0.4 is unchanged.
30
95
 
31
96
  ---
32
97
  [← Back to README](../README.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-pusher-push-notifications",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Push notifications for Expo: Pusher Beams (interests / users) or raw FCM/APNs device tokens (no EAS needed), with custom sounds, channels, badges and local notifications",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -66,6 +66,7 @@
66
66
  },
67
67
  "files": [
68
68
  "docs",
69
+ "skills",
69
70
  "build",
70
71
  "plugin/build",
71
72
  "ios",
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: migrate-from-b8ne
3
+ description: Migrate a React Native / Expo app from react-native-pusher-push-notifications (b8ne, ZeptInc, pusher-community forks) to expo-pusher-push-notifications 0.5.x. Use when an app imports react-native-pusher-push-notifications or has RNPusherPushNotifications native code.
4
+ ---
5
+
6
+ # Migrate from react-native-pusher-push-notifications
7
+
8
+ Not a drop-in swap: callbacks become promises, init becomes `start()`, native code becomes an Expo config plugin. Full reference: `docs/migrating.md` in this package.
9
+
10
+ ## Step 1 — Inventory (read-only)
11
+
12
+ ```sh
13
+ rg -n "react-native-pusher-push-notifications|RNPusherPushNotifications" --glob '!node_modules'
14
+ rg -n "setInstanceId|setAppKey|setUserId|setSubscriptions|getSubscriptions|setOnSubscriptionsChangedListener|clearAllState" --glob '!node_modules' -t js -t ts
15
+ rg -n "PushNotifications|RNPusher|incrementBadge" ios android --glob '!Pods'
16
+ ```
17
+
18
+ Record: instance ID source, interests used, whether users/`setUserId` is used, notification handler code, native files touched.
19
+
20
+ ## Step 2 — Dependencies
21
+
22
+ ```sh
23
+ npm uninstall react-native-pusher-push-notifications # or yarn/pnpm equivalent
24
+ npx expo install expo-pusher-push-notifications
25
+ ```
26
+ Bare RN without Expo modules: `npx install-expo-modules@latest` first. Expo Go is not supported (needs dev build).
27
+
28
+ ## Step 3 — Native config
29
+
30
+ 1. Add to `app.json`/`app.config.*` plugins: `["expo-pusher-push-notifications", { "instanceId": "<BEAMS_INSTANCE_ID>" }]`.
31
+ 2. Ensure `expo.android.googleServicesFile` points at `google-services.json`.
32
+ 3. If the project has committed `ios/`/`android/` (bare): delete `RNPusherPushNotifications` imports and calls in AppDelegate (`setDeviceToken`, `handleNotification`, didRegister/didReceive forwarding), Carthage/Pod entries for `PushNotifications` added manually, and Android `MainApplication`/manifest additions from the old README. Keep unrelated code.
33
+ 4. Run `npx expo prebuild --clean` (managed) or `cd ios && pod install` (bare).
34
+
35
+ ## Step 4 — JS rewrites
36
+
37
+ | Find | Replace with |
38
+ |---|---|
39
+ | `import X from 'react-native-pusher-push-notifications'` | `import { Interests, Users, on, getInitialNotification } from 'expo-pusher-push-notifications'` |
40
+ | `X.setInstanceId(ID)` | `await Interests.start(ID)` (or `Users.start(ID)` if users are used) |
41
+ | `X.subscribe(i, onErr, onOk)` | `try { await Interests.subscribe(i); onOk?.() } catch (e) { onErr?.(e) }` |
42
+ | `X.unsubscribe(i, onErr, onOk)` | same pattern with `Interests.unsubscribe` |
43
+ | `X.setSubscriptions(arr)` | `await Interests.set(arr)` |
44
+ | `X.getSubscriptions(cb)` | `cb(await Interests.get())` |
45
+ | `X.setOnSubscriptionsChangedListener(cb)` | `on('subscriptionsChanged', cb)` |
46
+ | `X.setUserId(uid, token, onErr, onOk)` | `await Users.login(uid, token)` (prefer `{ url, headers }` token provider) |
47
+ | `X.clearAllState()` | `await Users.logout()` |
48
+ | `X.on('registered'\|'notification', cb)` | `const sub = on(...)`; remove `sub` on unmount |
49
+
50
+ Rules:
51
+ - Make enclosing functions `async` or use `.then/.catch`. Never leave a floating promise without error handling.
52
+ - Remove logic that waits for `'registered'` before subscribing; `start()` resolves when ready.
53
+ - Call `start` once (app root), before any subscribe/login.
54
+ - Android cold-start taps: add `getInitialNotification()` + `on('opened', ...)`.
55
+ - If `expo-notifications` or `@react-native-firebase/messaging` is installed for push, flag it to the user — conflict.
56
+
57
+ ## Step 5 — Verify
58
+
59
+ ```sh
60
+ rg -n "react-native-pusher-push-notifications|RNPusherPushNotifications" --glob '!node_modules' # expect no hits
61
+ npx tsc --noEmit
62
+ npx expo run:ios && npx expo run:android
63
+ ```
64
+ Send a test push to an interest from the Beams dashboard on a real device; check foreground, background, and cold-start tap.
65
+
66
+ ## Checklist
67
+ - [ ] Old package + native code removed
68
+ - [ ] Plugin added with instanceId; googleServicesFile set; prebuild run
69
+ - [ ] All callbacks converted to promises with error handling
70
+ - [ ] Listeners return subscriptions that are removed
71
+ - [ ] Users flow: login after sign-in, logout on sign-out
72
+ - [ ] Typecheck passes; test push received on both platforms
73
+ - [ ] Summarize changes and any manual console steps (APNs key, Firebase) for the user