@suprsend/node-sdk 1.1.1 → 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/brands.js +245 -0
- package/dist/event.js +6 -1
- package/dist/index.js +12 -0
- package/dist/request_json/event.json +5 -0
- package/dist/request_json/list_broadcast.json +70 -0
- package/dist/request_json/workflow.json +5 -0
- package/dist/signature.js +6 -5
- package/dist/subscribers_list.js +484 -0
- package/dist/utils.js +60 -2
- package/dist/workflow.js +5 -0
- package/package.json +1 -1
- package/src/brands.js +120 -0
- package/src/event.js +4 -0
- package/src/index.js +10 -1
- package/src/request_json/event.json +5 -0
- package/src/request_json/list_broadcast.json +70 -0
- package/src/request_json/workflow.json +5 -0
- package/src/signature.js +5 -4
- package/src/subscribers_list.js +296 -0
- package/src/utils.js +39 -1
- package/src/workflow.js +4 -0
package/src/brands.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import get_request_signature from "./signature";
|
|
2
|
+
import { SuprsendApiError } from "./utils";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
|
|
5
|
+
class BrandsApi {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
this.list_url = this.__list_url();
|
|
9
|
+
this.__headers = this.__common_headers();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
__list_url() {
|
|
13
|
+
const list_uri_template = `${this.config.base_url}v1/brand/`;
|
|
14
|
+
return list_uri_template;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
__common_headers() {
|
|
18
|
+
return {
|
|
19
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
20
|
+
"User-Agent": this.config.user_agent,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
cleaned_limit_offset(limit, offset) {
|
|
25
|
+
let cleaned_limit =
|
|
26
|
+
typeof limit === "number" && limit > 0 && limit <= 1000 ? limit : 20;
|
|
27
|
+
let cleaned_offset = typeof offset === "number" && offset >= 0 ? offset : 0;
|
|
28
|
+
return [cleaned_limit, cleaned_offset];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
__dynamic_headers() {
|
|
32
|
+
return {
|
|
33
|
+
Date: new Date().toUTCString(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async list(kwargs = {}) {
|
|
38
|
+
const limit = kwargs?.limit;
|
|
39
|
+
const offset = kwargs?.offset;
|
|
40
|
+
const [cleaned_limit, cleaner_offset] = this.cleaned_limit_offset(
|
|
41
|
+
limit,
|
|
42
|
+
offset
|
|
43
|
+
);
|
|
44
|
+
const final_url_obj = new URL(this.list_url);
|
|
45
|
+
final_url_obj.searchParams.append("limit", cleaned_limit);
|
|
46
|
+
final_url_obj.searchParams.append("offset", cleaner_offset);
|
|
47
|
+
const final_url_string = final_url_obj.href;
|
|
48
|
+
|
|
49
|
+
const headers = { ...this.__headers, ...this.__dynamic_headers() };
|
|
50
|
+
|
|
51
|
+
const signature = get_request_signature(
|
|
52
|
+
final_url_string,
|
|
53
|
+
"GET",
|
|
54
|
+
"",
|
|
55
|
+
headers,
|
|
56
|
+
this.config.workspace_secret
|
|
57
|
+
);
|
|
58
|
+
headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const response = await axios.get(final_url_string, { headers });
|
|
62
|
+
return response.data;
|
|
63
|
+
} catch (err) {
|
|
64
|
+
throw new SuprsendApiError(err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
detail_url(brand_id = "") {
|
|
69
|
+
const cleaned_brand_id = brand_id.toString().trim();
|
|
70
|
+
const brand_id_encoded = encodeURI(cleaned_brand_id);
|
|
71
|
+
const url = `${this.list_url}${brand_id_encoded}/`;
|
|
72
|
+
return url;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async get(brand_id = "") {
|
|
76
|
+
const url = this.detail_url(brand_id);
|
|
77
|
+
|
|
78
|
+
const headers = { ...this.__headers, ...this.__dynamic_headers() };
|
|
79
|
+
const signature = get_request_signature(
|
|
80
|
+
url,
|
|
81
|
+
"GET",
|
|
82
|
+
"",
|
|
83
|
+
headers,
|
|
84
|
+
this.config.workspace_secret
|
|
85
|
+
);
|
|
86
|
+
headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const response = await axios.get(url, { headers });
|
|
90
|
+
return response.data;
|
|
91
|
+
} catch (err) {
|
|
92
|
+
throw new SuprsendApiError(err);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async upsert(brand_id = "", brand_payload = {}) {
|
|
97
|
+
const url = this.detail_url(brand_id);
|
|
98
|
+
|
|
99
|
+
const headers = { ...this.__headers, ...this.__dynamic_headers() };
|
|
100
|
+
const content_text = JSON.stringify(brand_payload);
|
|
101
|
+
|
|
102
|
+
const signature = get_request_signature(
|
|
103
|
+
url,
|
|
104
|
+
"POST",
|
|
105
|
+
content_text,
|
|
106
|
+
headers,
|
|
107
|
+
this.config.workspace_secret
|
|
108
|
+
);
|
|
109
|
+
headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const response = await axios.post(url, content_text, { headers });
|
|
113
|
+
return response.data;
|
|
114
|
+
} catch (err) {
|
|
115
|
+
throw new SuprsendApiError(err);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default BrandsApi;
|
package/src/event.js
CHANGED
|
@@ -32,6 +32,7 @@ export default class Event {
|
|
|
32
32
|
this.event_name = event_name;
|
|
33
33
|
this.properties = properties;
|
|
34
34
|
this.idempotency_key = kwargs?.idempotency_key;
|
|
35
|
+
this.brand_id = kwargs?.brand_id;
|
|
35
36
|
// --- validate
|
|
36
37
|
this.__validate_distinct_id();
|
|
37
38
|
this.__validate_event_name();
|
|
@@ -107,6 +108,9 @@ export default class Event {
|
|
|
107
108
|
if (this.idempotency_key) {
|
|
108
109
|
event_dict["$idempotency_key"] = this.idempotency_key;
|
|
109
110
|
}
|
|
111
|
+
if (this.brand_id) {
|
|
112
|
+
event_dict["brand_id"] = this.brand_id;
|
|
113
|
+
}
|
|
110
114
|
event_dict = validate_track_event_schema(event_dict);
|
|
111
115
|
const apparent_size = get_apparent_event_size(event_dict, is_part_of_bulk);
|
|
112
116
|
if (apparent_size > SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES) {
|
package/src/index.js
CHANGED
|
@@ -6,6 +6,11 @@ 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";
|
|
13
|
+
import BrandsApi from "./brands";
|
|
9
14
|
import { DEFAULT_UAT_URL, DEFAULT_URL } from "./constants";
|
|
10
15
|
|
|
11
16
|
const package_json = require("../package.json");
|
|
@@ -31,6 +36,10 @@ class Suprsend {
|
|
|
31
36
|
this._bulk_users = new BulkSubscribersFactory(this);
|
|
32
37
|
|
|
33
38
|
this._user = new SubscriberFactory(this);
|
|
39
|
+
|
|
40
|
+
this.brands = new BrandsApi(this);
|
|
41
|
+
this.subscribers_list = new SubscribersListApi(this);
|
|
42
|
+
|
|
34
43
|
this._validate();
|
|
35
44
|
}
|
|
36
45
|
|
|
@@ -122,4 +131,4 @@ class Suprsend {
|
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
133
|
|
|
125
|
-
export { Suprsend, Event, Workflow };
|
|
134
|
+
export { Suprsend, Event, Workflow, SubscribersListBroadcast };
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"maxLength": 64,
|
|
12
12
|
"description": "unique id provided by client for request"
|
|
13
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
|
+
},
|
|
14
19
|
"$insert_id": {
|
|
15
20
|
"type": "string",
|
|
16
21
|
"minLength": 36,
|
|
@@ -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
|
+
}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"maxLength": 64,
|
|
12
12
|
"description": "unique id provided by client for request"
|
|
13
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
|
+
},
|
|
14
19
|
"name": {
|
|
15
20
|
"$ref": "#/definitions/non_empty_string",
|
|
16
21
|
"description": "name of workflow"
|
package/src/signature.js
CHANGED
|
@@ -12,17 +12,18 @@ export default function get_request_signature(
|
|
|
12
12
|
headers,
|
|
13
13
|
secret
|
|
14
14
|
) {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
let content_md5 = "";
|
|
16
|
+
let content_type = headers["Content-Type"] || "";
|
|
17
|
+
if (content) {
|
|
18
|
+
content_md5 = crypto.createHash("md5").update(content).digest("hex");
|
|
17
19
|
}
|
|
18
|
-
const content_md5 = crypto.createHash("md5").update(content).digest("hex");
|
|
19
20
|
const request_uri = get_path(url);
|
|
20
21
|
const sign_string =
|
|
21
22
|
http_verb +
|
|
22
23
|
"\n" +
|
|
23
24
|
content_md5 +
|
|
24
25
|
"\n" +
|
|
25
|
-
|
|
26
|
+
content_type +
|
|
26
27
|
"\n" +
|
|
27
28
|
headers["Date"] +
|
|
28
29
|
"\n" +
|
|
@@ -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);
|
|
@@ -44,6 +45,19 @@ export class SuprsendConfigError extends Error {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
export class SuprsendApiError extends Error {
|
|
49
|
+
constructor(error) {
|
|
50
|
+
let message;
|
|
51
|
+
if (error.response) {
|
|
52
|
+
message = `${error.response.status}: ${error.response.data.message}`;
|
|
53
|
+
} else {
|
|
54
|
+
message = error.message;
|
|
55
|
+
}
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = "SuprsendApiError";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
47
61
|
export function is_string(value) {
|
|
48
62
|
return typeof value === "string";
|
|
49
63
|
}
|
|
@@ -109,6 +123,25 @@ export function validate_track_event_schema(body) {
|
|
|
109
123
|
}
|
|
110
124
|
}
|
|
111
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
|
+
|
|
112
145
|
export function get_apparent_workflow_body_size(body, is_part_of_bulk) {
|
|
113
146
|
let extra_bytes = WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES;
|
|
114
147
|
let apparent_body = body;
|
|
@@ -186,6 +219,11 @@ export function get_apparent_event_size(event, is_part_of_bulk) {
|
|
|
186
219
|
}
|
|
187
220
|
|
|
188
221
|
export function get_apparent_identity_event_size(event) {
|
|
189
|
-
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;
|
|
190
228
|
return body_size;
|
|
191
229
|
}
|
package/src/workflow.js
CHANGED
|
@@ -18,6 +18,7 @@ export default class Workflow {
|
|
|
18
18
|
}
|
|
19
19
|
this.body = body;
|
|
20
20
|
this.idempotency_key = kwargs?.idempotency_key;
|
|
21
|
+
this.brand_id = kwargs?.brand_id;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
add_attachment(file_path = "", kwargs = {}) {
|
|
@@ -46,6 +47,9 @@ export default class Workflow {
|
|
|
46
47
|
if (this.idempotency_key) {
|
|
47
48
|
this.body["$idempotency_key"] = this.idempotency_key;
|
|
48
49
|
}
|
|
50
|
+
if (this.brand_id) {
|
|
51
|
+
this.body["brand_id"] = this.brand_id;
|
|
52
|
+
}
|
|
49
53
|
this.body = validate_workflow_body_schema(this.body);
|
|
50
54
|
const apparent_size = get_apparent_workflow_body_size(
|
|
51
55
|
this.body,
|