Skip to content

Commit 460b0f3

Browse files
Merge pull request #7 from celestifyhq/feat/topics
Feat/topics
2 parents ce0f243 + 0a4bfe9 commit 460b0f3

File tree

11 files changed

+1762
-81
lines changed

11 files changed

+1762
-81
lines changed

.changeset/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changesets
2+
3+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4+
with multi-package repos, or single-package repos to help you version and publish your code. You can
5+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6+
7+
We have a quick list of common questions to get you started engaging with this project in
8+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

.changeset/config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "https://unpkg.com/@changesets/config@3.0.3/schema.json",
3+
"changelog": "@changesets/cli/changelog",
4+
"commit": false,
5+
"fixed": [],
6+
"linked": [],
7+
"access": "public",
8+
"baseBranch": "main",
9+
"updateInternalDependencies": "patch",
10+
"ignore": []
11+
}

.changeset/eleven-kiwis-yell.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
"fcm-cloudflare-workers": major
3+
---
4+
5+
BREAKING CHANGES:
6+
- Deprecated `sendMulticast` method in favor of new targeting options
7+
- Added new message targeting options: topic and condition-based messaging
8+
- Introduced platform-specific configuration options for iOS and Android
9+
10+
WHY:
11+
- Enhanced flexibility in message targeting to support broader use cases
12+
- Better control over platform-specific notification features
13+
- Improved alignment with Firebase Cloud Messaging's full capabilities
14+
- Simplified API by consolidating message targeting methods
15+
16+
HOW TO UPDATE:
17+
1. Replace `sendMulticast` calls with the new targeting methods:
18+
```typescript
19+
// Old way (deprecated)
20+
await fcm.sendMulticast(tokens, { notification });
21+
22+
// New way
23+
await fcm.sendToTokens(tokens, { notification });
24+
```
25+
26+
2. Message targeting now supports three modes:
27+
- Token-based (using `sendToTokens`)
28+
- Topic-based (new)
29+
- Condition-based (new)
30+
3. Platform configurations can now be specified separately for iOS and Android
31+
4. Update your message payload structure to use the new targeting options if needed
32+
33+
Example of new features:
34+
```typescript
35+
// Token-based messaging (replaces sendMulticast)
36+
await fcm.sendToTokens(['token1', 'token2'], {
37+
notification: { title: 'Update', body: 'New message!' }
38+
});
39+
40+
// Topic messaging
41+
await fcm.sendToTopic('news', {
42+
notification: { title: 'News Update', body: 'Check out the latest news!' }
43+
});
44+
45+
// Condition-based messaging
46+
await fcm.sendToCondition("'sports' in topics && ('game' in topics || 'match' in topics)", {
47+
notification: { title: 'Sports Update', body: 'New game results!' }
48+
});
49+
```
50+
51+

.github/workflows/npm-publish.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Publish to npm
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
release:
10+
name: Release
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout Repository
14+
uses: actions/checkout@v4
15+
with:
16+
fetch-depth: 0
17+
18+
- name: Setup Node.js
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: 20
22+
registry-url: https://registry.npmjs.org/
23+
24+
- name: Install Dependencies
25+
run: npm ci
26+
27+
- name: Create Release Pull Request or Publish
28+
id: changesets
29+
uses: changesets/action@v1
30+
with:
31+
publish: npm run build && npm publish
32+
commit: "chore: version packages"
33+
title: "chore: version packages"
34+
env:
35+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

README.md

Lines changed: 181 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,219 @@
1-
# fcm-cloudflare-workers
1+
# FCM Cloudflare Workers
22

