@suprsend/node-sdk 0.0.1

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/.babelrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "presets": ["@babel/preset-env"],
3
+ "plugins": [["@babel/transform-runtime"]]
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "editor.formatOnSave": true
3
+ }
package/dist/config.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports["default"] = void 0;
7
+ var config = {
8
+ staging: "https://collector-staging.suprsend.workers.dev/",
9
+ prod: "https://hub.suprsend.com/"
10
+ };
11
+ var _default = config;
12
+ exports["default"] = _default;
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
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 _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
+
12
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
+
14
+ var _config = _interopRequireDefault(require("./config"));
15
+
16
+ var _workflow = _interopRequireDefault(require("./workflow"));
17
+
18
+ var _path = _interopRequireDefault(require("path"));
19
+
20
+ var _mimeTypes = _interopRequireDefault(require("mime-types"));
21
+
22
+ var _utils = require("./utils");
23
+
24
+ var package_json = require("../package.json");
25
+
26
+ var Suprsend = /*#__PURE__*/function () {
27
+ function Suprsend(workspace_env, workspace_secret) {
28
+ var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
29
+ (0, _classCallCheck2["default"])(this, Suprsend);
30
+ this.env_key = workspace_env;
31
+ this.env_secret = workspace_secret;
32
+ this.config = config;
33
+ this.base_url = this._get_url(config.base_url);
34
+ this.auth_enabled = config.auth_enabled !== false;
35
+ this.include_signature_param = config.include_signature_param !== false;
36
+ this.user_agent = "suprsend/".concat(package_json.version, ";node/").concat(process.version.slice(1));
37
+
38
+ this._validate();
39
+ }
40
+
41
+ (0, _createClass2["default"])(Suprsend, [{
42
+ key: "_validate",
43
+ value: function _validate() {
44
+ if (!this.env_key) {
45
+ throw new Error("SuprsendError: Missing Mandatory WORKSPACE_ENVIRONEMENT");
46
+ } else if (!this.env_secret) {
47
+ throw new Error("SuprsendError: Missing Mandatory WORKSPACE_SECRET");
48
+ } else if (!this.base_url) {
49
+ throw new Error("SuprsendError: Missing Mandatory base url");
50
+ }
51
+ }
52
+ }, {
53
+ key: "_get_url",
54
+ value: function _get_url(base_url) {
55
+ if (base_url) {
56
+ base_url = base_url.trim();
57
+ }
58
+
59
+ if (!base_url) {
60
+ if (this.config.is_staging) {
61
+ base_url = _config["default"].staging;
62
+ } else {
63
+ base_url = _config["default"].prod;
64
+ }
65
+ }
66
+
67
+ base_url = base_url.trim();
68
+
69
+ if (!base_url.endsWith("/")) {
70
+ base_url += "/";
71
+ }
72
+
73
+ return base_url;
74
+ }
75
+ }, {
76
+ key: "add_attachment",
77
+ value: function add_attachment(body, file_path) {
78
+ if (!body.data) {
79
+ body.data = {};
80
+ }
81
+
82
+ if (!body.data instanceof Object) {
83
+ throw new Error("SuprsendError: data must be an object");
84
+ }
85
+
86
+ var attachment = this._get_attachment_json_for_file(file_path);
87
+
88
+ if (!body.data["$attachments"]) {
89
+ body["data"]["$attachments"] = [];
90
+ }
91
+
92
+ body["data"]["$attachments"].push(attachment);
93
+ return body;
94
+ }
95
+ }, {
96
+ key: "_get_attachment_json_for_file",
97
+ value: function _get_attachment_json_for_file(file_path) {
98
+ var abs_path = _path["default"].resolve((0, _utils.resolveTilde)(file_path));
99
+
100
+ return {
101
+ filename: _path["default"].basename(abs_path),
102
+ contentType: _mimeTypes["default"].lookup(abs_path),
103
+ data: (0, _utils.base64Encode)(abs_path)
104
+ };
105
+ }
106
+ }, {
107
+ key: "trigger_workflow",
108
+ value: function trigger_workflow(data) {
109
+ var wf = new _workflow["default"](this, data);
110
+ wf.validate_data();
111
+ return wf.execute_workflow();
112
+ }
113
+ }]);
114
+ return Suprsend;
115
+ }();
116
+
117
+ var _default = Suprsend;
118
+ exports["default"] = _default;
@@ -0,0 +1,192 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "http://github.com/suprsend/suprsend-node-sdk/request_json/workflow.json",
4
+ "title": "workflow_request",
5
+ "description": "Json schema for workflow request",
6
+ "$comment": "Json schema for workflow request",
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "$ref": "#/definitions/non_empty_string",
11
+ "description": "name of workflow"
12
+ },
13
+ "template": {
14
+ "$ref": "#/definitions/non_empty_string",
15
+ "description": "slug of Template"
16
+ },
17
+ "notification_category": {
18
+ "$ref": "#/definitions/non_empty_string",
19
+ "description": "slug of Notification category"
20
+ },
21
+ "delay": {
22
+ "type": ["string", "integer"],
23
+ "minimum": 0,
24
+ "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"
25
+ },
26
+ "trigger_at": {
27
+ "$ref": "#/definitions/non_empty_string",
28
+ "description": "timestamp in ISO-8601 format. e.g 2021-08-27T20:14:51.643Z"
29
+ },
30
+ "priority_algorithm": {
31
+ "type": "boolean"
32
+ },
33
+ "users": {
34
+ "type": "array",
35
+ "items": {
36
+ "$ref": "#/definitions/user_setting"
37
+ },
38
+ "description": "user object to run workflow for"
39
+ },
40
+ "data": {
41
+ "type": "object",
42
+ "description": "variables to be used in workflow. e.g replacing templates variables."
43
+ }
44
+ },
45
+ "required": ["name", "template", "notification_category", "users", "data"],
46
+ "definitions": {
47
+ "non_empty_string": {
48
+ "type": "string",
49
+ "minLength": 1
50
+ },
51
+ "user_setting": {
52
+ "type": "object",
53
+ "properties": {
54
+ "distinct_id": {
55
+ "$ref": "#/definitions/non_empty_string"
56
+ },
57
+ "$email": {
58
+ "oneOf": [
59
+ {
60
+ "$ref": "#/definitions/non_empty_string"
61
+ },
62
+ {
63
+ "type": "array",
64
+ "uniqueItems": true,
65
+ "maxItems": 10,
66
+ "minItems": 1,
67
+ "items": {
68
+ "$ref": "#/definitions/non_empty_string"
69
+ }
70
+ }
71
+ ]
72
+ },
73
+ "$sms": {
74
+ "oneOf": [
75
+ {
76
+ "$ref": "#/definitions/non_empty_string"
77
+ },
78
+ {
79
+ "type": "array",
80
+ "uniqueItems": true,
81
+ "maxItems": 10,
82
+ "minItems": 1,
83
+ "items": {
84
+ "$ref": "#/definitions/non_empty_string"
85
+ }
86
+ }
87
+ ]
88
+ },
89
+ "$androidpush": {
90
+ "oneOf": [
91
+ {
92
+ "$ref": "#/definitions/non_empty_string"
93
+ },
94
+ {
95
+ "type": "array",
96
+ "uniqueItems": true,
97
+ "maxItems": 10,
98
+ "minItems": 1,
99
+ "items": {
100
+ "$ref": "#/definitions/non_empty_string"
101
+ }
102
+ }
103
+ ]
104
+ },
105
+ "$iospush": {
106
+ "oneOf": [
107
+ {
108
+ "$ref": "#/definitions/non_empty_string"
109
+ },
110
+ {
111
+ "type": "array",
112
+ "uniqueItems": true,
113
+ "maxItems": 10,
114
+ "minItems": 1,
115
+ "items": {
116
+ "$ref": "#/definitions/non_empty_string"
117
+ }
118
+ }
119
+ ]
120
+ },
121
+ "$whatsapp": {
122
+ "oneOf": [
123
+ {
124
+ "$ref": "#/definitions/non_empty_string"
125
+ },
126
+ {
127
+ "type": "array",
128
+ "uniqueItems": true,
129
+ "maxItems": 10,
130
+ "minItems": 1,
131
+ "items": {
132
+ "$ref": "#/definitions/non_empty_string"
133
+ }
134
+ }
135
+ ]
136
+ },
137
+ "$webpush": {
138
+ "oneOf": [
139
+ {
140
+ "type": "object",
141
+ "minProperties": 1
142
+ },
143
+ {
144
+ "type": "array",
145
+ "uniqueItems": true,
146
+ "maxItems": 10,
147
+ "minItems": 1,
148
+ "items": {
149
+ "type": "object",
150
+ "minProperties": 1
151
+ }
152
+ }
153
+ ]
154
+ },
155
+ "$inbox": {
156
+ "oneOf": [
157
+ {
158
+ "$ref": "#/definitions/non_empty_string"
159
+ },
160
+ {
161
+ "type": "array",
162
+ "uniqueItems": true,
163
+ "maxItems": 10,
164
+ "minItems": 1,
165
+ "items": {
166
+ "$ref": "#/definitions/non_empty_string"
167
+ }
168
+ }
169
+ ]
170
+ },
171
+ "$messenger": {
172
+ "oneOf": [
173
+ {
174
+ "$ref": "#/definitions/non_empty_string"
175
+ },
176
+ {
177
+ "type": "array",
178
+ "uniqueItems": true,
179
+ "maxItems": 10,
180
+ "minItems": 1,
181
+ "items": {
182
+ "$ref": "#/definitions/non_empty_string"
183
+ }
184
+ }
185
+ ]
186
+ }
187
+ },
188
+ "required": ["distinct_id"],
189
+ "additionalProperties": false
190
+ }
191
+ }
192
+ }
@@ -0,0 +1,30 @@
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_request_signature;
9
+
10
+ var _crypto = _interopRequireDefault(require("crypto"));
11
+
12
+ function get_path(url) {
13
+ var url_info = new URL(url);
14
+ return url_info.pathname + url_info.search;
15
+ }
16
+
17
+ function get_request_signature(url, http_verb, content, headers, secret) {
18
+ if (http_verb === "GET") {
19
+ return "";
20
+ }
21
+
22
+ var content_md5 = _crypto["default"].createHash("md5").update(JSON.stringify(content)).digest("hex");
23
+
24
+ var request_uri = get_path(url);
25
+ var sign_string = http_verb + "\n" + content_md5 + "\n" + headers["Content-Type"] + "\n" + headers["Date"] + "\n" + request_uri;
26
+
27
+ var hash = _crypto["default"].createHmac("sha256", secret).update(sign_string);
28
+
29
+ return hash.digest("base64");
30
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports._get_schema = _get_schema;
9
+ exports.base64Encode = base64Encode;
10
+ exports.resolveTilde = resolveTilde;
11
+
12
+ var _os = _interopRequireDefault(require("os"));
13
+
14
+ var _fs = _interopRequireDefault(require("fs"));
15
+
16
+ var _path = _interopRequireDefault(require("path"));
17
+
18
+ function base64Encode(file) {
19
+ var body = _fs["default"].readFileSync(file);
20
+
21
+ return body.toString("base64");
22
+ }
23
+
24
+ function resolveTilde(filePath) {
25
+ if (!filePath || typeof filePath !== "string") {
26
+ return "";
27
+ }
28
+
29
+ if (filePath.startsWith("~/") || filePath === "~") {
30
+ return filePath.replace("~", _os["default"].homedir());
31
+ }
32
+
33
+ return filePath;
34
+ }
35
+
36
+ var __JSON_SCHEMAS = {};
37
+
38
+ function _get_schema(schema_name) {
39
+ var schema_body = __JSON_SCHEMAS[schema_name];
40
+
41
+ if (!schema_body) {
42
+ schema_body = _load_json_schema(schema_name);
43
+ __JSON_SCHEMAS[schema_name] = schema_body;
44
+ }
45
+
46
+ return schema_body;
47
+ }
48
+
49
+ function _load_json_schema(schema_name) {
50
+ var file_path = _path["default"].join(__dirname, "request_json/".concat(schema_name, ".json"));
51
+
52
+ var json_schema;
53
+
54
+ try {
55
+ var schema_string = _fs["default"].readFileSync(file_path, "utf8");
56
+
57
+ json_schema = JSON.parse(schema_string);
58
+ } catch (e) {
59
+ throw new Error("SuprsendError: Missing Schema");
60
+ }
61
+
62
+ return json_schema;
63
+ }
@@ -0,0 +1,148 @@
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 _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
15
+
16
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
17
+
18
+ var _signature = _interopRequireDefault(require("./signature"));
19
+
20
+ var _https = _interopRequireDefault(require("https"));
21
+
22
+ var _jsonschema = require("jsonschema");
23
+
24
+ var _utils = require("./utils");
25
+
26
+ var _axios = _interopRequireDefault(require("axios"));
27
+
28
+ var Workflow = /*#__PURE__*/function () {
29
+ function Workflow(ss_instance, data) {
30
+ (0, _classCallCheck2["default"])(this, Workflow);
31
+ this.ss_instance = ss_instance;
32
+ this.data = data;
33
+ this.url = this._get_url();
34
+ }
35
+
36
+ (0, _createClass2["default"])(Workflow, [{
37
+ key: "_get_url",
38
+ value: function _get_url() {
39
+ var url_template = "/trigger/";
40
+
41
+ if (this.ss_instance.include_signature_param) {
42
+ if (this.ss_instance.auth_enabled) {
43
+ url_template = url_template + "?verify=true";
44
+ } else {
45
+ url_template = url_template + "?verify=false";
46
+ }
47
+ }
48
+
49
+ var url_formatted = "".concat(this.ss_instance.base_url).concat(this.ss_instance.env_key).concat(url_template);
50
+ return url_formatted;
51
+ }
52
+ }, {
53
+ key: "_get_headers",
54
+ value: function _get_headers() {
55
+ return {
56
+ "Content-Type": "application/json",
57
+ Date: new Date().toUTCString(),
58
+ "User-Agent": this.ss_instance.user_agent
59
+ };
60
+ }
61
+ }, {
62
+ key: "execute_workflow",
63
+ value: function () {
64
+ var _execute_workflow = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
65
+ var headers, content_text, signature, response;
66
+ return _regenerator["default"].wrap(function _callee$(_context) {
67
+ while (1) {
68
+ switch (_context.prev = _context.next) {
69
+ case 0:
70
+ headers = this._get_headers();
71
+ content_text = JSON.stringify(this.data);
72
+
73
+ if (this.ss_instance.auth_enabled) {
74
+ signature = (0, _signature["default"])(this.url, "POST", this.data, headers, this.ss_instance.env_secret);
75
+ headers["Authorization"] = "".concat(this.ss_instance.env_key, ":").concat(signature);
76
+ }
77
+
78
+ _context.prev = 3;
79
+ _context.next = 6;
80
+ return _axios["default"].post(this.url, content_text, {
81
+ headers: headers
82
+ });
83
+
84
+ case 6:
85
+ response = _context.sent;
86
+ return _context.abrupt("return", {
87
+ status_code: response.status,
88
+ success: true,
89
+ message: response.statusText
90
+ });
91
+
92
+ case 10:
93
+ _context.prev = 10;
94
+ _context.t0 = _context["catch"](3);
95
+ return _context.abrupt("return", {
96
+ status_code: 400,
97
+ success: false,
98
+ message: _context.t0.message
99
+ });
100
+
101
+ case 13:
102
+ case "end":
103
+ return _context.stop();
104
+ }
105
+ }
106
+ }, _callee, this, [[3, 10]]);
107
+ }));
108
+
109
+ function execute_workflow() {
110
+ return _execute_workflow.apply(this, arguments);
111
+ }
112
+
113
+ return execute_workflow;
114
+ }()
115
+ }, {
116
+ key: "validate_data",
117
+ value: function validate_data() {
118
+ var _this$data;
119
+
120
+ if (!((_this$data = this.data) !== null && _this$data !== void 0 && _this$data.data)) {
121
+ this.data.data = {};
122
+ }
123
+
124
+ if (!(this.data.data instanceof Object)) {
125
+ throw new Error("SuprsendError: data must be a object");
126
+ }
127
+
128
+ var schema = (0, _utils._get_schema)("workflow");
129
+
130
+ try {
131
+ var v = new _jsonschema.Validator();
132
+ v.validate(this.data, schema);
133
+ } catch (e) {
134
+ if (e instanceof _jsonschema.SchemaError) {
135
+ throw new Error("SuprsendSchemaError:".concat(e.message));
136
+ } else if (e instanceof _jsonschema.ValidationError) {
137
+ throw new Error("SuprsendValidationError:".concat(e.message));
138
+ }
139
+ }
140
+
141
+ return this.data;
142
+ }
143
+ }]);
144
+ return Workflow;
145
+ }();
146
+
147
+ var _default = Workflow;
148
+ exports["default"] = _default;
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@suprsend/node-sdk",
3
+ "version": "0.0.1",
4
+ "description": "Suprsend Node SDK to trigger workflow from backend",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "rm -rf dist && babel ./src --out-dir dist && mkdir ./dist/request_json && cp ./src/request_json/workflow.json ./dist/request_json/"
8
+ },
9
+ "keywords": [
10
+ "suprsend-node-sdk",
11
+ "workflow"
12
+ ],
13
+ "author": "Sivaram Katta",
14
+ "license": "ISC",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/suprsend/suprsend-node-sdk.git"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "dependencies": {
23
+ "@babel/runtime": "^7.16.3",
24
+ "axios": "^0.24.0",
25
+ "jsonschema": "^1.4.0",
26
+ "mime-types": "^2.1.34"
27
+ },
28
+ "devDependencies": {
29
+ "@babel/cli": "^7.16.0",
30
+ "@babel/core": "^7.16.0",
31
+ "@babel/plugin-transform-runtime": "^7.16.4",
32
+ "@babel/preset-env": "^7.16.4"
33
+ }
34
+ }
package/src/config.js ADDED
@@ -0,0 +1,6 @@
1
+ const config = {
2
+ staging: "https://collector-staging.suprsend.workers.dev/",
3
+ prod: "https://hub.suprsend.com/",
4
+ };
5
+
6
+ export default config;
package/src/index.js ADDED
@@ -0,0 +1,84 @@
1
+ import config from "./config";
2
+ import Workflow from "./workflow";
3
+ import path from "path";
4
+ import mime from "mime-types";
5
+ import { base64Encode, resolveTilde } from "./utils";
6
+
7
+ const package_json = require("../package.json");
8
+
9
+ class Suprsend {
10
+ constructor(workspace_env, workspace_secret, config = {}) {
11
+ this.env_key = workspace_env;
12
+ this.env_secret = workspace_secret;
13
+ this.config = config;
14
+ this.base_url = this._get_url(config.base_url);
15
+ this.auth_enabled = config.auth_enabled !== false;
16
+ this.include_signature_param = config.include_signature_param !== false;
17
+ this.user_agent = `suprsend/${
18
+ package_json.version
19
+ };node/${process.version.slice(1)}`;
20
+ this._validate();
21
+ }
22
+
23
+ _validate() {
24
+ if (!this.env_key) {
25
+ throw new Error(
26
+ "SuprsendError: Missing Mandatory WORKSPACE_ENVIRONEMENT"
27
+ );
28
+ } else if (!this.env_secret) {
29
+ throw new Error("SuprsendError: Missing Mandatory WORKSPACE_SECRET");
30
+ } else if (!this.base_url) {
31
+ throw new Error("SuprsendError: Missing Mandatory base url");
32
+ }
33
+ }
34
+
35
+ _get_url(base_url) {
36
+ if (base_url) {
37
+ base_url = base_url.trim();
38
+ }
39
+ if (!base_url) {
40
+ if (this.config.is_staging) {
41
+ base_url = config.staging;
42
+ } else {
43
+ base_url = config.prod;
44
+ }
45
+ }
46
+ base_url = base_url.trim();
47
+ if (!base_url.endsWith("/")) {
48
+ base_url += "/";
49
+ }
50
+ return base_url;
51
+ }
52
+
53
+ add_attachment(body, file_path) {
54
+ if (!body.data) {
55
+ body.data = {};
56
+ }
57
+ if (!body.data instanceof Object) {
58
+ throw new Error("SuprsendError: data must be an object");
59
+ }
60
+ const attachment = this._get_attachment_json_for_file(file_path);
61
+ if (!body.data["$attachments"]) {
62
+ body["data"]["$attachments"] = [];
63
+ }
64
+ body["data"]["$attachments"].push(attachment);
65
+ return body;
66
+ }
67
+
68
+ _get_attachment_json_for_file(file_path) {
69
+ const abs_path = path.resolve(resolveTilde(file_path));
70
+ return {
71
+ filename: path.basename(abs_path),
72
+ contentType: mime.lookup(abs_path),
73
+ data: base64Encode(abs_path),
74
+ };
75
+ }
76
+
77
+ trigger_workflow(data) {
78
+ const wf = new Workflow(this, data);
79
+ wf.validate_data();
80
+ return wf.execute_workflow();
81
+ }
82
+ }
83
+
84
+ export default Suprsend;
@@ -0,0 +1,192 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "http://github.com/suprsend/suprsend-node-sdk/request_json/workflow.json",
4
+ "title": "workflow_request",
5
+ "description": "Json schema for workflow request",
6
+ "$comment": "Json schema for workflow request",
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "$ref": "#/definitions/non_empty_string",
11
+ "description": "name of workflow"
12
+ },
13
+ "template": {
14
+ "$ref": "#/definitions/non_empty_string",
15
+ "description": "slug of Template"
16
+ },
17
+ "notification_category": {
18
+ "$ref": "#/definitions/non_empty_string",
19
+ "description": "slug of Notification category"
20
+ },
21
+ "delay": {
22
+ "type": ["string", "integer"],
23
+ "minimum": 0,
24
+ "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"
25
+ },
26
+ "trigger_at": {
27
+ "$ref": "#/definitions/non_empty_string",
28
+ "description": "timestamp in ISO-8601 format. e.g 2021-08-27T20:14:51.643Z"
29
+ },
30
+ "priority_algorithm": {
31
+ "type": "boolean"
32
+ },
33
+ "users": {
34
+ "type": "array",
35
+ "items": {
36
+ "$ref": "#/definitions/user_setting"
37
+ },
38
+ "description": "user object to run workflow for"
39
+ },
40
+ "data": {
41
+ "type": "object",
42
+ "description": "variables to be used in workflow. e.g replacing templates variables."
43
+ }
44
+ },
45
+ "required": ["name", "template", "notification_category", "users", "data"],
46
+ "definitions": {
47
+ "non_empty_string": {
48
+ "type": "string",
49
+ "minLength": 1
50
+ },
51
+ "user_setting": {
52
+ "type": "object",
53
+ "properties": {
54
+ "distinct_id": {
55
+ "$ref": "#/definitions/non_empty_string"
56
+ },
57
+ "$email": {
58
+ "oneOf": [
59
+ {
60
+ "$ref": "#/definitions/non_empty_string"
61
+ },
62
+ {
63
+ "type": "array",
64
+ "uniqueItems": true,
65
+ "maxItems": 10,
66
+ "minItems": 1,
67
+ "items": {
68
+ "$ref": "#/definitions/non_empty_string"
69
+ }
70
+ }
71
+ ]
72
+ },
73
+ "$sms": {
74
+ "oneOf": [
75
+ {
76
+ "$ref": "#/definitions/non_empty_string"
77
+ },
78
+ {
79
+ "type": "array",
80
+ "uniqueItems": true,
81
+ "maxItems": 10,
82
+ "minItems": 1,
83
+ "items": {
84
+ "$ref": "#/definitions/non_empty_string"
85
+ }
86
+ }
87
+ ]
88
+ },
89
+ "$androidpush": {
90
+ "oneOf": [
91
+ {
92
+ "$ref": "#/definitions/non_empty_string"
93
+ },
94
+ {
95
+ "type": "array",
96
+ "uniqueItems": true,
97
+ "maxItems": 10,
98
+ "minItems": 1,
99
+ "items": {
100
+ "$ref": "#/definitions/non_empty_string"
101
+ }
102
+ }
103
+ ]
104
+ },
105
+ "$iospush": {
106
+ "oneOf": [
107
+ {
108
+ "$ref": "#/definitions/non_empty_string"
109
+ },
110
+ {
111
+ "type": "array",
112
+ "uniqueItems": true,
113
+ "maxItems": 10,
114
+ "minItems": 1,
115
+ "items": {
116
+ "$ref": "#/definitions/non_empty_string"
117
+ }
118
+ }
119
+ ]
120
+ },
121
+ "$whatsapp": {
122
+ "oneOf": [
123
+ {
124
+ "$ref": "#/definitions/non_empty_string"
125
+ },
126
+ {
127
+ "type": "array",
128
+ "uniqueItems": true,
129
+ "maxItems": 10,
130
+ "minItems": 1,
131
+ "items": {
132
+ "$ref": "#/definitions/non_empty_string"
133
+ }
134
+ }
135
+ ]
136
+ },
137
+ "$webpush": {
138
+ "oneOf": [
139
+ {
140
+ "type": "object",
141
+ "minProperties": 1
142
+ },
143
+ {
144
+ "type": "array",
145
+ "uniqueItems": true,
146
+ "maxItems": 10,
147
+ "minItems": 1,
148
+ "items": {
149
+ "type": "object",
150
+ "minProperties": 1
151
+ }
152
+ }
153
+ ]
154
+ },
155
+ "$inbox": {
156
+ "oneOf": [
157
+ {
158
+ "$ref": "#/definitions/non_empty_string"
159
+ },
160
+ {
161
+ "type": "array",
162
+ "uniqueItems": true,
163
+ "maxItems": 10,
164
+ "minItems": 1,
165
+ "items": {
166
+ "$ref": "#/definitions/non_empty_string"
167
+ }
168
+ }
169
+ ]
170
+ },
171
+ "$messenger": {
172
+ "oneOf": [
173
+ {
174
+ "$ref": "#/definitions/non_empty_string"
175
+ },
176
+ {
177
+ "type": "array",
178
+ "uniqueItems": true,
179
+ "maxItems": 10,
180
+ "minItems": 1,
181
+ "items": {
182
+ "$ref": "#/definitions/non_empty_string"
183
+ }
184
+ }
185
+ ]
186
+ }
187
+ },
188
+ "required": ["distinct_id"],
189
+ "additionalProperties": false
190
+ }
191
+ }
192
+ }
@@ -0,0 +1,35 @@
1
+ import crypto from "crypto";
2
+
3
+ function get_path(url) {
4
+ const url_info = new URL(url);
5
+ return url_info.pathname + url_info.search;
6
+ }
7
+
8
+ export default function get_request_signature(
9
+ url,
10
+ http_verb,
11
+ content,
12
+ headers,
13
+ secret
14
+ ) {
15
+ if (http_verb === "GET") {
16
+ return "";
17
+ }
18
+ const content_md5 = crypto
19
+ .createHash("md5")
20
+ .update(JSON.stringify(content))
21
+ .digest("hex");
22
+ const request_uri = get_path(url);
23
+ const sign_string =
24
+ http_verb +
25
+ "\n" +
26
+ content_md5 +
27
+ "\n" +
28
+ headers["Content-Type"] +
29
+ "\n" +
30
+ headers["Date"] +
31
+ "\n" +
32
+ request_uri;
33
+ const hash = crypto.createHmac("sha256", secret).update(sign_string);
34
+ return hash.digest("base64");
35
+ }
package/src/utils.js ADDED
@@ -0,0 +1,43 @@
1
+ import os from "os";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ export function base64Encode(file) {
6
+ var body = fs.readFileSync(file);
7
+ return body.toString("base64");
8
+ }
9
+
10
+ export function resolveTilde(filePath) {
11
+ if (!filePath || typeof filePath !== "string") {
12
+ return "";
13
+ }
14
+
15
+ if (filePath.startsWith("~/") || filePath === "~") {
16
+ return filePath.replace("~", os.homedir());
17
+ }
18
+
19
+ return filePath;
20
+ }
21
+
22
+ let __JSON_SCHEMAS = {};
23
+
24
+ export function _get_schema(schema_name) {
25
+ var schema_body = __JSON_SCHEMAS[schema_name];
26
+ if (!schema_body) {
27
+ schema_body = _load_json_schema(schema_name);
28
+ __JSON_SCHEMAS[schema_name] = schema_body;
29
+ }
30
+ return schema_body;
31
+ }
32
+
33
+ function _load_json_schema(schema_name) {
34
+ var file_path = path.join(__dirname, `request_json/${schema_name}.json`);
35
+ var json_schema;
36
+ try {
37
+ var schema_string = fs.readFileSync(file_path, "utf8");
38
+ json_schema = JSON.parse(schema_string);
39
+ } catch (e) {
40
+ throw new Error("SuprsendError: Missing Schema");
41
+ }
42
+ return json_schema;
43
+ }
@@ -0,0 +1,86 @@
1
+ import get_request_signature from "./signature";
2
+ import https from "https";
3
+ import { Validator, SchemaError, ValidationError } from "jsonschema";
4
+ import { _get_schema } from "./utils";
5
+ import axios from "axios";
6
+
7
+ class Workflow {
8
+ constructor(ss_instance, data) {
9
+ this.ss_instance = ss_instance;
10
+ this.data = data;
11
+ this.url = this._get_url();
12
+ }
13
+
14
+ _get_url() {
15
+ let url_template = "/trigger/";
16
+ if (this.ss_instance.include_signature_param) {
17
+ if (this.ss_instance.auth_enabled) {
18
+ url_template = url_template + "?verify=true";
19
+ } else {
20
+ url_template = url_template + "?verify=false";
21
+ }
22
+ }
23
+ const url_formatted = `${this.ss_instance.base_url}${this.ss_instance.env_key}${url_template}`;
24
+ return url_formatted;
25
+ }
26
+
27
+ _get_headers() {
28
+ return {
29
+ "Content-Type": "application/json",
30
+ Date: new Date().toUTCString(),
31
+ "User-Agent": this.ss_instance.user_agent,
32
+ };
33
+ }
34
+
35
+ async execute_workflow() {
36
+ const headers = this._get_headers();
37
+ const content_text = JSON.stringify(this.data);
38
+ if (this.ss_instance.auth_enabled) {
39
+ const signature = get_request_signature(
40
+ this.url,
41
+ "POST",
42
+ this.data,
43
+ headers,
44
+ this.ss_instance.env_secret
45
+ );
46
+ headers["Authorization"] = `${this.ss_instance.env_key}:${signature}`;
47
+ }
48
+ try {
49
+ const response = await axios.post(this.url, content_text, { headers });
50
+ return {
51
+ status_code: response.status,
52
+ success: true,
53
+ message: response.statusText,
54
+ };
55
+ } catch (err) {
56
+ return {
57
+ status_code: 400,
58
+ success: false,
59
+ message: err.message,
60
+ };
61
+ }
62
+ }
63
+
64
+ validate_data() {
65
+ if (!this.data?.data) {
66
+ this.data.data = {};
67
+ }
68
+ if (!(this.data.data instanceof Object)) {
69
+ throw new Error("SuprsendError: data must be a object");
70
+ }
71
+ const schema = _get_schema("workflow");
72
+ try {
73
+ var v = new Validator();
74
+ v.validate(this.data, schema);
75
+ } catch (e) {
76
+ if (e instanceof SchemaError) {
77
+ throw new Error(`SuprsendSchemaError:${e.message}`);
78
+ } else if (e instanceof ValidationError) {
79
+ throw new Error(`SuprsendValidationError:${e.message}`);
80
+ }
81
+ }
82
+ return this.data;
83
+ }
84
+ }
85
+
86
+ export default Workflow;