doopush-react-native-sdk 0.1.2

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.
Files changed (48) hide show
  1. package/README.md +177 -0
  2. package/android/build.gradle +54 -0
  3. package/android/src/main/AndroidManifest.xml +2 -0
  4. package/android/src/main/java/com/doopush/reactnative/DooPushReactNativeSDKModule.kt +146 -0
  5. package/app.plugin.js +1 -0
  6. package/build/DooPush.d.ts +40 -0
  7. package/build/DooPush.d.ts.map +1 -0
  8. package/build/DooPush.js +49 -0
  9. package/build/DooPush.js.map +1 -0
  10. package/build/DooPushModule.d.ts +7 -0
  11. package/build/DooPushModule.d.ts.map +1 -0
  12. package/build/DooPushModule.js +8 -0
  13. package/build/DooPushModule.js.map +1 -0
  14. package/build/events.d.ts +23 -0
  15. package/build/events.d.ts.map +1 -0
  16. package/build/events.js +11 -0
  17. package/build/events.js.map +1 -0
  18. package/build/index.d.ts +5 -0
  19. package/build/index.d.ts.map +1 -0
  20. package/build/index.js +5 -0
  21. package/build/index.js.map +1 -0
  22. package/build/types.d.ts +46 -0
  23. package/build/types.d.ts.map +1 -0
  24. package/build/types.js +2 -0
  25. package/build/types.js.map +1 -0
  26. package/expo-module.config.json +10 -0
  27. package/ios/DooPushAppDelegateSubscriber.swift +36 -0
  28. package/ios/DooPushReactNativeSDK.podspec +33 -0
  29. package/ios/DooPushReactNativeSDKModule.swift +134 -0
  30. package/package.json +48 -0
  31. package/plugin/build/android/withAndroid.d.ts +3 -0
  32. package/plugin/build/android/withAndroid.js +13 -0
  33. package/plugin/build/android/withAppBuildGradle.d.ts +3 -0
  34. package/plugin/build/android/withAppBuildGradle.js +43 -0
  35. package/plugin/build/android/withGoogleServices.d.ts +3 -0
  36. package/plugin/build/android/withGoogleServices.js +63 -0
  37. package/plugin/build/android/withRootBuildGradle.d.ts +7 -0
  38. package/plugin/build/android/withRootBuildGradle.js +25 -0
  39. package/plugin/build/index.d.ts +3 -0
  40. package/plugin/build/index.js +12 -0
  41. package/plugin/build/ios/withEntitlements.d.ts +6 -0
  42. package/plugin/build/ios/withEntitlements.js +14 -0
  43. package/plugin/build/ios/withIOS.d.ts +3 -0
  44. package/plugin/build/ios/withIOS.js +11 -0
  45. package/plugin/build/ios/withInfoPlist.d.ts +6 -0
  46. package/plugin/build/ios/withInfoPlist.js +19 -0
  47. package/plugin/build/schema.d.ts +78 -0
  48. package/plugin/build/schema.js +52 -0
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # DooPush React Native SDK
2
+
3
+ > **v0.1.1 alpha** —— 最小 API surface,端到端真实可用。
4
+ > 仅支持 FCM (Android) + APNs (iOS)。OEM 通道、React Hooks 在 v0.5.0 beta。
5
+
6
+ [DooPush](https://doopush.com) 推送通知服务的 React Native SDK。基于 Expo Modules API 实现,可在 Expo(managed / prebuild)和 bare React Native 项目里使用。
7
+
8
+ ## v0.1.x alpha 提供什么
9
+
10
+ - ✅ `DooPush.configure(config)`
11
+ - ✅ `DooPush.register()` —— iOS APNs / Android FCM 自动流程
12
+ - ✅ `DooPush.registerWithToken(token, vendor)` —— 调用方已经有 token 时(如配合 expo-notifications 共存)
13
+ - 🟡 `DooPush.getDeviceToken()` / `getDeviceId()` —— 当前都返回 `null`,原生 getter 还没暴露,v0.5.0 上线
14
+ - ✅ 事件监听:`addRegisterListener`、`addRegisterErrorListener`、`addMessageListener`
15
+ - ✅ Config 插件:FCM 厂商(google-services.json)、iOS entitlement
16
+ - ✅ Android Active 模式:DooPush 接管通知 UI;与 `expo-notifications` 通过广播 relay 共存(opt-in,JS bridge 在 v0.5.0)
17
+
18
+ ### v0.1 已知限制
19
+
20
+ - `register()` 返回 `{token, deviceId, vendor}`,但 Android 端 `deviceId` 当前是空字符串(服务端 deviceId 还没在 bridge 层捕获,v0.5.0 修)。`token` 和 `vendor` 字段是对的。
21
+ - `getDeviceToken()` / `getDeviceId()` 在 Android 上一直返回 `null`(底层 SDK 还没公开 getter)。
22
+
23
+ ## v0.1 不包含(v0.5.0+ 才有)
24
+
25
+ - React Hooks(`useDooPush`、`useDooPushToken`)
26
+ - OEM 通道(HMS / Honor / Xiaomi / OPPO / VIVO / Meizu)
27
+ - WebSocket gateway 的 JS API
28
+ - 统计 / 角标 / 通道相关的 JS API
29
+ - npm 发布(当前用 git tag)
30
+
31
+ ## 前置条件
32
+
33
+ - iOS 原生 SDK ≥ **1.1.1**(SPM tag `v1.1.1` of `doopush-ios-sdk`,或路径方式本地引用)
34
+ - Android 原生 SDK ≥ **1.1.0**(JitPack `com.github.doopush:doopush-android-sdk:v1.1.0`,或本地 mavenLocal)
35
+ - Expo SDK 50+(或 RN 0.73+ bare)。**新项目推荐 Expo SDK 54+**
36
+
37
+ ## 快速安装(公开发布后)
38
+
39
+ ```bash
40
+ npx expo install doopush-react-native-sdk
41
+ ```
42
+
43
+ > v0.1.x alpha **暂未发到 npm**,公开仓走 git tag:
44
+ > `npm install github:doopush/doopush-react-native-sdk#v0.1.1`
45
+
46
+ `app.json` 配 plugin:
47
+
48
+ ```json
49
+ {
50
+ "expo": {
51
+ "plugins": [
52
+ [
53
+ "doopush-react-native-sdk",
54
+ {
55
+ "appId": "your_app_id",
56
+ "apiKey": "your_api_key",
57
+ "baseURL": "https://doopush.com/api/v1",
58
+ "ios": { "mode": "production" },
59
+ "android": {
60
+ "vendors": {
61
+ "fcm": { "googleServicesFile": "./google-services.json" }
62
+ }
63
+ }
64
+ }
65
+ ]
66
+ ]
67
+ }
68
+ }
69
+ ```
70
+
71
+ ```bash
72
+ npx expo prebuild --clean
73
+ npx expo run:android # 或 run:ios
74
+ ```
75
+
76
+ ## 用法
77
+
78
+ ```tsx
79
+ import { useEffect, useState } from 'react';
80
+ import { DooPush, type DooPushMessage } from 'doopush-react-native-sdk';
81
+
82
+ export default function App() {
83
+ useEffect(() => {
84
+ DooPush.configure({
85
+ appId: 'your_app_id',
86
+ apiKey: 'your_api_key',
87
+ });
88
+ const sub = DooPush.addMessageListener((m: DooPushMessage) => {
89
+ console.log('收到推送', m);
90
+ });
91
+ return () => sub.remove();
92
+ }, []);
93
+
94
+ const handleRegister = async () => {
95
+ try {
96
+ const { token, deviceId } = await DooPush.register();
97
+ console.log('注册成功', token, deviceId);
98
+ } catch (e) {
99
+ console.error('注册失败', e);
100
+ }
101
+ };
102
+
103
+ // ...
104
+ }
105
+ ```
106
+
107
+ ## 本地开发
108
+
109
+ 本包是 [doopush monorepo](https://github.com/doopush/doopush) 的一部分,跟 iOS / Android 原生 SDK 平级。本地开发流程:
110
+
111
+ ```bash
112
+ # 1) 编译 SDK
113
+ cd sdk/react-native/DooPushSDK
114
+ pnpm install
115
+ pnpm build
116
+ pnpm test # plugin Jest 测试
117
+
118
+ # 2) 用同级的 demo app 验证
119
+ cd ../DooPushSDKExample
120
+ npm install
121
+ npm install file:../DooPushSDK --install-links # 用拷贝替代 symlink,避开 Metro 解析坑
122
+ npx expo run:ios # 模拟器,或 --device "<设备名>"
123
+ npx expo run:android # 模拟器,或 --device <id>
124
+ ```
125
+
126
+ 详细的真机跑步骤、故障排查、Mac LAN IP 注入等见 `../DooPushSDKExample/README.md`。
127
+
128
+ 仓库结构跟 iOS / Android SDK 对齐:
129
+
130
+ ```
131
+ sdk/react-native/
132
+ ├── DooPushSDK/ ← SDK 源(npm 包 doopush-react-native-sdk)
133
+ │ ├── src/ # JS API 层
134
+ │ ├── plugin/ # Expo config plugin(编译期 native 配置注入)
135
+ │ ├── ios/ # iOS 原生 bridge + AppDelegate subscriber
136
+ │ └── android/ # Android 原生 bridge
137
+ └── DooPushSDKExample/ ← 用 SDK 的 demo(与 iOS/Android example 平级)
138
+ ```
139
+
140
+ ## 与第三方共存
141
+
142
+ ### 与 `expo-notifications`
143
+
144
+ 默认兼容。iOS 上 DooPush 接管 `UNUserNotificationCenterDelegate` 但走 delegate-forwarding,`expo-notifications` 的监听依然能收到。Android 上 DooPush 接管 `FirebaseMessagingService`,如果你也想让 `expo-notifications` 收到 FCM 消息,调(v0.5.0+):
145
+
146
+ ```ts
147
+ DooPush.setExpoNotificationRelayEnabled(true);
148
+ ```
149
+
150
+ ### 与 `@react-native-firebase/messaging`
151
+
152
+ **二选一** —— 两个库都声明 `FirebaseMessagingService`,manifest merger 只能留一个。如果你已经在用 `react-native-firebase`,就在 DooPush plugin 里**省略 fcm 厂商**,用 `react-native-firebase` 拿 token 后再交给 DooPush:
153
+
154
+ ```ts
155
+ import messaging from '@react-native-firebase/messaging';
156
+ import { DooPush } from 'doopush-react-native-sdk';
157
+
158
+ const token = await messaging().getToken();
159
+ const { deviceId } = await DooPush.registerWithToken(token, 'fcm');
160
+ ```
161
+
162
+ ## License
163
+
164
+ MIT
165
+
166
+ ## CHANGELOG
167
+
168
+ ### v0.1.2
169
+ - **chore**:发版流水线连通性测试(无功能变更)。验证 monorepo `sync-rn-sdk.yml` → `doopush-react-native-sdk` 公仓 → `auto-publish-release.yml` → GitHub Release + npm publish 全链路。dist-tag 应解析为 `alpha`(0.1.x ≤ 0.4.x)。
170
+
171
+ ### v0.1.1
172
+ - **修复 (iOS)**:通过 `ExpoAppDelegateSubscriber` 转发 APNs delegate 回调。在此之前,Expo 应用里 AppDelegate 拿到 device token 后没通路回 `DooPushManager.shared.didRegisterForRemoteNotifications(with:)`,导致 `DooPush.register()` 在用户授权后**永远 hang**。新增 `DooPushAppDelegateSubscriber`,并在 `expo-module.config.json` 里注册(autolinking 把它写进 `ExpoModulesProvider`)。同时转发 `didFailToRegister` 与 `didReceiveRemoteNotification:fetchCompletionHandler:`。
173
+ - **依赖底座**:iOS 原生 SDK 升级到 v1.1.1(podspec 兼容性修复,移除自定义 module_map / 不存在的 LICENSE 引用 / 多余的 public_header_files)。
174
+ - **结构整理**:删除嵌套的 `DooPushSDK/example/` workspace,demo 移到同级的 `sdk/react-native/DooPushSDKExample/`,跟 iOS/Android example 对齐。
175
+
176
+ ### v0.1.0
177
+ - 首个 alpha。`configure`、`register`、`registerWithToken`、消息 / 注册监听器。仅 iOS APNs(active 模式)+ Android FCM。Config plugin 注入 FCM google-services。
@@ -0,0 +1,54 @@
1
+ apply plugin: 'com.android.library'
2
+ apply plugin: 'kotlin-android'
3
+
4
+ group = 'com.doopush.reactnative'
5
+ version = '0.1.0'
6
+
7
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
8
+ apply from: expoModulesCorePlugin
9
+ applyKotlinExpoModulesCorePlugin()
10
+ useCoreDependencies()
11
+ useExpoPublishing()
12
+
13
+ android {
14
+ namespace 'com.doopush.reactnative'
15
+ compileSdkVersion safeExtGet("compileSdkVersion", 34)
16
+
17
+ defaultConfig {
18
+ minSdkVersion safeExtGet("minSdkVersion", 26)
19
+ targetSdkVersion safeExtGet("targetSdkVersion", 34)
20
+ versionCode 1
21
+ versionName "0.1.0"
22
+ }
23
+
24
+ compileOptions {
25
+ sourceCompatibility JavaVersion.VERSION_1_8
26
+ targetCompatibility JavaVersion.VERSION_1_8
27
+ }
28
+ kotlinOptions {
29
+ jvmTarget = '1.8'
30
+ }
31
+ }
32
+
33
+ repositories {
34
+ mavenCentral()
35
+ google()
36
+ // JitPack for the published Android SDK.
37
+ maven { url 'https://jitpack.io' }
38
+ mavenLocal() // for local DooPush SDK during dev
39
+ }
40
+
41
+ dependencies {
42
+ // DooPush native Android SDK v1.1.0+
43
+ // During v0.1 alpha dev: rely on mavenLocal (./gradlew :lib:publishToMavenLocal in sdk/android/DooPushSDK).
44
+ // Once published, this resolves from JitPack via the maven{} block above.
45
+ implementation 'com.github.doopush:doopush-android-sdk:1.1.+'
46
+
47
+ // FCM (transitive via DooPush AAR's runtime deps for FCM, but explicit here for clarity).
48
+ implementation platform('com.google.firebase:firebase-bom:32.7.0')
49
+ implementation 'com.google.firebase:firebase-messaging-ktx'
50
+ }
51
+
52
+ def safeExtGet(prop, fallback) {
53
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
54
+ }
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,146 @@
1
+ package com.doopush.reactnative
2
+
3
+ import com.doopush.sdk.DooPushCallback
4
+ import com.doopush.sdk.DooPushManager
5
+ import com.doopush.sdk.DooPushNotificationHandler
6
+ import com.doopush.sdk.DooPushRegisterCallback
7
+ import com.doopush.sdk.models.DooPushError
8
+ import com.doopush.sdk.models.PushMessage
9
+ import expo.modules.kotlin.Promise
10
+ import expo.modules.kotlin.modules.Module
11
+ import expo.modules.kotlin.modules.ModuleDefinition
12
+
13
+ /**
14
+ * DooPush React Native SDK — Android bridge
15
+ * v0.1.0 alpha
16
+ *
17
+ * Mode: ACTIVE (default) — DooPush owns FCM display via DooPushFirebaseMessagingService.
18
+ * Coexistence with expo-notifications/react-native-firebase is via the relay broadcast
19
+ * (opt-in by host app calling setExpoNotificationRelayEnabled(true) from JS — not exposed in v0.1).
20
+ */
21
+ class DooPushReactNativeSDKModule : Module(), DooPushCallback {
22
+
23
+ override fun definition() = ModuleDefinition {
24
+ Name("DooPushReactNativeSDK")
25
+
26
+ Events("onRegister", "onRegisterError", "onMessage")
27
+
28
+ OnCreate {
29
+ DooPushManager.getInstance().setCallback(this@DooPushReactNativeSDKModule)
30
+ }
31
+
32
+ // ── configure ───────────────────────────────────────────────────
33
+ Function("configure") { config: Map<String, Any> ->
34
+ val appId = config["appId"] as? String
35
+ ?: throw IllegalArgumentException("configure requires appId")
36
+ val apiKey = config["apiKey"] as? String
37
+ ?: throw IllegalArgumentException("configure requires apiKey")
38
+ val baseURL = config["baseURL"] as? String
39
+ val context = appContext.reactContext
40
+ ?: throw IllegalStateException("React context unavailable")
41
+ if (baseURL.isNullOrBlank()) {
42
+ DooPushManager.getInstance().configure(context, appId, apiKey)
43
+ } else {
44
+ DooPushManager.getInstance().configure(context, appId, apiKey, baseURL)
45
+ }
46
+ }
47
+
48
+ // ── register ────────────────────────────────────────────────────
49
+ AsyncFunction("register") { promise: Promise ->
50
+ DooPushManager.getInstance().registerForPushNotifications(
51
+ object : DooPushRegisterCallback {
52
+ override fun onSuccess(token: String) {
53
+ promise.resolve(mapOf(
54
+ "token" to token,
55
+ "deviceId" to (DooPushManager.getInstance().run {
56
+ // Try to read deviceId via reflection / public getter; v1.1.0 doesn't expose
57
+ // a public getDeviceId(), so we fall back to empty string for v0.1.0.
58
+ // TODO P3: expose getDeviceId() on Android Manager parity with iOS.
59
+ ""
60
+ }),
61
+ "vendor" to currentVendor()
62
+ ))
63
+ }
64
+ override fun onError(error: DooPushError) {
65
+ promise.reject("E_REGISTER", error.message ?: "register failed", null)
66
+ }
67
+ }
68
+ )
69
+ }
70
+
71
+ // ── registerWithToken ───────────────────────────────────────────
72
+ AsyncFunction("registerWithToken") { token: String, vendor: String, promise: Promise ->
73
+ DooPushManager.getInstance().registerDevice(
74
+ token = token,
75
+ vendor = vendor,
76
+ callback = object : DooPushRegisterCallback {
77
+ override fun onSuccess(t: String) {
78
+ promise.resolve(mapOf("deviceId" to "")) // TODO P3: real deviceId
79
+ }
80
+ override fun onError(error: DooPushError) {
81
+ promise.reject("E_REGISTER", error.message ?: "register failed", null)
82
+ }
83
+ }
84
+ )
85
+ }
86
+
87
+ // ── token getters ───────────────────────────────────────────────
88
+ AsyncFunction("getDeviceToken") { ->
89
+ // Android SDK v1.1.0 doesn't expose a public getDeviceToken() — return null in v0.1.
90
+ // TODO P3: add public getter on Android Manager and wire here.
91
+ null as String?
92
+ }
93
+
94
+ AsyncFunction("getDeviceId") { ->
95
+ null as String? // same TODO
96
+ }
97
+ }
98
+
99
+ // MARK: - DooPushCallback
100
+
101
+ override fun onRegisterSuccess(token: String) {
102
+ sendEvent("onRegister", mapOf(
103
+ "token" to token,
104
+ "deviceId" to "", // TODO P3
105
+ "vendor" to currentVendor()
106
+ ))
107
+ }
108
+
109
+ override fun onRegisterError(error: DooPushError) {
110
+ sendEvent("onRegisterError", mapOf(
111
+ "code" to "E_REGISTER",
112
+ "message" to (error.message ?: "register failed")
113
+ ))
114
+ }
115
+
116
+ override fun onMessageReceived(message: PushMessage) {
117
+ sendEvent("onMessage", mapOf(
118
+ "vendor" to currentVendor(),
119
+ "title" to message.getDisplayTitle(),
120
+ "body" to message.getDisplayBody(),
121
+ "pushLogId" to message.pushLogId,
122
+ "dedupKey" to message.dedupKey,
123
+ "messageId" to message.messageId,
124
+ "data" to message.data
125
+ ))
126
+ }
127
+
128
+ // The DooPushCallback interface (v1.1.0) has additional non-default abstract methods
129
+ // that the plan code didn't list. Implement them as no-ops for v0.1.0 — surfacing
130
+ // direct token-fetch results to JS isn't part of the v0.1 surface (the JS layer only
131
+ // consumes onRegister/onRegisterError/onMessage). v0.5.0 may surface these.
132
+ override fun onTokenReceived(token: String) {
133
+ // No-op: not surfaced in v0.1.0.
134
+ }
135
+
136
+ override fun onTokenError(error: DooPushError) {
137
+ // No-op: not surfaced in v0.1.0.
138
+ }
139
+
140
+ override fun onNotificationClick(notificationData: DooPushNotificationHandler.NotificationData) {
141
+ // v0.5.0 will surface this as onNotificationClick. For v0.1, ignored.
142
+ }
143
+
144
+ /** Best-effort vendor inference for v0.1 (default fcm). v0.5.0 will read from active vendor state. */
145
+ private fun currentVendor(): String = "fcm"
146
+ }
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/build');
@@ -0,0 +1,40 @@
1
+ import { Subscription } from 'expo-modules-core';
2
+ import type { DooPushConfig, DooPushVendor, DooPushMessage } from './types';
3
+ import type { OnRegisterEvent, OnRegisterErrorEvent } from './events';
4
+ /**
5
+ * DooPush React Native SDK — imperative API
6
+ *
7
+ * v0.1.0 alpha — minimal surface: configure / register / token getters / event listeners
8
+ */
9
+ /**
10
+ * Configure the SDK. Call once per app launch, ideally in App entry point.
11
+ * Idempotent — calling again replaces the prior config.
12
+ */
13
+ export declare function configure(config: DooPushConfig): void;
14
+ /**
15
+ * Register for push notifications. Triggers permission request (iOS) and
16
+ * token retrieval, then registers the device with DooPush server.
17
+ *
18
+ * Returns the device token + DooPush deviceId on success.
19
+ * Rejects if user denies permission or network fails.
20
+ */
21
+ export declare function register(): Promise<{
22
+ token: string;
23
+ deviceId: string;
24
+ vendor: DooPushVendor;
25
+ }>;
26
+ /**
27
+ * Register with a token already obtained externally (e.g. via expo-notifications
28
+ * `getDevicePushTokenAsync()`). Skips SDK's internal permission/token flow.
29
+ */
30
+ export declare function registerWithToken(token: string, vendor?: DooPushVendor): Promise<{
31
+ deviceId: string;
32
+ }>;
33
+ /** Returns current device token (after register success), or null. */
34
+ export declare function getDeviceToken(): Promise<string | null>;
35
+ /** Returns DooPush server-assigned deviceId (after register success), or null. */
36
+ export declare function getDeviceId(): Promise<string | null>;
37
+ export declare function addRegisterListener(listener: (e: OnRegisterEvent) => void): Subscription;
38
+ export declare function addRegisterErrorListener(listener: (e: OnRegisterErrorEvent) => void): Subscription;
39
+ export declare function addMessageListener(listener: (msg: DooPushMessage) => void): Subscription;
40
+ //# sourceMappingURL=DooPush.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DooPush.d.ts","sourceRoot":"","sources":["../src/DooPush.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC,CAED;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,aAAqB,GAC5B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAE/B;AAED,sEAAsE;AACtE,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEvD;AAED,kFAAkF;AAClF,wBAAgB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEpD;AAID,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,IAAI,GACrC,YAAY,CAEd;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,CAAC,CAAC,EAAE,oBAAoB,KAAK,IAAI,GAC1C,YAAY,CAEd;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GACtC,YAAY,CAEd"}
@@ -0,0 +1,49 @@
1
+ import { DooPushModule } from './DooPushModule';
2
+ /**
3
+ * DooPush React Native SDK — imperative API
4
+ *
5
+ * v0.1.0 alpha — minimal surface: configure / register / token getters / event listeners
6
+ */
7
+ /**
8
+ * Configure the SDK. Call once per app launch, ideally in App entry point.
9
+ * Idempotent — calling again replaces the prior config.
10
+ */
11
+ export function configure(config) {
12
+ DooPushModule.configure(config);
13
+ }
14
+ /**
15
+ * Register for push notifications. Triggers permission request (iOS) and
16
+ * token retrieval, then registers the device with DooPush server.
17
+ *
18
+ * Returns the device token + DooPush deviceId on success.
19
+ * Rejects if user denies permission or network fails.
20
+ */
21
+ export function register() {
22
+ return DooPushModule.register();
23
+ }
24
+ /**
25
+ * Register with a token already obtained externally (e.g. via expo-notifications
26
+ * `getDevicePushTokenAsync()`). Skips SDK's internal permission/token flow.
27
+ */
28
+ export function registerWithToken(token, vendor = 'fcm') {
29
+ return DooPushModule.registerWithToken(token, vendor);
30
+ }
31
+ /** Returns current device token (after register success), or null. */
32
+ export function getDeviceToken() {
33
+ return DooPushModule.getDeviceToken();
34
+ }
35
+ /** Returns DooPush server-assigned deviceId (after register success), or null. */
36
+ export function getDeviceId() {
37
+ return DooPushModule.getDeviceId();
38
+ }
39
+ // ── Event subscriptions ──────────────────────────────────────────────────
40
+ export function addRegisterListener(listener) {
41
+ return DooPushModule.addListener('onRegister', listener);
42
+ }
43
+ export function addRegisterErrorListener(listener) {
44
+ return DooPushModule.addListener('onRegisterError', listener);
45
+ }
46
+ export function addMessageListener(listener) {
47
+ return DooPushModule.addListener('onMessage', listener);
48
+ }
49
+ //# sourceMappingURL=DooPush.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DooPush.js","sourceRoot":"","sources":["../src/DooPush.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWhD;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAAqB;IAC7C,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IAKtB,OAAO,aAAa,CAAC,QAAQ,EAAE,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,SAAwB,KAAK;IAE7B,OAAO,aAAa,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,cAAc;IAC5B,OAAO,aAAa,CAAC,cAAc,EAAE,CAAC;AACxC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,WAAW;IACzB,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC;AAED,4EAA4E;AAE5E,MAAM,UAAU,mBAAmB,CACjC,QAAsC;IAEtC,OAAO,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,QAA2C;IAE3C,OAAO,aAAa,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,QAAuC;IAEvC,OAAO,aAAa,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import { Subscription } from 'expo-modules-core';\nimport { DooPushModule } from './DooPushModule';\nimport type {\n DooPushConfig,\n DooPushVendor,\n DooPushMessage,\n} from './types';\nimport type {\n OnRegisterEvent,\n OnRegisterErrorEvent,\n} from './events';\n\n/**\n * DooPush React Native SDK — imperative API\n *\n * v0.1.0 alpha — minimal surface: configure / register / token getters / event listeners\n */\n\n/**\n * Configure the SDK. Call once per app launch, ideally in App entry point.\n * Idempotent — calling again replaces the prior config.\n */\nexport function configure(config: DooPushConfig): void {\n DooPushModule.configure(config);\n}\n\n/**\n * Register for push notifications. Triggers permission request (iOS) and\n * token retrieval, then registers the device with DooPush server.\n *\n * Returns the device token + DooPush deviceId on success.\n * Rejects if user denies permission or network fails.\n */\nexport function register(): Promise<{\n token: string;\n deviceId: string;\n vendor: DooPushVendor;\n}> {\n return DooPushModule.register();\n}\n\n/**\n * Register with a token already obtained externally (e.g. via expo-notifications\n * `getDevicePushTokenAsync()`). Skips SDK's internal permission/token flow.\n */\nexport function registerWithToken(\n token: string,\n vendor: DooPushVendor = 'fcm'\n): Promise<{ deviceId: string }> {\n return DooPushModule.registerWithToken(token, vendor);\n}\n\n/** Returns current device token (after register success), or null. */\nexport function getDeviceToken(): Promise<string | null> {\n return DooPushModule.getDeviceToken();\n}\n\n/** Returns DooPush server-assigned deviceId (after register success), or null. */\nexport function getDeviceId(): Promise<string | null> {\n return DooPushModule.getDeviceId();\n}\n\n// ── Event subscriptions ──────────────────────────────────────────────────\n\nexport function addRegisterListener(\n listener: (e: OnRegisterEvent) => void\n): Subscription {\n return DooPushModule.addListener('onRegister', listener);\n}\n\nexport function addRegisterErrorListener(\n listener: (e: OnRegisterErrorEvent) => void\n): Subscription {\n return DooPushModule.addListener('onRegisterError', listener);\n}\n\nexport function addMessageListener(\n listener: (msg: DooPushMessage) => void\n): Subscription {\n return DooPushModule.addListener('onMessage', listener);\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Raw native module accessor.
3
+ * DO NOT use directly in app code — use the `DooPush` namespace in `./DooPush`.
4
+ * Exposed for testing and for advanced consumers (e.g. RN bridge wrappers).
5
+ */
6
+ export declare const DooPushModule: any;
7
+ //# sourceMappingURL=DooPushModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DooPushModule.d.ts","sourceRoot":"","sources":["../src/DooPushModule.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,aAAa,KAA+C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ /**
3
+ * Raw native module accessor.
4
+ * DO NOT use directly in app code — use the `DooPush` namespace in `./DooPush`.
5
+ * Exposed for testing and for advanced consumers (e.g. RN bridge wrappers).
6
+ */
7
+ export const DooPushModule = requireNativeModule('DooPushReactNativeSDK');
8
+ //# sourceMappingURL=DooPushModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DooPushModule.js","sourceRoot":"","sources":["../src/DooPushModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAC,uBAAuB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\n/**\n * Raw native module accessor.\n * DO NOT use directly in app code — use the `DooPush` namespace in `./DooPush`.\n * Exposed for testing and for advanced consumers (e.g. RN bridge wrappers).\n */\nexport const DooPushModule = requireNativeModule('DooPushReactNativeSDK');\n"]}
@@ -0,0 +1,23 @@
1
+ import type { DooPushVendor, DooPushMessage } from './types';
2
+ /**
3
+ * Event names emitted by the native module.
4
+ * v0.1.0 alpha: register / message events only.
5
+ * v0.5.0 will add: gateway / click / present.
6
+ */
7
+ export declare const EVENT_NAMES: readonly ["onRegister", "onRegisterError", "onMessage"];
8
+ export type EventName = (typeof EVENT_NAMES)[number];
9
+ export interface OnRegisterEvent {
10
+ token: string;
11
+ deviceId: string;
12
+ vendor: DooPushVendor;
13
+ }
14
+ export interface OnRegisterErrorEvent {
15
+ code: string;
16
+ message: string;
17
+ }
18
+ export interface EventPayloadMap {
19
+ onRegister: OnRegisterEvent;
20
+ onRegisterError: OnRegisterErrorEvent;
21
+ onMessage: DooPushMessage;
22
+ }
23
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,SAAS,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,WAAW,yDAId,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,eAAe,CAAC;IAC5B,eAAe,EAAE,oBAAoB,CAAC;IACtC,SAAS,EAAE,cAAc,CAAC;CAC3B"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Event names emitted by the native module.
3
+ * v0.1.0 alpha: register / message events only.
4
+ * v0.5.0 will add: gateway / click / present.
5
+ */
6
+ export const EVENT_NAMES = [
7
+ 'onRegister',
8
+ 'onRegisterError',
9
+ 'onMessage',
10
+ ];
11
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY;IACZ,iBAAiB;IACjB,WAAW;CACH,CAAC","sourcesContent":["import type { DooPushVendor, DooPushMessage, DooPushError } from './types';\n\n/**\n * Event names emitted by the native module.\n * v0.1.0 alpha: register / message events only.\n * v0.5.0 will add: gateway / click / present.\n */\nexport const EVENT_NAMES = [\n 'onRegister',\n 'onRegisterError',\n 'onMessage',\n] as const;\nexport type EventName = (typeof EVENT_NAMES)[number];\n\nexport interface OnRegisterEvent {\n token: string;\n deviceId: string;\n vendor: DooPushVendor;\n}\n\nexport interface OnRegisterErrorEvent {\n code: string;\n message: string;\n}\n\n// Map event name → payload type. Used by typed addListener helpers.\nexport interface EventPayloadMap {\n onRegister: OnRegisterEvent;\n onRegisterError: OnRegisterErrorEvent;\n onMessage: DooPushMessage;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export * as DooPush from './DooPush';
2
+ export * from './types';
3
+ export type { OnRegisterEvent, OnRegisterErrorEvent, EventName, } from './events';
4
+ export { DooPushModule } from './DooPushModule';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AACrC,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import * as DooPush_1 from './DooPush';
2
+ export { DooPush_1 as DooPush };
3
+ export * from './types';
4
+ export { DooPushModule } from './DooPushModule';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"2BAAyB,WAAW;sBAAxB,OAAO;AACnB,cAAc,SAAS,CAAC;AAMxB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export * as DooPush from './DooPush';\nexport * from './types';\nexport type {\n OnRegisterEvent,\n OnRegisterErrorEvent,\n EventName,\n} from './events';\nexport { DooPushModule } from './DooPushModule';\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Vendor channel identifier — must match server-side device.channel field.
3
+ * v0.1.0 alpha only validates "apns" / "fcm"; OEM channels added in v0.5.0.
4
+ */
5
+ export type DooPushVendor = 'apns' | 'fcm' | 'hms' | 'honor' | 'xiaomi' | 'oppo' | 'vivo' | 'meizu';
6
+ export type DooPushLogLevel = 'debug' | 'info' | 'warning' | 'error' | 'off';
7
+ export interface DooPushConfig {
8
+ /** DooPush platform appId (assigned by server) */
9
+ appId: string;
10
+ /** DooPush platform apiKey (assigned by server) */
11
+ apiKey: string;
12
+ /** API base URL. Defaults to https://doopush.com/api/v1 if omitted. */
13
+ baseURL?: string;
14
+ /** Log level for native SDK side. */
15
+ log?: DooPushLogLevel;
16
+ }
17
+ /**
18
+ * Push message payload as observed at the JS layer.
19
+ * Fields are union-of-best-effort across iOS APNs and Android FCM/OEM.
20
+ */
21
+ export interface DooPushMessage {
22
+ /** Vendor that delivered this message */
23
+ vendor?: DooPushVendor;
24
+ /** Notification title (if push has notification block) */
25
+ title?: string;
26
+ /** Notification body */
27
+ body?: string;
28
+ /** Server-side push log id (if present in payload) */
29
+ pushLogId?: string;
30
+ /** Server-side dedup key (if present) */
31
+ dedupKey?: string;
32
+ /** Vendor-specific message id (FCM messageId / APNs apns-id / etc.) */
33
+ messageId?: string;
34
+ /** Original full data payload as a flat string-keyed map */
35
+ data: Record<string, string>;
36
+ }
37
+ /**
38
+ * Errors surfaced to JS from native bridge.
39
+ * `code` matches the native DooPushError integer code stringified, plus human-readable form.
40
+ */
41
+ export interface DooPushError {
42
+ code: string;
43
+ message: string;
44
+ vendor?: DooPushVendor;
45
+ }
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,KAAK,GACL,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAE7E,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,GAAG,CAAC,EAAE,eAAe,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB"}
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Vendor channel identifier — must match server-side device.channel field.\n * v0.1.0 alpha only validates \"apns\" / \"fcm\"; OEM channels added in v0.5.0.\n */\nexport type DooPushVendor =\n | 'apns'\n | 'fcm'\n | 'hms'\n | 'honor'\n | 'xiaomi'\n | 'oppo'\n | 'vivo'\n | 'meizu';\n\nexport type DooPushLogLevel = 'debug' | 'info' | 'warning' | 'error' | 'off';\n\nexport interface DooPushConfig {\n /** DooPush platform appId (assigned by server) */\n appId: string;\n /** DooPush platform apiKey (assigned by server) */\n apiKey: string;\n /** API base URL. Defaults to https://doopush.com/api/v1 if omitted. */\n baseURL?: string;\n /** Log level for native SDK side. */\n log?: DooPushLogLevel;\n}\n\n/**\n * Push message payload as observed at the JS layer.\n * Fields are union-of-best-effort across iOS APNs and Android FCM/OEM.\n */\nexport interface DooPushMessage {\n /** Vendor that delivered this message */\n vendor?: DooPushVendor;\n /** Notification title (if push has notification block) */\n title?: string;\n /** Notification body */\n body?: string;\n /** Server-side push log id (if present in payload) */\n pushLogId?: string;\n /** Server-side dedup key (if present) */\n dedupKey?: string;\n /** Vendor-specific message id (FCM messageId / APNs apns-id / etc.) */\n messageId?: string;\n /** Original full data payload as a flat string-keyed map */\n data: Record<string, string>;\n}\n\n/**\n * Errors surfaced to JS from native bridge.\n * `code` matches the native DooPushError integer code stringified, plus human-readable form.\n */\nexport interface DooPushError {\n code: string;\n message: string;\n vendor?: DooPushVendor;\n}\n"]}