@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 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-push/node
8
+ npm install @rivium/push-node
9
9
  ```
10
10
 
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
- import { RiviumPush } from '@rivium-push/node';
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: ['message.delivered', 'message.opened', 'message.clicked'],
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-push/node';
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
  }
@@ -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: 'equals' | 'contains' | 'starts_with' | 'in' | 'gt' | 'lt' | 'between';
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivium/push-node",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/Rivium-co/rivium-push-nodejs-sdk.git"