Skip to content

Commit cad896c

Browse files
committed
wip(feathers-webpush): Migrate feathers-webpush to this monorepo #2 (docs)
1 parent 8b09526 commit cad896c

6 files changed

Lines changed: 188 additions & 13 deletions

File tree

docs/.vitepress/config.mjs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export default withMermaid(
2222
{
2323
text: 'Packages',
2424
items: [
25-
{ text: 'feathers-keycloak-listener', link: '/packages/feathers-keycloak-listener/' }
25+
{ text: 'feathers-keycloak-listener', link: '/packages/feathers-keycloak-listener/' },
26+
{ text: 'feathers-webpush', link: '/packages/feathers-webpush/' }
2627
]
2728
}
2829
],
@@ -43,6 +44,16 @@ export default withMermaid(
4344
{ text: 'users', link: '/packages/feathers-keycloak-listener/api/hooks/hooks.users' }
4445
]}
4546
]}
47+
],
48+
'/packages/feathers-webpush/': [
49+
{ text: 'Usage', link: '/packages/feathers-webpush/index' },
50+
{ text: 'API', items: [
51+
{ text: 'server', items: [
52+
{ text: 'service', link: '/packages/feathers-keycloak-listener/api/server/service' },
53+
{ text: 'hooks', link: '/packages/feathers-keycloak-listener/api/server/hooks' }
54+
]},
55+
{ text: 'client', link: '/packages/feathers-webpush/api/client' }
56+
]}
4657
]
4758
},
4859
footer: {
@@ -59,10 +70,3 @@ export default withMermaid(
5970
}
6071
})
6172
)
62-
63-
64-
function getSideBar (pkg) {
65-
if (pkg === 'feathers-keycloak-listener') {
66-
return []
67-
}
68-
}

docs/packages/feathers-webpush/api/server.md

