@bentonow/bento-node-sdk 0.1.13 → 0.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.
Files changed (57) hide show
  1. package/README.md +39 -2
  2. package/dist/bento-node-sdk.cjs.development.js +321 -332
  3. package/dist/bento-node-sdk.cjs.development.js.map +1 -1
  4. package/dist/bento-node-sdk.cjs.production.min.js +1 -1
  5. package/dist/bento-node-sdk.cjs.production.min.js.map +1 -1
  6. package/dist/bento-node-sdk.esm.js +321 -332
  7. package/dist/bento-node-sdk.esm.js.map +1 -1
  8. package/dist/index.d.ts +3 -3
  9. package/dist/sdk/batch/errors.d.ts +10 -0
  10. package/dist/sdk/batch/events.d.ts +71 -0
  11. package/dist/sdk/batch/index.d.ts +19 -3
  12. package/dist/sdk/batch/types.d.ts +37 -0
  13. package/dist/sdk/client/errors.d.ts +2 -0
  14. package/dist/sdk/client/index.d.ts +3 -3
  15. package/dist/sdk/client/types.d.ts +3 -0
  16. package/dist/sdk/commands/index.d.ts +3 -3
  17. package/dist/sdk/commands/types.d.ts +32 -0
  18. package/dist/sdk/experimental/index.d.ts +3 -3
  19. package/dist/sdk/experimental/types.d.ts +41 -0
  20. package/dist/sdk/fields/index.d.ts +2 -2
  21. package/dist/sdk/fields/types.d.ts +17 -0
  22. package/dist/sdk/forms/index.d.ts +2 -2
  23. package/dist/sdk/forms/types.d.ts +28 -0
  24. package/dist/sdk/interfaces.d.ts +13 -0
  25. package/dist/sdk/subscribers/index.d.ts +2 -2
  26. package/dist/sdk/subscribers/types.d.ts +25 -0
  27. package/dist/sdk/tags/index.d.ts +2 -2
  28. package/dist/sdk/tags/types.d.ts +17 -0
  29. package/dist/sdk/types.d.ts +41 -0
  30. package/dist/versions/v1/index.d.ts +4 -4
  31. package/dist/versions/v1/types.d.ts +31 -0
  32. package/package.json +5 -9
  33. package/src/index.ts +2 -2
  34. package/src/sdk/batch/errors.ts +41 -4
  35. package/src/sdk/batch/{events.d.ts → events.ts} +4 -5
  36. package/src/sdk/batch/index.ts +75 -46
  37. package/src/sdk/batch/types.ts +44 -0
  38. package/src/sdk/client/errors.ts +13 -2
  39. package/src/sdk/client/index.ts +21 -15
  40. package/src/sdk/client/{types.d.ts → types.ts} +0 -0
  41. package/src/sdk/commands/index.ts +93 -121
  42. package/src/sdk/commands/{types.d.ts → types.ts} +1 -1
  43. package/src/sdk/experimental/index.ts +29 -45
  44. package/src/sdk/experimental/{types.d.ts → types.ts} +1 -1
  45. package/src/sdk/fields/index.ts +11 -19
  46. package/src/sdk/fields/{types.d.ts → types.ts} +1 -1
  47. package/src/sdk/forms/index.ts +11 -15
  48. package/src/sdk/forms/{types.d.ts → types.ts} +3 -3
  49. package/src/sdk/{interfaces.d.ts → interfaces.ts} +0 -0
  50. package/src/sdk/subscribers/index.ts +17 -25
  51. package/src/sdk/subscribers/{types.d.ts → types.ts} +1 -1
  52. package/src/sdk/tags/index.ts +11 -19
  53. package/src/sdk/tags/{types.d.ts → types.ts} +1 -1
  54. package/src/sdk/{types.d.ts → types.ts} +2 -0
  55. package/src/versions/v1/index.ts +65 -86
  56. package/src/versions/v1/{types.d.ts → types.ts} +4 -2
  57. package/src/sdk/batch/types.d.ts +0 -25
