@suprsend/node-sdk 1.1.2 → 1.2.0

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/dist/index.js CHANGED
@@ -13,6 +13,12 @@ Object.defineProperty(exports, "Event", {
13
13
  return _event["default"];
14
14
  }
15
15
  });
16
+ Object.defineProperty(exports, "SubscribersListBroadcast", {
17
+ enumerable: true,
18
+ get: function get() {
19
+ return _subscribers_list.SubscribersListBroadcast;
20
+ }
21
+ });
16
22
  exports.Suprsend = void 0;
17
23
  Object.defineProperty(exports, "Workflow", {
18
24
  enumerable: true,
@@ -41,6 +47,8 @@ var _subscriber = _interopRequireDefault(require("./subscriber"));
41
47
 
42
48
  var _subscribers_bulk = _interopRequireDefault(require("./subscribers_bulk"));
43
49
 
50
+ var _subscribers_list = require("./subscribers_list");
51
+
44
52
  var _brands = _interopRequireDefault(require("./brands"));
45
53
 
46
54
  var _constants = require("./constants");
@@ -69,6 +77,7 @@ var Suprsend = /*#__PURE__*/function () {
69
77
  this._bulk_users = new _subscribers_bulk["default"](this);
70
78
  this._user = new _subscriber["default"](this);
71
79
  this.brands = new _brands["default"](this);
80
+ this.subscribers_list = new _subscribers_list.SubscribersListApi(this);
72
81
 
73
82
  this._validate();
74
83
  }
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "http://github.com/suprsend/suprsend-node-sdk/request_json/list_broadcast.json",
4
+ "title": "list_broadcast_request",
5
+ "description": "Json schema for list_broadcast request",
6
+ "$comment": "Json schema for list_broadcast request",
7
+ "type": "object",
8
+ "properties": {
9
+ "$idempotency_key": {
10
+ "type": ["string", "null"],
11
+ "maxLength": 64,
12
+ "description": "unique id provided by client for request"
13
+ },
14
+ "brand_id": {
15
+ "type": ["string", "null"],
16
+ "maxLength": 64,
17
+ "description": "brand id for workflow to be run in context of a brand"
18
+ },
19
+ "$insert_id": {
20
+ "type": "string",
21
+ "minLength": 36,
22
+ "description": "unique uuid generated per request"
23
+ },
24
+ "$time": {
25
+ "type": "integer",
26
+ "minimum": 1640995200000,
27
+ "description": "Timestamp: unix epoch in milliseconds"
28
+ },
29
+ "list_id": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "description": "SubscriberList id"
33
+ },
34
+ "template": {
35
+ "$ref": "#/definitions/non_empty_string",
36
+ "description": "slug of Template"
37
+ },
38
+ "notification_category": {
39
+ "$ref": "#/definitions/non_empty_string",
40
+ "description": "slug of Notification category"
41
+ },
42
+ "delay": {
43
+ "type": ["string", "integer"],
44
+ "minimum": 0,
45
+ "description": "If string: format [XX]d[XX]h[XX]m[XX]s e.g 1d2h30m10s(for 1day 2hours 30minutes 10sec). If integer: value in number of seconds"
46
+ },
47
+ "trigger_at": {
48
+ "type": "string",
49
+ "description": "timestamp in ISO-8601 format. e.g 2021-08-27T20:14:51.643Z"
50
+ },
51
+ "data": {
52
+ "type": "object",
53
+ "description": "variables to be used in workflow. e.g replacing templates variables."
54
+ }
55
+ },
56
+ "required": [
57
+ "$insert_id",
58
+ "$time",
59
+ "list_id",
60
+ "template",
61
+ "notification_category",
62
+ "data"
63
+ ],
64
+ "definitions": {
65
+ "non_empty_string": {
66
+ "type": "string",
67
+ "minLength": 2
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,484 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.SubscribersListBroadcast = exports.SubscribersListApi = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
15
+
16
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
17
+
18
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
19
+
20
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
21
+
22
+ var _utils = require("./utils");
23
+
24
+ var _signature = _interopRequireDefault(require("./signature"));
25
+
26
+ var _axios = _interopRequireDefault(require("axios"));
27
+
28
+ var _constants = require("./constants");
29
+
30
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
31
+
32
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
33
+
34
+ var SubscribersListBroadcast = /*#__PURE__*/function () {
35
+ function SubscribersListBroadcast(body) {
36
+ var kwargs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
37
+ (0, _classCallCheck2["default"])(this, SubscribersListBroadcast);
38
+
39
+ if (!(body instanceof Object)) {
40
+ throw new _utils.SuprsendError("broadcast body must be a json/dictionary");
41
+ }
42
+
43
+ this.body = body;
44
+ this.idempotency_key = kwargs === null || kwargs === void 0 ? void 0 : kwargs.idempotency_key;
45
+ this.brand_id = kwargs === null || kwargs === void 0 ? void 0 : kwargs.brand_id;
46
+ }
47
+
48
+ (0, _createClass2["default"])(SubscribersListBroadcast, [{
49
+ key: "get_final_json",
50
+ value: function get_final_json() {
51
+ this.body["$insert_id"] = (0, _utils.uuid)();
52
+ this.body["$time"] = (0, _utils.epoch_milliseconds)();
53
+
54
+ if (this.idempotency_key) {
55
+ this.body["$idempotency_key"] = this.idempotency_key;
56
+ }
57
+
58
+ if (this.brand_id) {
59
+ this.body["brand_id"] = this.brand_id;
60
+ }
61
+
62
+ this.body = (0, _utils.validate_list_broadcast_body_schema)(this.body);
63
+ var apparent_size = (0, _utils.get_apparent_list_broadcast_body_size)(this.body);
64
+
65
+ if (apparent_size > _constants.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES) {
66
+ throw new _utils.SuprsendError("SubscriberListBroadcast body too big - ".concat(apparent_size, " Bytes, must not cross ").concat(_constants.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE));
67
+ }
68
+
69
+ return [this.body, apparent_size];
70
+ }
71
+ }]);
72
+ return SubscribersListBroadcast;
73
+ }();
74
+
75
+ exports.SubscribersListBroadcast = SubscribersListBroadcast;
76
+
77
+ var SubscribersListApi = /*#__PURE__*/function () {
78
+ function SubscribersListApi(config) {
79
+ (0, _classCallCheck2["default"])(this, SubscribersListApi);
80
+ this.config = config;
81
+ this.subscriber_list_url = "".concat(this.config.base_url, "v1/subscriber_list/");
82
+ this.broadcast_url = "".concat(this.config.base_url).concat(this.config.workspace_key, "/broadcast/");
83
+ this.__headers = this.__common_headers();
84
+ this.non_error_default_response = {
85
+ success: true
86
+ };
87
+ }
88
+
89
+ (0, _createClass2["default"])(SubscribersListApi, [{
90
+ key: "__common_headers",
91
+ value: function __common_headers() {
92
+ return {
93
+ "Content-Type": "application/json; charset=utf-8",
94
+ "User-Agent": this.config.user_agent
95
+ };
96
+ }
97
+ }, {
98
+ key: "__dynamic_headers",
99
+ value: function __dynamic_headers() {
100
+ return {
101
+ Date: new Date().toUTCString()
102
+ };
103
+ }
104
+ }, {
105
+ key: "_validate_list_id",
106
+ value: function _validate_list_id(list_id) {
107
+ if (typeof list_id != "string") {
108
+ throw new _utils.SuprsendError("list_id must be a string");
109
+ }
110
+
111
+ var cleaned_list_id = list_id.trim();
112
+
113
+ if (!cleaned_list_id) {
114
+ throw new _utils.SuprsendError("missing list_id");
115
+ }
116
+
117
+ return list_id;
118
+ }
119
+ }, {
120
+ key: "create",
121
+ value: function () {
122
+ var _create = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(payload) {
123
+ var list_id, headers, content_text, signature, response;
124
+ return _regenerator["default"].wrap(function _callee$(_context) {
125
+ while (1) {
126
+ switch (_context.prev = _context.next) {
127
+ case 0:
128
+ if (payload) {
129
+ _context.next = 2;
130
+ break;
131
+ }
132
+
133
+ throw new _utils.SuprsendError("missing payload");
134
+
135
+ case 2:
136
+ list_id = payload["list_id"];
137
+
138
+ if (list_id) {
139
+ _context.next = 5;
140
+ break;
141
+ }
142
+
143
+ throw new _utils.SuprsendError("missing list_id in payload");
144
+
145
+ case 5:
146
+ list_id = this._validate_list_id(list_id);
147
+ payload["list_id"] = list_id;
148
+ headers = _objectSpread(_objectSpread({}, this.__headers), this.__dynamic_headers());
149
+ content_text = JSON.stringify(payload);
150
+ signature = (0, _signature["default"])(this.subscriber_list_url, "POST", content_text, headers, this.config.workspace_secret);
151
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
152
+ _context.prev = 11;
153
+ _context.next = 14;
154
+ return _axios["default"].post(this.subscriber_list_url, content_text, {
155
+ headers: headers
156
+ });
157
+
158
+ case 14:
159
+ response = _context.sent;
160
+ return _context.abrupt("return", response.data);
161
+
162
+ case 18:
163
+ _context.prev = 18;
164
+ _context.t0 = _context["catch"](11);
165
+ throw new _utils.SuprsendApiError(_context.t0);
166
+
167
+ case 21:
168
+ case "end":
169
+ return _context.stop();
170
+ }
171
+ }
172
+ }, _callee, this, [[11, 18]]);
173
+ }));
174
+
175
+ function create(_x) {
176
+ return _create.apply(this, arguments);
177
+ }
178
+
179
+ return create;
180
+ }()
181
+ }, {
182
+ key: "cleaned_limit_offset",
183
+ value: function cleaned_limit_offset(limit, offset) {
184
+ var cleaned_limit = typeof limit === "number" && limit > 0 && limit <= 1000 ? limit : 20;
185
+ var cleaned_offset = typeof offset === "number" && offset >= 0 ? offset : 0;
186
+ return [cleaned_limit, cleaned_offset];
187
+ }
188
+ }, {
189
+ key: "get_all",
190
+ value: function () {
191
+ var _get_all = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
192
+ var kwargs,
193
+ limit,
194
+ offset,
195
+ _this$cleaned_limit_o,
196
+ _this$cleaned_limit_o2,
197
+ cleaned_limit,
198
+ cleaner_offset,
199
+ final_url_obj,
200
+ url,
201
+ headers,
202
+ signature,
203
+ response,
204
+ _args2 = arguments;
205
+
206
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
207
+ while (1) {
208
+ switch (_context2.prev = _context2.next) {
209
+ case 0:
210
+ kwargs = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {};
211
+ limit = kwargs === null || kwargs === void 0 ? void 0 : kwargs.limit;
212
+ offset = kwargs === null || kwargs === void 0 ? void 0 : kwargs.offset;
213
+ _this$cleaned_limit_o = this.cleaned_limit_offset(limit, offset), _this$cleaned_limit_o2 = (0, _slicedToArray2["default"])(_this$cleaned_limit_o, 2), cleaned_limit = _this$cleaned_limit_o2[0], cleaner_offset = _this$cleaned_limit_o2[1];
214
+ final_url_obj = new URL("".concat(this.config.base_url, "v1/subscriber_list"));
215
+ final_url_obj.searchParams.append("limit", cleaned_limit);
216
+ final_url_obj.searchParams.append("offset", cleaner_offset);
217
+ url = final_url_obj.href;
218
+ headers = _objectSpread(_objectSpread({}, this.__headers), this.__dynamic_headers());
219
+ signature = (0, _signature["default"])(url, "GET", "", headers, this.config.workspace_secret);
220
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
221
+ _context2.prev = 11;
222
+ _context2.next = 14;
223
+ return _axios["default"].get(url, {
224
+ headers: headers
225
+ });
226
+
227
+ case 14:
228
+ response = _context2.sent;
229
+ return _context2.abrupt("return", response.data);
230
+
231
+ case 18:
232
+ _context2.prev = 18;
233
+ _context2.t0 = _context2["catch"](11);
234
+ throw new _utils.SuprsendApiError(_context2.t0);
235
+
236
+ case 21:
237
+ case "end":
238
+ return _context2.stop();
239
+ }
240
+ }
241
+ }, _callee2, this, [[11, 18]]);
242
+ }));
243
+
244
+ function get_all() {
245
+ return _get_all.apply(this, arguments);
246
+ }
247
+
248
+ return get_all;
249
+ }()
250
+ }, {
251
+ key: "__subscriber_list_detail_url",
252
+ value: function __subscriber_list_detail_url(list_id) {
253
+ return "".concat(this.config.base_url, "v1/subscriber_list/").concat(list_id, "/");
254
+ }
255
+ }, {
256
+ key: "get",
257
+ value: function () {
258
+ var _get = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(list_id) {
259
+ var cleaned_list_id, url, headers, signature, response;
260
+ return _regenerator["default"].wrap(function _callee3$(_context3) {
261
+ while (1) {
262
+ switch (_context3.prev = _context3.next) {
263
+ case 0:
264
+ cleaned_list_id = this._validate_list_id(list_id);
265
+ url = this.__subscriber_list_detail_url(cleaned_list_id);
266
+ headers = _objectSpread(_objectSpread({}, this.__headers), this.__dynamic_headers());
267
+ signature = (0, _signature["default"])(url, "GET", "", headers, this.config.workspace_secret);
268
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
269
+ _context3.prev = 5;
270
+ _context3.next = 8;
271
+ return _axios["default"].get(url, {
272
+ headers: headers
273
+ });
274
+
275
+ case 8:
276
+ response = _context3.sent;
277
+ return _context3.abrupt("return", response.data);
278
+
279
+ case 12:
280
+ _context3.prev = 12;
281
+ _context3.t0 = _context3["catch"](5);
282
+ throw new _utils.SuprsendApiError(_context3.t0);
283
+
284
+ case 15:
285
+ case "end":
286
+ return _context3.stop();
287
+ }
288
+ }
289
+ }, _callee3, this, [[5, 12]]);
290
+ }));
291
+
292
+ function get(_x2) {
293
+ return _get.apply(this, arguments);
294
+ }
295
+
296
+ return get;
297
+ }()
298
+ }, {
299
+ key: "add",
300
+ value: function () {
301
+ var _add = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(list_id, distinct_ids) {
302
+ var cleaned_list_id, url, headers, content_text, signature, response;
303
+ return _regenerator["default"].wrap(function _callee4$(_context4) {
304
+ while (1) {
305
+ switch (_context4.prev = _context4.next) {
306
+ case 0:
307
+ cleaned_list_id = this._validate_list_id(list_id);
308
+
309
+ if (Array.isArray(distinct_ids)) {
310
+ _context4.next = 3;
311
+ break;
312
+ }
313
+
314
+ throw new _utils.SuprsendError("distinct_ids must be list of strings");
315
+
316
+ case 3:
317
+ if (!(distinct_ids.length === 0)) {
318
+ _context4.next = 5;
319
+ break;
320
+ }
321
+
322
+ return _context4.abrupt("return", this.non_error_default_response);
323
+
324
+ case 5:
325
+ url = "".concat(this.__subscriber_list_detail_url(cleaned_list_id), "subscriber/add");
326
+ headers = _objectSpread(_objectSpread({}, this.__headers), this.__dynamic_headers());
327
+ content_text = JSON.stringify({
328
+ distinct_ids: distinct_ids
329
+ });
330
+ signature = (0, _signature["default"])(url, "POST", content_text, headers, this.config.workspace_secret);
331
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
332
+ _context4.prev = 10;
333
+ _context4.next = 13;
334
+ return _axios["default"].post(url, content_text, {
335
+ headers: headers
336
+ });
337
+
338
+ case 13:
339
+ response = _context4.sent;
340
+ return _context4.abrupt("return", response.data);
341
+
342
+ case 17:
343
+ _context4.prev = 17;
344
+ _context4.t0 = _context4["catch"](10);
345
+ throw new _utils.SuprsendApiError(_context4.t0);
346
+
347
+ case 20:
348
+ case "end":
349
+ return _context4.stop();
350
+ }
351
+ }
352
+ }, _callee4, this, [[10, 17]]);
353
+ }));
354
+
355
+ function add(_x3, _x4) {
356
+ return _add.apply(this, arguments);
357
+ }
358
+
359
+ return add;
360
+ }()
361
+ }, {
362
+ key: "remove",
363
+ value: function () {
364
+ var _remove = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(list_id) {
365
+ var distinct_ids,
366
+ cleaned_list_id,
367
+ url,
368
+ headers,
369
+ content_text,
370
+ signature,
371
+ response,
372
+ _args5 = arguments;
373
+ return _regenerator["default"].wrap(function _callee5$(_context5) {
374
+ while (1) {
375
+ switch (_context5.prev = _context5.next) {
376
+ case 0:
377
+ distinct_ids = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : [];
378
+ cleaned_list_id = this._validate_list_id(list_id);
379
+
380
+ if (Array.isArray(distinct_ids)) {
381
+ _context5.next = 4;
382
+ break;
383
+ }
384
+
385
+ throw new _utils.SuprsendError("distinct_ids must be list of strings");
386
+
387
+ case 4:
388
+ if (!(distinct_ids.length === 0)) {
389
+ _context5.next = 6;
390
+ break;
391
+ }
392
+
393
+ return _context5.abrupt("return", this.non_error_default_response);
394
+
395
+ case 6:
396
+ url = "".concat(this.__subscriber_list_detail_url(cleaned_list_id), "subscriber/remove");
397
+ headers = _objectSpread(_objectSpread({}, this.__headers), this.__dynamic_headers());
398
+ content_text = JSON.stringify({
399
+ distinct_ids: distinct_ids
400
+ });
401
+ signature = (0, _signature["default"])(url, "POST", content_text, headers, this.config.workspace_secret);
402
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
403
+ _context5.prev = 11;
404
+ _context5.next = 14;
405
+ return _axios["default"].post(url, content_text, {
406
+ headers: headers
407
+ });
408
+
409
+ case 14:
410
+ response = _context5.sent;
411
+ return _context5.abrupt("return", response.data);
412
+
413
+ case 18:
414
+ _context5.prev = 18;
415
+ _context5.t0 = _context5["catch"](11);
416
+ throw new _utils.SuprsendApiError(_context5.t0);
417
+
418
+ case 21:
419
+ case "end":
420
+ return _context5.stop();
421
+ }
422
+ }
423
+ }, _callee5, this, [[11, 18]]);
424
+ }));
425
+
426
+ function remove(_x5) {
427
+ return _remove.apply(this, arguments);
428
+ }
429
+
430
+ return remove;
431
+ }() // async broadcast(broadcast_instance) {
432
+ // if (!(broadcast_instance instanceof SubscribersListBroadcast)) {
433
+ // throw new SuprsendError(
434
+ // "argument must be an instance of suprsend.SubscriberListBroadcast"
435
+ // );
436
+ // }
437
+ // const [broadcast_body, body_size] = broadcast_instance.get_final_json(
438
+ // this.config
439
+ // );
440
+ // const headers = { ...this.__headers, ...this.__dynamic_headers() };
441
+ // const content_text = JSON.stringify(broadcast_body);
442
+ // const signature = get_request_signature(
443
+ // this.broadcast_url,
444
+ // "POST",
445
+ // content_text,
446
+ // headers,
447
+ // this.config.workspace_secret
448
+ // );
449
+ // headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
450
+ // try {
451
+ // const response = await axios.post(this.broadcast_url, content_text, {
452
+ // headers,
453
+ // });
454
+ // const ok_response = Math.floor(response.status / 100) == 2;
455
+ // if (ok_response) {
456
+ // return {
457
+ // success: true,
458
+ // status: "success",
459
+ // status_code: response.status,
460
+ // message: response.statusText,
461
+ // };
462
+ // } else {
463
+ // return {
464
+ // success: false,
465
+ // status: "fail",
466
+ // status_code: response.status,
467
+ // message: response.statusText,
468
+ // };
469
+ // }
470
+ // } catch (err) {
471
+ // return {
472
+ // success: false,
473
+ // status: "fail",
474
+ // status_code: err.status || 500,
475
+ // message: err.message,
476
+ // };
477
+ // }
478
+ // }
479
+
480
+ }]);
481
+ return SubscribersListApi;
482
+ }();
483
+
484
+ exports.SubscribersListApi = SubscribersListApi;
package/dist/utils.js CHANGED
@@ -10,6 +10,7 @@ exports.base64Encode = base64Encode;
10
10
  exports.epoch_milliseconds = epoch_milliseconds;
