@flink-app/apn-plugin 0.12.1-alpha.9 → 0.13.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.
@@ -1,4 +1,4 @@
1
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
1
+ // Generated Sat Jan 10 2026 11:36:58 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);
@@ -1,4 +1,4 @@
1
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
1
+ // Generated Sat Jan 10 2026 11:36:58 GMT+0100 (Central European Standard Time)
2
2
  import { autoRegisteredJobs } from "@flink-app/flink";
3
3
  export const jobs = [];
4
4
  autoRegisteredJobs.push(...jobs);
@@ -1,4 +1,4 @@
1
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
1
+ // Generated Sat Jan 10 2026 11:36:58 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 Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
1
+ // Generated Sat Jan 10 2026 11:36:58 GMT+0100 (Central European Standard Time)
package/.flink/start.ts CHANGED
@@ -1,5 +1,6 @@
1
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
1
+ // Generated Sat Jan 10 2026 11:36:58 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
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @flink-app/apn-plugin
2
+
3
+ ## 0.13.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed invalid types and improve typescript error message during schema compilation
8
+
9
+ ## 0.13.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Migrate to pnpm and streamlines build process.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handlers = void 0;
4
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
4
+ // Generated Sat Jan 10 2026 11:36:58 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 Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
4
+ // Generated Sat Jan 10 2026 11:36:58 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 Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
4
+ // Generated Sat Jan 10 2026 11:36:58 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 Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
2
+ // Generated Sat Jan 10 2026 11:36:58 GMT+0100 (Central European Standard Time)
@@ -2,3 +2,5 @@ import "./generatedHandlers";
2
2
  import "./generatedRepos";
3
3
  import "./generatedJobs";
4
4
  import "../src/index";
5
+ declare const _default: {};
6
+ export default _default;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- // Generated Fri Apr 11 2025 20:43:00 GMT+0200 (Central European Summer Time)
3
+ // Generated Sat Jan 10 2026 11:36:58 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
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
package/package.json CHANGED
@@ -1,29 +1,26 @@
1
1
  {
2
- "name": "@flink-app/apn-plugin",
3
- "version": "0.12.1-alpha.9",
4
- "description": "Flink plugin to send push notifications to APN",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\"",
7
- "build": "flink build",
8
- "prepare": "npm run build",
9
- "watch": "nodemon --exec \"flink build\""
10
- },
11
- "author": "joel@frost.se",
12
- "license": "MIT",
13
- "types": "dist/src/index.d.ts",
14
- "main": "dist/src/index.js",
15
- "publishConfig": {
16
- "access": "public"
17
- },
18
- "dependencies": {
19
- "@parse/node-apn": "6.4.3"
20
- },
21
- "devDependencies": {
22
- "@flink-app/flink": "^0.12.1-alpha.9",
23
- "@types/node": "22.13.10",
24
- "nodemon": "^2.0.7",
25
- "ts-node": "^9.1.1",
26
- "typescript": "5.4.5"
27
- },
28
- "gitHead": "3007ad036607014176930446fde56203bde8d6f5"
29
- }
2
+ "name": "@flink-app/apn-plugin",
3
+ "version": "0.13.1",
4
+ "description": "Flink plugin to send push notifications to APN",
5
+ "author": "joel@frost.se",
6
+ "license": "MIT",
7
+ "types": "dist/src/index.d.ts",
8
+ "main": "dist/src/index.js",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "dependencies": {
13
+ "@parse/node-apn": "6.4.3"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "22.13.10",
17
+ "@flink-app/flink": "0.13.1"
18
+ },
19
+ "gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113",
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\"",
22
+ "build": "flink build",
23
+ "watch": "nodemon --exec \"flink build\"",
24
+ "clean": "rimraf dist .flink"
25
+ }
26
+ }
package/readme.md CHANGED
@@ -1,52 +1,193 @@
1
1
  # APN Plugin
2
2
 
3
- A FLINK plugin used for sending push notifications using APN (Apple Push Notification) service.
3
+ A Flink plugin for sending push notifications to iOS devices via Apple Push Notification service (APNs) using certificate-based authentication.
4
4
 
5
- ## Usage
6
-
7
- Install plugin to your flink app project:
5
+ ## Installation
8
6
 
9
- ```
10
- npm i -S @flink-app/apn-plugin
7
+ ```bash
8
+ npm install @flink-app/apn-plugin
11
9
  ```
12
10
 
13
- Add and configure plugin in your app startup:
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
- token: {
24
- key: "./path/to/AuthKey_XXXXXXXXXX.p8", // Absolute or relative path to your .p8 file
25
- keyId: "XXXXXXXXXX", // Your APNs Auth Key ID
26
- teamId: "YYYYYYYYYY", // Your Apple Developer Team ID
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 if you want to use the production APNs server
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 it to your app context (normally `Ctx.ts` in the root folder of your project)
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
- export interface Ctx extends FlinkContext<ApnPluginContext> {
41
- // your context here
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
- ## Configuration
189
+ ## Requirements
47
190
 
48
- - `token` - APNs Auth Key configuration
49
- - `key` - Absolute or relative path to your .p8 file
50
- - `keyId` - Your APNs Auth Key ID
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
package/tsconfig.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "noEmit": false,
16
16
  "declaration": true,
17
17
  "experimentalDecorators": true,
18
- "checkJs": true,
18
+ "checkJs": false,
19
19
  "outDir": "dist"
20
20
  },
21
21
  "include": ["./src/**/*.ts", "./.flink/**/*"],