-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
120 lines (101 loc) · 2.51 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { browser, toReadable, toWritable, unstore } from "@sveu/shared"
import type { FirebaseApp } from "firebase/app"
import {
onMessage as _onMessage,
getMessaging,
getToken,
} from "firebase/messaging"
import type { GetTokenOptions, Messaging } from "firebase/messaging"
interface FcmOptions {
swPath?: string
}
/**
* Wrapper for Firebase Messaging
*
* @param firebase - Firebase app
*
* @param vapidKey - VAPID key
*
* @param options - Options
* - `swPath` - Service worker path
*
* @example
* ```ts
* const { token, error, supported, messaging, onMessage } = fcm(firebase, vapidKey)
* ```
* @returns
* - `token` - Readable store that contains token
* - `error` - Readable store that contains error if one occurred
* - `supported` - Readable store that indicates whether FCM is supported
* - `messaging` - Readable store with messaging instance
* - `onMessage` - Function for handling incoming messages
*
*/
export function fcm(
firebase: FirebaseApp,
vapidKey: string,
options: FcmOptions = {}
) {
const { swPath } = options
const token = toWritable<string | null>(null)
const error = toWritable<Error | null>(null)
const supported = toWritable<boolean>(false)
const messaging = toWritable<Messaging | null>(null)
let sw: any
/** Create messaging instance and get token */
async function init() {
if (swPath) {
try {
sw = await navigator.serviceWorker.register(swPath)
} catch {
error.set(new Error("Service worker registration failed"))
}
}
const token_options: GetTokenOptions = {
vapidKey: vapidKey,
serviceWorkerRegistration: sw,
}
const _messaging = unstore(messaging)
if (_messaging) {
try {
const _token = await getToken(_messaging, token_options)
token.set(_token)
} catch (e: any) {
error.set(e)
}
}
}
if (browser) {
messaging.set(getMessaging(firebase))
if (!messaging) {
supported.set(false)
error.set(new Error("Firebase Messaging is not supported"))
}
supported.set(true)
init()
}
/** Handle incoming messages
*
* @param fn - Function to handle incoming messages
*
* @example
* ```ts
* const { onMessage } = fcm(firebase, vapidKey)
*
* onMessage((payload) => {
* console.log(payload)
* })
* ```
*/
function onMessage(fn: (payload: unknown) => void) {
const _messaging = unstore(messaging)
if (_messaging) _onMessage(_messaging, fn)
}
return {
token: toReadable(token),
error: toReadable(error),
supported: toReadable(supported),
messaging: toReadable(messaging),
onMessage,
}
}