11
11
  exports.get_apparent_event_size = get_apparent_event_size;
12
12
  exports.get_apparent_identity_event_size = get_apparent_identity_event_size;
13
+ exports.get_apparent_list_broadcast_body_size = get_apparent_list_broadcast_body_size;
13
14
  exports.get_apparent_workflow_body_size = get_apparent_workflow_body_size;
14
15
  exports.has_special_char = void 0;
15
16
  exports.is_empty = is_empty;
@@ -17,6 +18,7 @@ exports.is_object = is_object;
17
18
  exports.is_string = is_string;
18
19
  exports.resolveTilde = resolveTilde;
19
20
  exports.uuid = uuid;
21
+ exports.validate_list_broadcast_body_schema = validate_list_broadcast_body_schema;
20
22
  exports.validate_track_event_schema = validate_track_event_schema;
21
23
  exports.validate_workflow_body_schema = validate_workflow_body_schema;
22
24
 
@@ -58,6 +60,8 @@ var workflow_schema = require("./request_json/workflow.json");
58
60
 
59
61
  var event_schema = require("./request_json/event.json");
60
62
 
63
+ var list_broadcast_schema = require("./request_json/list_broadcast.json");
64
+
61
65
  function base64Encode(file) {
62
66
  var body = _fs["default"].readFileSync(file);
63
67
 
@@ -215,6 +219,28 @@ function validate_track_event_schema(body) {
215
219
  }
216
220
  }
