@engage_so/core 1.6.0 → 2.0.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/.eslintignore ADDED
@@ -0,0 +1,3 @@
1
+ dist
2
+ node_modules
3
+ tests
package/jest.config.js ADDED
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ transform: {
3
+ '^.+\\.ts?$': ['ts-jest', { diagnostics: false }]
4
+ },
5
+ testRegex: '/tests/.*\\.(test|spec)?\\.(ts|tsx)$',
6
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
7
+ };
package/package.json CHANGED
@@ -1,22 +1,29 @@
1
1
  {
2
2
  "name": "@engage_so/core",
3
- "version": "1.6.0",
4
- "description": "Event driven customer segmentation and targeted engagement.",
5
- "main": "index.js",
3
+ "version": "2.0.0",
4
+ "description": "Engage JS core.",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
6
7
  "scripts": {
7
- "test": "jest"
8
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
9
+ "build": "tsc -p tsconfig.json",
10
+ "prepublishOnly": "npm run build"
8
11
  },
9
12
  "publishConfig": {
10
13
  "access": "public"
11
14
  },
12
15
  "author": "Engage",
13
16
  "license": "MIT",
14
- "dependencies": {
15
- "buffer": "^6.0.3",
16
- "cross-fetch": "^3.1.5"
17
- },
18
17
  "devDependencies": {
19
- "jest": "^26.4.2"
18
+ "@tsconfig/recommended": "^1.0.3",
19
+ "@types/jest": "^29.5.12",
20
+ "@types/node": "^20.11.19",
21
+ "jest": "^29.7.0",
22
+ "ts-jest": "^29.1.2",
23
+ "ts-standard": "^12.0.2"
24
+ },
25
+ "dependencies": {
26
+ "cross-fetch": "^4.0.0"
20
27
  },
21
- "gitHead": "7db0b36d47cee47daf1bb9412ced6bec0f23462b"
28
+ "gitHead": "ecc6ef9a3277da36b56fb4169dbfafbdde9b926b"
22
29
  }
