@suprsend/node-sdk 1.9.1 → 1.11.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/README.md +601 -13
- package/dist/constants.js +2 -4
- package/dist/index.js +14 -5
- package/dist/object.js +902 -0
- package/dist/object_helper.js +659 -0
- package/dist/request_json/workflow.json +4 -0
- package/dist/request_json/workflow_trigger.json +360 -0
- package/dist/subscriber.js +7 -0
- package/dist/subscriber_helper.js +8 -2
- package/dist/utils.js +20 -0
- package/dist/workflow.js +1 -1
- package/dist/workflow_api.js +108 -0
- package/dist/workflow_request.js +93 -0
- package/dist/workflow_trigger_bulk.js +316 -0
- package/package.json +1 -1
- package/src/constants.js +0 -2
- package/src/index.js +18 -7
- package/src/object.js +618 -0
- package/src/object_helper.js +593 -0
- package/src/request_json/workflow.json +4 -0
- package/src/request_json/workflow_trigger.json +360 -0
- package/src/subscriber.js +6 -0
- package/src/subscriber_helper.js +7 -1
- package/src/utils.js +20 -0
- package/src/workflow.js +1 -1
- package/src/workflow_api.js +71 -0
- package/src/workflow_request.js +92 -0
- package/src/workflow_trigger_bulk.js +218 -0
- package/types/index.d.ts +97 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { cloneDeep } from "lodash";
|
|
3
|
+
import get_request_signature from "./signature";
|
|
4
|
+
import BulkResponse from "./bulk_response";
|
|
5
|
+
import { invalid_record_json, InputValueError } from "./utils";
|
|
6
|
+
import WorkflowTriggerRequest from "./workflow_request";
|
|
7
|
+
import {
|
|
8
|
+
SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES,
|
|
9
|
+
SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE,
|
|
10
|
+
BODY_MAX_APPARENT_SIZE_IN_BYTES,
|
|
11
|
+
BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE,
|
|
12
|
+
MAX_WORKFLOWS_IN_BULK_API,
|
|
13
|
+
ALLOW_ATTACHMENTS_IN_BULK_API,
|
|
14
|
+
} from "./constants";
|
|
15
|
+
|
|
16
|
+
export class _BulkWorkflowTriggerChunk {
|
|
17
|
+
static _chunk_apparent_size_in_bytes = BODY_MAX_APPARENT_SIZE_IN_BYTES;
|
|
18
|
+
static _chunk_apparent_size_in_bytes_readable =
|
|
19
|
+
BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE;
|
|
20
|
+
static _max_records_in_chunk = MAX_WORKFLOWS_IN_BULK_API;
|
|
21
|
+
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.url = this.__url = `${this.config.base_url}trigger/`;
|
|
25
|
+
this.__chunk = [];
|
|
26
|
+
this.__running_size = 0;
|
|
27
|
+
this.__running_length = 0;
|
|
28
|
+
this.response = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_get_headers() {
|
|
32
|
+
return {
|
|
33
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
34
|
+
"User-Agent": this.config.user_agent,
|
|
35
|
+
Date: new Date().toUTCString(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
__add_body_to_chunk(body, body_size) {
|
|
40
|
+
this.__running_size += body_size;
|
|
41
|
+
this.__chunk.push(body);
|
|
42
|
+
this.__running_length++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_check_limit_reached() {
|
|
46
|
+
return (
|
|
47
|
+
this.__running_length >=
|
|
48
|
+
_BulkWorkflowTriggerChunk._max_records_in_chunk ||
|
|
49
|
+
this.__running_size >=
|
|
50
|
+
_BulkWorkflowTriggerChunk._chunk_apparent_size_in_bytes
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try_to_add_into_chunk(body, body_size) {
|
|
55
|
+
if (!body) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (this._check_limit_reached()) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (body_size > SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES) {
|
|
62
|
+
throw new InputValueError(
|
|
63
|
+
`workflow body too big - ${body_size} Bytes, must not exceed ${SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
this.__running_size + body_size >
|
|
68
|
+
_BulkWorkflowTriggerChunk._chunk_apparent_size_in_bytes
|
|
69
|
+
) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!ALLOW_ATTACHMENTS_IN_BULK_API) {
|
|
74
|
+
delete body.data["$attachments"];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.__add_body_to_chunk(body, body_size);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async trigger() {
|
|
82
|
+
const headers = this._get_headers();
|
|
83
|
+
const content_text = JSON.stringify(this.__chunk);
|
|
84
|
+
|
|
85
|
+
const signature = get_request_signature(
|
|
86
|
+
this.__url,
|
|
87
|
+
"POST",
|
|
88
|
+
content_text,
|
|
89
|
+
headers,
|
|
90
|
+
this.config.workspace_secret
|
|
91
|
+
);
|
|
92
|
+
headers["Authorization"] = `${this.config.workspace_key}:${signature}`;
|
|
93
|
+
try {
|
|
94
|
+
const resp = await axios.post(this.__url, content_text, {
|
|
95
|
+
headers,
|
|
96
|
+
transformResponse: [(data) => data], // dont assume type of response
|
|
97
|
+
});
|
|
98
|
+
this.response = {
|
|
99
|
+
status: "success",
|
|
100
|
+
status_code: resp.status,
|
|
101
|
+
total: this.__chunk.length,
|
|
102
|
+
success: this.__chunk.length,
|
|
103
|
+
failure: 0,
|
|
104
|
+
failed_records: [],
|
|
105
|
+
};
|
|
106
|
+
} catch (err) {
|
|
107
|
+
if (err?.response) {
|
|
108
|
+
const resp_data = err.response;
|
|
109
|
+
this.response = {
|
|
110
|
+
status: "fail",
|
|
111
|
+
status_code: resp_data.status,
|
|
112
|
+
total: this.__chunk.length,
|
|
113
|
+
success: 0,
|
|
114
|
+
failure: this.__chunk.length,
|
|
115
|
+
failed_records: this.__chunk.map((record) => ({
|
|
116
|
+
record: record,
|
|
117
|
+
error: resp_data.data,
|
|
118
|
+
code: resp_data.status,
|
|
119
|
+
})),
|
|
120
|
+
};
|
|
121
|
+
} else {
|
|
122
|
+
this.response = {
|
|
123
|
+
status: "fail",
|
|
124
|
+
status_code: 500,
|
|
125
|
+
total: this.__chunk.length,
|
|
126
|
+
success: 0,
|
|
127
|
+
failure: this.__chunk.length,
|
|
128
|
+
failed_records: this.__chunk.map((record) => ({
|
|
129
|
+
record: record,
|
|
130
|
+
error: err.message,
|
|
131
|
+
code: 500,
|
|
132
|
+
})),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export class BulkWorkflowTrigger {
|
|
140
|
+
constructor(config) {
|
|
141
|
+
this.config = config;
|
|
142
|
+
this.__workflows = [];
|
|
143
|
+
this.__pending_records = [];
|
|
144
|
+
this.chunks = [];
|
|
145
|
+
this.response = new BulkResponse();
|
|
146
|
+
// invalid_record json: {"record": workflow-json, "error": error_str, "code": 500}
|
|
147
|
+
this.__invalid_records = [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
__validate_workflows() {
|
|
151
|
+
for (const wf of this.__workflows) {
|
|
152
|
+
try {
|
|
153
|
+
const is_part_of_bulk = true;
|
|
154
|
+
const [wf_body, body_size] = wf.get_final_json(
|
|
155
|
+
this.config,
|
|
156
|
+
is_part_of_bulk
|
|
157
|
+
);
|
|
158
|
+
this.__pending_records.push([wf_body, body_size]);
|
|
159
|
+
} catch (ex) {
|
|
160
|
+
const inv_rec = invalid_record_json(wf.as_json(), ex);
|
|
161
|
+
this.__invalid_records.push(inv_rec);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
__chunkify(start_idx = 0) {
|
|
167
|
+
const curr_chunk = new _BulkWorkflowTriggerChunk(this.config);
|
|
168
|
+
this.chunks.push(curr_chunk);
|
|
169
|
+
const entries = this.__pending_records.slice(start_idx).entries();
|
|
170
|
+
for (const [rel_idx, rec] of entries) {
|
|
171
|
+
const is_added = curr_chunk.try_to_add_into_chunk(rec[0], rec[1]);
|
|
172
|
+
if (!is_added) {
|
|
173
|
+
// create chunks from remaining records
|
|
174
|
+
this.__chunkify(start_idx + rel_idx);
|
|
175
|
+
// Don't forget to break. As current loop must not continue further
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
append(...workflows) {
|
|
182
|
+
if (!workflows.length) return;
|
|
183
|
+
for (const wf of workflows) {
|
|
184
|
+
if (wf instanceof WorkflowTriggerRequest) {
|
|
185
|
+
const wf_copy = cloneDeep(wf);
|
|
186
|
+
this.__workflows.push(wf_copy);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async trigger() {
|
|
192
|
+
this.__validate_workflows();
|
|
193
|
+
if (this.__invalid_records.length > 0) {
|
|
194
|
+
const ch_response = BulkResponse.invalid_records_chunk_response(
|
|
195
|
+
this.__invalid_records
|
|
196
|
+
);
|
|
197
|
+
this.response.merge_chunk_response(ch_response);
|
|
198
|
+
}
|
|
199
|
+
if (this.__pending_records.length) {
|
|
200
|
+
this.__chunkify();
|
|
201
|
+
for (const [c_idx, ch] of this.chunks.entries()) {
|
|
202
|
+
if (this.config.req_log_level > 0) {
|
|
203
|
+
console.log(`DEBUG: triggering api call for chunk: ${cIdx}`);
|
|
204
|
+
}
|
|
205
|
+
// do api call
|
|
206
|
+
await ch.trigger();
|
|
207
|
+
// merge response
|
|
208
|
+
this.response.merge_chunk_response(ch.response);
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
if (this.__invalid_records.length === 0)
|
|
212
|
+
this.response.merge_chunk_response(
|
|
213
|
+
BulkResponse.empty_chunk_success_response()
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return this.response;
|
|
217
|
+
}
|
|
218
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ declare namespace suprsend {
|
|
|
86
86
|
unset(keys: string | string[]): void;
|
|
87
87
|
|
|
88
88
|
set_preferred_language(lang_code: string): void;
|
|
89
|
+
set_timezone(timezone: string): void;
|
|
89
90
|
|
|
90
91
|
add_email(email: string): void;
|
|
91
92
|
remove_email(email: string): void;
|
|
@@ -207,11 +208,101 @@ declare namespace suprsend {
|
|
|
207
208
|
delete_version(list_id: string, version_id: string): Promise<Dictionary>;
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
interface WorkflowTriggerRequest {
|
|
212
|
+
new (
|
|
213
|
+
body: Dictionary,
|
|
214
|
+
kwargs?: {
|
|
215
|
+
idempotency_key?: string;
|
|
216
|
+
tenant_id?: string;
|
|
217
|
+
cancellation_id?: string;
|
|
218
|
+
}
|
|
219
|
+
): WorkflowTriggerRequest;
|
|
220
|
+
|
|
221
|
+
add_attachment(
|
|
222
|
+
file_path: string,
|
|
223
|
+
kwargs?: { file_name?: string; ignore_if_error?: boolean }
|
|
224
|
+
): void;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
interface WorkflowsApi {
|
|
228
|
+
trigger(workflow: WorkflowTriggerRequest): Promise<SBulkResponse>;
|
|
229
|
+
|
|
230
|
+
bulk_trigger_instance(): BulkWorkflowTrigger;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface BulkWorkflowTrigger {
|
|
234
|
+
append(...workflows: WorkflowTriggerRequest[]): void;
|
|
235
|
+
|
|
236
|
+
trigger(): Promise<SBulkResponse>;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// objects
|
|
240
|
+
interface ObjectsApi {
|
|
241
|
+
list(object_type: string, options?: {}): Promise<Dictionary>;
|
|
242
|
+
|
|
243
|
+
get(object_type: string, object_id: string): Promise<Dictionary>;
|
|
244
|
+
|
|
245
|
+
upsert(object_type: string, object_id: string, object_payload?: Dictionary): Promise<Dictionary>;
|
|
246
|
+
|
|
247
|
+
edit(object_type: string, object_id: string, edit_payload?: Dictionary): Promise<Dictionary>;
|
|
248
|
+
|
|
249
|
+
delete(object_type: string, object_id: string): Promise<Dictionary>;
|
|
250
|
+
|
|
251
|
+
bulk_delete(object_type: string, payload?: Dictionary): Promise<Dictionary>;
|
|
252
|
+
|
|
253
|
+
get_subscriptions(object_type: string, object_id: string, options?: {}): Promise<Dictionary>;
|
|
254
|
+
|
|
255
|
+
create_subscriptions(object_type: string, object_id: string, subscriptions?: Dictionary): Promise<Dictionary>;
|
|
256
|
+
|
|
257
|
+
delete_subscriptions(object_type: string, object_id: string, subscriptions?: Dictionary): Promise<Dictionary>;
|
|
258
|
+
|
|
259
|
+
get_instance(object_type: string, object_id: string): Object;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// subscribers
|
|
263
|
+
interface Object {
|
|
264
|
+
save(): Promise<SResponse>;
|
|
265
|
+
|
|
266
|
+
append(key: string | Dictionary, value?: any): void;
|
|
267
|
+
set(key: string | Dictionary, value?: any): void;
|
|
268
|
+
set_once(key: string | Dictionary, value?: any): void;
|
|
269
|
+
increment(key: string | Dictionary, value?: number): void;
|
|
270
|
+
remove(key: string | Dictionary, value?: any): void;
|
|
271
|
+
unset(keys: string | string[]): void;
|
|
272
|
+
|
|
273
|
+
set_preferred_language(lang_code: string): void;
|
|
274
|
+
set_timezone(timezone: string): void;
|
|
275
|
+
|
|
276
|
+
add_email(email: string): void;
|
|
277
|
+
remove_email(email: string): void;
|
|
278
|
+
|
|
279
|
+
add_sms(mobile_no: string): void;
|
|
280
|
+
remove_sms(mobile_no: string): void;
|
|
281
|
+
|
|
282
|
+
add_whatsapp(mobile_no: string): void;
|
|
283
|
+
remove_whatsapp(mobile_no: string): void;
|
|
284
|
+
|
|
285
|
+
add_androidpush(push_token: string, provider?: string): void;
|
|
286
|
+
remove_androidpush(push_token: string, provider?: string): void;
|
|
287
|
+
|
|
288
|
+
add_iospush(push_token: string, provider?: string): void;
|
|
289
|
+
remove_iospush(push_token: string, provider?: string): void;
|
|
290
|
+
|
|
291
|
+
add_webpush(push_token: Dictionary, provider?: string): void;
|
|
292
|
+
remove_webpush(push_token: Dictionary, provider?: string): void;
|
|
293
|
+
|
|
294
|
+
add_slack(value: Dictionary): void;
|
|
295
|
+
remove_slack(value: Dictionary): void;
|
|
296
|
+
|
|
297
|
+
add_ms_teams(value: Dictionary): void;
|
|
298
|
+
remove_ms_teams(value: Dictionary): void;
|
|
299
|
+
}
|
|
300
|
+
|
|
210
301
|
interface Suprsend {
|
|
211
302
|
new (
|
|
212
303
|
workspace_env: string,
|
|
213
304
|
workspace_secret: string,
|
|
214
|
-
config?: {
|
|
305
|
+
config?: { base_url?: string }
|
|
215
306
|
): Suprsend;
|
|
216
307
|
|
|
217
308
|
get bulk_workflows(): BulkWorkflowsFactory;
|
|
@@ -228,6 +319,10 @@ declare namespace suprsend {
|
|
|
228
319
|
|
|
229
320
|
subscriber_lists: SubscriberListsApi;
|
|
230
321
|
|
|
322
|
+
workflows: WorkflowsApi;
|
|
323
|
+
|
|
324
|
+
objects: ObjectsApi;
|
|
325
|
+
|
|
231
326
|
add_attachment(
|
|
232
327
|
body: Dictionary,
|
|
233
328
|
file_path: string,
|
|
@@ -255,3 +350,4 @@ export const Suprsend: suprsend.Suprsend;
|
|
|
255
350
|
export const Event: suprsend.Event;
|
|
256
351
|
export const Workflow: suprsend.Workflow;
|
|
257
352
|
export const SubscriberListBroadcast: suprsend.SubscriberListBroadcast;
|
|
353
|
+
export const WorkflowTriggerRequest: suprsend.WorkflowTriggerRequest;
|