@suprsend/node-sdk 0.1.1 → 1.1.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.
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports["default"] = get_attachment_json;
9
+
10
+ var _path = _interopRequireDefault(require("path"));
11
+
12
+ var _mimeTypes = _interopRequireDefault(require("mime-types"));
13
+
14
+ var _utils = require("./utils");
15
+
16
+ function check_is_web_url() {
17
+ var file_path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
18
+ return file_path.startsWith("http://") || file_path.startsWith("https://");
19
+ }
20
+
21
+ function get_attachment_json_for_file(file_path, file_name, ignore_if_error) {
22
+ var abs_path = _path["default"].resolve((0, _utils.resolveTilde)(file_path));
23
+
24
+ var final_file_name = _path["default"].basename(abs_path);
25
+
26
+ if (file_name && file_name.trim()) {
27
+ final_file_name = file_name.trim();
28
+ }
29
+
30
+ return {
31
+ filename: final_file_name,
32
+ contentType: _mimeTypes["default"].lookup(abs_path),
33
+ data: (0, _utils.base64Encode)(abs_path),
34
+ url: null,
35
+ ignore_if_error: ignore_if_error
36
+ };
37
+ }
38
+
39
+ function get_attachment_json_for_url(file_url, file_name, ignore_if_error) {
40
+ return {
41
+ filename: file_name,
42
+ contentType: null,
43
+ data: null,
44
+ url: file_url,
45
+ ignore_if_error: ignore_if_error
46
+ };
47
+ }
48
+
49
+ function get_attachment_json(file_path, file_name) {
50
+ var ignore_if_error = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
51
+
52
+ if (check_is_web_url(file_path)) {
53
+ return get_attachment_json_for_url(file_path, file_name, ignore_if_error);
54
+ } else {
55
+ return get_attachment_json_for_file(file_path, file_name, ignore_if_error);
56
+ }
57
+ }
58
+
59
+ module.exports = exports.default;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports["default"] = void 0;
9
+
10
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+
12
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
+
14
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
15
+
16
+ var BulkResponse = /*#__PURE__*/function () {
17
+ function BulkResponse() {
18
+ (0, _classCallCheck2["default"])(this, BulkResponse);
19
+ this.status;
20
+ this.failed_records = [];
21
+ this.total = 0;
22
+ this.success = 0;
23
+ this.failure = 0;
24
+ this.warnings = [];
25
+ }
26
+
27
+ (0, _createClass2["default"])(BulkResponse, [{
28
+ key: "merge_chunk_response",
29
+ value: function merge_chunk_response(ch_resp) {
30
+ if (!ch_resp) {
31
+ return;
32
+ } // possible status: success/partial/fail
33
+
34
+
35
+ if (!this.status) {
36
+ this.status = ch_resp["status"];
37
+ } else {
38
+ if (this.status === "success") {
39
+ if (ch_resp.status === "fail") {
40
+ this.status = "partial";
41
+ }
42
+ } else if (this.status === "fail") {
43
+ if (ch_resp.status === "success") {
44
+ this.status = "partial";
45
+ }
46
+ }
47
+ }
48
+
49
+ this.total += ch_resp.total || 0;
50
+ this.success += ch_resp.success || 0;
51
+ this.failure += ch_resp.failure || 0;
52
+ var failed_recs = ch_resp.failed_records || [];
53
+ this.failed_records = [].concat((0, _toConsumableArray2["default"])(this.failed_records), (0, _toConsumableArray2["default"])(failed_recs));
54
+ }
55
+ }]);
56
+ return BulkResponse;
57
+ }();
58
+
59
+ exports["default"] = BulkResponse;
60
+ module.exports = exports.default;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES = exports.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = exports.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = exports.MAX_WORKFLOWS_IN_BULK_API = exports.MAX_IDENTITY_EVENTS_IN_BULK_API = exports.MAX_EVENTS_IN_BULK_API = exports.IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = exports.IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = exports.DEFAULT_URL = exports.DEFAULT_UAT_URL = exports.BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE = exports.BODY_MAX_APPARENT_SIZE_IN_BYTES = exports.ATTACHMENT_URL_POTENTIAL_SIZE_IN_BYTES = exports.ATTACHMENT_UPLOAD_ENABLED = exports.ALLOW_ATTACHMENTS_IN_BULK_API = void 0;
7
+ // Default urls
8
+ var DEFAULT_URL = "https://hub.suprsend.com/";
9
+ exports.DEFAULT_URL = DEFAULT_URL;
10
+ var DEFAULT_UAT_URL = "https://collector-staging.suprsend.workers.dev/"; // an Event should not have apparent body size of more than 100KB
11
+
12
+ exports.DEFAULT_UAT_URL = DEFAULT_UAT_URL;
13
+ var SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = 100 * 1024; // 100 * 1024
14
+
15
+ exports.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES;
16
+ var SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = "100KB"; // a API call should not have apparent body size of more than 800KB
17
+
18
+ exports.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE;
19
+ var BODY_MAX_APPARENT_SIZE_IN_BYTES = 800 * 1024; // 800 * 1024
20
+
21
+ exports.BODY_MAX_APPARENT_SIZE_IN_BYTES = BODY_MAX_APPARENT_SIZE_IN_BYTES;
22
+ var BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE = "800KB"; // in general url-size wont exceed 2048 chars or 2048 utf-8 bytes
23
+
24
+ exports.BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE = BODY_MAX_APPARENT_SIZE_IN_BYTES_READABLE;
25
+ var ATTACHMENT_URL_POTENTIAL_SIZE_IN_BYTES = 2100; // few keys added in-flight, amounting to almost 200 bytes increase per workflow-body
26
+
27
+ exports.ATTACHMENT_URL_POTENTIAL_SIZE_IN_BYTES = ATTACHMENT_URL_POTENTIAL_SIZE_IN_BYTES;
28
+ var WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES = 200; // max workflow-records in one bulk api call.
29
+
30
+ exports.WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES = WORKFLOW_RUNTIME_KEYS_POTENTIAL_SIZE_IN_BYTES;
31
+ var MAX_WORKFLOWS_IN_BULK_API = 100; // max event-records in one bulk api call
32
+
33
+ exports.MAX_WORKFLOWS_IN_BULK_API = MAX_WORKFLOWS_IN_BULK_API;
34
+ var MAX_EVENTS_IN_BULK_API = 100;
35
+ exports.MAX_EVENTS_IN_BULK_API = MAX_EVENTS_IN_BULK_API;
36
+ var ALLOW_ATTACHMENTS_IN_BULK_API = true;
37
+ exports.ALLOW_ATTACHMENTS_IN_BULK_API = ALLOW_ATTACHMENTS_IN_BULK_API;
38
+ var ATTACHMENT_UPLOAD_ENABLED = false; // -- single Identity event limit
39
+
40
+ exports.ATTACHMENT_UPLOAD_ENABLED = ATTACHMENT_UPLOAD_ENABLED;
41
+ var IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = 2 * 1024;
42
+ exports.IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES = IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES;
43
+ var IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = "2KB";
44
+ exports.IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE = IDENTITY_SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE;
45
+ var MAX_IDENTITY_EVENTS_IN_BULK_API = 400;
46
+ exports.MAX_IDENTITY_EVENTS_IN_BULK_API = MAX_IDENTITY_EVENTS_IN_BULK_API;
package/dist/event.js CHANGED
@@ -5,12 +5,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports["default"] = void 0;
8
+ exports["default"] = exports.EventCollector = void 0;
9
9
 
