@ariary/notification 3.0.5 → 3.0.8

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
@@ -8,6 +8,12 @@ SMS and notification task SDK for the Ariary API.
8
8
  yarn add @ariary/notification
9
9
  ```
10
10
 
11
+ ## Get your credentials
12
+
13
+ 1. Sign in at [ariari.mg](https://ariari.mg)
14
+ 2. Create a project
15
+ 3. You'll receive a `projectId` and a `secret`
16
+
11
17
  ## Setup
12
18
 
13
19
  ```ts
@@ -23,6 +29,13 @@ Ariari.config({
23
29
 
24
30
  `Ariari.send()` accepts one or more messages. Phone numbers are automatically normalized (`+261340000000`, `261340000000`, `0340000000` all work).
25
31
 
32
+ Each message has the following shape:
33
+
34
+ | Field | Type | Required | Description |
35
+ |---|---|---|---|
36
+ | `phone` | string \| string[] | Yes | Recipient phone number(s) |
37
+ | `message` | string | Yes | SMS content |
38
+
26
39
  ```ts
27
40
  // single recipient
28
41
  const task = await Ariari.send({ phone: '0340000000', message: 'Hello!' })
@@ -37,10 +50,96 @@ const task = await Ariari.send(
37
50
  )
38
51
  ```
39
52
 
53
+ #### Deferred sending
54
+
55
+ Pass a schedule string as the first argument to delay sending. Supports shorthand durations or ISO dates.
56
+
57
+ | Format | Example | Description |
58
+ |---|---|---|
59
+ | Minutes | `30m` | Send in 30 minutes |
60
+ | Hours | `2h` | Send in 2 hours |
61
+ | Combined | `1h30m` | Send in 1 hour 30 minutes |
62
+ | ISO date | `2026-03-01T08:00:00.000Z` | Send at exact date/time |
63
+
64
+ ```ts
65
+ // in 1 hour
66
+ const task = await Ariari.send('1h', { phone: '0340000000', message: 'See you soon!' })
67
+
68
+ // in 1h30m
69
+ const task = await Ariari.send('1h30m', { phone: '0340000000', message: 'Reminder' })
70
+
71
+ // at exact date
72
+ const task = await Ariari.send(
73
+ '2026-03-01T08:00:00.000Z',
74
+ { phone: '0340000000', message: 'Happy March!' }
75
+ )
76
+ ```
77
+
78
+ ## Estimate
79
+
80
+ Estimate credit consumption before sending.
81
+
82
+ | Field | Type | Required | Description |
83
+ |---|---|---|---|
84
+ | `text` | string | Yes | SMS content |
85
+ | `repeat` | number | No | Number of recipients (defaults to 1) |
86
+
87
+ Returns:
88
+
89
+ | Field | Type | Description |
90
+ |---|---|---|
91
+ | `sms` | number | Total SMS records (messages exceeding 9 pages are split into multiple SMS) |
92
+ | `credit` | number | Total page count (actual credit consumption) |
93
+
94
+ ```ts
95
+ const estimate = await Ariari.estimate(
96
+ { text: 'Bonjour, votre commande est prête', repeat: 9 },
97
+ { text: 'Votre code: 123456', repeat: 3 }
98
+ )
99
+ // { sms: 12, credit: 12 }
100
+ ```
101
+
40
102
  ## Track a Task
41
103
 
42
104
  `send()` returns a `Task` object. Call `.status()` to check delivery progress.
43
105
 
106
+ ### `task.status()` — TaskStatus
107
+
108
+ | Field | Type | Description |
109
+ |---|---|---|
110
+ | `total` | number | Total SMS count |
111
+ | `sent` | number | Successfully sent |
112
+ | `failed` | number | Failed to send |
113
+ | `delivered` | number | Confirmed delivered |
114
+
115
+ ### `task.status(count, page?)` — TaskWithDetails
116
+
117
+ | Field | Type | Description |
118
+ |---|---|---|
119
+ | `task` | TaskResponse | Task metadata (see below) |
120
+ | `sms` | SmsDetail[] | List of SMS details |
121
+ | `total` | number | Total SMS count |
122
+
123
+ ### TaskResponse
124
+
125
+ | Field | Type | Description |
126
+ |---|---|---|
127
+ | `_id` | string | Task ID |
128
+ | `status` | TaskStatus | Delivery counters per SMS |
129
+ | `statusPage` | TaskStatus | Delivery counters per SMS page |
130
+ | `createdAt` | string | Creation date |
131
+ | `scheduledAt` | string? | Scheduled date |
132
+
133
+ ### SmsDetail
134
+
135
+ | Field | Type | Description |
136
+ |---|---|---|
137
+ | `smsId` | string | SMS ID |
138
+ | `phone` | string | Recipient phone number |
139
+ | `message` | string | SMS content |
140
+ | `status` | SmsStatus | `SCHEDULED` \| `PENDING` \| `SENT` \| `DELIVERED` \| `FAILED` |
141
+ | `retryCount` | number | Number of retry attempts |
142
+
44
143
  ```ts
45
144
  const task = await Ariari.send({ phone: '0340000000', message: 'Hello!' })
46
145
 
@@ -76,7 +175,7 @@ const task = await Ariari.send({ phone: '0340000000', message: 'Hello!' })
76
175
  const taskId = task.id // save this
77
176
 
78
177
  // later
79
- const task = await Ariari.getTask(taskId)
178
+ const task = Ariari.getTask(taskId)
80
179
  const status = await task.status()
81
180
  ```
82
181
 
package/dist/index.d.mts CHANGED
@@ -21,9 +21,6 @@ type Message = {
21
21
  phone: string[] | string;
22
22
  message: string;
23
23
  };
24
- type SendOptions = {
25
- scheduledAt?: string;
26
- };
27
24
  declare enum SmsStatus {
28
25
  SCHEDULED = "SCHEDULED",
29
26
  PENDING = "PENDING",
@@ -57,6 +54,14 @@ type TaskWithDetails = {
57
54
  sms: SmsDetail[];
58
55
  total: number;
59
56
  };
57
+ type EstimateMessage = {
58
+ text: string;
59
+ repeat?: number;
60
+ };
61
+ type EstimateResponse = {
62
+ sms: number;
63
+ credit: number;
64
+ };
60
65
 
61
66
  declare class Task {
62
67
  id: string;
@@ -76,10 +81,12 @@ declare class Ariari {
76
81
  name?: string;
77
82
  }) => Ariari;
78
83
  static get: (name?: string) => Ariari;
79
- send: (...args: [SendOptions, ...Message[]] | Message[]) => Promise<Task>;
84
+ send: (...args: [string, ...Message[]] | Message[]) => Promise<Task>;
80
85
  getTask: (taskId: string) => Task;
81
- static send: (...args: [SendOptions, ...Message[]] | Message[]) => Promise<Task>;
82
- static getTask: (taskId: string) => Promise<Task>;
86
+ estimate: (...messages: EstimateMessage[]) => Promise<EstimateResponse>;
87
+ static send: (...args: [string, ...Message[]] | Message[]) => Promise<Task>;
88
+ static getTask: (taskId: string) => Task;
89
+ static estimate: (...messages: EstimateMessage[]) => Promise<EstimateResponse>;
83
90
  }
84
91
 
85
92
  export { SmsStatus, Ariari as default };
package/dist/index.d.ts CHANGED
@@ -21,9 +21,6 @@ type Message = {
21
21
  phone: string[] | string;
22
22
  message: string;
23
23
  };
24
- type SendOptions = {
25
- scheduledAt?: string;
26
- };
27
24
  declare enum SmsStatus {
28
25
  SCHEDULED = "SCHEDULED",
29
26
  PENDING = "PENDING",
@@ -57,6 +54,14 @@ type TaskWithDetails = {
57
54
  sms: SmsDetail[];
58
55
  total: number;
59
56
  };
57
+ type EstimateMessage = {
58
+ text: string;
59
+ repeat?: number;
60
+ };
61
+ type EstimateResponse = {
62
+ sms: number;
63
+ credit: number;
64
+ };
60
65
 
61
66
  declare class Task {
62
67
  id: string;
@@ -76,10 +81,12 @@ declare class Ariari {
76
81
  name?: string;
77
82
  }) => Ariari;
78
83
  static get: (name?: string) => Ariari;
79
- send: (...args: [SendOptions, ...Message[]] | Message[]) => Promise<Task>;
84
+ send: (...args: [string, ...Message[]] | Message[]) => Promise<Task>;
80
85
  getTask: (taskId: string) => Task;
81
- static send: (...args: [SendOptions, ...Message[]] | Message[]) => Promise<Task>;
82
- static getTask: (taskId: string) => Promise<Task>;
86
+ estimate: (...messages: EstimateMessage[]) => Promise<EstimateResponse>;
87
+ static send: (...args: [string, ...Message[]] | Message[]) => Promise<Task>;
88
+ static getTask: (taskId: string) => Task;
89
+ static estimate: (...messages: EstimateMessage[]) => Promise<EstimateResponse>;
83
90
  }
84
91
 
85
92
  export { SmsStatus, Ariari as default };
package/dist/index.js CHANGED
@@ -79,6 +79,17 @@ var SmsStatus = /* @__PURE__ */ ((SmsStatus2) => {
79
79
  })(SmsStatus || {});
80
80
 
81
81
  // src/index.ts
82
+ var parseSchedule = (input) => {
83
+ const match = input.match(/^(?:(\d+)h)?(?:(\d+)m)?$/);
84
+ if (match && (match[1] || match[2])) {
85
+ const ms = (parseInt(match[1] || "0") * 60 + parseInt(match[2] || "0")) * 6e4;
86
+ return new Date(Date.now() + ms).toISOString();
87
+ }
88
+ if (isNaN(Date.parse(input))) {
89
+ throw new Error(`Invalid schedule format: "${input}". Use a duration (e.g. "1h", "30m", "1h30m") or an ISO date.`);
90
+ }
91
+ return input;
92
+ };
82
93
  var instances = {};
83
94
  var Task = class {
84
95
  constructor(id, requester) {
@@ -97,20 +108,23 @@ var Task = class {
97
108
  var _Ariari = class _Ariari {
98
109
  constructor({ name = "main", ...config }) {
99
110
  this.send = async (...args) => {
100
- const hasOptions = args[0] && "scheduledAt" in args[0];
101
- const options = hasOptions ? args[0] : {};
102
- const data = hasOptions ? args.slice(1) : args;
111
+ const hasSchedule = typeof args[0] === "string";
112
+ const scheduledAt = hasSchedule ? parseSchedule(args[0]) : void 0;
113
+ const data = hasSchedule ? args.slice(1) : args;
103
114
  const body = {
104
115
  messages: data.map((item) => ({
105
116
  phones: (Array.isArray(item.phone) ? item.phone : [item.phone]).map(normalizePhoneNumber),
106
117
  message: item.message
107
118
  })),
108
- ...options.scheduledAt && { scheduledAt: options.scheduledAt }
119
+ ...scheduledAt && { scheduledAt }
109
120
  };
110
121
  const response = await this._requester.post("/api/sms/bulk", { body });
111
122
  return new Task(response._id, this._requester);
112
123
  };
113
124
  this.getTask = (taskId) => new Task(taskId, this._requester);
125
+ this.estimate = async (...messages) => {
126
+ return this._requester.post("/api/sms/estimate", { body: { messages } });
127
+ };
114
128
  this._config = config;
115
129
  this._requester = createRequester(config);
116
130
  instances[name] = this;
@@ -123,7 +137,8 @@ _Ariari.get = (name = "main") => {
123
137
  return instances[name];
124
138
  };
125
139
  _Ariari.send = async (...args) => await _Ariari.get("main")?.send(...args);
126
- _Ariari.getTask = async (taskId) => _Ariari.get("main")?.getTask(taskId);
140
+ _Ariari.getTask = (taskId) => _Ariari.get("main")?.getTask(taskId);
141
+ _Ariari.estimate = async (...messages) => await _Ariari.get("main")?.estimate(...messages);
127
142
  var Ariari = _Ariari;
128
143
  var src_default = Ariari;
129
144
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -52,6 +52,17 @@ var SmsStatus = /* @__PURE__ */ ((SmsStatus2) => {
52
52
  })(SmsStatus || {});
53
53
 
54
54
  // src/index.ts
55
+ var parseSchedule = (input) => {
56
+ const match = input.match(/^(?:(\d+)h)?(?:(\d+)m)?$/);
57
+ if (match && (match[1] || match[2])) {
58
+ const ms = (parseInt(match[1] || "0") * 60 + parseInt(match[2] || "0")) * 6e4;
59
+ return new Date(Date.now() + ms).toISOString();
60
+ }
61
+ if (isNaN(Date.parse(input))) {
62
+ throw new Error(`Invalid schedule format: "${input}". Use a duration (e.g. "1h", "30m", "1h30m") or an ISO date.`);
63
+ }
64
+ return input;
65
+ };
55
66
  var instances = {};
56
67
  var Task = class {
57
68
  constructor(id, requester) {
@@ -70,20 +81,23 @@ var Task = class {
70
81
  var _Ariari = class _Ariari {
71
82
  constructor({ name = "main", ...config }) {
72
83
  this.send = async (...args) => {
73
- const hasOptions = args[0] && "scheduledAt" in args[0];
74
- const options = hasOptions ? args[0] : {};
75
- const data = hasOptions ? args.slice(1) : args;
84
+ const hasSchedule = typeof args[0] === "string";
85
+ const scheduledAt = hasSchedule ? parseSchedule(args[0]) : void 0;
86
+ const data = hasSchedule ? args.slice(1) : args;
76
87
  const body = {
77
88
  messages: data.map((item) => ({
78
89
  phones: (Array.isArray(item.phone) ? item.phone : [item.phone]).map(normalizePhoneNumber),
79
90
  message: item.message
80
91
  })),
81
- ...options.scheduledAt && { scheduledAt: options.scheduledAt }
92
+ ...scheduledAt && { scheduledAt }
82
93
  };
83
94
  const response = await this._requester.post("/api/sms/bulk", { body });
84
95
  return new Task(response._id, this._requester);
85
96
  };
86
97
  this.getTask = (taskId) => new Task(taskId, this._requester);
98
+ this.estimate = async (...messages) => {
99
+ return this._requester.post("/api/sms/estimate", { body: { messages } });
100
+ };
87
101
  this._config = config;
88
102
  this._requester = createRequester(config);
89
103
  instances[name] = this;
@@ -96,7 +110,8 @@ _Ariari.get = (name = "main") => {
96
110
  return instances[name];
97
111
  };
98
112
  _Ariari.send = async (...args) => await _Ariari.get("main")?.send(...args);
99
- _Ariari.getTask = async (taskId) => _Ariari.get("main")?.getTask(taskId);
113
+ _Ariari.getTask = (taskId) => _Ariari.get("main")?.getTask(taskId);
114
+ _Ariari.estimate = async (...messages) => await _Ariari.get("main")?.estimate(...messages);
100
115
  var Ariari = _Ariari;
101
116
  var src_default = Ariari;
102
117
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ariary/notification",
3
- "version": "3.0.5",
3
+ "version": "3.0.8",
4
4
  "description": "SMS et Notification Task SDK pour l'API Ariary",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",