@fanapps/react-native 0.3.1 → 0.4.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 +65 -21
- package/dist/apple.d.mts +5 -0
- package/dist/apple.d.ts +5 -0
- package/dist/apple.js +73 -0
- package/dist/apple.js.map +1 -0
- package/dist/apple.mjs +38 -0
- package/dist/apple.mjs.map +1 -0
- package/dist/google.d.mts +5 -0
- package/dist/google.d.ts +5 -0
- package/dist/google.js +52 -0
- package/dist/google.js.map +1 -0
- package/dist/google.mjs +17 -0
- package/dist/google.mjs.map +1 -0
- package/dist/index.d.mts +29 -26
- package/dist/index.d.ts +29 -26
- package/dist/index.js +21 -234
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -229
- package/dist/index.mjs.map +1 -1
- package/dist/push.d.mts +21 -0
- package/dist/push.d.ts +21 -0
- package/dist/push.js +199 -0
- package/dist/push.js.map +1 -0
- package/dist/push.mjs +161 -0
- package/dist/push.mjs.map +1 -0
- package/dist/storage-D6z5ScLn.d.mts +14 -0
- package/dist/storage-D6z5ScLn.d.ts +14 -0
- package/package.json +43 -8
package/dist/push.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/push/index.ts
|
|
31
|
+
var push_exports = {};
|
|
32
|
+
__export(push_exports, {
|
|
33
|
+
useRegisterDevice: () => useRegisterDevice,
|
|
34
|
+
useTopicSubscription: () => useTopicSubscription
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(push_exports);
|
|
37
|
+
|
|
38
|
+
// src/push/useRegisterDevice.ts
|
|
39
|
+
var import_react = require("react");
|
|
40
|
+
var import_react_native = require("react-native");
|
|
41
|
+
|
|
42
|
+
// src/push/messaging.ts
|
|
43
|
+
var import_messaging = __toESM(require("@react-native-firebase/messaging"));
|
|
44
|
+
var cached = null;
|
|
45
|
+
function firebaseMessaging() {
|
|
46
|
+
if (cached) return cached;
|
|
47
|
+
cached = (0, import_messaging.default)();
|
|
48
|
+
return cached;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/push/storage.ts
|
|
52
|
+
var import_async_storage = __toESM(require("@react-native-async-storage/async-storage"));
|
|
53
|
+
function resolveStorage(explicit) {
|
|
54
|
+
return explicit ?? import_async_storage.default;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/push/targetIdStore.ts
|
|
58
|
+
var KEY = "fanapps.pushTargetId";
|
|
59
|
+
var TargetIdStore = class {
|
|
60
|
+
constructor(storage) {
|
|
61
|
+
this.storage = storage;
|
|
62
|
+
}
|
|
63
|
+
get() {
|
|
64
|
+
return this.storage.getItem(KEY);
|
|
65
|
+
}
|
|
66
|
+
async set(id) {
|
|
67
|
+
await this.storage.setItem(KEY, id);
|
|
68
|
+
}
|
|
69
|
+
async clear() {
|
|
70
|
+
await this.storage.removeItem(KEY);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
function generateTargetId() {
|
|
74
|
+
const bytes = new Uint8Array(16);
|
|
75
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
76
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
77
|
+
} else {
|
|
78
|
+
for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
79
|
+
}
|
|
80
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/push/useRegisterDevice.ts
|
|
84
|
+
var import_react_native2 = require("@fanapps/react-native");
|
|
85
|
+
function useRegisterDevice() {
|
|
86
|
+
const { client, storage } = (0, import_react_native2.useFanapps)();
|
|
87
|
+
const [targetId, setTargetId] = (0, import_react.useState)(null);
|
|
88
|
+
const [token, setToken] = (0, import_react.useState)(null);
|
|
89
|
+
const [target, setTarget] = (0, import_react.useState)(null);
|
|
90
|
+
const [isRegistering, setIsRegistering] = (0, import_react.useState)(false);
|
|
91
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
92
|
+
const targetStoreRef = (0, import_react.useRef)(null);
|
|
93
|
+
if (!targetStoreRef.current) {
|
|
94
|
+
targetStoreRef.current = new TargetIdStore(resolveStorage(storage));
|
|
95
|
+
}
|
|
96
|
+
const targetStore = targetStoreRef.current;
|
|
97
|
+
const tokenRefreshUnsubRef = (0, import_react.useRef)(null);
|
|
98
|
+
(0, import_react.useEffect)(() => {
|
|
99
|
+
return () => {
|
|
100
|
+
tokenRefreshUnsubRef.current?.();
|
|
101
|
+
tokenRefreshUnsubRef.current = null;
|
|
102
|
+
};
|
|
103
|
+
}, []);
|
|
104
|
+
const register = (0, import_react.useCallback)(async () => {
|
|
105
|
+
setIsRegistering(true);
|
|
106
|
+
setError(null);
|
|
107
|
+
try {
|
|
108
|
+
const messaging = firebaseMessaging();
|
|
109
|
+
await messaging.requestPermission();
|
|
110
|
+
const fcmToken = await messaging.getToken();
|
|
111
|
+
setToken(fcmToken);
|
|
112
|
+
const existingId = await targetStore.get();
|
|
113
|
+
let result;
|
|
114
|
+
if (existingId) {
|
|
115
|
+
try {
|
|
116
|
+
result = await client.updatePushTarget(existingId, fcmToken);
|
|
117
|
+
} catch {
|
|
118
|
+
result = await client.createPushTarget({
|
|
119
|
+
targetId: existingId,
|
|
120
|
+
identifier: fcmToken,
|
|
121
|
+
osName: import_react_native.Platform.OS === "ios" ? "iOS" : "Android"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
const newId = generateTargetId();
|
|
126
|
+
result = await client.createPushTarget({
|
|
127
|
+
targetId: newId,
|
|
128
|
+
identifier: fcmToken,
|
|
129
|
+
osName: import_react_native.Platform.OS === "ios" ? "iOS" : "Android"
|
|
130
|
+
});
|
|
131
|
+
await targetStore.set(result.id);
|
|
132
|
+
}
|
|
133
|
+
setTargetId(result.id);
|
|
134
|
+
setTarget(result);
|
|
135
|
+
if (!tokenRefreshUnsubRef.current) {
|
|
136
|
+
tokenRefreshUnsubRef.current = messaging.onTokenRefresh(async (newToken) => {
|
|
137
|
+
try {
|
|
138
|
+
const id = await targetStore.get();
|
|
139
|
+
if (!id) return;
|
|
140
|
+
const updated = await client.updatePushTarget(id, newToken);
|
|
141
|
+
setToken(newToken);
|
|
142
|
+
setTarget(updated);
|
|
143
|
+
} catch (e) {
|
|
144
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
} catch (e) {
|
|
150
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
151
|
+
setError(err);
|
|
152
|
+
throw err;
|
|
153
|
+
} finally {
|
|
154
|
+
setIsRegistering(false);
|
|
155
|
+
}
|
|
156
|
+
}, [client, targetStore]);
|
|
157
|
+
const unregister = (0, import_react.useCallback)(async () => {
|
|
158
|
+
const id = await targetStore.get();
|
|
159
|
+
if (id) {
|
|
160
|
+
try {
|
|
161
|
+
await client.deletePushTarget(id);
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
await targetStore.clear();
|
|
165
|
+
}
|
|
166
|
+
tokenRefreshUnsubRef.current?.();
|
|
167
|
+
tokenRefreshUnsubRef.current = null;
|
|
168
|
+
setTargetId(null);
|
|
169
|
+
setToken(null);
|
|
170
|
+
setTarget(null);
|
|
171
|
+
}, [client, targetStore]);
|
|
172
|
+
return {
|
|
173
|
+
targetId,
|
|
174
|
+
token,
|
|
175
|
+
target,
|
|
176
|
+
isRegistering,
|
|
177
|
+
error,
|
|
178
|
+
register,
|
|
179
|
+
unregister
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/push/useTopicSubscription.ts
|
|
184
|
+
var import_react2 = require("react");
|
|
185
|
+
function useTopicSubscription() {
|
|
186
|
+
const subscribe = (0, import_react2.useCallback)(async (topic) => {
|
|
187
|
+
await firebaseMessaging().subscribeToTopic(topic);
|
|
188
|
+
}, []);
|
|
189
|
+
const unsubscribe = (0, import_react2.useCallback)(async (topic) => {
|
|
190
|
+
await firebaseMessaging().unsubscribeFromTopic(topic);
|
|
191
|
+
}, []);
|
|
192
|
+
return { subscribe, unsubscribe };
|
|
193
|
+
}
|
|
194
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
195
|
+
0 && (module.exports = {
|
|
196
|
+
useRegisterDevice,
|
|
197
|
+
useTopicSubscription
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=push.js.map
|
package/dist/push.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/push/index.ts","../src/push/useRegisterDevice.ts","../src/push/messaging.ts","../src/push/storage.ts","../src/push/targetIdStore.ts","../src/push/useTopicSubscription.ts"],"sourcesContent":["export {\n useRegisterDevice,\n type UseRegisterDeviceResult,\n} from './useRegisterDevice';\nexport {\n useTopicSubscription,\n type UseTopicSubscriptionResult,\n} from './useTopicSubscription';\nexport type { StorageAdapter } from './storage';\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { Platform } from 'react-native';\nimport { firebaseMessaging } from './messaging';\nimport { resolveStorage } from './storage';\nimport { generateTargetId, TargetIdStore } from './targetIdStore';\nimport { useFanapps, type PushTarget } from '@fanapps/react-native';\n\nexport interface UseRegisterDeviceResult {\n targetId: string | null;\n token: string | null;\n target: PushTarget | null;\n isRegistering: boolean;\n error: Error | null;\n register(): Promise<PushTarget>;\n unregister(): Promise<void>;\n}\n\nexport function useRegisterDevice(): UseRegisterDeviceResult {\n const { client, storage } = useFanapps();\n\n const [targetId, setTargetId] = useState<string | null>(null);\n const [token, setToken] = useState<string | null>(null);\n const [target, setTarget] = useState<PushTarget | null>(null);\n const [isRegistering, setIsRegistering] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const targetStoreRef = useRef<TargetIdStore | null>(null);\n if (!targetStoreRef.current) {\n targetStoreRef.current = new TargetIdStore(resolveStorage(storage));\n }\n const targetStore = targetStoreRef.current;\n\n const tokenRefreshUnsubRef = useRef<(() => void) | null>(null);\n\n useEffect(() => {\n return () => {\n tokenRefreshUnsubRef.current?.();\n tokenRefreshUnsubRef.current = null;\n };\n }, []);\n\n const register = useCallback(async (): Promise<PushTarget> => {\n setIsRegistering(true);\n setError(null);\n try {\n const messaging = firebaseMessaging();\n\n // Request permission (idempotent; no-op if already granted).\n await messaging.requestPermission();\n\n const fcmToken = await messaging.getToken();\n setToken(fcmToken);\n\n const existingId = await targetStore.get();\n\n let result: PushTarget;\n if (existingId) {\n try {\n result = await client.updatePushTarget(existingId, fcmToken);\n } catch {\n // If the stored target is gone (404), create a new one with the same id.\n result = await client.createPushTarget({\n targetId: existingId,\n identifier: fcmToken,\n osName: Platform.OS === 'ios' ? 'iOS' : 'Android',\n });\n }\n } else {\n const newId = generateTargetId();\n result = await client.createPushTarget({\n targetId: newId,\n identifier: fcmToken,\n osName: Platform.OS === 'ios' ? 'iOS' : 'Android',\n });\n await targetStore.set(result.id);\n }\n\n setTargetId(result.id);\n setTarget(result);\n\n // Subscribe to onTokenRefresh once.\n if (!tokenRefreshUnsubRef.current) {\n tokenRefreshUnsubRef.current = messaging.onTokenRefresh(async (newToken: string) => {\n try {\n const id = await targetStore.get();\n if (!id) return;\n const updated = await client.updatePushTarget(id, newToken);\n setToken(newToken);\n setTarget(updated);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n }\n });\n }\n\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setIsRegistering(false);\n }\n }, [client, targetStore]);\n\n const unregister = useCallback(async (): Promise<void> => {\n const id = await targetStore.get();\n if (id) {\n try {\n await client.deletePushTarget(id);\n } catch {\n // Swallow network/404; we still want to clear local state.\n }\n await targetStore.clear();\n }\n tokenRefreshUnsubRef.current?.();\n tokenRefreshUnsubRef.current = null;\n setTargetId(null);\n setToken(null);\n setTarget(null);\n }, [client, targetStore]);\n\n return {\n targetId,\n token,\n target,\n isRegistering,\n error,\n register,\n unregister,\n };\n}\n","import messagingImport, {\n type FirebaseMessagingTypes,\n} from '@react-native-firebase/messaging';\n\nlet cached: FirebaseMessagingTypes.Module | null = null;\n\nexport function firebaseMessaging(): FirebaseMessagingTypes.Module {\n if (cached) return cached;\n cached = messagingImport();\n return cached;\n}\n","import AsyncStorage from '@react-native-async-storage/async-storage';\nimport type { StorageAdapter } from '../storage';\n\nexport function resolveStorage(explicit?: StorageAdapter): StorageAdapter {\n return explicit ?? AsyncStorage;\n}\n\nexport type { StorageAdapter };\n","import type { StorageAdapter } from './storage';\n\nconst KEY = 'fanapps.pushTargetId';\n\nexport class TargetIdStore {\n constructor(private readonly storage: StorageAdapter) {}\n\n get(): Promise<string | null> {\n return this.storage.getItem(KEY);\n }\n\n async set(id: string): Promise<void> {\n await this.storage.setItem(KEY, id);\n }\n\n async clear(): Promise<void> {\n await this.storage.removeItem(KEY);\n }\n}\n\nexport function generateTargetId(): string {\n // 16 bytes of URL-safe hex — safely within Appwrite's 36-char, safe-char constraint.\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n","import { useCallback } from 'react';\nimport { firebaseMessaging } from './messaging';\n\nexport interface UseTopicSubscriptionResult {\n subscribe(topic: string): Promise<void>;\n unsubscribe(topic: string): Promise<void>;\n}\n\nexport function useTopicSubscription(): UseTopicSubscriptionResult {\n const subscribe = useCallback(async (topic: string) => {\n await firebaseMessaging().subscribeToTopic(topic);\n }, []);\n\n const unsubscribe = useCallback(async (topic: string) => {\n await firebaseMessaging().unsubscribeFromTopic(topic);\n }, []);\n\n return { subscribe, unsubscribe };\n}\n"],"mappings":"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","names":["messagingImport","AsyncStorage","import_react_native","import_react"]}
|
package/dist/push.mjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/push/useRegisterDevice.ts
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Platform } from "react-native";
|
|
4
|
+
|
|
5
|
+
// src/push/messaging.ts
|
|
6
|
+
import messagingImport from "@react-native-firebase/messaging";
|
|
7
|
+
var cached = null;
|
|
8
|
+
function firebaseMessaging() {
|
|
9
|
+
if (cached) return cached;
|
|
10
|
+
cached = messagingImport();
|
|
11
|
+
return cached;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/push/storage.ts
|
|
15
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
16
|
+
function resolveStorage(explicit) {
|
|
17
|
+
return explicit ?? AsyncStorage;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/push/targetIdStore.ts
|
|
21
|
+
var KEY = "fanapps.pushTargetId";
|
|
22
|
+
var TargetIdStore = class {
|
|
23
|
+
constructor(storage) {
|
|
24
|
+
this.storage = storage;
|
|
25
|
+
}
|
|
26
|
+
get() {
|
|
27
|
+
return this.storage.getItem(KEY);
|
|
28
|
+
}
|
|
29
|
+
async set(id) {
|
|
30
|
+
await this.storage.setItem(KEY, id);
|
|
31
|
+
}
|
|
32
|
+
async clear() {
|
|
33
|
+
await this.storage.removeItem(KEY);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
function generateTargetId() {
|
|
37
|
+
const bytes = new Uint8Array(16);
|
|
38
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
39
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
40
|
+
} else {
|
|
41
|
+
for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
42
|
+
}
|
|
43
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/push/useRegisterDevice.ts
|
|
47
|
+
import { useFanapps } from "@fanapps/react-native";
|
|
48
|
+
function useRegisterDevice() {
|
|
49
|
+
const { client, storage } = useFanapps();
|
|
50
|
+
const [targetId, setTargetId] = useState(null);
|
|
51
|
+
const [token, setToken] = useState(null);
|
|
52
|
+
const [target, setTarget] = useState(null);
|
|
53
|
+
const [isRegistering, setIsRegistering] = useState(false);
|
|
54
|
+
const [error, setError] = useState(null);
|
|
55
|
+
const targetStoreRef = useRef(null);
|
|
56
|
+
if (!targetStoreRef.current) {
|
|
57
|
+
targetStoreRef.current = new TargetIdStore(resolveStorage(storage));
|
|
58
|
+
}
|
|
59
|
+
const targetStore = targetStoreRef.current;
|
|
60
|
+
const tokenRefreshUnsubRef = useRef(null);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
return () => {
|
|
63
|
+
tokenRefreshUnsubRef.current?.();
|
|
64
|
+
tokenRefreshUnsubRef.current = null;
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
67
|
+
const register = useCallback(async () => {
|
|
68
|
+
setIsRegistering(true);
|
|
69
|
+
setError(null);
|
|
70
|
+
try {
|
|
71
|
+
const messaging = firebaseMessaging();
|
|
72
|
+
await messaging.requestPermission();
|
|
73
|
+
const fcmToken = await messaging.getToken();
|
|
74
|
+
setToken(fcmToken);
|
|
75
|
+
const existingId = await targetStore.get();
|
|
76
|
+
let result;
|
|
77
|
+
if (existingId) {
|
|
78
|
+
try {
|
|
79
|
+
result = await client.updatePushTarget(existingId, fcmToken);
|
|
80
|
+
} catch {
|
|
81
|
+
result = await client.createPushTarget({
|
|
82
|
+
targetId: existingId,
|
|
83
|
+
identifier: fcmToken,
|
|
84
|
+
osName: Platform.OS === "ios" ? "iOS" : "Android"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
const newId = generateTargetId();
|
|
89
|
+
result = await client.createPushTarget({
|
|
90
|
+
targetId: newId,
|
|
91
|
+
identifier: fcmToken,
|
|
92
|
+
osName: Platform.OS === "ios" ? "iOS" : "Android"
|
|
93
|
+
});
|
|
94
|
+
await targetStore.set(result.id);
|
|
95
|
+
}
|
|
96
|
+
setTargetId(result.id);
|
|
97
|
+
setTarget(result);
|
|
98
|
+
if (!tokenRefreshUnsubRef.current) {
|
|
99
|
+
tokenRefreshUnsubRef.current = messaging.onTokenRefresh(async (newToken) => {
|
|
100
|
+
try {
|
|
101
|
+
const id = await targetStore.get();
|
|
102
|
+
if (!id) return;
|
|
103
|
+
const updated = await client.updatePushTarget(id, newToken);
|
|
104
|
+
setToken(newToken);
|
|
105
|
+
setTarget(updated);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
} catch (e) {
|
|
113
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
114
|
+
setError(err);
|
|
115
|
+
throw err;
|
|
116
|
+
} finally {
|
|
117
|
+
setIsRegistering(false);
|
|
118
|
+
}
|
|
119
|
+
}, [client, targetStore]);
|
|
120
|
+
const unregister = useCallback(async () => {
|
|
121
|
+
const id = await targetStore.get();
|
|
122
|
+
if (id) {
|
|
123
|
+
try {
|
|
124
|
+
await client.deletePushTarget(id);
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
await targetStore.clear();
|
|
128
|
+
}
|
|
129
|
+
tokenRefreshUnsubRef.current?.();
|
|
130
|
+
tokenRefreshUnsubRef.current = null;
|
|
131
|
+
setTargetId(null);
|
|
132
|
+
setToken(null);
|
|
133
|
+
setTarget(null);
|
|
134
|
+
}, [client, targetStore]);
|
|
135
|
+
return {
|
|
136
|
+
targetId,
|
|
137
|
+
token,
|
|
138
|
+
target,
|
|
139
|
+
isRegistering,
|
|
140
|
+
error,
|
|
141
|
+
register,
|
|
142
|
+
unregister
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/push/useTopicSubscription.ts
|
|
147
|
+
import { useCallback as useCallback2 } from "react";
|
|
148
|
+
function useTopicSubscription() {
|
|
149
|
+
const subscribe = useCallback2(async (topic) => {
|
|
150
|
+
await firebaseMessaging().subscribeToTopic(topic);
|
|
151
|
+
}, []);
|
|
152
|
+
const unsubscribe = useCallback2(async (topic) => {
|
|
153
|
+
await firebaseMessaging().unsubscribeFromTopic(topic);
|
|
154
|
+
}, []);
|
|
155
|
+
return { subscribe, unsubscribe };
|
|
156
|
+
}
|
|
157
|
+
export {
|
|
158
|
+
useRegisterDevice,
|
|
159
|
+
useTopicSubscription
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=push.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/push/useRegisterDevice.ts","../src/push/messaging.ts","../src/push/storage.ts","../src/push/targetIdStore.ts","../src/push/useTopicSubscription.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { Platform } from 'react-native';\nimport { firebaseMessaging } from './messaging';\nimport { resolveStorage } from './storage';\nimport { generateTargetId, TargetIdStore } from './targetIdStore';\nimport { useFanapps, type PushTarget } from '@fanapps/react-native';\n\nexport interface UseRegisterDeviceResult {\n targetId: string | null;\n token: string | null;\n target: PushTarget | null;\n isRegistering: boolean;\n error: Error | null;\n register(): Promise<PushTarget>;\n unregister(): Promise<void>;\n}\n\nexport function useRegisterDevice(): UseRegisterDeviceResult {\n const { client, storage } = useFanapps();\n\n const [targetId, setTargetId] = useState<string | null>(null);\n const [token, setToken] = useState<string | null>(null);\n const [target, setTarget] = useState<PushTarget | null>(null);\n const [isRegistering, setIsRegistering] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const targetStoreRef = useRef<TargetIdStore | null>(null);\n if (!targetStoreRef.current) {\n targetStoreRef.current = new TargetIdStore(resolveStorage(storage));\n }\n const targetStore = targetStoreRef.current;\n\n const tokenRefreshUnsubRef = useRef<(() => void) | null>(null);\n\n useEffect(() => {\n return () => {\n tokenRefreshUnsubRef.current?.();\n tokenRefreshUnsubRef.current = null;\n };\n }, []);\n\n const register = useCallback(async (): Promise<PushTarget> => {\n setIsRegistering(true);\n setError(null);\n try {\n const messaging = firebaseMessaging();\n\n // Request permission (idempotent; no-op if already granted).\n await messaging.requestPermission();\n\n const fcmToken = await messaging.getToken();\n setToken(fcmToken);\n\n const existingId = await targetStore.get();\n\n let result: PushTarget;\n if (existingId) {\n try {\n result = await client.updatePushTarget(existingId, fcmToken);\n } catch {\n // If the stored target is gone (404), create a new one with the same id.\n result = await client.createPushTarget({\n targetId: existingId,\n identifier: fcmToken,\n osName: Platform.OS === 'ios' ? 'iOS' : 'Android',\n });\n }\n } else {\n const newId = generateTargetId();\n result = await client.createPushTarget({\n targetId: newId,\n identifier: fcmToken,\n osName: Platform.OS === 'ios' ? 'iOS' : 'Android',\n });\n await targetStore.set(result.id);\n }\n\n setTargetId(result.id);\n setTarget(result);\n\n // Subscribe to onTokenRefresh once.\n if (!tokenRefreshUnsubRef.current) {\n tokenRefreshUnsubRef.current = messaging.onTokenRefresh(async (newToken: string) => {\n try {\n const id = await targetStore.get();\n if (!id) return;\n const updated = await client.updatePushTarget(id, newToken);\n setToken(newToken);\n setTarget(updated);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n }\n });\n }\n\n return result;\n } catch (e) {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n } finally {\n setIsRegistering(false);\n }\n }, [client, targetStore]);\n\n const unregister = useCallback(async (): Promise<void> => {\n const id = await targetStore.get();\n if (id) {\n try {\n await client.deletePushTarget(id);\n } catch {\n // Swallow network/404; we still want to clear local state.\n }\n await targetStore.clear();\n }\n tokenRefreshUnsubRef.current?.();\n tokenRefreshUnsubRef.current = null;\n setTargetId(null);\n setToken(null);\n setTarget(null);\n }, [client, targetStore]);\n\n return {\n targetId,\n token,\n target,\n isRegistering,\n error,\n register,\n unregister,\n };\n}\n","import messagingImport, {\n type FirebaseMessagingTypes,\n} from '@react-native-firebase/messaging';\n\nlet cached: FirebaseMessagingTypes.Module | null = null;\n\nexport function firebaseMessaging(): FirebaseMessagingTypes.Module {\n if (cached) return cached;\n cached = messagingImport();\n return cached;\n}\n","import AsyncStorage from '@react-native-async-storage/async-storage';\nimport type { StorageAdapter } from '../storage';\n\nexport function resolveStorage(explicit?: StorageAdapter): StorageAdapter {\n return explicit ?? AsyncStorage;\n}\n\nexport type { StorageAdapter };\n","import type { StorageAdapter } from './storage';\n\nconst KEY = 'fanapps.pushTargetId';\n\nexport class TargetIdStore {\n constructor(private readonly storage: StorageAdapter) {}\n\n get(): Promise<string | null> {\n return this.storage.getItem(KEY);\n }\n\n async set(id: string): Promise<void> {\n await this.storage.setItem(KEY, id);\n }\n\n async clear(): Promise<void> {\n await this.storage.removeItem(KEY);\n }\n}\n\nexport function generateTargetId(): string {\n // 16 bytes of URL-safe hex — safely within Appwrite's 36-char, safe-char constraint.\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n","import { useCallback } from 'react';\nimport { firebaseMessaging } from './messaging';\n\nexport interface UseTopicSubscriptionResult {\n subscribe(topic: string): Promise<void>;\n unsubscribe(topic: string): Promise<void>;\n}\n\nexport function useTopicSubscription(): UseTopicSubscriptionResult {\n const subscribe = useCallback(async (topic: string) => {\n await firebaseMessaging().subscribeToTopic(topic);\n }, []);\n\n const unsubscribe = useCallback(async (topic: string) => {\n await firebaseMessaging().unsubscribeFromTopic(topic);\n }, []);\n\n return { subscribe, unsubscribe };\n}\n"],"mappings":"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","names":["useCallback","useCallback"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape for SDK persistent storage. Matches `@react-native-async-storage/async-storage`'s
|
|
3
|
+
* default-export interface so users can pass it through directly.
|
|
4
|
+
*
|
|
5
|
+
* The interface lives in the core entry (no implementation import) so consumers who don't
|
|
6
|
+
* use push features don't pull AsyncStorage into their bundle.
|
|
7
|
+
*/
|
|
8
|
+
interface StorageAdapter {
|
|
9
|
+
getItem(key: string): Promise<string | null>;
|
|
10
|
+
setItem(key: string, value: string): Promise<void>;
|
|
11
|
+
removeItem(key: string): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type { StorageAdapter as S };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape for SDK persistent storage. Matches `@react-native-async-storage/async-storage`'s
|
|
3
|
+
* default-export interface so users can pass it through directly.
|
|
4
|
+
*
|
|
5
|
+
* The interface lives in the core entry (no implementation import) so consumers who don't
|
|
6
|
+
* use push features don't pull AsyncStorage into their bundle.
|
|
7
|
+
*/
|
|
8
|
+
interface StorageAdapter {
|
|
9
|
+
getItem(key: string): Promise<string | null>;
|
|
10
|
+
setItem(key: string, value: string): Promise<void>;
|
|
11
|
+
removeItem(key: string): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type { StorageAdapter as S };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanapps/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "React Native SDK for the Fanapps API.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -12,6 +12,24 @@
|
|
|
12
12
|
"react-native": "./dist/index.js",
|
|
13
13
|
"import": "./dist/index.mjs",
|
|
14
14
|
"require": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./push": {
|
|
17
|
+
"types": "./dist/push.d.ts",
|
|
18
|
+
"react-native": "./dist/push.js",
|
|
19
|
+
"import": "./dist/push.mjs",
|
|
20
|
+
"require": "./dist/push.js"
|
|
21
|
+
},
|
|
22
|
+
"./google": {
|
|
23
|
+
"types": "./dist/google.d.ts",
|
|
24
|
+
"react-native": "./dist/google.js",
|
|
25
|
+
"import": "./dist/google.mjs",
|
|
26
|
+
"require": "./dist/google.js"
|
|
27
|
+
},
|
|
28
|
+
"./apple": {
|
|
29
|
+
"types": "./dist/apple.d.ts",
|
|
30
|
+
"react-native": "./dist/apple.js",
|
|
31
|
+
"import": "./dist/apple.mjs",
|
|
32
|
+
"require": "./dist/apple.js"
|
|
15
33
|
}
|
|
16
34
|
},
|
|
17
35
|
"files": [
|
|
@@ -23,21 +41,38 @@
|
|
|
23
41
|
"dev": "tsup --watch",
|
|
24
42
|
"typecheck": "tsc --noEmit"
|
|
25
43
|
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@invertase/react-native-apple-authentication": "^2.4.0",
|
|
28
|
-
"@react-native-async-storage/async-storage": "^1.24.0",
|
|
29
|
-
"@react-native-firebase/auth": "^23.8.8",
|
|
30
|
-
"@react-native-firebase/messaging": "^23.8.8",
|
|
31
|
-
"@react-native-google-signin/google-signin": "^13.0.0"
|
|
32
|
-
},
|
|
33
44
|
"peerDependencies": {
|
|
45
|
+
"@invertase/react-native-apple-authentication": ">=2",
|
|
46
|
+
"@react-native-async-storage/async-storage": ">=3.0.2",
|
|
34
47
|
"@react-native-firebase/app": ">=23",
|
|
48
|
+
"@react-native-firebase/auth": ">=23",
|
|
49
|
+
"@react-native-firebase/messaging": ">=23",
|
|
50
|
+
"@react-native-google-signin/google-signin": ">=16",
|
|
35
51
|
"@tanstack/react-query": ">=5",
|
|
36
52
|
"react": ">=18",
|
|
37
53
|
"react-native": ">=0.73"
|
|
38
54
|
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"@invertase/react-native-apple-authentication": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@react-native-async-storage/async-storage": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"@react-native-firebase/messaging": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"@react-native-google-signin/google-signin": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
39
69
|
"devDependencies": {
|
|
70
|
+
"@invertase/react-native-apple-authentication": "^2.5.1",
|
|
71
|
+
"@react-native-async-storage/async-storage": "^3.0.2",
|
|
40
72
|
"@react-native-firebase/app": "^23.8.8",
|
|
73
|
+
"@react-native-firebase/auth": "^23.8.8",
|
|
74
|
+
"@react-native-firebase/messaging": "^23.8.8",
|
|
75
|
+
"@react-native-google-signin/google-signin": "^16.0.0",
|
|
41
76
|
"@tanstack/react-query": "^5.0.0",
|
|
42
77
|
"@types/react": "^19.0.0",
|
|
43
78
|
"react": "^19.0.0",
|