package/src/error.ts ADDED
@@ -0,0 +1,6 @@
1
+ export class EngageError extends Error {
2
+ constructor (message: string) {
3
+ super(message)
4
+ this.name = 'EngageError'
5
+ }
6
+ }
package/src/index.ts ADDED
@@ -0,0 +1,242 @@
1
+ import { Buffer } from 'buffer'
2
+ import fetch from 'cross-fetch'
3
+ import { EngageError } from './error'
4
+
5
+ if (typeof btoa === 'undefined') {
6
+ global.btoa = function (str) {
7
+ return Buffer.from(str).toString('base64')
8
+ }
9
+ }
10
+
11
+ interface Key {
12
+ key?: string
13
+ secret?: string
14
+ }
15
+ interface EventParameter {
16
+ event: string
17
+ value?: string | number | Date | boolean
18
+ properties?: {
19
+ [key: string]: string | number | Date | boolean
20
+ }
21
+ timestamp?: string | number | Date
22
+ }
23
+ type UserAttrParams = {
24
+ [key: string]: string | number | Date | boolean
25
+ }
26
+ type UserIdentifyParams = UserAttrParams & { id: string }
27
+ type DataParameters = {
28
+ [key: string]: string | number | Date | boolean
29
+ } & {
30
+ meta?: {
31
+ [key: string]: string | number | Date | boolean
32
+ }
33
+ }
34
+ type Methods = 'POST' | 'PUT' | 'DELETE'
35
+ // type UserIdentifyParams = {
36
+ // id: string
37
+ // [key: string]: string | number | Date | boolean
38
+ // }
39
+ // type UserAttrParams = Omit<UserIdentifyParams, 'id'>
40
+
41
+ const rootURL = 'https://api.engage.so/v1'
42
+ let auth: string = ''
43
+ const notMeta = ['created_at', 'is_account', 'number', 'device_token', 'device_platform', 'email', 'first_name', 'last_name', 'tz', 'app_version', 'app_build', 'app_last_active']
44
+ const apiRoot = 'https://api.engage.so/'
45
+
46
+ async function _request (url: string, params: Record<string, any> | null, method: Methods) {
47
+ try {
48
+ const o: any = {
49
+ method,
50
+ headers: {
51
+ 'Content-Type': 'application/json;charset=utf-8',
52
+ Authorization: `Basic ${auth}`
53
+ },
54
+ // throwHttpErrors: false,
55
+ // prefixUrl: rootURL
56
+ }
57
+ if (params) {
58
+ o.body = JSON.stringify(params)
59
+ }
60
+ // const response = await ky(url, o)
61
+ const response = await fetch(`${apiRoot}${url}`, o)
62
+ const body: any = await response.json()
63
+ let error = 'API connection error'
64
+ if (!response.ok) {
65
+ if (body && body.error) {
66
+ error = body.error
67
+ }
68
+ return { error }
69
+ }
70
+ return body
71
+ } catch (e) {
72
+ return { error: 'API connection error' }
73
+ }
74
+ }
75
+ // Alias of _request method
76
+ // Same with _request for now but can later have modifications
77
+ export function request (url: string, params: Record<string, any> | null, method: Methods): object {
78
+ return _request(url, params, method)
79
+ }
80
+
81
+ export function init (key: Key | string) {
82
+ if (!key) {
83
+ throw new EngageError('You need to pass in your API key(s).')
84
+ }
85
+ const options: Key = {
86
+ key: undefined,
87
+ secret: ''
88
+ }
89
+ if (typeof key === 'string') {
90
+ options.key = key
91
+ } else {
92
+ if (!key.key) {
93
+ throw new EngageError('`key` missing in object.')
94
+ }
95
+ if (key.key) {
96
+ options.key = `${key.key}`
97
+ }
98
+ if (key.secret) {
99
+ options.secret = `${key.secret}`
100
+ }
101
+ }
102
+ // Set auth
103
+ // auth = Buffer.from(`${options.key}:${options.secret}`).toString('base64')
104
+ auth = btoa(`${options.key}:${options.secret}`)
105
+ }
106
+
107
+ // Data tracking
108
+ export async function identify (user: UserIdentifyParams) {
109
+ if (!user) {
110
+ throw new EngageError('You need to pass an object with at least an id.')
111
+ }
112
+ if (!user.id) {
113
+ throw new EngageError('ID missing.')
114
+ }
115
+ if (user.email && (typeof user.email !== 'string' || !/^\S+@\S+$/.test(user.email))) {
116
+ throw new EngageError('Email invalid.')
117
+ }
118
+ const params: DataParameters = {}
119
+ params.meta = {}
120
+ for (const k in user) {
121
+ if (k === 'id' || notMeta.includes(k)) {
122
+ params[k] = user[k]
123
+ } else {
124
+ params.meta[k] = user[k]
125
+ }
126
+ }
127
+
128
+ return _request(`users/${user.id}`, params, 'PUT')
129
+ }
130
+ export async function addAttribute (uid: string, attributes: UserAttrParams) {
131
+ if (!uid) {
132
+ throw new EngageError('User ID missing.')
133
+ }
134
+ if (!attributes) {
135
+ throw new EngageError('Attributes missing.')
136
+ }
137
+ if (!Object.keys(attributes).length) {
138
+ throw new EngageError('Attributes missing.')
139
+ }
140
+ const params: DataParameters = {}
141
+ params.meta = {}
142
+ for (const k in attributes) {
143
+ if (notMeta.includes(k)) {
144
+ params[k] = attributes[k]
145
+ } else {
146
+ params.meta[k] = attributes[k]
147
+ Object.assign(params.meta, k, attributes[k])
148
+ }
149
+ }
150
+ if (Object.keys(params.meta).length) {
151
+ delete params.meta
152
+ }
153
+
154
+ return _request(`users/${uid}`, params, 'PUT')
155
+ }
156
+ export async function track (uid: string, data: EventParameter) {
157
+ if (!uid) {
158
+ throw new EngageError('User ID missing.')
159
+ }
160
+ if (!data) {
161
+ throw new EngageError('Event data missing.')
162
+ }
163
+ if (typeof data === 'string') {
164
+ data = {
165
+ event: data,
166
+ value: true
167
+ }
168
+ } else {
169
+ if (!Object.keys(data).length) {
170
+ throw new EngageError('Attributes missing.')
171
+ }
172
+ }
173
+
174
+ return _request(`users/${uid}/events`, data, 'POST')
175
+ }
176
+
177
+ export async function merge (sourceUid: string, destinationUid: string) {
178
+ if (!sourceUid) {
179
+ throw new EngageError('Source ID missing.')
180
+ }
181
+ if (!destinationUid) {
182
+ throw new EngageError('Destination ID missing.')
183
+ }
184
+
185
+ return _request(`users/merge`, {
186
+ source: sourceUid,
187
+ destination: destinationUid
188
+ }, 'POST')
189
+ }
190
+
191
+ // Account functions
192
+ export async function addToAccount(uid: string, accountId: string, role: string) {
193
+ if (!uid) {
194
+ throw new EngageError('User ID missing.')
195
+ }
196
+ if (!accountId) {
197
+ throw new EngageError('Account ID missing.')
198
+ }
199
+ if (role && typeof role !== 'string') {
200
+ throw new EngageError('Role should be a text.')
201
+ }
202
+ const g: Record<string, string> = {
203
+ id: accountId
204
+ }
205
+ if (role) {
206
+ g.role = role
207
+ }
208
+ return _request(`users/${uid}/accounts`, { accounts: [g] }, 'POST')
209
+ }
210
+ export async function removeFromAccount (uid: string, accountId: string){
211
+ if (!uid) {
212
+ throw new EngageError('User ID missing.')
213
+ }
214
+ if (!accountId) {
215
+ throw new EngageError('Account ID missing.')
216
+ }
217
+ return _request(`users/${uid}/accounts/${accountId}`, null, 'DELETE')
218
+ }
219
+ export async function changeAccountRole (uid: string, accountId: string, role: string) {
220
+ if (!uid) {
221
+ throw new EngageError('User ID missing.')
222
+ }
223
+ if (!accountId) {
224
+ throw new EngageError('Account ID missing.')
225
+ }
226
+ if (!role) {
227
+ throw new EngageError('New role missing.')
228
+ }
229
+ return _request(`users/${uid}/accounts/${accountId}`, { role }, 'PUT')
230
+ }
231
+ export async function convertToCustomer (uid: string) {
232
+ if (!uid) {
233
+ throw new EngageError('User ID missing.')
234
+ }
235
+ return _request(`users/${uid}/convert`, { type: 'customer' }, 'POST')
236
+ }
237
+ export async function convertToAccount (uid: string) {
238
+ if (!uid) {
239
+ throw new EngageError('User ID missing.')
240
+ }
241
+ return _request(`users/${uid}/convert`, { type: 'account' }, 'POST')
242
+ }
@@ -0,0 +1,231 @@
1
+ import * as Engage from '../src/index'
2
+ const id = 'uzl38704@omeie.com'
3
+ const sid = 'a6236e83-f7c1-4003-8e1a-951f6e1d5c60'
4
+ const gid = '7d1a5e27-5a6b-4b38-a8bd-e59b8a1b2f41'
5
+
6
+ describe('Init', () => {
7
+ test('should throw if no parameters sent', () => {
8
+ expect(() => {
9
+ Engage.init()
10
+ }).toThrow('API')
11
+ })
12
+ test('should throw if parameter is empty object', () => {
13
+ expect(() => {
14
+ Engage.init({})
15
+ }).toThrow('key')
16
+ })
17
+ test('should throw if empty key sent', () => {
18
+ expect(() => {
19
+ Engage.init('')
20
+ }).toThrow()
21
+ })
22
+ test('should not throw if key/secret is sent', () => {
23
+ expect(() => {
24
+ Engage.init({
25
+ key: process.env.KEY,
26
+ secret: process.env.SECRET
27
+ })
28
+ }).not.toThrow()
29
+ })
30
+ })
31
+
32
+ describe('Identify', () => {
33
+ test('should throw if no parameter passed', async () => {
34
+ await expect(Engage.identify()).rejects.toThrow('object')
35
+ })
36
+ test('should throw if empty string passed', async () => {
37
+ await expect(Engage.identify('')).rejects.toThrow('id')
38
+ })
39
+ test('should throw if empty object passed', async () => {
40
+ await expect(Engage.identify({})).rejects.toThrow(/id/i)
41
+ })
42
+ test('should not throw if no email passed', async () => {
43
+ await expect(() => {
44
+ Engage.identify({ id: gid })
45
+ }).not.toThrow()
46
+ })
47
+ test('should throw if invalid email passed', async () => {
48
+ await expect(Engage.identify({
49
+ id,
50
+ email: 'invalid'
51
+ })).rejects.toThrow(/email/i)
52
+ })
53
+ test('should work if id and email passed', async () => {
54
+ await expect(Engage.identify({
55
+ id,
56
+ email: 'fickledreams@yahoo.com'
57
+ })).resolves.toMatchObject({
58
+ uid: id,
59
+ email: 'fickledreams@yahoo.com'
60
+ })
61
+ })
62
+ test('should turn to account if has is_account', async () => {
63
+ await expect(Engage.identify({
64
+ id,
65
+ is_account: true
66
+ })).resolves.toMatchObject({
67
+ is_account: true
68
+ })
69
+ })
70
+ test('should turn to user if is_account is false', async () => {
71
+ await expect(Engage.identify({
72
+ id,
73
+ is_account: false
74
+ })).resolves.toMatchObject({
75
+ is_account: false
76
+ })
77
+ })
78
+ })
79
+
80
+ describe('Add attribute', () => {
81
+ test('should throw if no parameter passed', async () => {
82
+ await expect(Engage.addAttribute()).rejects.toThrow('id')
83
+ })
84
+ test('should throw if no data attribute passed', async () => {
85
+ await expect(Engage.addAttribute(id)).rejects.toThrow(/attributes/i)
86
+ })
87
+ test('should throw if empty object passed', async () => {
88
+ await expect(Engage.addAttribute(id, {})).rejects.toThrow(/attributes/i)
89
+ })
90
+ test('should resolve if parameters passed', async () => {
91
+ await expect(Engage.addAttribute(sid, {
92
+ first_name: 'Opeyemi',
93
+ active: true,
94
+ created_at: '2020-08-11'
95
+ })).resolves.toMatchObject({
96
+ uid: sid,
97
+ first_name: 'Opeyemi'
98
+ })
99
+ })
100
+ test('should turn to account if has is_account', async () => {
101
+ await expect(Engage.addAttribute(id, {
102
+ is_account: true
103
+ })).resolves.toMatchObject({
104
+ is_account: true
105
+ })
106
+ })
107
+ test('should turn to user if is_account is not added', async () => {
108
+ await expect(Engage.addAttribute(id, {
109
+ is_account: false
110
+ })).resolves.toMatchObject({
111
+ is_account: false
112
+ })
113
+ })
114
+ })
115
+
116
+ describe('Track', () => {
117
+ test('should throw if no parameter passed', async () => {
118
+ await expect(Engage.track()).rejects.toThrow('ID')
119
+ })
120
+ test('should throw if no data attribute passed', async () => {
121
+ await expect(Engage.track(id)).rejects.toThrow(/data/i)
122
+ })
123
+ test('should throw if empty object passed', async () => {
124
+ await expect(Engage.track(id, {})).rejects.toThrow(/attributes/i)
125
+ })
126
+ test('should pass if string property passed', async () => {
127
+ await expect(Engage.track(id, 'loggedin')).resolves.toMatchObject({
128
+ status: 'ok'
129
+ })
130
+ })
131
+ test('should pass if right parameters passed', async () => {
132
+ await expect(Engage.track(id, {
133
+ event: 'played',
134
+ value: 'vid_133',
135
+ timestamp: '2020-05-30T09:30:10Z'
136
+ })).resolves.toMatchObject({
137
+ status: 'ok'
138
+ })
139
+ })
140
+ test('should resolve if other variant passed', async () => {
141
+ await expect(Engage.track(id, {
142
+ event: 'loggedin',
143
+ properties: {
144
+ ip: '127.0.0.1',
145
+ referral: 'localhost'
146
+ }
147
+ })).resolves.toMatchObject({
148
+ status: 'ok'
149
+ })
150
+ })
151
+ })
152
+
153
+ describe('Merge users', () => {
154
+ test('should throw if no source id', async () => {
155
+ await expect(Engage.merge()).rejects.toThrow(/id/i)
156
+ })
157
+ test('should throw if no destination id', async () => {
158
+ await expect(Engage.merge(id)).rejects.toThrow(/id/i)
159
+ })
160
+ test('should merge if all is well', async () => {
161
+ await expect(Engage.merge(sid, id)).resolves.toMatchObject({
162
+ status: 'queued'
163
+ })
164
+ })
165
+ })
166
+
167
+ describe('Convert to account', () => {
168
+ test('should convert to account', async () => {
169
+ await expect(Engage.convertToAccount(gid)).resolves.toMatchObject({
170
+ is_account: true
171
+ })
172
+ })
173
+ })
174
+
175
+ describe('Convert to customer', () => {
176
+ test('should convert to customer', async () => {
177
+ await expect(Engage.convertToCustomer(gid)).resolves.toMatchObject({
178
+ is_account: false
179
+ })
180
+ })
181
+ })
182
+
183
+ describe('Add to account', () => {
184
+ test('should throw if no account id added', async () => {
185
+ await expect(Engage.addToAccount(id)).rejects.toThrow(/id/i)
186
+ })
187
+ test('should throw if role and role not string', async () => {
188
+ await expect(Engage.addToAccount(id, gid, [ 'something' ])).rejects.toThrow(/Role/)
189
+ })
190
+ test('should pass if account id added', async () => {
191
+ await expect(Engage.addToAccount(id, gid)).resolves.toMatchObject({
192
+ accounts: [{
193
+ id: gid
194
+ }]
195
+ })
196
+ })
197
+ })
198
+
199
+ describe('Change account role', () => {
200
+ test('should throw if no parameters', async () => {
201
+ await expect(Engage.changeAccountRole()).rejects.toThrow(/missing/)
202
+ })
203
+ test('should throw if no account id', async () => {
204
+ await expect(Engage.changeAccountRole(id)).rejects.toThrow(/missing/)
205
+ })
206
+ test('should throw if no role', async () => {
207
+ await expect(Engage.changeAccountRole(id, gid)).rejects.toThrow(/missing/)
208
+ })
209
+ test('should pass if all parameters set', async () => {
210
+ await expect(Engage.changeAccountRole(id, gid, 'owner')).resolves.toMatchObject({
211
+ accounts: [{
212
+ id: gid,
213
+ role: 'owner'
214
+ }]
215
+ })
216
+ })
217
+ })
218
+
219
+ describe('Remove from account', () => {
220
+ test('should throw if no parameters', async () => {
221
+ await expect(Engage.removeFromAccount()).rejects.toThrow(/missing/)
222
+ })
223
+ test('should throw if no account id', async () => {
224
+ await expect(Engage.removeFromAccount(id)).rejects.toThrow(/missing/)
225
+ })
226
+ test('should pass if all parameters set', async () => {
227
+ await expect(Engage.removeFromAccount(id, gid)).resolves.toMatchObject({
228
+ accounts: []
229
+ })
230
+ })
231
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2015",
4
+ "module": "NodeNext",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "outDir": "./dist",
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "strict": true,
11
+ "skipLibCheck": true
12
+ },
13
+ "exclude": [
14
+ "node_modules",
15
+ "tests",
16
+ "dist"
17
+ ]
18
+ }
package/error.js DELETED
@@ -1,8 +0,0 @@
1
- class EngageError extends Error {
2
- constructor (message, cause) {
3
- super(message)
4
- this.cause = cause
5
- this.name = 'EngageError'
6
- }
7
- }
8
- module.exports = EngageError
package/index.js DELETED
@@ -1,204 +0,0 @@
1
- const fetch = require('cross-fetch')
2
- const Buffer = require('buffer/').Buffer
3
- const EngageError = require('./error')
4
- const root = 'https://api.engage.so/v1'
5
- if (typeof btoa === 'undefined') {
6
- global.btoa = function (str) {
7
- return Buffer.from(str).toString('base64')
8
- }
9
- }
10
-
11
- const options = {
12
- key: null,
13
- secret: ''
14
- }
15
-
16
- async function _request (url, params, method) {
17
- try {
18
- const o = {
19
- method,
20
- headers: {
21
- 'Content-Type': 'application/json;charset=utf-8',
22
- Authorization: `Basic ${btoa(`${options.key}:${options.secret}`)}`
23
- },
24
- }
25
- if (params) {
26
- o.body = JSON.stringify(params)
27
- }
28
- const response = await fetch(url, o)
29
- const body = await response.json()
30
- let error = 'API connection error'
31
- if (!response.ok) {
32
- if (body && body.error) {
33
- error = body.error
34
- }
35
- return { error }
36
- }
37
- return body
38
- } catch (e) {
39
- // console.log(e)
40
- return { error: 'API connection error' }
41
- }
42
- }
43
-
44
- // Alias of _request method
45
- // Same with _request for now but can later have modifications
46
- const request = (url, params, method) => {
47
- return _request(`${root}${url}`, params, method)
48
- }
49
-
50
- const init = (o) => {
51
- if (!o) {
52
- throw new EngageError('You need to pass in your API key.')
53
- }
54
- if (typeof o === 'string') {
55
- options.key = o
56
- return
57
- }
58
-
59
- if (!o.key) {
60
- throw new EngageError('`key` missing in object.')
61
- }
62
- if (o.key) {
63
- options.key = `${o.key}`
64
- }
65
- if (o.secret) {
66
- options.secret = `${o.secret}`
67
- }
68
- }
69
-
70
- const identify = async (o) => {
71
- if (!o) {
72
- throw new EngageError('You need to pass an object with at least an id and email.')
73
- }
74
- if (!o.id) {
75
- throw new EngageError('ID missing.')
76
- }
77
- if (o.email && !/^\S+@\S+$/.test(o.email)) {
78
- throw new EngageError('Email invalid.')
79
- }
80
- const allowed = ['id', 'is_account', 'email', 'number', 'created_at', 'device_token', 'device_platform', 'first_name', 'last_name']
81
- const params = {
82
- meta: {}
83
- }
84
- for (const k in o) {
85
- if (allowed.includes(k)) {
86
- params[k] = o[k]
87
- } else {
88
- params.meta[k] = o[k]
89
- }
90
- }
91
-
92
- return _request(`${root}/users/${o.id}`, params, 'PUT')
93
- }
94
-
95
- const addAttribute = async (uid, data) => {
96
- if (!uid) {
97
- throw new EngageError('User id missing.')
98
- }
99
- if (!data) {
100
- throw new EngageError('Attributes missing.')
101
- }
102
- if (!Object.keys(data).length) {
103
- throw new EngageError('Attributes missing.')
104
- }
105
- const notMeta = ['created_at', 'is_account', 'number', 'device_token', 'device_platform', 'email', 'first_name', 'last_name']
106
- const params = { meta: {} }
107
- for (const k in data) {
108
- if (notMeta.includes(k)) {
109
- params[k] = data[k]
110
- } else {
111
- params.meta[k] = data[k]
112
- }
113
- }
114
-
115
- return _request(`${root}/users/${uid}`, params, 'PUT')
116
- }
117
-
118
- const track = async (uid, data) => {
119
- if (!uid) {
120
- throw new EngageError('User id missing.')
121
- }
122
- if (!data) {
123
- throw new EngageError('Attributes missing.')
124
- }
125
- if (typeof data === 'string') {
126
- data = {
127
- event: data,
128
- value: true
129
- }
130
- } else {
131
- if (!Object.keys(data).length) {
132
- throw new EngageError('Attributes missing.')
133
- }
134
- }
135
-
136
- return _request(`${root}/users/${uid}/events`, data, 'POST')
137
- }
138
-
139
- const addToAccount = async (uid, gid, role) => {
140
- if (!uid) {
141
- throw new EngageError('User id missing.')
142
- }
143
- if (!gid) {
144
- throw new EngageError('Account id missing.')
145
- }
146
- if (role && typeof role !== 'string') {
147
- throw new EngageError('Role should be a text.')
148
- }
149
- const g = {
150
- id: gid
151
- }
152
- if (role) {
153
- g.role = role
154
- }
155
- return _request(`${root}/users/${uid}/accounts`, { accounts: [g] }, 'POST')
156
- }
157
- const removeFromAccount = async (uid, gid) => {
158
- if (!uid) {
159
- throw new EngageError('User id missing.')
160
- }
161
- if (!gid) {
162
- throw new EngageError('Account id missing.')
163
- }
164
- return _request(`${root}/users/${uid}/accounts/${gid}`, null, 'DELETE')
165
- }
166
-
167
- const changeAccountRole = async (uid, gid, role) => {
168
- if (!uid) {
169
- throw new EngageError('User id missing.')
170
- }
171
- if (!gid) {
172
- throw new EngageError('Account id missing.')
173
- }
174
- if (!role) {
175
- throw new EngageError('New role missing.')
176
- }
177
- return _request(`${root}/users/${uid}/accounts/${gid}`, { role }, 'PUT')
178
- }
179
-
180
- const convertToCustomer = async (uid) => {
181
- if (!uid) {
182
- throw new EngageError('User id missing.')
183
- }
184
- return _request(`${root}/users/${uid}/convert`, { type: 'customer' }, 'POST')
185
- }
186
- const convertToAccount = async (uid) => {
187
- if (!uid) {
188
- throw new EngageError('User id missing.')
189
- }
190
- return _request(`${root}/users/${uid}/convert`, { type: 'account' }, 'POST')
191
- }
192
-
193
- module.exports = {
194
- init,
195
- identify,
196
- addAttribute,
197
- track,
198
- request,
199
- addToAccount,
200
- removeFromAccount,
201
- changeAccountRole,
202
- convertToCustomer,
203
- convertToAccount
204
- }