@@ -1,18 +1,23 @@
1
+ import type { BentoClient } from '../client';
1
2
  import {
2
- BatchImportEventsParameter,
3
- BatchImportEventsResponse,
4
- BatchImportSubscribersParameter,
5
- BatchImportSubscribersResponse,
6
- } from './types';
7
- import { BentoClient } from '../client';
8
- import {
3
+ TooFewEmailsError,
9
4
  TooFewEventsError,
10
5
  TooFewSubscribersError,
6
+ TooManyEmailsError,
11
7
  TooManyEventsError,
12
8
  TooManySubscribersError,
13
9
  } from './errors';
10
+ import type {
11
+ BatchSendTransactionalEmailsParameter,
12
+ BatchsendTransactionalEmailsResponse,
13
+ BatchImportEventsParameter,
14
+ BatchImportEventsResponse,
15
+ BatchImportSubscribersParameter,
16
+ BatchImportSubscribersResponse,
17
+ } from './types';
14
18
 
15
- export class BentoBatch<S, E> {
19
+ export class BentoBatch<S, E extends string> {
20
+ private readonly _maxEmailBatchSize = 100;
16
21
  private readonly _maxBatchSize = 1000;
17
22
  private readonly _url = '/batch';
18
23
 
@@ -39,30 +44,26 @@ export class BentoBatch<S, E> {
39
44
  public async importSubscribers(
40
45
  parameters: BatchImportSubscribersParameter<S>
41
46
  ): Promise<number> {
42
- try {
43
- if (parameters.subscribers.length === 0) {
44
- throw new TooFewSubscribersError(
45
- `You must send between 1 and 1,000 subscribers.`
46
- );
47
- }
48
-
49
- if (parameters.subscribers.length > this._maxBatchSize) {
50
- throw new TooManySubscribersError(
51
- `You must send between 1 and 1,000 subscribers.`
52
- );
53
- }
54
-
55
- const result = await this._client.post<BatchImportSubscribersResponse>(
56
- `${this._url}/subscribers`,
57
- {
58
- subscribers: parameters.subscribers,
59
- }
47
+ if (parameters.subscribers.length === 0) {
48
+ throw new TooFewSubscribersError(
49
+ `You must send between 1 and 1,000 subscribers.`
60
50
  );
51
+ }
61
52
 
62
- return result.results;
63
- } catch (error) {
64
- throw error;
53
+ if (parameters.subscribers.length > this._maxBatchSize) {
54
+ throw new TooManySubscribersError(
55
+ `You must send between 1 and 1,000 subscribers.`
56
+ );
65
57
  }
58
+
59
+ const result = await this._client.post<BatchImportSubscribersResponse>(
60
+ `${this._url}/subscribers`,
61
+ {
62
+ subscribers: parameters.subscribers,
63
+ }
64
+ );
65
+
66
+ return result.results;
66
67
  }
67
68
 
68
69
  /**
@@ -79,29 +80,57 @@ export class BentoBatch<S, E> {
79
80
  public async importEvents(
80
81
  parameters: BatchImportEventsParameter<S, E>
81
82
  ): Promise<number> {
82
- try {
83
- if (parameters.events.length === 0) {
84
- throw new TooFewEventsError(
85
- `You must send between 1 and 1,000 events.`
86
- );
87
- }
83
+ if (parameters.events.length === 0) {
84
+ throw new TooFewEventsError(`You must send between 1 and 1,000 events.`);
85
+ }
88
86
 
89
- if (parameters.events.length > this._maxBatchSize) {
90
- throw new TooManyEventsError(
91
- `You must send between 1 and 1,000 events.`
92
- );
87
+ if (parameters.events.length > this._maxBatchSize) {
88
+ throw new TooManyEventsError(`You must send between 1 and 1,000 events.`);
89
+ }
90
+
91
+ const result = await this._client.post<BatchImportEventsResponse>(
92
+ `${this._url}/events`,
93
+ {
94
+ events: parameters.events,
93
95
  }
96
+ );
94
97
 
95
- const result = await this._client.post<BatchImportEventsResponse>(
96
- `${this._url}/events`,
98
+ return result.results;
99
+ }
100
+
101
+ /**
102
+ * Creates a batch job to send transactional emails from Bento's infrastructure. You can pass in
103
+ * between 1 and 100 emails to send.
104
+ *
105
+ * Each email must have a `to` address, a `from` address, a `subject`, an `html_body`
106
+ * and `transactional: true`.
107
+ * In addition you can add a `personalizations` object to provide
108
+ * liquid tsags that will be injected into the email.
109
+ *
110
+ * Returns the number of events that were imported.
111
+ *
112
+ * @param parameters
113
+ * @returns Promise\<number\>
114
+ */
115
+ public async sendTransactionalEmails(
116
+ parameters: BatchSendTransactionalEmailsParameter
117
+ ): Promise<number> {
118
+ if (parameters.emails.length === 0) {
119
+ throw new TooFewEmailsError(`You must send between 1 and 100 emails.`);
120
+ }
121
+
122
+ if (parameters.emails.length > this._maxEmailBatchSize) {
123
+ throw new TooManyEmailsError(`You must send between 1 and 100 emails.`);
124
+ }
125
+
126
+ const result =
127
+ await this._client.post<BatchsendTransactionalEmailsResponse>(
128
+ `${this._url}/emails`,
97
129
  {
98
- events: parameters.events,
130
+ emails: parameters.emails,
99
131
  }
100
132
  );
101
133
 
102
- return result.results;
103
- } catch (error) {
104
- throw error;
105
- }
134
+ return result.results;
106
135
  }
107
136
  }
@@ -0,0 +1,44 @@
1
+ import type { BentoEvent } from './events';
2
+
3
+ /**
4
+ * Batch Method Parameter Types
5
+ */
6
+ export type BatchImportSubscribersParameter<S> = {
7
+ subscribers: ({
8
+ email: string;
9
+ } & Partial<S>)[];
10
+ };
11
+
12
+ export type BatchImportEventsParameter<S, E extends string> = {
13
+ events: BentoEvent<S, E>[];
14
+ };
15
+
16
+ export type TransactionalEmail = {
17
+ to: string;
18
+ from: string;
19
+ subject: string;
20
+ html_body: string;
21
+ transactional: boolean;
22
+ personalizations?: {
23
+ [key: string]: string | number | boolean;
24
+ };
25
+ };
26
+
27
+ export type BatchSendTransactionalEmailsParameter = {
28
+ emails: TransactionalEmail[];
29
+ };
30
+
31
+ /**
32
+ * Batch Method Response Types
33
+ */
34
+ export type BatchImportSubscribersResponse = {
35
+ results: number;
36
+ };
37
+
38
+ export type BatchImportEventsResponse = {
39
+ results: number;
40
+ };
41
+
42
+ export type BatchsendTransactionalEmailsResponse = {
43
+ results: number;
44
+ };
@@ -1,2 +1,13 @@
1
- export class NotAuthorizedError extends Error {}
2
- export class RateLimitedError extends Error {}
1
+ export class NotAuthorizedError extends Error {
2
+ constructor(message = 'Not authorized') {
3
+ super(message);
4
+ this.name = 'NotAuthorizedError';
5
+ }
6
+ }
7
+
8
+ export class RateLimitedError extends Error {
9
+ constructor(message = 'You are being rate limited') {
10
+ super(message);
11
+ this.name = 'RateLimitedError';
12
+ }
13
+ }
@@ -1,5 +1,5 @@
1
1
  import fetch from 'isomorphic-fetch';
2
- import { AnalyticsOptions, AuthenticationOptions } from '../interfaces';
2
+ import type { AnalyticsOptions, AuthenticationOptions } from '../interfaces';
3
3
  import { NotAuthorizedError, RateLimitedError } from './errors';
4
4
 
5
5
  export class BentoClient {
@@ -23,7 +23,10 @@ export class BentoClient {
23
23
  * @param payload object
24
24
  * @returns Promise\<T\>
25
25
  * */
26
- public get<T>(endpoint: string, payload: object = {}): Promise<T> {
26
+ public get<T>(
27
+ endpoint: string,
28
+ payload: Record<string, unknown> = {}
29
+ ): Promise<T> {
27
30
  return new Promise<T>((resolve, reject) => {
28
31
  const queryParameters = this._getQueryParameters(payload);
29
32
 
@@ -31,15 +34,15 @@ export class BentoClient {
31
34
  method: 'GET',
32
35
  headers: this._headers,
33
36
  })
34
- .then(async result => {
37
+ .then(async (result) => {
35
38
  if (this._isSuccessfulStatus(result.status)) {
36
39
  return result.json();
37
40
  }
38
41
 
39
42
  throw await this._getErrorForResponse(result);
40
43
  })
41
- .then(data => resolve(data))
42
- .catch(error => reject(error));
44
+ .then((data) => resolve(data))
45
+ .catch((error) => reject(error));
43
46
  });
44
47
  }
45
48
 
@@ -51,7 +54,10 @@ export class BentoClient {
51
54
  * @param payload object
52
55
  * @returns Promise\<T\>
53
56
  * */
54
- public post<T>(endpoint: string, payload: object = {}): Promise<T> {
57
+ public post<T>(
58
+ endpoint: string,
59
+ payload: Record<string, unknown> = {}
60
+ ): Promise<T> {
55
61
  return new Promise<T>((resolve, reject) => {
56
62
  const body = this._getBody(payload);
57
63
 
@@ -63,15 +69,15 @@ export class BentoClient {
63
69
  },
64
70
  body,
65
71
  })
66
- .then(async result => {
72
+ .then(async (result) => {
67
73
  if (this._isSuccessfulStatus(result.status)) {
68
74
  return result.json();
69
75
  }
70
76
 
71
77
  throw await this._getErrorForResponse(result);
72
78
  })
73
- .then(data => resolve(data))
74
- .catch(error => reject(error));
79
+ .then((data) => resolve(data))
80
+ .catch((error) => reject(error));
75
81
  });
76
82
  }
77
83
 
@@ -99,7 +105,7 @@ export class BentoClient {
99
105
  * @param payload object
100
106
  * @returns string
101
107
  */
102
- private _getBody(payload: object): string {
108
+ private _getBody(payload: Record<string, unknown>): string {
103
109
  return JSON.stringify({
104
110
  ...payload,
105
111
  site_uuid: this._siteUuid,
@@ -113,7 +119,7 @@ export class BentoClient {
113
119
  * @param payload object
114
120
  * @returns string
115
121
  */
116
- private _getQueryParameters(payload: object): string {
122
+ private _getQueryParameters(payload: Record<string, unknown>): string {
117
123
  const body = {
118
124
  ...payload,
119
125
  site_uuid: this._siteUuid,
@@ -146,6 +152,10 @@ export class BentoClient {
146
152
  * @returns Error
147
153
  */
148
154
  private async _getErrorForResponse(response: Response): Promise<Error> {
155
+ if (this._logErrors) {
156
+ console.error(response);
157
+ }
158
+
149
159
  if (response.status === 401) return new NotAuthorizedError();
150
160
  if (response.status === 429) return new RateLimitedError();
151
161
 
@@ -164,10 +174,6 @@ export class BentoClient {
164
174
  break;
165
175
  }
166
176
 
167
- if (this._logErrors) {
168
- console.error(response);
169
- }
170
-
171
177
  return new Error(`[${response.status}] - ${responseMessage}`);
172
178
  }
173
179
  }
File without changes
@@ -1,8 +1,8 @@
1
- import { BentoClient } from '../client';
2
- import { DataResponse } from '../client/types';
3
- import { Subscriber } from '../subscribers/types';
1
+ import type { BentoClient } from '../client';
2
+ import type { DataResponse } from '../client/types';
3
+ import type { Subscriber } from '../subscribers/types';
4
4
  import { CommandTypes } from './enums';
5
- import {
5
+ import type {
6
6
  AddFieldParameters,
7
7
  AddTagParameters,
8
8
  ChangeEmailParameters,
@@ -33,23 +33,19 @@ export class BentoCommands<S> {
33
33
  public async addTag(
34
34
  parameters: AddTagParameters
35
35
  ): Promise<Subscriber<S> | null> {
36
- try {
37
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
38
- this._url,
39
- {
40
- command: {
41
- command: CommandTypes.ADD_TAG,
42
- email: parameters.email,
43
- query: parameters.tagName,
44
- },
45
- }
46
- );
47
-
48
- if (Object.keys(result).length === 0 || !result.data) return null;
49
- return result.data;
50
- } catch (error) {
51
- throw error;
52
- }
36
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
37
+ this._url,
38
+ {
39
+ command: {
40
+ command: CommandTypes.ADD_TAG,
41
+ email: parameters.email,
42
+ query: parameters.tagName,
43
+ },
44
+ }
45
+ );
46
+
47
+ if (Object.keys(result).length === 0 || !result.data) return null;
48
+ return result.data;
53
49
  }
54
50
 
55
51
  /**
@@ -61,23 +57,19 @@ export class BentoCommands<S> {
61
57
  public async removeTag(
62
58
  parameters: RemoveTagParameters
63
59
  ): Promise<Subscriber<S> | null> {
64
- try {
65
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
66
- this._url,
67
- {
68
- command: {
69
- command: CommandTypes.REMOVE_TAG,
70
- email: parameters.email,
71
- query: parameters.tagName,
72
- },
73
- }
74
- );
75
-
76
- if (Object.keys(result).length === 0 || !result.data) return null;
77
- return result.data;
78
- } catch (error) {
79
- throw error;
80
- }
60
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
61
+ this._url,
62
+ {
63
+ command: {
64
+ command: CommandTypes.REMOVE_TAG,
65
+ email: parameters.email,
66
+ query: parameters.tagName,
67
+ },
68
+ }
69
+ );
70
+
71
+ if (Object.keys(result).length === 0 || !result.data) return null;
72
+ return result.data;
81
73
  }
82
74
 
83
75
  /**
@@ -95,23 +87,19 @@ export class BentoCommands<S> {
95
87
  public async addField(
96
88
  parameters: AddFieldParameters<S>
97
89
  ): Promise<Subscriber<S> | null> {
98
- try {
99
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
100
- this._url,
101
- {
102
- command: {
103
- command: CommandTypes.ADD_FIELD,
104
- email: parameters.email,
105
- query: parameters.field,
106
- },
107
- }
108
- );
109
-
110
- if (Object.keys(result).length === 0 || !result.data) return null;
111
- return result.data;
112
- } catch (error) {
113
- throw error;
114
- }
90
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
91
+ this._url,
92
+ {
93
+ command: {
94
+ command: CommandTypes.ADD_FIELD,
95
+ email: parameters.email,
96
+ query: parameters.field,
97
+ },
98
+ }
99
+ );
100
+
101
+ if (Object.keys(result).length === 0 || !result.data) return null;
102
+ return result.data;
115
103
  }
116
104
 
117
105
  /**
@@ -123,23 +111,19 @@ export class BentoCommands<S> {
123
111
  public async removeField(
124
112
  parameters: RemoveFieldParameters<S>
125
113
  ): Promise<Subscriber<S> | null> {
126
- try {
127
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
128
- this._url,
129
- {
130
- command: {
131
- command: CommandTypes.REMOVE_FIELD,
132
- email: parameters.email,
133
- query: parameters.fieldName,
134
- },
135
- }
136
- );
137
-
138
- if (Object.keys(result).length === 0 || !result.data) return null;
139
- return result.data;
140
- } catch (error) {
141
- throw error;
142
- }
114
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
115
+ this._url,
116
+ {
117
+ command: {
118
+ command: CommandTypes.REMOVE_FIELD,
119
+ email: parameters.email,
120
+ query: parameters.fieldName,
121
+ },
122
+ }
123
+ );
124
+
125
+ if (Object.keys(result).length === 0 || !result.data) return null;
126
+ return result.data;
143
127
  }
144
128
 
145
129
  /**
@@ -155,22 +139,18 @@ export class BentoCommands<S> {
155
139
  public async subscribe(
156
140
  parameters: SubscribeParameters
157
141
  ): Promise<Subscriber<S> | null> {
158
- try {
159
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
160
- this._url,
161
- {
162
- command: {
163
- command: CommandTypes.SUBSCRIBE,
164
- email: parameters.email,
165
- },
166
- }
167
- );
168
-
169
- if (Object.keys(result).length === 0 || !result.data) return null;
170
- return result.data;
171
- } catch (error) {
172
- throw error;
173
- }
142
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
143
+ this._url,
144
+ {
145
+ command: {
146
+ command: CommandTypes.SUBSCRIBE,
147
+ email: parameters.email,
148
+ },
149
+ }
150
+ );
151
+
152
+ if (Object.keys(result).length === 0 || !result.data) return null;
153
+ return result.data;
174
154
  }
175
155
 
176
156
  /**
@@ -187,22 +167,18 @@ export class BentoCommands<S> {
187
167
  public async unsubscribe(
188
168
  parameters: UnsubscribeParameters
189
169
  ): Promise<Subscriber<S> | null> {
190
- try {
191
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
192
- this._url,
193
- {
194
- command: {
195
- command: CommandTypes.UNSUBSCRIBE,
196
- email: parameters.email,
197
- },
198
- }
199
- );
200
-
201
- if (Object.keys(result).length === 0 || !result.data) return null;
202
- return result.data;
203
- } catch (error) {
204
- throw error;
205
- }
170
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
171
+ this._url,
172
+ {
173
+ command: {
174
+ command: CommandTypes.UNSUBSCRIBE,
175
+ email: parameters.email,
176
+ },
177
+ }
178
+ );
179
+
180
+ if (Object.keys(result).length === 0 || !result.data) return null;
181
+ return result.data;
206
182
  }
207
183
 
208
184
  /**
@@ -214,22 +190,18 @@ export class BentoCommands<S> {
214
190
  public async changeEmail(
215
191
  parameters: ChangeEmailParameters
216
192
  ): Promise<Subscriber<S> | null> {
217
- try {
218
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
219
- this._url,
220
- {
221
- command: {
222
- command: CommandTypes.CHANGE_EMAIL,
223
- email: parameters.oldEmail,
224
- query: parameters.newEmail,
225
- },
226
- }
227
- );
228
-
229
- if (Object.keys(result).length === 0 || !result.data) return null;
230
- return result.data;
231
- } catch (error) {
232
- throw error;
233
- }
193
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(
194
+ this._url,
195
+ {
196
+ command: {
197
+ command: CommandTypes.CHANGE_EMAIL,
198
+ email: parameters.oldEmail,
199
+ query: parameters.newEmail,
200
+ },
201
+ }
202
+ );
203
+
204
+ if (Object.keys(result).length === 0 || !result.data) return null;
205
+ return result.data;
234
206
  }
235
207
  }
@@ -15,7 +15,7 @@ export type AddFieldParameters<S> = {
15
15
  email: string;
16
16
  field: {
17
17
  key: keyof S;
18
- value: any;
18
+ value: unknown;
19
19
  };
20
20
  };
21
21