@bentonow/bento-node-sdk 0.2.1 → 1.0.5

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 (76) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +604 -1031
  3. package/dist/index.d.ts +9 -9
  4. package/dist/index.js +1306 -5
  5. package/dist/sdk/batch/enums.d.ts +8 -8
  6. package/dist/sdk/batch/errors.d.ts +18 -18
  7. package/dist/sdk/batch/events.d.ts +71 -71
  8. package/dist/sdk/batch/index.d.ts +55 -55
  9. package/dist/sdk/batch/types.d.ts +37 -37
  10. package/dist/sdk/broadcasts/index.d.ts +26 -0
  11. package/dist/sdk/broadcasts/types.d.ts +32 -0
  12. package/dist/sdk/client/errors.d.ts +12 -6
  13. package/dist/sdk/client/index.d.ts +94 -64
  14. package/dist/sdk/client/types.d.ts +3 -3
  15. package/dist/sdk/commands/enums.d.ts +12 -12
  16. package/dist/sdk/commands/index.d.ts +79 -79
  17. package/dist/sdk/commands/types.d.ts +32 -32
  18. package/dist/sdk/email-templates/index.d.ts +21 -0
  19. package/dist/sdk/email-templates/types.d.ts +23 -0
  20. package/dist/sdk/enums.d.ts +12 -9
  21. package/dist/sdk/errors.d.ts +2 -2
  22. package/dist/sdk/experimental/index.d.ts +75 -57
  23. package/dist/sdk/experimental/types.d.ts +71 -41
  24. package/dist/sdk/fields/index.d.ts +29 -29
  25. package/dist/sdk/fields/types.d.ts +17 -17
  26. package/dist/sdk/forms/index.d.ts +14 -14
  27. package/dist/sdk/forms/types.d.ts +28 -28
  28. package/dist/sdk/index.d.ts +11 -8
  29. package/dist/sdk/interfaces.d.ts +17 -13
  30. package/dist/sdk/sequences/index.d.ts +13 -0
  31. package/dist/sdk/sequences/types.d.ts +18 -0
  32. package/dist/sdk/stats/index.d.ts +24 -0
  33. package/dist/sdk/stats/types.d.ts +26 -0
  34. package/dist/sdk/subscribers/index.d.ts +20 -20
  35. package/dist/sdk/subscribers/types.d.ts +25 -25
  36. package/dist/sdk/tags/index.d.ts +20 -20
  37. package/dist/sdk/tags/types.d.ts +17 -17
  38. package/dist/sdk/types.d.ts +41 -41
  39. package/dist/sdk/workflows/index.d.ts +13 -0
  40. package/dist/sdk/workflows/types.d.ts +18 -0
  41. package/dist/versions/v1/index.d.ts +168 -132
  42. package/dist/versions/v1/types.d.ts +31 -31
  43. package/package.json +31 -44
  44. package/src/sdk/batch/events.ts +1 -1
  45. package/src/sdk/batch/index.ts +15 -22
  46. package/src/sdk/broadcasts/index.ts +44 -0
  47. package/src/sdk/broadcasts/types.ts +38 -0
  48. package/src/sdk/client/errors.ts +14 -0
  49. package/src/sdk/client/index.ts +205 -49
  50. package/src/sdk/commands/index.ts +54 -89
  51. package/src/sdk/email-templates/index.ts +39 -0
  52. package/src/sdk/email-templates/types.ts +27 -0
  53. package/src/sdk/enums.ts +3 -0
  54. package/src/sdk/experimental/index.ts +44 -26
  55. package/src/sdk/experimental/types.ts +35 -0
  56. package/src/sdk/fields/index.ts +1 -3
  57. package/src/sdk/forms/index.ts +4 -9
  58. package/src/sdk/forms/types.ts +1 -7
  59. package/src/sdk/index.ts +3 -0
  60. package/src/sdk/interfaces.ts +4 -0
  61. package/src/sdk/sequences/index.ts +21 -0
  62. package/src/sdk/sequences/types.ts +21 -0
  63. package/src/sdk/stats/index.ts +37 -0
  64. package/src/sdk/stats/types.ts +28 -0
  65. package/src/sdk/subscribers/index.ts +5 -15
  66. package/src/sdk/tags/index.ts +1 -3
  67. package/src/sdk/types.ts +1 -1
  68. package/src/sdk/workflows/index.ts +21 -0
  69. package/src/sdk/workflows/types.ts +21 -0
  70. package/src/versions/v1/index.ts +65 -10
  71. package/dist/bento-node-sdk.cjs.development.js +0 -2071
  72. package/dist/bento-node-sdk.cjs.development.js.map +0 -1
  73. package/dist/bento-node-sdk.cjs.production.min.js +0 -2
  74. package/dist/bento-node-sdk.cjs.production.min.js.map +0 -1
  75. package/dist/bento-node-sdk.esm.js +0 -2063
  76. package/dist/bento-node-sdk.esm.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import type { BentoClient } from '../client';