Whitespace-only changes.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: hooks
3+
---
4+
5+
# Hooks
6+
7+
## deleteExpiredSubscriptions
8+
9+
### Signature
10+
11+
```js
12+
deleteExpiredSubscriptions(hook)
13+
```
14+
15+
### Description
16+
17+
After hook that automatically removes expired web push subscriptions
18+
from a Feathers service after a notification delivery attempt.
19+
20+
The hook inspects `hook.result.failed` and looks for failed push attempts
21+
with HTTP status codes `410` (Gone) or `404` (Not Found).
22+
23+
For each matching error, it:
24+
25+
- Retrieves all records from the configured subscription service
26+
- Finds subscriptions matching the failed `endpoint`
27+
- Removes the expired subscription from the record
28+
- Patches the record in the database
29+
- Logs the deletion using `debug`
30+
31+
This hook must be registered as an **after** hook.
32+
33+
### Parameters
34+
35+
| Name | Type | Required | Description |
36+
|--------|--------|----------|--------------------------------------------------|
37+
| `hook` | object | yes | The FeathersJS hook context. Must be an after hook. |
38+
39+
The hook expects the following properties inside `hook.result`:
40+
41+
| Name | Type | Required | Description |
42+
|------------------------|--------|----------|--------------------------------------------------------------|
43+
| `failed` | array | yes | Array of failed push attempts (`statusCode`, `endpoint`). |
44+
| `subscriptionService` | string | yes | Name of the Feathers service storing subscriptions. |
45+
| `subscriptionProperty` | string | yes | Property name containing the subscriptions array. |
46+
47+
### Returns
48+
49+
| Type | Description |
50+
|-------------------|----------------------------|
51+
| `Promise<object>` | The original hook context. |
52+
53+
### Throws
54+
55+
| Type | Description |
56+
|-------|--------------------------------------------------|
57+
| `Error` | If the hook is not used as an `after` hook. |
58+
59+
### Examples
60+
61+
```js
62+
import { deleteExpiredSubscriptions } from '@kalisio/feathers-webpush/server'
63+
64+
app.service('push').hooks({
65+
after: {
66+
create: [deleteExpiredSubscriptions]
67+
}
68+
})
69+
```
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
title: Service
3+
---
4+
5+
# Service
6+
7+
## Service
8+
9+
### Signature
10+
11+
```js
12+
new Service(options)
13+
```
14+
15+
### Description
16+
17+
A Feathers service for sending web push notifications to subscribed users.
18+
19+
This service retrieves subscriptions from a specified Feathers service,
20+
validates them, and sends notifications using the `web-push` library.
21+
It handles successful and failed deliveries and logs relevant debug information.
22+
23+
### Constructor Parameters
24+
25+
| Name | Type | Required | Description |
26+
|------|------|----------|-------------|
27+
| `options` | object | yes | Configuration object for the service. |
28+
| `options.app` | object | yes | The Feathers application instance. |
29+
| `options.vapidDetails` | object | yes | VAPID key details for sending push notifications. Must contain `subject`, `publicKey`, and `privateKey`. |
30+
31+
### Throws (constructor)
32+
33+
| Type | Description |
34+
|------|-------------|
35+
| `Error` | If `options`, `options.app`, or `options.vapidDetails` are missing. |
36+
37+
---
38+
39+
## create
40+
41+
### Signature
42+
43+
```js
44+
service.create(data, params)
45+
```
46+
47+
### Description
48+
49+
Sends a web push notification to all subscriptions retrieved from the specified service.
50+
51+
Steps:
52+
53+
1. Validates the required parameters in `data`:
54+
- `notification`
55+
- `subscriptionService`
56+
- `subscriptionProperty`
57+
2. Retrieves subscriptions from the specified service using an optional `subscriptionFilter`.
58+
3. Iterates over each subscription, validates the subscription keys (`endpoint`, `keys.auth`, `keys.p256dh`).
59+
4. Sends the notification using `web-push.sendNotification`.
60+
5. Returns an object containing arrays of successful and failed deliveries.
61+
62+
### Parameters
63+
64+
| Name | Type | Required | Description |
65+
|------|------|----------|-------------|
66+
| `data` | object | yes | Data for sending the notification. |
67+
| `data.notification` | object | yes | The notification payload. |
68+
| `data.subscriptionService` | string | yes | Name of the Feathers service storing subscriptions. |
69+
| `data.subscriptionProperty` | string | yes | Property containing subscriptions in the service. |
70+
| `data.subscriptionFilter` | object | no | Optional filter/query for retrieving subscriptions. |
71+
| `params` | object | no | FeathersJS service call params. |
72+
73+
### Returns
74+
75+
| Type | Description |
76+
|------|-------------|
77+
| `Promise<object>` | An object containing: <br> - `succesful`: array of successful notifications <br> - `failed`: array of errors <br> - `subscriptionService` and `subscriptionProperty` used. |
78+
79+
### Throws (create)
80+
81+
| Type | Description |
82+
|------|-------------|
83+
| `BadRequest` | If required `data` parameters are missing or if subscription object is invalid. |
84+
85+
### Examples
86+
87+
```js
88+
import { Service } from '@kalisio/feathers-webpush/server'
89+
90+
const pushService = new Service({
91+
app,
92+
vapidDetails: {
93+
subject: 'mailto:admin@example.com',
94+
publicKey: process.env.VAPID_PUBLIC_KEY,
95+
privateKey: process.env.VAPID_PRIVATE_KEY
96+
}
97+
})
98+
99+
const result = await pushService.create({
100+
notification: { title: 'Hello!', body: 'Test notification' },
101+
subscriptionService: 'users',
102+
subscriptionProperty: 'subscriptions'
103+
})
104+
105+
console.log(result.succesful, result.failed)
106+
```

docs/packages/feathers-webpush/index.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@ pnpm add @kalisio/feathers-webpush
1212

1313
## Configuration
1414

15-
16-
## Example
17-
1815
The provided [example](./example/README.md) illustrates how to setup:
1916

2017
* a server app
2118

2219
https://github.com/kalisio/feathers-webpush/blob/6b09d58428923c95e26cd5keycloak-listener8d130bc6b268c4cb30/example/server.mjs#L1-L46
2320

24-
* a browser client app
21+
* a client app
2522

2623
https://github.com/kalisio/feathers-webpush/blob/6b09d58428923c95e26cd58d130bc6b268c4cb30/example/src/index.html#L1-L66
2724

packages/feathers-webpush/src/server/hooks.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export async function deleteExpiredSubscriptions (hook) {
1212
const resultFailed = hook.result.failed
1313
const subscriptionProperty = hook.result.subscriptionProperty
1414
const subscriptions = await app.service(subscriptionService).find({ paginate: false })
15-
1615
_.forEach(_.filter(resultFailed, error => (error.statusCode === 410 || error.statusCode === 404)), async error => {
1716
_.forEach(subscriptions, async subscription => {
1817
if (_.has(subscription, subscriptionProperty) && _.find(_.get(subscription, subscriptionProperty), subscription => subscription.endpoint === error.endpoint)) {

0 commit comments

Comments
 (0)