217
221
 
222
+ function validate_list_broadcast_body_schema(body) {
223
+ if (!(body !== null && body !== void 0 && body.data)) {
224
+ body.data = {};
225
+ }
226
+
227
+ if (!(body.data instanceof Object)) {
228
+ throw new SuprsendError("data must be a object");
229
+ }
230
+
231
+ var schema = list_broadcast_schema;
232
+ var v = new _jsonschema.Validator();
233
+ var validated_data = v.validate(body, schema);
234
+
235
+ if (validated_data.valid) {
236
+ return body;
237
+ } else {
238
+ var error_obj = validated_data.errors[0];
239
+ var error_msg = "".concat(error_obj.property, " ").concat(error_obj.message);
240
+ throw new SuprsendError(error_msg);
241
+ }
242
+ }
243
+
218
244
  function get_apparent_workflow_body_size(body, is_part_of_bulk) {
219
245
  var extra_bytes = _constants.WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES;
220
246
  var apparent_body = body;
@@ -338,6 +364,11 @@ function get_apparent_event_size(event, is_part_of_bulk) {
338
364
  }
339
365
 
340
366
  function get_apparent_identity_event_size(event) {
341
- var body_size = JSON.stringify(event);
367
+ var body_size = JSON.stringify(event).length;
368
+ return body_size;
369
+ }
370
+
371
+ function get_apparent_list_broadcast_body_size(body) {
372
+ var body_size = JSON.stringify(body).length;
342
373
  return body_size;
343
374
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suprsend/node-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Suprsend Node SDK to trigger workflow from backend",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -6,6 +6,10 @@ import Event, { EventCollector } from "./event";
6
6
  import { BulkEventsFactory } from "./events_bulk";
7
7
  import SubscriberFactory from "./subscriber";
8
8
  import BulkSubscribersFactory from "./subscribers_bulk";
9
+ import {
10
+ SubscribersListApi,
11
+ SubscribersListBroadcast,
12
+ } from "./subscribers_list";
9
13
  import BrandsApi from "./brands";
10
14
  import { DEFAULT_UAT_URL, DEFAULT_URL } from "./constants";
11
15
 
@@ -34,6 +38,7 @@ class Suprsend {
34
38
  this._user = new SubscriberFactory(this);
35
39
 
36
40
  this.brands = new BrandsApi(this);
41
+ this.subscribers_list = new SubscribersListApi(this);
37
42
 
38
43
  this._validate();
39
44
  }
@@ -126,4 +131,4 @@ class Suprsend {
126
131
  }
127
132
  }
128
133
 
129
- export { Suprsend, Event, Workflow };
134
+ export { Suprsend, Event, Workflow, SubscribersListBroadcast };
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "http://github.com/suprsend/suprsend-node-sdk/request_json/list_broadcast.json",
4
+ "title": "list_broadcast_request",
5
+ "description": "Json schema for list_broadcast request",
6
+ "$comment": "Json schema for list_broadcast request",
7
+ "type": "object",
8
+ "properties": {
9
+ "$idempotency_key": {
10
+ "type": ["string", "null"],
11
+ "maxLength": 64,
12
+ "description": "unique id provided by client for request"
13
+ },
14
+ "brand_id": {
15
+ "type": ["string", "null"],
16
+ "maxLength": 64,
17
+ "description": "brand id for workflow to be run in context of a brand"
18
+ },
19
+ "$insert_id": {
20
+ "type": "string",
21
+ "minLength": 36,
22
+ "description": "unique uuid generated per request"
23
+ },
24
+ "$time": {
25
+ "type": "integer",
26
+ "minimum": 1640995200000,
27
+ "description": "Timestamp: unix epoch in milliseconds"
28
+ },
29
+ "list_id": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "description": "SubscriberList id"
33
+ },
34
+ "template": {
35
+ "$ref": "#/definitions/non_empty_string",
36
+ "description": "slug of Template"
37
+ },
38
+ "notification_category": {
39
+ "$ref": "#/definitions/non_empty_string",
40
+ "description": "slug of Notification category"
41
+ },
42
+ "delay": {
43
+ "type": ["string", "integer"],
44
+ "minimum": 0,
45
+ "description": "If string: format [XX]d[XX]h[XX]m[XX]s e.g 1d2h30m10s(for 1day 2hours 30minutes 10sec). If integer: value in number of seconds"
46
+ },
47
+ "trigger_at": {
48
+ "type": "string",
49
+ "description": "timestamp in ISO-8601 format. e.g 2021-08-27T20:14:51.643Z"
50
+ },
51
+ "data": {
52
+ "type": "object",
53
+ "description": "variables to be used in workflow. e.g replacing templates variables."
54
+ }
55
+ },
56
+ "required": [
57
+ "$insert_id",
58
+ "$time",
59
+ "list_id",
60
+ "template",
61
+ "notification_category",
62
+ "data"
63
+ ],
64
+ "definitions": {
65
+ "non_empty_string": {
66
+ "type": "string",
67
+ "minLength": 2
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,296 @@
1
+ import {
2
+ SuprsendError,
3
+ SuprsendApiError,
4
+ validate_list_broadcast_body_schema,
5
+ get_apparent_list_broadcast_body_size,
6
+ uuid,
7
+ epoch_milliseconds,
8
+ } from "./utils";
9
+ import get_request_signature from "./signature";
10
+ import axios from "axios";
11
+ import {
12
+ SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES,
13
+ SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE,
14
+ } from "./constants";
15
+
16
+ class SubscribersListBroadcast {
17
+ constructor(body, kwargs = {}) {
18
+ if (!(body instanceof Object)) {
19
+ throw new SuprsendError("broadcast body must be a json/dictionary");
20
+ }
21
+ this.body = body;
22
+ this.idempotency_key = kwargs?.idempotency_key;
23
+ this.brand_id = kwargs?.brand_id;
24
+ }
25
+
26
+ get_final_json() {
27
+ this.body["$insert_id"] = uuid();
28
+ this.body["$time"] = epoch_milliseconds();
29
+ if (this.idempotency_key) {
30
+ this.body["$idempotency_key"] = this.idempotency_key;
31
+ }
32
+ if (this.brand_id) {
33
+ this.body["brand_id"] = this.brand_id;
34
+ }
35
+ this.body = validate_list_broadcast_body_schema(this.body);
36
+ const apparent_size = get_apparent_list_broadcast_body_size(this.body);
37
+ if (apparent_size > SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES) {
38
+ throw new SuprsendError(
39
+ `SubscriberListBroadcast body too big - ${apparent_size} Bytes, must not cross ${SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE}`
40
+ );
41
+ }
42
+ return [this.body, apparent_size];
43
+ }
44
+ }
45
+
46
+ class SubscribersListApi {
47
+ constructor(config) {
48
+ this.config = config;
49
+ this.subscriber_list_url = `${this.config.base_url}v1/subscriber_list/`;
50
+ this.broadcast_url = `${this.config.base_url}${this.config.workspace_key}/broadcast/`;
51
+ this.__headers = this.__common_headers();
52
+ this.non_error_default_response = { success: true };
53
+ }
54
+
55
+ __common_headers() {
56
+ return {
57
+ "Content-Type": "application/json; charset=utf-8",
58
+ "User-Agent": this.config.user_agent,
59
+ };
60
+ }
61
+
62
+ __dynamic_headers() {
63
+ return {
64
+ Date: new Date().toUTCString(),
65
+ };
66
+ }
67
+
68
+ _validate_list_id(list_id) {
69
+ if (typeof list_id != "string") {
70
+ throw new SuprsendError("list_id must be a string");
71
+ }
72
+ let cleaned_list_id = list_id.trim();
73
+ if (!cleaned_list_id) {
74
+ throw new SuprsendError("missing list_id");
75
+ }
76
+ return list_id;
77
+ }
78
+
79
+ async create(payload) {
80
+ if (!payload) {
81
+ throw new SuprsendError("missing payload");
82
+ }
83
+ let list_id = payload["list_id"];
84
+ if (!list_id) {
85
+ throw new SuprsendError("missing list_id in payload");
86
+ }
87
+ list_id = this._validate_list_id(list_id);
88
+ payload["list_id"] = list_id;
89
+
90
+ const headers = { ...this.__headers, ...this.__dynamic_headers() };
91
+ const content_text = JSON.stringify(payload);
92
+
93
+ const signature = get_request_signature(
94
+ this.subscriber_list_url,
95
+ "POST",
96
+ content_text,
97
+ headers,
98
+ this.config.workspace_secret
99
+ );
100
+ headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
101
+
102
+ try {
103
+ const response = await axios.post(
104
+ this.subscriber_list_url,
105
+ content_text,
106
+ { headers }
107
+ );
108
+ return response.data;
109
+ } catch (err) {
110
+ throw new SuprsendApiError(err);
111
+ }
112
+ }
113
+
114
+ cleaned_limit_offset(limit, offset) {
115
+ let cleaned_limit =
116
+ typeof limit === "number" && limit > 0 && limit <= 1000 ? limit : 20;
117
+ let cleaned_offset = typeof offset === "number" && offset >= 0 ? offset : 0;
118
+ return [cleaned_limit, cleaned_offset];
119
+ }
120
+
121
+ async get_all(kwargs = {}) {
122
+ let limit = kwargs?.limit;
123
+ let offset = kwargs?.offset;
124
+ const [cleaned_limit, cleaner_offset] = this.cleaned_limit_offset(
125
+ limit,
126
+ offset
127
+ );
128
+ const final_url_obj = new URL(`${this.config.base_url}v1/subscriber_list`);
129
+ final_url_obj.searchParams.append("limit", cleaned_limit);
130
+ final_url_obj.searchParams.append("offset", cleaner_offset);
131
+ const url = final_url_obj.href;
132
+
133
+ const headers = { ...this.__headers, ...this.__dynamic_headers() };
134
+
135
+ const signature = get_request_signature(
136
+ url,
137
+ "GET",
138
+ "",
139
+ headers,
140
+ this.config.workspace_secret
141
+ );
142
+ headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
143
+
144
+ try {
145
+ const response = await axios.get(url, { headers });
146
+ return response.data;
147
+ } catch (err) {
148
+ throw new SuprsendApiError(err);
149
+ }
150
+ }
151
+
152
+ __subscriber_list_detail_url(list_id) {
153
+ return `${this.config.base_url}v1/subscriber_list/${list_id}/`;
154
+ }
155
+
156
+ async get(list_id) {
157
+ const cleaned_list_id = this._validate_list_id(list_id);
158
+
159
+ const url = this.__subscriber_list_detail_url(cleaned_list_id);
160
+
161
+ const headers = { ...this.__headers, ...this.__dynamic_headers() };
162
+
163
+ const signature = get_request_signature(
164
+ url,
165
+ "GET",
166
+ "",
167
+ headers,
168
+ this.config.workspace_secret
169
+ );
170
+ headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
171
+
172
+ try {
173
+ const response = await axios.get(url, { headers });
174
+ return response.data;
175
+ } catch (err) {
176
+ throw new SuprsendApiError(err);
177
+ }
178
+ }
179
+
180
+ async add(list_id, distinct_ids) {
181
+ const cleaned_list_id = this._validate_list_id(list_id);
182
+ if (!Array.isArray(distinct_ids)) {
183
+ throw new SuprsendError("distinct_ids must be list of strings");
184
+ }
185
+ if (distinct_ids.length === 0) {
186
+ return this.non_error_default_response;
187
+ }
188
+
189
+ const url = `${this.__subscriber_list_detail_url(
190
+ cleaned_list_id
191
+ )}subscriber/add`;
192
+ const headers = { ...this.__headers, ...this.__dynamic_headers() };
193
+ const content_text = JSON.stringify({ distinct_ids: distinct_ids });
194
+
195
+ const signature = get_request_signature(
196
+ url,
197
+ "POST",
198
+ content_text,
199
+ headers,
200
+ this.config.workspace_secret
201
+ );
202
+ headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
203
+
204
+ try {
205
+ const response = await axios.post(url, content_text, { headers });
206
+ return response.data;
207
+ } catch (err) {
208
+ throw new SuprsendApiError(err);
209
+ }
210
+ }
211
+
212
+ async remove(list_id, distinct_ids = []) {
213
+ const cleaned_list_id = this._validate_list_id(list_id);
214
+ if (!Array.isArray(distinct_ids)) {
215
+ throw new SuprsendError("distinct_ids must be list of strings");
216
+ }
217
+ if (distinct_ids.length === 0) {
218
+ return this.non_error_default_response;
219
+ }
220
+
221
+ const url = `${this.__subscriber_list_detail_url(
222
+ cleaned_list_id
223
+ )}subscriber/remove`;
224
+ const headers = { ...this.__headers, ...this.__dynamic_headers() };
225
+ const content_text = JSON.stringify({ distinct_ids: distinct_ids });
226
+
227
+ const signature = get_request_signature(
228
+ url,
229
+ "POST",
230
+ content_text,
231
+ headers,
232
+ this.config.workspace_secret
233
+ );
234
+ headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
235
+
236
+ try {
237
+ const response = await axios.post(url, content_text, { headers });
238
+ return response.data;
239
+ } catch (err) {
240
+ throw new SuprsendApiError(err);
241
+ }
242
+ }
243
+
244
+ // async broadcast(broadcast_instance) {
245
+ // if (!(broadcast_instance instanceof SubscribersListBroadcast)) {
246
+ // throw new SuprsendError(
247
+ // "argument must be an instance of suprsend.SubscriberListBroadcast"
248
+ // );
249
+ // }
250
+ // const [broadcast_body, body_size] = broadcast_instance.get_final_json(
251
+ // this.config
252
+ // );
253
+ // const headers = { ...this.__headers, ...this.__dynamic_headers() };
254
+ // const content_text = JSON.stringify(broadcast_body);
255
+
256
+ // const signature = get_request_signature(
257
+ // this.broadcast_url,
258
+ // "POST",
259
+ // content_text,
260
+ // headers,
261
+ // this.config.workspace_secret
262
+ // );
263
+ // headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
264
+
265
+ // try {
266
+ // const response = await axios.post(this.broadcast_url, content_text, {
267
+ // headers,
268
+ // });
269
+ // const ok_response = Math.floor(response.status / 100) == 2;
270
+ // if (ok_response) {
271
+ // return {
272
+ // success: true,
273
+ // status: "success",
274
+ // status_code: response.status,
275
+ // message: response.statusText,
276
+ // };
277
+ // } else {
278
+ // return {
279
+ // success: false,
280
+ // status: "fail",
281
+ // status_code: response.status,
282
+ // message: response.statusText,
283
+ // };
284
+ // }
285
+ // } catch (err) {
286
+ // return {
287
+ // success: false,
288
+ // status: "fail",
289
+ // status_code: err.status || 500,
290
+ // message: err.message,
291
+ // };
292
+ // }
293
+ // }
294
+ }
295
+
296
+ export { SubscribersListApi, SubscribersListBroadcast };
package/src/utils.js CHANGED
@@ -12,6 +12,7 @@ import { cloneDeep } from "lodash";
12
12
 
13
13
  const workflow_schema = require("./request_json/workflow.json");
14
14
  const event_schema = require("./request_json/event.json");
15
+ const list_broadcast_schema = require("./request_json/list_broadcast.json");
15
16
 
16
17
  export function base64Encode(file) {
17
18
  var body = fs.readFileSync(file);
@@ -122,6 +123,25 @@ export function validate_track_event_schema(body) {
122
123
  }
123
124
  }
124
125
 
126
+ export function validate_list_broadcast_body_schema(body) {
127
+ if (!body?.data) {
128
+ body.data = {};
129
+ }
130
+ if (!(body.data instanceof Object)) {
131
+ throw new SuprsendError("data must be a object");
132
+ }
133
+ const schema = list_broadcast_schema;
134
+ var v = new Validator();
135
+ const validated_data = v.validate(body, schema);
136
+ if (validated_data.valid) {
137
+ return body;
138
+ } else {
139
+ const error_obj = validated_data.errors[0];
140
+ const error_msg = `${error_obj.property} ${error_obj.message}`;
141
+ throw new SuprsendError(error_msg);
142
+ }
143
+ }
144
+
125
145
  export function get_apparent_workflow_body_size(body, is_part_of_bulk) {
126
146
  let extra_bytes = WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES;
127
147
  let apparent_body = body;
@@ -199,6 +219,11 @@ export function get_apparent_event_size(event, is_part_of_bulk) {
199
219
  }
200
220
 
201
221
  export function get_apparent_identity_event_size(event) {
202
- const body_size = JSON.stringify(event);
222
+ const body_size = JSON.stringify(event).length;
223
+ return body_size;
224
+ }
225
+
226
+ export function get_apparent_list_broadcast_body_size(body) {
227
+ const body_size = JSON.stringify(body).length;
203
228
  return body_size;
204
229
  }