33
[![npm version](https://badge.fury.io/js/fcm-cloudflare-workers.svg)](https://badge.fury.io/js/fcm-cloudflare-workers)
44

5-
Send multicast notifications using the [FCM HTTP v1 API](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages/send).
6-
This project is a fork of [fcm-http2](https://www.npmjs.com/package/fcm-http2) and has been modified to work with Cloudflare Workers.
5+
Send Firebase Cloud Messages (FCM) through the FCM HTTP v1 API on Cloudflare Workers.
76

8-
Features supported by **fcm-cloudflare-workers**:
7+
This project is a fork of [fcm-http2](https://www.npmjs.com/package/fcm-http2) and has been modified to work with Cloudflare Workers.
98

10-
- [X] HTTP/2 session & stream concurrency
11-
- [X] Token batching support
12-
- [X] Uninstall detection
13-
- [X] Retry mechanism
14-
- [X] (Optional) Access token caching using KV
15-
- [X] Zero dependencies
9+
## Features
1610

17-
## How to use?
11+
- 🚀 Full support for FCM HTTP v1 API message format
12+
- 💪 TypeScript support with comprehensive type definitions
13+
- ⚡️ Optimized for Cloudflare Workers
14+
- 🔄 Automatic token rotation and caching
15+
- 📦 Batched message sending support
16+
- 🎯 Multiple targeting options (token, topic, condition)
17+
- ✨ Zero dependencies
1818

19-
First you need to install the library via npm:
19+
## Installation
2020

21-
```shell
22-
npm i fcm-cloudflare-workers
21+
```bash
22+
npm install fcm-cloudflare-workers
2323
```
2424

25-
Once the library has been installed you can start using it in this way:
25+
## Usage
26+
27+
### Initialize FCM
2628

27-
```js
28-
import { FCM, FcmOptions, FcmMessage } from "fcm-cloudflare-workers";
29+
```typescript
30+
import { FCM, FcmOptions } from 'fcm-cloudflare-workers';
2931

3032
// Init FCM with options (minimal example)
31-
const fcmOptions = new FcmOptions(
33+
const fcmOptions = new FcmOptions({
3234
// Pass in your service account JSON private key file (https://console.firebase.google.com/u/0/project/_/settings/serviceaccounts/adminsdk)
3335
serviceAccount: JSON.parse(env.FIREBASE_SERVICE_ACCOUNT_JSON),
34-
);
36+
});
3537

3638
// Or, init FCM with access token caching using KV (optional but recommended for performance)
37-
const fcmOptions = new FcmOptions(
39+
const fcmOptions = new FcmOptions({
3840
serviceAccount: JSON.parse(env.FIREBASE_SERVICE_ACCOUNT_JSON),
3941
// Specify a KV namespace
4042
kvStore: env.MY_KV_NAMESPACE,
4143
// Specify a key to use for caching the access token
4244
kvCacheKey: 'fcm_access_token',
43-
);
45+
});
46+
47+
const fcm = new FCM(fcmOptions);
48+
```
49+
50+
### Send to Single Device
51+
52+
```typescript
53+
import { EnhancedFcmMessage } from 'fcm-cloudflare-workers';
54+
55+
const message: EnhancedFcmMessage = {
56+
notification: {
57+
title: "New Message",
58+
body: "You have a new message!",
59+
image: "https://example.com/image.png"
60+
},
61+
data: {
62+
key: "value",
63+
},
64+
// Optional platform-specific configurations
65+
android: {
66+
notification: {
67+
click_action: "OPEN_MESSAGE",
68+
channel_id: "messages",
69+
icon: "message_icon"
70+
}
71+
},
72+
apns: {
73+
payload: {
74+
aps: {
75+
badge: 1,
76+
sound: "default"
77+
}
78+
}
79+
},
80+
webpush: {
81+
notification: {
82+
icon: "https://example.com/icon.png",
83+
badge: "https://example.com/badge.png",
84+
actions: [
85+
{
86+
action: "view",
87+
title: "View Message"
88+
}
89+
]
90+
}
91+
}
92+
};
93+
94+
try {
95+
await fcm.sendToToken(message, "device-token");
96+
} catch (error) {
97+
console.error("Error sending message:", error);
98+
}
99+
```
100+
101+
### Send to Multiple Devices
102+
103+
```typescript
104+
const tokens = [
105+
"device-token-1",
106+
"device-token-2",
107+
"device-token-3"
108+
];
109+
110+
try {
111+
const unregisteredTokens = await fcm.sendToTokens(message, tokens);
112+
if (unregisteredTokens.length > 0) {
113+
console.log("Some tokens are no longer registered:", unregisteredTokens);
114+
}
115+
} catch (error) {
116+
console.error("Error sending to multiple devices:", error);
117+
}
118+
```
44119

45-
const fcmClient = new FCM(fcmOptions);
120+
### Send to Topic
46121

47-
// Recipient device tokens
48-
const tokens = ["TOKEN_1", "TOKEN_N"];
122+
```typescript
123+
try {
124+
await fcm.sendToTopic(message, "news");
125+
} catch (error) {
126+
console.error("Error sending to topic:", error);
127+
}
128+
```
49129

50-
// Message to send
51-
const message = {
52-
notification: {
53-
title: "Test",
54-
body: "Hello from Cloudflare Workers",
55-
},
56-
data: {
57-
notification: "true",
58-
},
59-
} satisfies FcmMessage;
130+
### Send with Condition
60131

132+
```typescript
61133
try {
62-
const unregisteredTokens = await fcmClient.sendMulticast(message, tokens);
63-
64-
// Sending successful
65-
console.log("Message sent successfully");
66-
67-
// Remove unregistered tokens from your database
68-
if (unregisteredTokens.length > 0) {
69-
console.log(
70-
"Unregistered device token(s): ",
71-
unregisteredTokens.join(", ")
72-
);
73-
}
134+
await fcm.sendToCondition(message, "'sports' in topics && 'news' in topics");
74135
} catch (error) {
75-
console.log("Sending failed", error.message);
136+
console.error("Error sending to condition:", error);
76137
}
77138
```
78139

140+
## Migration Guide
141+
142+
### Upgrading from `sendMulticast`
143+
144+
The `sendMulticast` method is now deprecated in favor of the new `sendToTokens` method. Here's how to upgrade your code:
145+
146+
```typescript
147+
// Old way (deprecated)
148+
import { FCM, FcmMessage } from 'fcm-cloudflare-workers';
149+
150+
const message: FcmMessage = {
151+
notification: {
152+
title: "Hello",
153+
body: "World"
154+
},
155+
data: {
156+
key: "value"
157+
}
158+
};
159+
160+
const unregisteredTokens = await fcm.sendMulticast(message, tokens);
161+
162+
// New way
163+
import { FCM, EnhancedFcmMessage } from 'fcm-cloudflare-workers';
164+
165+
const message: EnhancedFcmMessage = {
166+
notification: {
167+
title: "Hello",
168+
body: "World"
169+
},
170+
data: {
171+
key: "value"
172+
},
173+
// Now you can also use platform-specific configurations
174+
android: {
175+
notification: {
176+
channel_id: "default"
177+
}
178+
}
179+
};
180+
181+
const unregisteredTokens = await fcm.sendToTokens(message, tokens);
182+
```
183+
184+
The new `sendToTokens` method:
185+
- Maintains the same batching and performance optimizations as `sendMulticast`
186+
- Returns unregistered tokens in the same way
187+
- Adds support for all FCM HTTP v1 API message properties (android, apns, webpush, etc.)
188+
- Provides better TypeScript type safety
189+
190+
## API Reference
191+
192+
### FCM Methods
193+
194+
- `sendToToken(message: EnhancedFcmMessage, token: string): Promise<void>`
195+
Sends a message to a single device using its FCM token.
196+
197+
- `sendToTokens(message: EnhancedFcmMessage, tokens: string[]): Promise<string[]>`
198+
Sends a message to multiple devices. Returns an array of tokens that are no longer registered.
199+
200+
- `sendToTopic(message: EnhancedFcmMessage, topic: string): Promise<void>`
201+
Sends a message to all devices subscribed to a specific topic.
202+
203+
- `sendToCondition(message: EnhancedFcmMessage, condition: string): Promise<void>`
204+
Sends a message to devices that match the specified condition.
205+
206+
- `sendMulticast(message: FcmMessage, tokens: string[]): Promise<string[]>`
207+
**Deprecated**: Use `sendToTokens` instead. Kept for backward compatibility.
208+
79209
## Contributions
80210

81211
This repo is based on previous work by [kenble](https://gitlab.com/kenble) and [eladnava](https://github.com/eladnava).
82212

83213
## Support
84214

85215
Please open an issue on this repo if you have any questions or need support.
216+
217+
## License
218+
219+
Apache-2.0

0 commit comments

Comments
 (0)