10
10
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
11
 
12
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
13
 
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+
14
16
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
15
17
 
16
18
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
@@ -21,25 +23,139 @@ var _utils = require("./utils");
21
23
 
22
24
  var _signature = _interopRequireDefault(require("./signature"));
23
25
 
24
- var _jsonschema = require("jsonschema");
25
-
26
26
  var _axios = _interopRequireDefault(require("axios"));
27
27
 
28
+ var _attachment = _interopRequireDefault(require("./attachment"));
29
+
30
+ var _constants = require("./constants");
31
+
28
32
  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; }
29
33
 
30
34
  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; }
31
35
 
32
- var event_schema = require("./request_json/event.json");
33
-
34
36
  var RESERVED_EVENT_NAMES = ["$identify", "$notification_delivered", "$notification_dismiss", "$notification_clicked", "$app_launched", "$user_login", "$user_logout"];
35
37
 
38
+ var Event = /*#__PURE__*/function () {
39
+ function Event(distinct_id, event_name, properties) {
40
+ var kwargs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
41
+ (0, _classCallCheck2["default"])(this, Event);
42
+ this.distinct_id = distinct_id;
43
+ this.event_name = event_name;
44
+ this.properties = properties;
45
+ this.idempotency_key = kwargs === null || kwargs === void 0 ? void 0 : kwargs.idempotency_key; // --- validate
46
+
47
+ this.__validate_distinct_id();
48
+
49
+ this.__validate_event_name();
50
+
51
+ this.__validate_properties();
52
+ }
53
+
54
+ (0, _createClass2["default"])(Event, [{
55
+ key: "__validate_distinct_id",
56
+ value: function __validate_distinct_id() {
57
+ if (this.distinct_id instanceof String) {
58
+ throw new _utils.SuprsendError("distinct_id must be a string. an Id which uniquely identify a user in your app");
59
+ }
60
+
61
+ var distinct_id = this.distinct_id.trim();
62
+
63
+ if (!distinct_id) {
64
+ throw new _utils.SuprsendError("distinct_id missing");
65
+ }
66
+
67
+ this.distinct_id = distinct_id;
68
+ }
69
+ }, {
70
+ key: "__validate_properties",
71
+ value: function __validate_properties() {
72
+ if (!this.properties) {
73
+ this.properties = {};
74
+ }
75
+
76
+ if (!(this.properties instanceof Object)) {
77
+ throw new _utils.SuprsendError("properties must be a dictionary");
78
+ }
79
+ }
80
+ }, {
81
+ key: "__check_event_prefix",
82
+ value: function __check_event_prefix(event_name) {
83
+ if (!RESERVED_EVENT_NAMES.includes(event_name)) {
84
+ if ((0, _utils.has_special_char)(event_name)) {
85
+ throw new _utils.SuprsendError("event_names starting with [$,ss_] are reserved by SuprSend");
86
+ }
87
+ }
88
+ }
89
+ }, {
90
+ key: "__validate_event_name",
91
+ value: function __validate_event_name() {
92
+ if (!(0, _utils.is_string)(this.event_name)) {
93
+ throw new _utils.SuprsendError("event_name must be a string");
94
+ }
95
+
96
+ var event_name = this.event_name.trim();
97
+
98
+ this.__check_event_prefix(event_name);
99
+
100
+ this.event_name = event_name;
101
+ }
102
+ }, {
103
+ key: "add_attachment",
104
+ value: function add_attachment(file_path) {
105
+ var _kwargs$ignore_if_err;
106
+
107
+ var kwargs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
108
+ var file_name = kwargs === null || kwargs === void 0 ? void 0 : kwargs.file_name;
109
+ var ignore_if_error = (_kwargs$ignore_if_err = kwargs === null || kwargs === void 0 ? void 0 : kwargs.ignore_if_error) !== null && _kwargs$ignore_if_err !== void 0 ? _kwargs$ignore_if_err : false;
110
+ var attachment = (0, _attachment["default"])(file_path, file_name, ignore_if_error); // --- add the attachment to properties->$attachments
111
+
112
+ if (!this.properties["$attachments"]) {
113
+ this.properties["$attachments"] = [];
114
+ }
115
+
116
+ this.properties["$attachments"].push(attachment);
117
+ }
118
+ }, {
119
+ key: "get_final_json",
120
+ value: function get_final_json(config) {
121
+ var is_part_of_bulk = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
122
+ var super_props = {
123
+ $ss_sdk_version: config.user_agent
124
+ };
125
+ var event_dict = {
126
+ $insert_id: (0, _utils.uuid)(),
127
+ $time: (0, _utils.epoch_milliseconds)(),
128
+ event: this.event_name,
129
+ env: config.workspace_key,
130
+ distinct_id: this.distinct_id,
131
+ properties: _objectSpread(_objectSpread({}, this.properties), super_props)
132
+ };
133
+
134
+ if (this.idempotency_key) {
135
+ event_dict["$idempotency_key"] = this.idempotency_key;
136
+ }
137
+
138
+ event_dict = (0, _utils.validate_track_event_schema)(event_dict);
139
+ var apparent_size = (0, _utils.get_apparent_event_size)(event_dict, is_part_of_bulk);
140
+
141
+ if (apparent_size > _constants.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES) {
142
+ throw new _utils.SuprsendError("Event size too big - ".concat(apparent_size, " Bytes,must not cross ").concat(_constants.SINGLE_EVENT_MAX_APPARENT_SIZE_IN_BYTES_READABLE));
143
+ }
144
+
145
+ return [event_dict, apparent_size];
146
+ }
147
+ }]);
148
+ return Event;
149
+ }();
150
+
151
+ exports["default"] = Event;
152
+
36
153
  var EventCollector = /*#__PURE__*/function () {
37
154
  function EventCollector(config) {
38
155
  (0, _classCallCheck2["default"])(this, EventCollector);
39
156
  this.config = config;
40
157
  this.__url = this.__get_url();
41
158
  this.__headers = this.__common_headers();
42
- this.__supr_props = this.__super_properties();
43
159
  }
44
160
 
45
161
  (0, _createClass2["default"])(EventCollector, [{
@@ -72,81 +188,21 @@ var EventCollector = /*#__PURE__*/function () {
72
188
  Date: new Date().toUTCString()
73
189
  };
74
190
  }
75
- }, {
76
- key: "__super_properties",
77
- value: function __super_properties() {
78
- return {
79
- $ss_sdk_version: this.config.user_agent
80
- };
81
- }
82
- }, {
83
- key: "__check_event_prefix",
84
- value: function __check_event_prefix(event_name) {
85
- if (!RESERVED_EVENT_NAMES.includes(event_name)) {
86
- if ((0, _utils.has_special_char)(event_name)) {
87
- throw new _utils.SuprsendError("event_names starting with [$,ss_] are reserved");
88
- }
89
- }
90
- }
91
- }, {
92
- key: "__validate_event_name",
93
- value: function __validate_event_name(event_name) {
94
- if (!(0, _utils.is_string)(event_name)) {
95
- throw new _utils.SuprsendError("event_name must be a string");
96
- }
97
-
98
- event_name = event_name.trim();
99
-
100
- this.__check_event_prefix(event_name);
101
-
102
- return event_name;
103
- }
104
- }, {
105
- key: "validate_track_event_schema",
106
- value: function validate_track_event_schema(data) {
107
- if (!data["properties"]) {
108
- data["properties"] = {};
109
- }
110
-
111
- var schema = event_schema;
112
- var v = new _jsonschema.Validator();
113
- var validated_data = v.validate(data, schema);
114
-
115
- if (validated_data.valid) {
116
- return data;
117
- } else {
118
- var error_obj = validated_data.errors[0];
119
- var error_msg = "".concat(error_obj.property, " ").concat(error_obj.message);
120
- throw new _utils.SuprsendError(error_msg);
121
- }
122
- }
123
191
  }, {
124
192
  key: "collect",
125
- value: function collect(distinct_id, event_name) {
126
- var properties = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
127
- event_name = this.__validate_event_name(event_name);
193
+ value: function collect(event) {
194
+ var _event$get_final_json = event.get_final_json(this.config, false),
195
+ _event$get_final_json2 = (0, _slicedToArray2["default"])(_event$get_final_json, 2),
196
+ event_dict = _event$get_final_json2[0],
197
+ event_size = _event$get_final_json2[1];
128
198
 
129
- if (!(0, _utils.is_object)(properties)) {
130
- throw new _utils.SuprsendError("properties must be a dictionary");
131
- }
132
-
133
- properties = _objectSpread(_objectSpread({}, properties), this.__supr_props);
134
- var event = {
135
- $insert_id: (0, _utils.uuid)(),
136
- $time: (0, _utils.epoch_milliseconds)(),
137
- event: event_name,
138
- env: this.config.env_key,
139
- distinct_id: distinct_id,
140
- properties: properties
141
- };
142
- event = this.validate_track_event_schema(event);
143
- return this.send(event);
199
+ return this.send(event_dict);
144
200
  }
145
201
  }, {
146
202
  key: "send",
147
203
  value: function () {
148
204
  var _send = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(event) {
149
- var headers, content_text, signature, response;
205
+ var headers, content_text, signature, response, ok_response;
150
206
  return _regenerator["default"].wrap(function _callee$(_context) {
151
207
  while (1) {
152
208
  switch (_context.prev = _context.next) {
@@ -155,8 +211,8 @@ var EventCollector = /*#__PURE__*/function () {
155
211
  content_text = JSON.stringify(event);
156
212
 
157
213
  if (this.config.auth_enabled) {
158
- signature = (0, _signature["default"])(this.__url, "POST", content_text, headers, this.config.env_secret);
159
- headers["Authorization"] = "".concat(this.config.env_key, ":").concat(signature);
214
+ signature = (0, _signature["default"])(this.__url, "POST", content_text, headers, this.config.workspace_secret);
215
+ headers["Authorization"] = "".concat(this.config.workspace_key, ":").concat(signature);
160
216
  }
161
217
 
162
218
  _context.prev = 3;
@@ -167,27 +223,48 @@ var EventCollector = /*#__PURE__*/function () {
167
223
 
168
224
  case 6:
169
225
  response = _context.sent;
226
+ ok_response = Math.floor(response.status / 100) == 2;
227
+
228
+ if (!ok_response) {
229
+ _context.next = 12;
230
+ break;
231
+ }
232
+
170
233
  return _context.abrupt("return", {
171
- status_code: response.status,
172
234
  success: true,
235
+ status: "success",
236
+ status_code: response.status,
173
237
  message: response.statusText
174
238
  });
175
239
 
176
- case 10:
177
- _context.prev = 10;
240
+ case 12:
241
+ return _context.abrupt("return", {
242
+ success: false,
243
+ status: "fail",
244
+ status_code: response.status,
245
+ message: response.statusText
246
+ });
247
+
248
+ case 13:
249
+ _context.next = 18;
250
+ break;
251
+
252
+ case 15:
253
+ _context.prev = 15;
178
254
  _context.t0 = _context["catch"](3);
179
255
  return _context.abrupt("return", {
180
- status_code: 400,
181
256
  success: false,
257
+ status: "fail",
258
+ status_code: _context.t0.status || 500,
182
259
  message: _context.t0.message
183
260
  });
184
261
 
185
- case 13:
262
+ case 18:
186
263
  case "end":
187
264
  return _context.stop();
188
265
  }
189
266
  }
190
- }, _callee, this, [[3, 10]]);
267
+ }, _callee, this, [[3, 15]]);
191
268
  }));
192
269
 
193
270
  function send(_x) {
@@ -200,6 +277,4 @@ var EventCollector = /*#__PURE__*/function () {
200
277
  return EventCollector;
201
278
  }();
202
279
 
203
- var _default = EventCollector;
204
- exports["default"] = _default;
205
- module.exports = exports.default;
280
+ exports.EventCollector = EventCollector;