@ariary/notification 3.0.6 → 3.0.9

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
@@ -30,12 +36,6 @@ Each message has the following shape:
30
36
  | `phone` | string \| string[] | Yes | Recipient phone number(s) |
31
37
  | `message` | string | Yes | SMS content |
32
38
 
33
- You can also pass a `SendOptions` object as the first argument:
34
-
35
- | Field | Type | Required | Description |
36
- |---|---|---|---|
37
- | `scheduledAt` | string | No | ISO date to schedule the SMS |
38
-
39
39
  ```ts
40
40
  // single recipient
41
41
  const task = await Ariari.send({ phone: '0340000000', message: 'Hello!' })
@@ -50,6 +50,55 @@ const task = await Ariari.send(
50
50
  )
51
51
  ```
52
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
+
53
102
  ## Track a Task
54
103
 
55
104
  `send()` returns a `Task` object. Call `.status()` to check delivery progress.
@@ -76,7 +125,8 @@ const task = await Ariari.send(
76
125
  | Field | Type | Description |
77
126
  |---|---|---|
78
127
  | `_id` | string | Task ID |
79
- | `status` | TaskStatus | Delivery counters |
128
+ | `status` | TaskStatus | Delivery counters per SMS |
129
+ | `statusPage` | TaskStatus | Delivery counters per SMS page |
80
130
  | `createdAt` | string | Creation date |
81
131
  | `scheduledAt` | string? | Scheduled date |
82
132
 
@@ -125,7 +175,7 @@ const task = await Ariari.send({ phone: '0340000000', message: 'Hello!' })
125
175
  const taskId = task.id // save this
126
176
 
127
177
  // later
128
- const task = await Ariari.getTask(taskId)
178
+ const task = Ariari.getTask(taskId)
129
179
  const status = await task.status()
130
180
  ```
131
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@ariary/notification",
3
- "version": "3.0.6",
4
- "description": "SMS et Notification Task SDK pour l'API Ariary",
3
+ "version": "3.0.9",
4
+ "description": "Ariary SMS & Notification SDK (ariari.mg) Send SMS in Madagascar with automatic phone normalization, bulk messaging, deferred/scheduled sending, delivery tracking, credit estimation. Supports Orange, Airtel, Telma. Multi-instance, TypeScript-first.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -23,7 +23,40 @@
23
23
  "ariary",
24
24
  "sms",
25
25
  "notification",
26
- "api"
26
+ "bulk-sms",
27
+ "sms-api",
28
+ "sms-gateway",
29
+ "sms-sdk",
30
+ "send-sms",
31
+ "messaging",
32
+ "text-message",
33
+ "madagascar",
34
+ "orange",
35
+ "airtel",
36
+ "telma",
37
+ "scheduled-sms",
38
+ "deferred-sms",
39
+ "delivery-tracking",
40
+ "delivery-status",
41
+ "sms-status",
42
+ "credit-estimation",
43
+ "phone-normalization",
44
+ "bulk-messaging",
45
+ "mass-sms",
46
+ "campaign",
47
+ "marketing-sms",
48
+ "transactional-sms",
49
+ "otp",
50
+ "verification",
51
+ "api",
52
+ "sdk",
53
+ "typescript",
54
+ "nodejs",
55
+ "node",
56
+ "africa",
57
+ "ariary-mg",
58
+ "ariari.mg",
59
+ "notification-service"
27
60
  ],
28
61
  "author": "Ariary",
29
62
  "license": "ISC",