mbnotify-app 1.0.0

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.
@@ -0,0 +1,16 @@
1
+ export interface NotificationPayload {
2
+ title?: string;
3
+ body?: string;
4
+ icon?: string;
5
+ image?: string;
6
+ url?: string;
7
+ data?: Record<string, any>;
8
+ }
9
+ /**
10
+ * Request notification permission (Expo)
11
+ */
12
+ export declare function requestPermission(): Promise<boolean>;
13
+ /**
14
+ * Subscribe to notifications and return token
15
+ */
16
+ export declare function getToken(appName: string, brokerUrl?: string): Promise<string>;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestPermission = requestPermission;
4
+ exports.getToken = getToken;
5
+ const mqtt_1 = require("mqtt");
6
+ const Notifications = require("expo-notifications");
7
+ const async_storage_1 = require("@react-native-async-storage/async-storage");
8
+ const DEFAULT_BROKER = "wss://broker.hivemq.com:8884/mqtt";
9
+ let client = null;
10
+ /**
11
+ * Request notification permission (Expo)
12
+ */
13
+ async function requestPermission() {
14
+ const { status } = await Notifications.requestPermissionsAsync();
15
+ return status === "granted";
16
+ }
17
+ /**
18
+ * Generate or retrieve device token
19
+ */
20
+ async function generateToken() {
21
+ let token = await async_storage_1.default.getItem("mbnotify_token");
22
+ if (!token) {
23
+ token =
24
+ "dev_" +
25
+ Math.random().toString(36).substring(2) +
26
+ Date.now().toString(36);
27
+ await async_storage_1.default.setItem("mbnotify_token", token);
28
+ }
29
+ return token;
30
+ }
31
+ /**
32
+ * Connect MQTT broker
33
+ */
34
+ function connectMQTT(brokerUrl) {
35
+ if (client)
36
+ return client;
37
+ client = mqtt_1.default.connect(brokerUrl, {
38
+ reconnectPeriod: 5000,
39
+ connectTimeout: 10000
40
+ });
41
+ client.on("connect", () => {
42
+ console.log("mbnotify app connected");
43
+ });
44
+ client.on("error", (err) => {
45
+ console.error("MQTT error:", err);
46
+ });
47
+ return client;
48
+ }
49
+ /**
50
+ * Show notification using Expo
51
+ */
52
+ async function showNotification(payload) {
53
+ await Notifications.scheduleNotificationAsync({
54
+ content: {
55
+ title: payload.title || "",
56
+ body: payload.body || "",
57
+ data: payload.data || {}
58
+ },
59
+ trigger: null
60
+ });
61
+ }
62
+ /**
63
+ * Subscribe to notifications and return token
64
+ */
65
+ async function getToken(appName, brokerUrl = DEFAULT_BROKER) {
66
+ if (!appName) {
67
+ throw new Error("appName required");
68
+ }
69
+ const token = await generateToken();
70
+ const topic = `/${appName}/${token}/notification`;
71
+ const mqttClient = connectMQTT(brokerUrl);
72
+ mqttClient.subscribe(topic);
73
+ console.log("Subscribed:", topic);
74
+ mqttClient.on("message", async (_, message) => {
75
+ try {
76
+ const payload = JSON.parse(message.toString());
77
+ await showNotification(payload);
78
+ }
79
+ catch (err) {
80
+ console.error("Invalid notification payload", err);
81
+ }
82
+ });
83
+ return token;
84
+ }
@@ -0,0 +1,16 @@
1
+ export interface NotificationPayload {
2
+ title?: string;
3
+ body?: string;
4
+ icon?: string;
5
+ image?: string;
6
+ url?: string;
7
+ data?: Record<string, any>;
8
+ }
9
+ /**
10
+ * Request notification permission (Expo)
11
+ */
12
+ export declare function requestPermission(): Promise<boolean>;
13
+ /**
14
+ * Subscribe to notifications and return token
15
+ */
16
+ export declare function getToken(appName: string, brokerUrl?: string): Promise<string>;
@@ -0,0 +1,80 @@
1
+ import mqtt from "mqtt";
2
+ import * as Notifications from "expo-notifications";
3
+ import AsyncStorage from "@react-native-async-storage/async-storage";
4
+ const DEFAULT_BROKER = "wss://broker.hivemq.com:8884/mqtt";
5
+ let client = null;
6
+ /**
7
+ * Request notification permission (Expo)
8
+ */
9
+ export async function requestPermission() {
10
+ const { status } = await Notifications.requestPermissionsAsync();
11
+ return status === "granted";
12
+ }
13
+ /**
14
+ * Generate or retrieve device token
15
+ */
16
+ async function generateToken() {
17
+ let token = await AsyncStorage.getItem("mbnotify_token");
18
+ if (!token) {
19
+ token =
20
+ "dev_" +
21
+ Math.random().toString(36).substring(2) +
22
+ Date.now().toString(36);
23
+ await AsyncStorage.setItem("mbnotify_token", token);
24
+ }
25
+ return token;
26
+ }
27
+ /**
28
+ * Connect MQTT broker
29
+ */
30
+ function connectMQTT(brokerUrl) {
31
+ if (client)
32
+ return client;
33
+ client = mqtt.connect(brokerUrl, {
34
+ reconnectPeriod: 5000,
35
+ connectTimeout: 10000
36
+ });
37
+ client.on("connect", () => {
38
+ console.log("mbnotify app connected");
39
+ });
40
+ client.on("error", (err) => {
41
+ console.error("MQTT error:", err);
42
+ });
43
+ return client;
44
+ }
45
+ /**
46
+ * Show notification using Expo
47
+ */
48
+ async function showNotification(payload) {
49
+ await Notifications.scheduleNotificationAsync({
50
+ content: {
51
+ title: payload.title || "",
52
+ body: payload.body || "",
53
+ data: payload.data || {}
54
+ },
55
+ trigger: null
56
+ });
57
+ }
58
+ /**
59
+ * Subscribe to notifications and return token
60
+ */
61
+ export async function getToken(appName, brokerUrl = DEFAULT_BROKER) {
62
+ if (!appName) {
63
+ throw new Error("appName required");
64
+ }
65
+ const token = await generateToken();
66
+ const topic = `/${appName}/${token}/notification`;
67
+ const mqttClient = connectMQTT(brokerUrl);
68
+ mqttClient.subscribe(topic);
69
+ console.log("Subscribed:", topic);
70
+ mqttClient.on("message", async (_, message) => {
71
+ try {
72
+ const payload = JSON.parse(message.toString());
73
+ await showNotification(payload);
74
+ }
75
+ catch (err) {
76
+ console.error("Invalid notification payload", err);
77
+ }
78
+ });
79
+ return token;
80
+ }
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "mbnotify-app",
3
+ "version": "1.0.0",
4
+ "description": "React Native (Expo) client for mbnotify MQTT push notifications",
5
+ "main": "dist/cjs/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "type": "module",
9
+ "scripts": {
10
+ "build": "npm run build:esm && npm run build:cjs",
11
+ "build:esm": "tsc",
12
+ "build:cjs": "tsc -p tsconfig.cjs.json"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/esm/index.js",
17
+ "require": "./dist/cjs/index.js"
18
+ }
19
+ },
20
+ "keywords": [
21
+ "mqtt",
22
+ "expo",
23
+ "react-native",
24
+ "push-notification",
25
+ "mbnotify"
26
+ ],
27
+ "author": "Manoj Gowda",
28
+ "license": "ISC",
29
+ "dependencies": {
30
+ "mqtt": "^5.15.0",
31
+ "expo-notifications": "^0.28.0",
32
+ "@react-native-async-storage/async-storage": "^1.23.1"
33
+ },
34
+ "devDependencies": {
35
+ "typescript": "^5.9.3"
36
+ }
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,127 @@
1
+ import mqtt from "mqtt";
2
+ import * as Notifications from "expo-notifications";
3
+ import AsyncStorage from "@react-native-async-storage/async-storage";
4
+
5
+ const DEFAULT_BROKER = "wss://broker.hivemq.com:8884/mqtt";
6
+
7
+ let client: mqtt.MqttClient | null = null;
8
+
9
+ export interface NotificationPayload {
10
+ title?: string
11
+ body?: string
12
+ icon?: string
13
+ image?: string
14
+ url?: string
15
+ data?: Record<string, any>
16
+ }
17
+
18
+ /**
19
+ * Request notification permission (Expo)
20
+ */
21
+ export async function requestPermission(): Promise<boolean> {
22
+
23
+ const { status } = await Notifications.requestPermissionsAsync();
24
+
25
+ return status === "granted";
26
+ }
27
+
28
+ /**
29
+ * Generate or retrieve device token
30
+ */
31
+ async function generateToken(): Promise<string> {
32
+
33
+ let token = await AsyncStorage.getItem("mbnotify_token");
34
+
35
+ if (!token) {
36
+
37
+ token =
38
+ "dev_" +
39
+ Math.random().toString(36).substring(2) +
40
+ Date.now().toString(36);
41
+
42
+ await AsyncStorage.setItem("mbnotify_token", token);
43
+ }
44
+
45
+ return token;
46
+ }
47
+
48
+ /**
49
+ * Connect MQTT broker
50
+ */
51
+ function connectMQTT(brokerUrl: string): mqtt.MqttClient {
52
+
53
+ if (client) return client;
54
+
55
+ client = mqtt.connect(brokerUrl, {
56
+ reconnectPeriod: 5000,
57
+ connectTimeout: 10000
58
+ });
59
+
60
+ client.on("connect", () => {
61
+ console.log("mbnotify app connected");
62
+ });
63
+
64
+ client.on("error", (err) => {
65
+ console.error("MQTT error:", err);
66
+ });
67
+
68
+ return client;
69
+ }
70
+
71
+ /**
72
+ * Show notification using Expo
73
+ */
74
+ async function showNotification(payload: NotificationPayload) {
75
+
76
+ await Notifications.scheduleNotificationAsync({
77
+ content: {
78
+ title: payload.title || "",
79
+ body: payload.body || "",
80
+ data: payload.data || {}
81
+ },
82
+ trigger: null
83
+ });
84
+
85
+ }
86
+
87
+ /**
88
+ * Subscribe to notifications and return token
89
+ */
90
+ export async function getToken(
91
+ appName: string,
92
+ brokerUrl: string = DEFAULT_BROKER
93
+ ): Promise<string> {
94
+
95
+ if (!appName) {
96
+ throw new Error("appName required");
97
+ }
98
+
99
+ const token = await generateToken();
100
+
101
+ const topic = `/${appName}/${token}/notification`;
102
+
103
+ const mqttClient = connectMQTT(brokerUrl);
104
+
105
+ mqttClient.subscribe(topic);
106
+
107
+ console.log("Subscribed:", topic);
108
+
109
+ mqttClient.on("message", async (_, message) => {
110
+
111
+ try {
112
+
113
+ const payload: NotificationPayload =
114
+ JSON.parse(message.toString());
115
+
116
+ await showNotification(payload);
117
+
118
+ } catch (err) {
119
+
120
+ console.error("Invalid notification payload", err);
121
+
122
+ }
123
+
124
+ });
125
+
126
+ return token;
127
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "CommonJS",
5
+ "outDir": "dist/cjs"
6
+ }
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "outDir": "dist/esm",
7
+ "declaration": true,
8
+ "strict": true,
9
+ "skipLibCheck": true
10
+ },
11
+ "include": ["src"]
12
+ }