@rivium/push-node 0.1.0 → 0.1.2
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/README.md +56 -4
- package/dist/modules/segments.d.ts +18 -1
- package/dist/modules/segments.js +21 -0
- package/dist/types.d.ts +22 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@ Server-side SDK for [RiviumPush](https://rivium.co) — push notifications, inbo
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @rivium-
|
|
8
|
+
npm install @rivium/push-node
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { RiviumPush } from '@rivium-
|
|
14
|
+
import { RiviumPush } from '@rivium/push-node';
|
|
15
15
|
|
|
16
16
|
const riviumPush = new RiviumPush({
|
|
17
17
|
apiKey: 'rv_live_xxxxxxxxxxxxxxxxxxxxx',
|
|
@@ -75,6 +75,41 @@ await riviumPush.push.broadcast({
|
|
|
75
75
|
});
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
### Handling the Response
|
|
79
|
+
|
|
80
|
+
Every send returns `{ success, failed, reason? }`. When the target had **zero registered devices** the message is not attempted and `reason` is set to `'no_recipients'` — distinct from a real delivery failure:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const result = await riviumPush.push.sendToUser({
|
|
84
|
+
userId: 'user-123',
|
|
85
|
+
title: 'Your order shipped',
|
|
86
|
+
body: 'Track it from the app',
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (result.reason === 'no_recipients') {
|
|
90
|
+
// User has no device registered with Rivium Push.
|
|
91
|
+
// Fall back to email / SMS, mark them as push-unreachable, etc.
|
|
92
|
+
} else if (result.failed > 0) {
|
|
93
|
+
// Real delivery failure on at least one device.
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### App Identifier
|
|
98
|
+
|
|
99
|
+
If your project has multiple apps (e.g. a shopping app and a chat app), use `appIdentifier` to target a specific app. This is the bundle ID / package name of the app (e.g. `com.myapp.ios`).
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// Send only to a specific app on the device
|
|
103
|
+
await riviumPush.push.sendToUser({
|
|
104
|
+
userId: 'user-123',
|
|
105
|
+
title: 'New Order',
|
|
106
|
+
body: 'Your order is ready',
|
|
107
|
+
appIdentifier: 'com.myshop.app', // only this app receives it
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> **Note:** `appIdentifier` is optional. If not set, the notification is sent to all apps registered under your project. Most projects have a single app, so you don't need to set it.
|
|
112
|
+
|
|
78
113
|
### Rich Notifications
|
|
79
114
|
|
|
80
115
|
```typescript
|
|
@@ -128,6 +163,16 @@ await riviumPush.inbox.sendToUsers({
|
|
|
128
163
|
},
|
|
129
164
|
});
|
|
130
165
|
|
|
166
|
+
// Send to a specific app only
|
|
167
|
+
await riviumPush.inbox.sendToUser({
|
|
168
|
+
userId: 'user-123',
|
|
169
|
+
appIdentifier: 'com.myshop.app',
|
|
170
|
+
content: {
|
|
171
|
+
title: 'Order Update',
|
|
172
|
+
body: 'Your order has shipped',
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
|
|
131
176
|
// Broadcast to all
|
|
132
177
|
await riviumPush.inbox.broadcast({
|
|
133
178
|
content: {
|
|
@@ -224,7 +269,14 @@ await riviumPush.scheduled.cancel(scheduled.id);
|
|
|
224
269
|
const webhook = await riviumPush.webhooks.create({
|
|
225
270
|
name: 'Order Events',
|
|
226
271
|
url: 'https://example.com/webhooks/rivium-push',
|
|
227
|
-
events: [
|
|
272
|
+
events: [
|
|
273
|
+
'message.sent',
|
|
274
|
+
'message.delivered',
|
|
275
|
+
'message.failed',
|
|
276
|
+
'message.no_recipients',
|
|
277
|
+
'message.opened',
|
|
278
|
+
'message.clicked',
|
|
279
|
+
],
|
|
228
280
|
secret: 'my-secret-key',
|
|
229
281
|
});
|
|
230
282
|
|
|
@@ -306,7 +358,7 @@ await riviumPush.inApp.activate('your-app-id', message.id);
|
|
|
306
358
|
## Error Handling
|
|
307
359
|
|
|
308
360
|
```typescript
|
|
309
|
-
import { RiviumPush, RiviumPushError } from '@rivium-
|
|
361
|
+
import { RiviumPush, RiviumPushError } from '@rivium/push-node';
|
|
310
362
|
|
|
311
363
|
try {
|
|
312
364
|
await riviumPush.push.sendToUser({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpClient } from '../client';
|
|
2
|
-
import { Segment, CreateSegmentOptions, UpdateSegmentOptions, Device } from '../types';
|
|
2
|
+
import { Segment, CreateSegmentOptions, UpdateSegmentOptions, Device, SegmentPreviewOptions, SegmentPreviewResult } from '../types';
|
|
3
3
|
export declare class Segments {
|
|
4
4
|
private client;
|
|
5
5
|
constructor(client: HttpClient);
|
|
@@ -41,4 +41,21 @@ export declare class Segments {
|
|
|
41
41
|
recalculateAll(): Promise<{
|
|
42
42
|
success: boolean;
|
|
43
43
|
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Preview a set of filters without saving. Returns the total match count
|
|
46
|
+
* plus a small sample of matching devices — useful for validating filters
|
|
47
|
+
* before creating a segment.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const { count, preview } = await rivium.segments.preview({
|
|
52
|
+
* filters: [
|
|
53
|
+
* { field: 'platform', operator: 'equals', value: 'ios' },
|
|
54
|
+
* { field: 'metadata.plan', operator: 'equals', value: 'premium' },
|
|
55
|
+
* ],
|
|
56
|
+
* });
|
|
57
|
+
* console.log(`${count} devices match`);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
preview(options?: SegmentPreviewOptions): Promise<SegmentPreviewResult>;
|
|
44
61
|
}
|
package/dist/modules/segments.js
CHANGED
|
@@ -53,5 +53,26 @@ class Segments {
|
|
|
53
53
|
async recalculateAll() {
|
|
54
54
|
return this.client.post('/segments/recalculate-all');
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Preview a set of filters without saving. Returns the total match count
|
|
58
|
+
* plus a small sample of matching devices — useful for validating filters
|
|
59
|
+
* before creating a segment.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const { count, preview } = await rivium.segments.preview({
|
|
64
|
+
* filters: [
|
|
65
|
+
* { field: 'platform', operator: 'equals', value: 'ios' },
|
|
66
|
+
* { field: 'metadata.plan', operator: 'equals', value: 'premium' },
|
|
67
|
+
* ],
|
|
68
|
+
* });
|
|
69
|
+
* console.log(`${count} devices match`);
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
async preview(options = {}) {
|
|
73
|
+
const { limit, ...body } = options;
|
|
74
|
+
const path = limit ? `/segments/preview?limit=${limit}` : '/segments/preview';
|
|
75
|
+
return this.client.post(path, body);
|
|
76
|
+
}
|
|
56
77
|
}
|
|
57
78
|
exports.Segments = Segments;
|
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface BillingInfo {
|
|
|
15
15
|
export interface SendResult {
|
|
16
16
|
success: number;
|
|
17
17
|
failed: number;
|
|
18
|
+
reason?: 'no_recipients';
|
|
18
19
|
billing?: BillingInfo;
|
|
19
20
|
}
|
|
20
21
|
export interface NotificationAction {
|
|
@@ -111,10 +112,11 @@ export interface Template {
|
|
|
111
112
|
createdAt: string;
|
|
112
113
|
updatedAt: string;
|
|
113
114
|
}
|
|
115
|
+
export type SegmentFilterOperator = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'greater_than' | 'less_than' | 'in' | 'not_in' | 'exists';
|
|
114
116
|
export interface SegmentFilter {
|
|
115
117
|
field: string;
|
|
116
|
-
operator:
|
|
117
|
-
value: string | number | string[];
|
|
118
|
+
operator: SegmentFilterOperator;
|
|
119
|
+
value: string | number | boolean | string[];
|
|
118
120
|
}
|
|
119
121
|
export interface CreateSegmentOptions {
|
|
120
122
|
name: string;
|
|
@@ -134,6 +136,23 @@ export interface Segment {
|
|
|
134
136
|
createdAt: string;
|
|
135
137
|
updatedAt: string;
|
|
136
138
|
}
|
|
139
|
+
export interface SegmentPreviewOptions {
|
|
140
|
+
filters?: SegmentFilter[];
|
|
141
|
+
/** Number of sample devices to return (max 50, default 20). */
|
|
142
|
+
limit?: number;
|
|
143
|
+
}
|
|
144
|
+
export interface SegmentPreviewResult {
|
|
145
|
+
/** Total number of devices matching the filters. */
|
|
146
|
+
count: number;
|
|
147
|
+
/** Small sample of matching devices (up to `limit`). */
|
|
148
|
+
preview: Array<{
|
|
149
|
+
deviceId: string;
|
|
150
|
+
platform: string;
|
|
151
|
+
userId: string | null;
|
|
152
|
+
topics: string[] | null;
|
|
153
|
+
metadata: Record<string, any> | null;
|
|
154
|
+
}>;
|
|
155
|
+
}
|
|
137
156
|
export interface CreateScheduledOptions {
|
|
138
157
|
title: string;
|
|
139
158
|
body: string;
|
|
@@ -279,7 +298,7 @@ export interface ABTest {
|
|
|
279
298
|
variants: any[];
|
|
280
299
|
createdAt: string;
|
|
281
300
|
}
|
|
282
|
-
export type WebhookEvent = 'message.sent' | 'message.delivered' | 'message.opened' | 'message.clicked' | 'device.registered' | 'device.unregistered';
|
|
301
|
+
export type WebhookEvent = 'message.sent' | 'message.delivered' | 'message.failed' | 'message.no_recipients' | 'message.opened' | 'message.clicked' | 'device.registered' | 'device.unregistered';
|
|
283
302
|
export interface CreateWebhookOptions {
|
|
284
303
|
name: string;
|
|
285
304
|
url: string;
|