@gesher/sdk
v0.1.1
Published
Browser SDK for Gesher push notification service
Maintainers
Readme
@gesher/sdk
Gesher is Otomator’s hosted web push service: your backend sends notifications; this SDK helps browsers subscribe and receive them—without exposing API keys in the client.
Install
npm install @gesher/sdkQuick start
Copy
node_modules/@gesher/sdk/gesher-sw.js(or import path@gesher/sdk/swfor bundler resolution of the file) to your site’s public root, e.g.public/gesher-sw.js, so it is served at/gesher-sw.js.Point the SDK at your backend URLs; your server proxies to
api.gesher.prowith the Bearer API key.
import { GesherClient } from '@gesher/sdk'
const gesher = new GesherClient({
subscribeEndpoint: '/api/push/subscribe',
unsubscribeEndpoint: '/api/push/unsubscribe',
// Optional: omit to fetch from https://api.gesher.pro/vapid-key
// vapidPublicKey: '...',
})
const result = await gesher.subscribe('user-123')
if (!result.ok) console.error(result.error)
if (await gesher.isSubscribed()) {
// ...
}
await gesher.unsubscribe() // or unsubscribe('user-123')PWA install (optional)
If your app is a Progressive Web App with a web app manifest, you can use the SDK helpers to capture beforeinstallprompt and show an install button.
const gesher = new GesherClient({
subscribeEndpoint: '/api/push/subscribe',
unsubscribeEndpoint: '/api/push/unsubscribe',
})
// Call once at app startup
gesher.watchInstall()
// Show an "Install App" button when ready
gesher.onInstallStateChange((state) => {
if (state === 'available') showInstallButton()
if (state === 'installed') hideInstallButton()
})
// On button click
document.getElementById('install-btn')!.onclick = async () => {
const result = await gesher.install()
if (result.accepted) console.log('App installed!')
}Backend proxy (Express)
Your route receives the JSON body from the SDK and forwards it to Gesher with the secret key:
app.post('/api/push/subscribe', async (req, res) => {
const r = await fetch('https://api.gesher.pro/subscribe', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GESHER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(req.body),
})
res.status(r.status).send(await r.text())
})Unsubscribe uses the same JSON body (userId, endpoint) with DELETE:
app.post('/api/push/unsubscribe', async (req, res) => {
const r = await fetch('https://api.gesher.pro/unsubscribe', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.GESHER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(req.body),
})
res.status(r.status).send(await r.text())
})Configuration
| Option | Description |
|--------|-------------|
| subscribeEndpoint | Your backend URL; SDK POSTs { userId, subscription }. |
| unsubscribeEndpoint | Your backend URL; SDK POSTs { userId, endpoint }. |
| vapidPublicKey | Optional. URL-safe base64 public key; if omitted, fetched from vapidKeyEndpoint. |
| vapidKeyEndpoint | Optional. Defaults to https://api.gesher.pro/vapid-key. |
| serviceWorkerPath | Optional. Default /gesher-sw.js. |
| serviceWorkerScope | Optional. Default /. |
TypeScript
Types for config and payloads are exported from @gesher/sdk.
Docs
More detail: https://gesher.pro/docs
