@flink-app/apn-plugin 0.12.1-alpha.4 → 0.12.1-alpha.40
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/.flink/generatedHandlers.ts +1 -1
- package/.flink/generatedJobs.ts +1 -1
- package/.flink/generatedRepos.ts +1 -1
- package/.flink/schemas/schemas.ts +1 -1
- package/.flink/start.ts +2 -1
- package/dist/.flink/generatedHandlers.js +1 -1
- package/dist/.flink/generatedJobs.js +1 -1
- package/dist/.flink/generatedRepos.js +1 -1
- package/dist/.flink/schemas/schemas.js +1 -1
- package/dist/.flink/start.d.ts +2 -0
- package/dist/.flink/start.js +2 -1
- package/package.json +4 -4
- package/readme.md +165 -24
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredHandlers, HttpMethod } from "@flink-app/flink";
|
|
3
3
|
export const handlers = [];
|
|
4
4
|
autoRegisteredHandlers.push(...handlers);
|
package/.flink/generatedJobs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredJobs } from "@flink-app/flink";
|
|
3
3
|
export const jobs = [];
|
|
4
4
|
autoRegisteredJobs.push(...jobs);
|
package/.flink/generatedRepos.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredRepos } from "@flink-app/flink";
|
|
3
3
|
export const repos = [];
|
|
4
4
|
autoRegisteredRepos.push(...repos);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
package/.flink/start.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import "./generatedHandlers";
|
|
3
3
|
import "./generatedRepos";
|
|
4
4
|
import "./generatedJobs";
|
|
5
5
|
import "../src/index";
|
|
6
|
+
export default {}; // Export an empty object to make it a module
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handlers = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.handlers = [];
|
|
7
7
|
flink_1.autoRegisteredHandlers.push.apply(flink_1.autoRegisteredHandlers, exports.handlers);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.jobs = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.jobs = [];
|
|
7
7
|
flink_1.autoRegisteredJobs.push.apply(flink_1.autoRegisteredJobs, exports.jobs);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.repos = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.repos = [];
|
|
7
7
|
flink_1.autoRegisteredRepos.push.apply(flink_1.autoRegisteredRepos, exports.repos);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Generated
|
|
2
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
package/dist/.flink/start.d.ts
CHANGED
package/dist/.flink/start.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
// Generated
|
|
3
|
+
// Generated Sun Nov 02 2025 21:40:04 GMT+0100 (Central European Standard Time)
|
|
4
4
|
require("./generatedHandlers");
|
|
5
5
|
require("./generatedRepos");
|
|
6
6
|
require("./generatedJobs");
|
|
7
7
|
require("../src/index");
|
|
8
|
+
exports.default = {}; // Export an empty object to make it a module
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flink-app/apn-plugin",
|
|
3
|
-
"version": "0.12.1-alpha.
|
|
3
|
+
"version": "0.12.1-alpha.40",
|
|
4
4
|
"description": "Flink plugin to send push notifications to APN",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\"",
|
|
7
7
|
"build": "flink build",
|
|
8
|
-
"
|
|
8
|
+
"prepare": "npm run build",
|
|
9
9
|
"watch": "nodemon --exec \"flink build\""
|
|
10
10
|
},
|
|
11
11
|
"author": "joel@frost.se",
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"@parse/node-apn": "6.4.3"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@flink-app/flink": "^0.12.1-alpha.
|
|
22
|
+
"@flink-app/flink": "^0.12.1-alpha.40",
|
|
23
23
|
"@types/node": "22.13.10",
|
|
24
24
|
"nodemon": "^2.0.7",
|
|
25
25
|
"ts-node": "^9.1.1",
|
|
26
26
|
"typescript": "5.4.5"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "456502f273fe9473df05b71a803f3eda1a2f8931"
|
|
29
29
|
}
|
package/readme.md
CHANGED
|
@@ -1,52 +1,193 @@
|
|
|
1
1
|
# APN Plugin
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A Flink plugin for sending push notifications to iOS devices via Apple Push Notification service (APNs) using certificate-based authentication.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
Install plugin to your flink app project:
|
|
5
|
+
## Installation
|
|
8
6
|
|
|
9
|
-
```
|
|
10
|
-
npm
|
|
7
|
+
```bash
|
|
8
|
+
npm install @flink-app/apn-plugin
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Add and configure the plugin in your app startup:
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
import { apnPlugin } from "@flink-app/apn-plugin";
|
|
17
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
18
|
+
import AppContext from "./ApplicationContext";
|
|
17
19
|
|
|
18
|
-
function start() {
|
|
19
|
-
new FlinkApp<AppContext>({
|
|
20
|
+
async function start() {
|
|
21
|
+
await new FlinkApp<AppContext>({
|
|
20
22
|
name: "My app",
|
|
21
23
|
plugins: [
|
|
22
24
|
apnPlugin({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
certificate: {
|
|
26
|
+
cert: process.env.APNS_CERT_BASE64, // Base64 encoded certificate (PEM format)
|
|
27
|
+
key: process.env.APNS_KEY_BASE64, // Base64 encoded private key (PEM format)
|
|
28
|
+
passphrase: process.env.APNS_PASSPHRASE, // Optional: key passphrase
|
|
27
29
|
},
|
|
28
|
-
production: false, // Set to true
|
|
30
|
+
production: false, // Set to true for production APNs server
|
|
31
|
+
topic: "com.example.app.voip", // Your app's bundle ID or VoIP topic
|
|
32
|
+
defaultPriority: 10, // Optional: default notification priority (1-10)
|
|
29
33
|
}),
|
|
30
34
|
],
|
|
31
35
|
}).start();
|
|
32
36
|
}
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
Add
|
|
39
|
+
Add the plugin context to your application context:
|
|
36
40
|
|
|
37
|
-
```
|
|
41
|
+
```typescript
|
|
38
42
|
import { ApnPluginContext } from "@flink-app/apn-plugin";
|
|
43
|
+
import { FlinkContext } from "@flink-app/flink";
|
|
44
|
+
|
|
45
|
+
interface ApplicationContext extends FlinkContext<ApnPluginContext> {
|
|
46
|
+
// your context here
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default ApplicationContext;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Configuration Options
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
interface ApnPluginOptions {
|
|
56
|
+
certificate: {
|
|
57
|
+
cert: string; // Base64 encoded APNs certificate (PEM format)
|
|
58
|
+
key: string; // Base64 encoded private key (PEM format)
|
|
59
|
+
passphrase?: string; // Optional: key passphrase if encrypted
|
|
60
|
+
};
|
|
61
|
+
production: boolean; // Use production APNs server (default: false)
|
|
62
|
+
topic: string; // Default APNs topic (typically your app's bundle ID)
|
|
63
|
+
defaultPriority?: number; // Default notification priority 1-10 (default: 10)
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Sending Push Notifications
|
|
68
|
+
|
|
69
|
+
### From a Handler
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Handler } from "@flink-app/flink";
|
|
73
|
+
import AppContext from "../ApplicationContext";
|
|
39
74
|
|
|
40
|
-
|
|
41
|
-
|
|
75
|
+
const SendNotification: Handler<AppContext, SendNotificationReq, SendNotificationRes> = async ({ ctx, req }) => {
|
|
76
|
+
await ctx.plugins.apn.send({
|
|
77
|
+
to: ["device-token-1", "device-token-2"], // Array of device tokens
|
|
78
|
+
alert: "Hello from APN!", // Alert text to display
|
|
79
|
+
payload: { // Custom data payload
|
|
80
|
+
messageId: "123",
|
|
81
|
+
action: "view",
|
|
82
|
+
},
|
|
83
|
+
topic: "com.example.app.voip", // Optional: override default topic
|
|
84
|
+
pushType: "alert", // Optional: "alert", "background", or "voip"
|
|
85
|
+
priority: 10, // Optional: override default priority
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
status: 200,
|
|
90
|
+
data: { success: true },
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default SendNotification;
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Message Schema
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
interface ApnMessage {
|
|
101
|
+
to: string[]; // Array of device tokens to send to
|
|
102
|
+
alert?: string; // Alert text to display to user
|
|
103
|
+
payload: { // Custom data payload (key-value pairs)
|
|
104
|
+
[x: string]: string;
|
|
105
|
+
};
|
|
106
|
+
topic?: string; // Optional: override default topic
|
|
107
|
+
pushType?: "alert" | "background" | "voip" | "complication" | "fileprovider" | "mdm";
|
|
108
|
+
priority?: number; // Optional: override default priority (1-10)
|
|
42
109
|
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Certificate Setup
|
|
113
|
+
|
|
114
|
+
### 1. Generate Certificate from Apple Developer Portal
|
|
115
|
+
1. Go to Apple Developer Portal → Certificates, Identifiers & Profiles
|
|
116
|
+
2. Create a new APNs certificate (or VoIP Services certificate)
|
|
117
|
+
3. Download the certificate (.cer file)
|
|
118
|
+
|
|
119
|
+
### 2. Convert to PEM Format
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Convert certificate
|
|
123
|
+
openssl x509 -in aps_certificate.cer -inform DER -out cert.pem -outform PEM
|
|
124
|
+
|
|
125
|
+
# Export private key from keychain (if not already exported)
|
|
126
|
+
# This step depends on how the certificate was created
|
|
127
|
+
|
|
128
|
+
# Encode to base64
|
|
129
|
+
cat cert.pem | base64
|
|
130
|
+
cat key.pem | base64
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 3. Set Environment Variables
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
export APNS_CERT_BASE64="<base64-encoded-cert>"
|
|
137
|
+
export APNS_KEY_BASE64="<base64-encoded-key>"
|
|
138
|
+
export APNS_PASSPHRASE="<passphrase-if-any>"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Push Types
|
|
142
|
+
|
|
143
|
+
- **alert**: Standard push notification (default)
|
|
144
|
+
- **background**: Silent push notification
|
|
145
|
+
- **voip**: VoIP push notification
|
|
146
|
+
- **complication**: Update a watchOS complication
|
|
147
|
+
- **fileprovider**: Signal a file provider app
|
|
148
|
+
- **mdm**: Mobile device management
|
|
43
149
|
|
|
150
|
+
## Priority Levels
|
|
151
|
+
|
|
152
|
+
- **10**: High priority - delivered immediately (default)
|
|
153
|
+
- **5**: Low priority - delivered based on device power considerations
|
|
154
|
+
|
|
155
|
+
## Context API
|
|
156
|
+
|
|
157
|
+
The plugin exposes the following method through your application context:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
ctx.plugins.apn.send(message: ApnMessage): Promise<any>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Features
|
|
164
|
+
|
|
165
|
+
- ✅ Certificate-based authentication
|
|
166
|
+
- ✅ Batch sending to multiple devices
|
|
167
|
+
- ✅ Support for all push types (alert, VoIP, background, etc.)
|
|
168
|
+
- ✅ Automatic base64 certificate/key decoding
|
|
169
|
+
- ✅ Detailed logging of send results
|
|
170
|
+
- ✅ Production and sandbox environment support
|
|
171
|
+
|
|
172
|
+
## Error Handling
|
|
173
|
+
|
|
174
|
+
The plugin logs detailed information about send successes and failures:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
try {
|
|
178
|
+
await ctx.plugins.apn.send({
|
|
179
|
+
to: ["device-token"],
|
|
180
|
+
alert: "Test notification",
|
|
181
|
+
payload: { test: "data" },
|
|
182
|
+
});
|
|
183
|
+
} catch (error) {
|
|
184
|
+
// Handle errors
|
|
185
|
+
console.error("Failed to send push notification:", error);
|
|
186
|
+
}
|
|
44
187
|
```
|
|
45
188
|
|
|
46
|
-
##
|
|
189
|
+
## Requirements
|
|
47
190
|
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- `teamId` - Your Apple Developer Team ID
|
|
52
|
-
- `production` - Set to true if you want to use the production APNs server
|
|
191
|
+
- Valid APNs certificate and private key
|
|
192
|
+
- Device tokens from your iOS app
|
|
193
|
+
- Correct app bundle ID configured as topic
|