2
2
  import type { LocationData } from '../types';
3
3
  import type {
4
+ BlacklistCheckInput,
4
5
  BlacklistParameters,
5
- BlacklistResponse,
6
+ BlacklistResponse, BlacklistResult, ContentModerationResult,
6
7
  GeolocateParameters,
7
8
  GeolocateResponse,
8
9
  GuessGenderParameters,
@@ -29,18 +30,13 @@ export class BentoExperimental {
29
30
  * @param parameters
30
31
  * @returns Promise\<boolean\>
31
32
  */
32
- public async validateEmail(
33
- parameters: ValidateEmailParameters
34
- ): Promise<boolean> {
35
- const result = await this._client.post<ValidateEmailResponse>(
36
- `${this._url}/validation`,
37
- {
38
- email: parameters.email,
39
- ip: parameters.ip,
40
- name: parameters.name,
41
- user_agent: parameters.userAgent,
42
- }
43
- );
33
+ public async validateEmail(parameters: ValidateEmailParameters): Promise<boolean> {
34
+ const result = await this._client.post<ValidateEmailResponse>(`${this._url}/validation`, {
35
+ email: parameters.email,
36
+ ip: parameters.ip,
37
+ name: parameters.name,
38
+ user_agent: parameters.userAgent,
39
+ });
44
40
 
45
41
  return result.valid;
46
42
  }
@@ -58,13 +54,8 @@ export class BentoExperimental {
58
54
  * @param parameters
59
55
  * @returns Promise\<GuessGenderResponse\>
60
56
  */
61
- public async guessGender(
62
- parameters: GuessGenderParameters
63
- ): Promise<GuessGenderResponse> {
64
- const result = await this._client.post<GuessGenderResponse>(
65
- `${this._url}/gender`,
66
- parameters
67
- );
57
+ public async guessGender(parameters: GuessGenderParameters): Promise<GuessGenderResponse> {
58
+ const result = await this._client.post<GuessGenderResponse>(`${this._url}/gender`, parameters);
68
59
 
69
60
  return result;
70
61
  }
@@ -78,9 +69,7 @@ export class BentoExperimental {
78
69
  * @param parameters
79
70
  * @returns Promise\<GeolocateResponse\>
80
71
  */
81
- public async geolocate(
82
- parameters: GeolocateParameters
83
- ): Promise<LocationData | null> {
72
+ public async geolocate(parameters: GeolocateParameters): Promise<LocationData | null> {
84
73
  const result = await this._client.get<GeolocateResponse>(
85
74
  `${this._url}/geolocation`,
86
75
  parameters
@@ -100,9 +89,7 @@ export class BentoExperimental {
100
89
  * @param parameters
101
90
  * @returns Promise\<BlacklistResponse\>
102
91
  */
103
- public async checkBlacklist(
104
- parameters: BlacklistParameters
105
- ): Promise<BlacklistResponse> {
92
+ public async checkBlacklist(parameters: BlacklistParameters): Promise<BlacklistResponse> {
106
93
  const result = await this._client.get<BlacklistResponse>(
107
94
  `${this._url}/blacklist.json`,
108
95
  parameters
@@ -110,4 +97,35 @@ export class BentoExperimental {
110
97
 
111
98
  return result;
112
99
  }
100
+
101
+ /**
102
+ * Checks if a domain or IP is blacklisted
103
+ * @param input Domain or IP to check
104
+ * @returns Promise<BlacklistResult>
105
+ */
106
+ public async getBlacklistStatus(input: BlacklistCheckInput): Promise<BlacklistResult> {
107
+ return this._client.get<BlacklistResult>(`${this._url}/blacklist`, input);
108
+ }
109
+
110
+ /**
111
+ * Performs content moderation on provided text
112
+ * @param content Text content to moderate
113
+ * @returns Promise<ContentModerationResult>
114
+ */
115
+ public async getContentModeration(content: string): Promise<ContentModerationResult> {
116
+ return this._client.post<ContentModerationResult>(`${this._url}/moderation`, {
117
+ content
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Gets geolocation data for an IP address
123
+ * @param ipAddress IP address to geolocate
124
+ * @returns Promise<LocationData>
125
+ */
126
+ public async geoLocateIP(ipAddress: string): Promise<LocationData> {
127
+ return this._client.get<LocationData>(`${this._url}/geolocation`, {
128
+ ip: ipAddress
129
+ });
130
+ }
113
131
  }
@@ -28,6 +28,13 @@ export type BlacklistParameters =
28
28
  ip: string;
29
29
  };
30
30
 
31
+ export type BlacklistCheckInput = {
32
+ domain?: string;
33
+ ipAddress?: string;
34
+ };
35
+
36
+
37
+
31
38
  /**
32
39
  * Experimental Method Response Types
33
40
  */
@@ -47,3 +54,31 @@ export type BlacklistResponse = {
47
54
  query: string;
48
55
  results: { [key: string]: boolean };
49
56
  };
57
+
58
+ export type BlacklistResult = {
59
+ description: string;
60
+ query: string;
61
+ results: Record<string, boolean>;
62
+ };
63
+
64
+ export type ContentModerationResult = {
65
+ flagged: boolean;
66
+ categories: {
67
+ hate: boolean;
68
+ 'hate/threatening': boolean;
69
+ 'self-harm': boolean;
70
+ sexual: boolean;
71
+ 'sexual/minors': boolean;
72
+ violence: boolean;
73
+ 'violence/graphic': boolean;
74
+ };
75
+ category_scores: {
76
+ hate: number;
77
+ 'hate/threatening': number;
78
+ 'self-harm': number;
79
+ sexual: number;
80
+ 'sexual/minors': number;
81
+ violence: number;
82
+ 'violence/graphic': number;
83
+ };
84
+ };
@@ -34,9 +34,7 @@ export class BentoFields {
34
34
  * @param parameters \{ key: string \}
35
35
  * @returns Promise<Field[]>
36
36
  */
37
- public async createField(
38
- parameters: CreateFieldParameters
39
- ): Promise<Field[] | null> {
37
+ public async createField(parameters: CreateFieldParameters): Promise<Field[] | null> {
40
38
  const result = await this._client.post<DataResponse<Field[]>>(this._url, {
41
39
  field: parameters,
42
40
  });
@@ -13,15 +13,10 @@ export class BentoForms {
13
13
  * @param formIdentifier string
14
14
  * @returns Promise\<FormResponse[] | null\>
15
15
  */
16
- public async getResponses(
17
- formIdentifier: string
18
- ): Promise<FormResponse[] | null> {
19
- const result = await this._client.get<DataResponse<FormResponse[]>>(
20
- this._url,
21
- {
22
- id: formIdentifier,
23
- }
24
- );
16
+ public async getResponses(formIdentifier: string): Promise<FormResponse[] | null> {
17
+ const result = await this._client.get<DataResponse<FormResponse[]>>(this._url, {
18
+ id: formIdentifier,
19
+ });
25
20
 
26
21
  if (Object.keys(result).length === 0 || !result.data) return null;
27
22
  return result.data;
@@ -1,10 +1,4 @@
1
- import type {
2
- BaseEntity,
3
- BrowserData,
4
- IdentityData,
5
- LocationData,
6
- PageData,
7
- } from '../types';
1
+ import type { BaseEntity, BrowserData, IdentityData, LocationData, PageData } from '../types';
8
2
 
9
3
  /**
10
4
  * Core Form Types
package/src/sdk/index.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  export * from './batch';
2
2
  export * from './client';
3
3
  export * from './commands';
4
+ export * from './email-templates';
4
5
  export * from './experimental';
5
6
  export * from './fields';
6
7
  export * from './forms';
8
+ export * from './sequences';
7
9
  export * from './subscribers';
8
10
  export * from './tags';
11
+ export * from './workflows';
@@ -12,4 +12,8 @@ export interface AuthenticationOptions {
12
12
 
13
13
  export interface ClientOptions {
14
14
  baseUrl?: string;
15
+ /**
16
+ * Request timeout in milliseconds. Defaults to 30000 (30 seconds).
17
+ */
18
+ timeout?: number;
15
19
  }
@@ -0,0 +1,21 @@
1
+ import type { BentoClient } from '../client';
2
+ import type { DataResponse } from '../client/types';
3
+ import type { Sequence } from './types';
4
+
5
+ export class BentoSequences {
6
+ private readonly _url = '/fetch/sequences';
7
+
8
+ constructor(private readonly _client: BentoClient) {}
9
+
10
+ /**
11
+ * Returns all of the sequences for the site, including their email templates.
12
+ *
13
+ * @returns Promise\<Sequence[]\>
14
+ */
15
+ public async getSequences(): Promise<Sequence[]> {
16
+ const result = await this._client.get<DataResponse<Sequence[]>>(this._url);
17
+
18
+ if (!result || Object.keys(result).length === 0) return [];
19
+ return result.data ?? [];
20
+ }
21
+ }
@@ -0,0 +1,21 @@
1
+ import type { BaseEntity } from '../types';
2
+
3
+ /**
4
+ * Embedded Email Template in Sequence
5
+ */
6
+ export type SequenceEmailTemplate = {
7
+ id: number;
8
+ subject: string;
9
+ stats: Record<string, unknown> | null;
10
+ };
11
+
12
+ /**
13
+ * Core Sequence Types
14
+ */
15
+ export type SequenceAttributes = {
16
+ name: string;
17
+ created_at: string;
18
+ email_templates: SequenceEmailTemplate[];
19
+ };
20
+
21
+ export type Sequence = BaseEntity<SequenceAttributes>;
@@ -0,0 +1,37 @@
1
+ import type { BentoClient } from '../client';
2
+ import type { SiteStats, SegmentStats, ReportStats } from './types';
3
+
4
+ export class BentoStats {
5
+ private readonly _url = '/stats';
6
+
7
+ constructor(private readonly _client: BentoClient) {}
8
+
9
+ /**
10
+ * Retrieves overall statistics for the site
11
+ * @returns Promise<SiteStats>
12
+ */
13
+ public async getSiteStats(): Promise<SiteStats> {
14
+ const result = await this._client.get<SiteStats>(`${this._url}/site`);
15
+ return result;
16
+ }
17
+
18
+ /**
19
+ * Retrieves statistics for a specific segment
20
+ * @param segmentId ID of the segment to get stats for
21
+ * @returns Promise<SegmentStats>
22
+ */
23
+ public async getSegmentStats(segmentId: string): Promise<SegmentStats> {
24
+ const result = await this._client.get<SegmentStats>(`${this._url}/segments/${segmentId}`);
25
+ return result;
26
+ }
27
+
28
+ /**
29
+ * Retrieves statistics for a specific report
30
+ * @param reportId ID of the report to get stats for
31
+ * @returns Promise<ReportStats>
32
+ */
33
+ public async getReportStats(reportId: string): Promise<ReportStats> {
34
+ const result = await this._client.get<ReportStats>(`${this._url}/reports/${reportId}`);
35
+ return result;
36
+ }
37
+ }
@@ -0,0 +1,28 @@
1
+ export type SiteStats = {
2
+ total_subscribers: number;
3
+ active_subscribers: number;
4
+ unsubscribed_count: number;
5
+ broadcast_count: number;
6
+ average_open_rate: number;
7
+ average_click_rate: number;
8
+ };
9
+
10
+ export type SegmentStats = {
11
+ segment_id: string;
12
+ subscriber_count: number;
13
+ growth_rate: number;
14
+ engagement_rate: number;
15
+ last_updated: string;
16
+ };
17
+
18
+ export type ReportStats = {
19
+ report_id: string;
20
+ total_sent: number;
21
+ total_opens: number;
22
+ unique_opens: number;
23
+ total_clicks: number;
24
+ unique_clicks: number;
25
+ unsubscribes: number;
26
+ spam_reports: number;
27
+ created_at: string;
28
+ };
@@ -1,10 +1,6 @@
1
1
  import type { BentoClient } from '../client';
2
2
  import type { DataResponse } from '../client/types';
3
- import type {
4
- CreateSubscriberParameters,
5
- GetSubscribersParameters,
6
- Subscriber,
7
- } from './types';
3
+ import type { CreateSubscriberParameters, GetSubscribersParameters, Subscriber } from './types';
8
4
 
9
5
  export class BentoSubscribers<S> {
10
6
  private readonly _url = '/fetch/subscribers';
@@ -19,10 +15,7 @@ export class BentoSubscribers<S> {
19
15
  public async getSubscribers(
20
16
  parameters?: GetSubscribersParameters
21
17
  ): Promise<Subscriber<S> | null> {
22
- const result = await this._client.get<DataResponse<Subscriber<S>>>(
23
- this._url,
24
- parameters
25
- );
18
+ const result = await this._client.get<DataResponse<Subscriber<S>>>(this._url, parameters);
26
19
 
27
20
  if (Object.keys(result).length === 0 || !result.data) return null;
28
21
  return result.data;
@@ -37,12 +30,9 @@ export class BentoSubscribers<S> {
37
30
  public async createSubscriber(
38
31
  parameters: CreateSubscriberParameters
39
32
  ): Promise<Subscriber<S> | null> {
40
- const result = await this._client.post<DataResponse<Subscriber<S>>>(
41
- this._url,
42
- {
43
- subscriber: parameters,
44
- }
45
- );
33
+ const result = await this._client.post<DataResponse<Subscriber<S>>>(this._url, {
34
+ subscriber: parameters,
35
+ });
46
36
 
47
37
  if (Object.keys(result).length === 0 || !result.data) return null;
48
38
  return result.data;
@@ -25,9 +25,7 @@ export class BentoTags {
25
25
  * @param parameters CreateTagParameters
26
26
  * @returns Promise\<Tag[] | null\>
27
27
  */
28
- public async createTag(
29
- parameters: CreateTagParameters
30
- ): Promise<Tag[] | null> {
28
+ public async createTag(parameters: CreateTagParameters): Promise<Tag[] | null> {
31
29
  const result = await this._client.post<DataResponse<Tag[]>>(this._url, {
32
30
  tag: parameters,
33
31
  });
package/src/sdk/types.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Core Types
3
3
  */
4
4
 
5
- import type { EntityType } from "./enums";
5
+ import type { EntityType } from './enums';
6
6
 
7
7
  export type BaseEntity<T> = {
8
8
  attributes: T;
@@ -0,0 +1,21 @@
1
+ import type { BentoClient } from '../client';
2
+ import type { DataResponse } from '../client/types';
3
+ import type { Workflow } from './types';
4
+
5
+ export class BentoWorkflows {
6
+ private readonly _url = '/fetch/workflows';
7
+
8
+ constructor(private readonly _client: BentoClient) {}
9
+
10
+ /**
11
+ * Returns all of the workflows for the site, including their email templates.
12
+ *
13
+ * @returns Promise\<Workflow[]\>
14
+ */
15
+ public async getWorkflows(): Promise<Workflow[]> {
16
+ const result = await this._client.get<DataResponse<Workflow[]>>(this._url);
17
+
18
+ if (!result || Object.keys(result).length === 0) return [];
19
+ return result.data ?? [];
20
+ }
21
+ }
@@ -0,0 +1,21 @@
1
+ import type { BaseEntity } from '../types';
2
+
3
+ /**
4
+ * Embedded Email Template in Workflow
5
+ */
6
+ export type WorkflowEmailTemplate = {
7
+ id: number;
8
+ subject: string;
9
+ stats: Record<string, unknown> | null;
10
+ };
11
+
12
+ /**
13
+ * Core Workflow Types
14
+ */
15
+ export type WorkflowAttributes = {
16
+ name: string;
17
+ created_at: string;
18
+ email_templates: WorkflowEmailTemplate[];
19
+ };
20
+
21
+ export type Workflow = BaseEntity<WorkflowAttributes>;
@@ -2,11 +2,14 @@ import {
2
2
  BentoBatch,
3
3
  BentoClient,
4
4
  BentoCommands,
5
+ BentoEmailTemplates,
5
6
  BentoExperimental,
6
7
  BentoFields,
7
8
  BentoForms,
9
+ BentoSequences,
8
10
  BentoSubscribers,
9
11
  BentoTags,
12
+ BentoWorkflows,
10
13
  } from '../../sdk';
11
14
  import { BentoEvents } from '../../sdk/batch/enums';
12
15
  import type { AnalyticsOptions } from '../../sdk/interfaces';
@@ -18,30 +21,40 @@ import type {
18
21
  TrackPurchaseParameters,
19
22
  UpdateFieldsParameters,
20
23
  } from './types';
24
+ import { BentoBroadcasts } from '../../sdk/broadcasts';
25
+ import { BentoStats } from '../../sdk/stats';
26
+ import type { Subscriber } from '../../sdk/subscribers/types';
21
27
 
22
- export class BentoAPIV1<
23
- S = { [key: string]: unknown },
24
- E extends string = '$custom'
25
- > {
28
+ export class BentoAPIV1<S = { [key: string]: unknown }, E extends string = '$custom'> {
26
29
  private readonly _client: BentoClient;
27
30
 
31
+ public readonly Broadcasts: BentoBroadcasts;
32
+ public readonly EmailTemplates: BentoEmailTemplates;
33
+ public readonly Stats: BentoStats;
28
34
  public readonly Batch: BentoBatch<S, E>;
29
35
  public readonly Commands: BentoCommands<S>;
30
36
  public readonly Experimental: BentoExperimental;
31
37
  public readonly Fields: BentoFields;
32
38
  public readonly Forms: BentoForms;
39
+ public readonly Sequences: BentoSequences;
33
40
  public readonly Subscribers: BentoSubscribers<S>;
34
41
  public readonly Tags: BentoTags;
42
+ public readonly Workflows: BentoWorkflows;
35
43
 
36
44
  constructor(options: AnalyticsOptions) {
37
45
  this._client = new BentoClient(options);
46
+ this.Broadcasts = new BentoBroadcasts(this._client);
47
+ this.EmailTemplates = new BentoEmailTemplates(this._client);
48
+ this.Stats = new BentoStats(this._client);
38
49
  this.Batch = new BentoBatch(this._client);
39
50
  this.Commands = new BentoCommands(this._client);
40
51
  this.Experimental = new BentoExperimental(this._client);
41
52
  this.Fields = new BentoFields(this._client);
42
53
  this.Forms = new BentoForms(this._client);
54
+ this.Sequences = new BentoSequences(this._client);
43
55
  this.Subscribers = new BentoSubscribers(this._client);
44
56
  this.Tags = new BentoTags(this._client);
57
+ this.Workflows = new BentoWorkflows(this._client);
45
58
  }
46
59
 
47
60
  /**
@@ -98,9 +111,7 @@ export class BentoAPIV1<
98
111
  * @param parameters AddSubscriberParameters
99
112
  * @returns Promise\<boolean\>
100
113
  */
101
- async addSubscriber(
102
- parameters: AddSubscriberParameters<S>
103
- ): Promise<boolean> {
114
+ async addSubscriber(parameters: AddSubscriberParameters<S>): Promise<boolean> {
104
115
  const result = await this.Batch.importEvents({
105
116
  events: [
106
117
  {
@@ -134,9 +145,7 @@ export class BentoAPIV1<
134
145
  * @param parameters RemoveSubscriberParameters
135
146
  * @returns Promise\<boolean\>
136
147
  */
137
- async removeSubscriber(
138
- parameters: RemoveSubscriberParameters
139
- ): Promise<boolean> {
148
+ async removeSubscriber(parameters: RemoveSubscriberParameters): Promise<boolean> {
140
149
  const result = await this.Batch.importEvents({
141
150
  events: [
142
151
  {
@@ -241,4 +250,50 @@ export class BentoAPIV1<
241
250
 
242
251
  return result === 1;
243
252
  }
253
+
254
+ /**
255
+ * Upserts a subscriber in Bento. If the subscriber exists, their data will be updated.
256
+ * If they don't exist, they will be created with the provided data.
257
+ *
258
+ * This method still relies on the batch import queue (which can take 1-5 minutes to
259
+ * finish processing), but it automatically attempts to fetch and return the subscriber
260
+ * record after the import has been queued.
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * const subscriber = await analytics.V1.upsertSubscriber({
265
+ * email: 'user@example.com',
266
+ * fields: {
267
+ * firstName: 'John',
268
+ * lastName: 'Doe'
269
+ * },
270
+ * tags: 'lead,mql',
271
+ * remove_tags: 'customer'
272
+ * });
273
+ * ```
274
+ *
275
+ * @param parameters Object containing subscriber data including email, fields, and tags
276
+ * @returns Promise<Subscriber<S> | null> The created or updated subscriber
277
+ */
278
+ public async upsertSubscriber(
279
+ parameters: Omit<AddSubscriberParameters<S>, 'date'> & {
280
+ tags?: string;
281
+ remove_tags?: string;
282
+ }
283
+ ): Promise<Subscriber<S> | null> {
284
+ await this.Batch.importSubscribers({
285
+ subscribers: [
286
+ {
287
+ email: parameters.email,
288
+ ...parameters.fields,
289
+ ...(parameters.tags && { tags: parameters.tags }),
290
+ ...(parameters.remove_tags && { remove_tags: parameters.remove_tags }),
291
+ } as { email: string } & Partial<S>,
292
+ ],
293
+ });
294
+
295
+ return this.Subscribers.getSubscribers({
296
+ email: parameters.email,
297
+ });
298
+ }
244
299
  }