@rawdash/connector-hubspot 0.15.0 → 0.17.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/LICENSE +202 -0
- package/README.md +62 -134
- package/dist/index.d.ts +240 -6
- package/dist/index.js +97 -95
- package/dist/index.js.map +1 -1
- package/package.json +14 -13
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseConnector, ConnectorContext, SyncOptions, StorageHandle, SyncResult,
|
|
1
|
+
import { BaseConnector, ConnectorContext, SyncOptions, StorageHandle, SyncResult, ConnectorDoc } from '@rawdash/core';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
declare const configFields: z.ZodObject<{
|
|
@@ -14,6 +14,7 @@ declare const configFields: z.ZodObject<{
|
|
|
14
14
|
email_stats: "email_stats";
|
|
15
15
|
}>>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
|
+
declare const doc: ConnectorDoc;
|
|
17
18
|
interface HubSpotSettings {
|
|
18
19
|
resources?: readonly HubSpotResource[];
|
|
19
20
|
}
|
|
@@ -27,12 +28,246 @@ type HubSpotCredentials = typeof hubspotCredentials;
|
|
|
27
28
|
declare const PHASE_ORDER: readonly ["contacts", "companies", "deals", "deal_events", "email_campaigns", "email_stats"];
|
|
28
29
|
type HubSpotPhase = (typeof PHASE_ORDER)[number];
|
|
29
30
|
type HubSpotResource = HubSpotPhase;
|
|
31
|
+
declare const hubspotResources: {
|
|
32
|
+
readonly hubspot_contact: {
|
|
33
|
+
readonly shape: "entity";
|
|
34
|
+
readonly description: "CRM contacts with email, lifecycle stage, lead status, owner, and creation time.";
|
|
35
|
+
readonly endpoint: "POST /crm/v3/objects/contacts/search";
|
|
36
|
+
readonly responses: {
|
|
37
|
+
readonly contacts: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
readonly hubspot_company: {
|
|
41
|
+
readonly shape: "entity";
|
|
42
|
+
readonly description: "CRM companies with name, domain, industry, lifecycle stage, and creation time.";
|
|
43
|
+
readonly endpoint: "POST /crm/v3/objects/companies/search";
|
|
44
|
+
readonly responses: {
|
|
45
|
+
readonly companies: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
readonly hubspot_deal: {
|
|
49
|
+
readonly shape: "entity";
|
|
50
|
+
readonly description: "CRM deals with name, stage, pipeline, amount, close date, owner, and creation time.";
|
|
51
|
+
readonly endpoint: "POST /crm/v3/objects/deals/search";
|
|
52
|
+
readonly responses: {
|
|
53
|
+
readonly deals: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
readonly hubspot_deal_stage_change: {
|
|
57
|
+
readonly shape: "event";
|
|
58
|
+
readonly description: "Deal stage-change events derived from deal property history, one event per stage transition.";
|
|
59
|
+
readonly endpoint: "GET /crm/v3/objects/deals?propertiesWithHistory=dealstage";
|
|
60
|
+
readonly responses: {
|
|
61
|
+
readonly deal_events: z.ZodArray<z.ZodObject<{
|
|
62
|
+
id: z.ZodString;
|
|
63
|
+
propertiesWithHistory: z.ZodOptional<z.ZodObject<{
|
|
64
|
+
dealstage: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
65
|
+
value: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
66
|
+
timestamp: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
67
|
+
sourceType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
68
|
+
}, z.core.$strip>>>;
|
|
69
|
+
}, z.core.$strip>>;
|
|
70
|
+
}, z.core.$strip>>;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
readonly hubspot_email_campaign: {
|
|
74
|
+
readonly shape: "entity";
|
|
75
|
+
readonly description: "Marketing email campaigns with name, subject, sender, type, send date, and recipient count.";
|
|
76
|
+
readonly endpoint: "GET /email/public/v1/campaigns";
|
|
77
|
+
readonly responses: {
|
|
78
|
+
readonly email_campaigns: z.ZodArray<z.ZodObject<{
|
|
79
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
80
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
81
|
+
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
82
|
+
fromName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
83
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
84
|
+
lastProcessingFinishedAt: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
85
|
+
numIncluded: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
86
|
+
counters: z.ZodOptional<z.ZodObject<{
|
|
87
|
+
sent: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
delivered: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
open: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
click: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
bounce: z.ZodOptional<z.ZodNumber>;
|
|
92
|
+
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
readonly hubspot_email_stats: {
|
|
98
|
+
readonly shape: "metric";
|
|
99
|
+
readonly description: "Per-campaign marketing email engagement stats (sent, delivered, opened, clicked, bounced, unsubscribed) timestamped at the campaign send time.";
|
|
100
|
+
readonly endpoint: "GET /email/public/v1/campaigns/{id}";
|
|
101
|
+
readonly unit: "emails";
|
|
102
|
+
readonly notes: "One sample per campaign; value is the sent count, and every counter (delivered, opened, clicked, bounced, unsubscribed) is also exposed in attributes.";
|
|
103
|
+
readonly dimensions: [{
|
|
104
|
+
readonly name: "campaignId";
|
|
105
|
+
readonly description: "HubSpot campaign id.";
|
|
106
|
+
}, {
|
|
107
|
+
readonly name: "campaignName";
|
|
108
|
+
readonly description: "Campaign name.";
|
|
109
|
+
}, {
|
|
110
|
+
readonly name: "delivered";
|
|
111
|
+
readonly description: "Number of emails delivered.";
|
|
112
|
+
}, {
|
|
113
|
+
readonly name: "opened";
|
|
114
|
+
readonly description: "Number of emails opened.";
|
|
115
|
+
}, {
|
|
116
|
+
readonly name: "clicked";
|
|
117
|
+
readonly description: "Number of emails clicked.";
|
|
118
|
+
}, {
|
|
119
|
+
readonly name: "bounced";
|
|
120
|
+
readonly description: "Number of emails bounced.";
|
|
121
|
+
}, {
|
|
122
|
+
readonly name: "unsubscribed";
|
|
123
|
+
readonly description: "Number of recipients who unsubscribed.";
|
|
124
|
+
}];
|
|
125
|
+
readonly responses: {
|
|
126
|
+
readonly email_stats: z.ZodArray<z.ZodObject<{
|
|
127
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
128
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
129
|
+
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
|
+
fromName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
131
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
132
|
+
lastProcessingFinishedAt: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
133
|
+
numIncluded: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
134
|
+
counters: z.ZodOptional<z.ZodObject<{
|
|
135
|
+
sent: z.ZodOptional<z.ZodNumber>;
|
|
136
|
+
delivered: z.ZodOptional<z.ZodNumber>;
|
|
137
|
+
open: z.ZodOptional<z.ZodNumber>;
|
|
138
|
+
click: z.ZodOptional<z.ZodNumber>;
|
|
139
|
+
bounce: z.ZodOptional<z.ZodNumber>;
|
|
140
|
+
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
142
|
+
}, z.core.$strip>>;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
declare const id = "hubspot";
|
|
30
147
|
declare class HubSpotConnector extends BaseConnector<HubSpotSettings, HubSpotCredentials> {
|
|
31
148
|
static readonly id = "hubspot";
|
|
149
|
+
static readonly resources: {
|
|
150
|
+
readonly hubspot_contact: {
|
|
151
|
+
readonly shape: "entity";
|
|
152
|
+
readonly description: "CRM contacts with email, lifecycle stage, lead status, owner, and creation time.";
|
|
153
|
+
readonly endpoint: "POST /crm/v3/objects/contacts/search";
|
|
154
|
+
readonly responses: {
|
|
155
|
+
readonly contacts: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
readonly hubspot_company: {
|
|
159
|
+
readonly shape: "entity";
|
|
160
|
+
readonly description: "CRM companies with name, domain, industry, lifecycle stage, and creation time.";
|
|
161
|
+
readonly endpoint: "POST /crm/v3/objects/companies/search";
|
|
162
|
+
readonly responses: {
|
|
163
|
+
readonly companies: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
readonly hubspot_deal: {
|
|
167
|
+
readonly shape: "entity";
|
|
168
|
+
readonly description: "CRM deals with name, stage, pipeline, amount, close date, owner, and creation time.";
|
|
169
|
+
readonly endpoint: "POST /crm/v3/objects/deals/search";
|
|
170
|
+
readonly responses: {
|
|
171
|
+
readonly deals: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
readonly hubspot_deal_stage_change: {
|
|
175
|
+
readonly shape: "event";
|
|
176
|
+
readonly description: "Deal stage-change events derived from deal property history, one event per stage transition.";
|
|
177
|
+
readonly endpoint: "GET /crm/v3/objects/deals?propertiesWithHistory=dealstage";
|
|
178
|
+
readonly responses: {
|
|
179
|
+
readonly deal_events: z.ZodArray<z.ZodObject<{
|
|
180
|
+
id: z.ZodString;
|
|
181
|
+
propertiesWithHistory: z.ZodOptional<z.ZodObject<{
|
|
182
|
+
dealstage: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
183
|
+
value: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
184
|
+
timestamp: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
185
|
+
sourceType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
186
|
+
}, z.core.$strip>>>;
|
|
187
|
+
}, z.core.$strip>>;
|
|
188
|
+
}, z.core.$strip>>;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
readonly hubspot_email_campaign: {
|
|
192
|
+
readonly shape: "entity";
|
|
193
|
+
readonly description: "Marketing email campaigns with name, subject, sender, type, send date, and recipient count.";
|
|
194
|
+
readonly endpoint: "GET /email/public/v1/campaigns";
|
|
195
|
+
readonly responses: {
|
|
196
|
+
readonly email_campaigns: z.ZodArray<z.ZodObject<{
|
|
197
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
198
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
199
|
+
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
200
|
+
fromName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
201
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
202
|
+
lastProcessingFinishedAt: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
203
|
+
numIncluded: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
204
|
+
counters: z.ZodOptional<z.ZodObject<{
|
|
205
|
+
sent: z.ZodOptional<z.ZodNumber>;
|
|
206
|
+
delivered: z.ZodOptional<z.ZodNumber>;
|
|
207
|
+
open: z.ZodOptional<z.ZodNumber>;
|
|
208
|
+
click: z.ZodOptional<z.ZodNumber>;
|
|
209
|
+
bounce: z.ZodOptional<z.ZodNumber>;
|
|
210
|
+
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
211
|
+
}, z.core.$strip>>;
|
|
212
|
+
}, z.core.$strip>>;
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
readonly hubspot_email_stats: {
|
|
216
|
+
readonly shape: "metric";
|
|
217
|
+
readonly description: "Per-campaign marketing email engagement stats (sent, delivered, opened, clicked, bounced, unsubscribed) timestamped at the campaign send time.";
|
|
218
|
+
readonly endpoint: "GET /email/public/v1/campaigns/{id}";
|
|
219
|
+
readonly unit: "emails";
|
|
220
|
+
readonly notes: "One sample per campaign; value is the sent count, and every counter (delivered, opened, clicked, bounced, unsubscribed) is also exposed in attributes.";
|
|
221
|
+
readonly dimensions: [{
|
|
222
|
+
readonly name: "campaignId";
|
|
223
|
+
readonly description: "HubSpot campaign id.";
|
|
224
|
+
}, {
|
|
225
|
+
readonly name: "campaignName";
|
|
226
|
+
readonly description: "Campaign name.";
|
|
227
|
+
}, {
|
|
228
|
+
readonly name: "delivered";
|
|
229
|
+
readonly description: "Number of emails delivered.";
|
|
230
|
+
}, {
|
|
231
|
+
readonly name: "opened";
|
|
232
|
+
readonly description: "Number of emails opened.";
|
|
233
|
+
}, {
|
|
234
|
+
readonly name: "clicked";
|
|
235
|
+
readonly description: "Number of emails clicked.";
|
|
236
|
+
}, {
|
|
237
|
+
readonly name: "bounced";
|
|
238
|
+
readonly description: "Number of emails bounced.";
|
|
239
|
+
}, {
|
|
240
|
+
readonly name: "unsubscribed";
|
|
241
|
+
readonly description: "Number of recipients who unsubscribed.";
|
|
242
|
+
}];
|
|
243
|
+
readonly responses: {
|
|
244
|
+
readonly email_stats: z.ZodArray<z.ZodObject<{
|
|
245
|
+
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
246
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
247
|
+
subject: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
248
|
+
fromName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
249
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
250
|
+
lastProcessingFinishedAt: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
251
|
+
numIncluded: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
252
|
+
counters: z.ZodOptional<z.ZodObject<{
|
|
253
|
+
sent: z.ZodOptional<z.ZodNumber>;
|
|
254
|
+
delivered: z.ZodOptional<z.ZodNumber>;
|
|
255
|
+
open: z.ZodOptional<z.ZodNumber>;
|
|
256
|
+
click: z.ZodOptional<z.ZodNumber>;
|
|
257
|
+
bounce: z.ZodOptional<z.ZodNumber>;
|
|
258
|
+
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
259
|
+
}, z.core.$strip>>;
|
|
260
|
+
}, z.core.$strip>>;
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
};
|
|
32
264
|
static readonly schemas: {
|
|
33
265
|
readonly contacts: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
266
|
+
} & {
|
|
34
267
|
readonly companies: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
268
|
+
} & {
|
|
35
269
|
readonly deals: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
270
|
+
} & {
|
|
36
271
|
readonly deal_events: z.ZodArray<z.ZodObject<{
|
|
37
272
|
id: z.ZodString;
|
|
38
273
|
propertiesWithHistory: z.ZodOptional<z.ZodObject<{
|
|
@@ -43,6 +278,7 @@ declare class HubSpotConnector extends BaseConnector<HubSpotSettings, HubSpotCre
|
|
|
43
278
|
}, z.core.$strip>>>;
|
|
44
279
|
}, z.core.$strip>>;
|
|
45
280
|
}, z.core.$strip>>;
|
|
281
|
+
} & {
|
|
46
282
|
readonly email_campaigns: z.ZodArray<z.ZodObject<{
|
|
47
283
|
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
48
284
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -60,6 +296,7 @@ declare class HubSpotConnector extends BaseConnector<HubSpotSettings, HubSpotCre
|
|
|
60
296
|
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
61
297
|
}, z.core.$strip>>;
|
|
62
298
|
}, z.core.$strip>>;
|
|
299
|
+
} & {
|
|
63
300
|
readonly email_stats: z.ZodArray<z.ZodObject<{
|
|
64
301
|
id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
65
302
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -77,7 +314,7 @@ declare class HubSpotConnector extends BaseConnector<HubSpotSettings, HubSpotCre
|
|
|
77
314
|
unsubscribed: z.ZodOptional<z.ZodNumber>;
|
|
78
315
|
}, z.core.$strip>>;
|
|
79
316
|
}, z.core.$strip>>;
|
|
80
|
-
}
|
|
317
|
+
} & Readonly<Record<string, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
81
318
|
static create(input: unknown, ctx?: ConnectorContext): HubSpotConnector;
|
|
82
319
|
readonly id = "hubspot";
|
|
83
320
|
readonly credentials: {
|
|
@@ -101,9 +338,6 @@ declare class HubSpotConnector extends BaseConnector<HubSpotSettings, HubSpotCre
|
|
|
101
338
|
private clearScopeOnFirstPage;
|
|
102
339
|
private writePhase;
|
|
103
340
|
sync(options: SyncOptions, storage: StorageHandle, signal?: AbortSignal): Promise<SyncResult>;
|
|
104
|
-
aggregate(req: AggregateRequest, signal?: AbortSignal): Promise<AggregateValue>;
|
|
105
|
-
validateCountFilter(resource: string, filter: FilterClause[]): void;
|
|
106
|
-
private translateCountFilter;
|
|
107
341
|
}
|
|
108
342
|
|
|
109
|
-
export { HubSpotConnector, type HubSpotResource, type HubSpotSettings, configFields, HubSpotConnector as default };
|
|
343
|
+
export { HubSpotConnector, type HubSpotResource, type HubSpotSettings, configFields, HubSpotConnector as default, doc, id, hubspotResources as resources };
|
package/dist/index.js
CHANGED
|
@@ -30,8 +30,11 @@ function parseEpoch(value, unit) {
|
|
|
30
30
|
import {
|
|
31
31
|
BaseConnector,
|
|
32
32
|
defineConfigFields,
|
|
33
|
+
defineConnectorDoc,
|
|
34
|
+
defineResources,
|
|
33
35
|
makeChunkedCursorGuard,
|
|
34
36
|
paginateChunked,
|
|
37
|
+
schemasFromResources,
|
|
35
38
|
selectActivePhases
|
|
36
39
|
} from "@rawdash/core";
|
|
37
40
|
import { z } from "zod";
|
|
@@ -58,6 +61,32 @@ var configFields = defineConfigFields(
|
|
|
58
61
|
})
|
|
59
62
|
})
|
|
60
63
|
);
|
|
64
|
+
var doc = defineConnectorDoc({
|
|
65
|
+
displayName: "HubSpot",
|
|
66
|
+
category: "sales",
|
|
67
|
+
brandColor: "#FF7A59",
|
|
68
|
+
tagline: "Sync CRM contacts, companies, and deals plus deal stage-change events and marketing email campaign stats from HubSpot.",
|
|
69
|
+
vendor: {
|
|
70
|
+
name: "HubSpot",
|
|
71
|
+
apiDocs: "https://developers.hubspot.com/docs/api/overview",
|
|
72
|
+
website: "https://www.hubspot.com"
|
|
73
|
+
},
|
|
74
|
+
auth: {
|
|
75
|
+
summary: "A HubSpot private app access token with read scopes for the resources you sync (contacts, companies, deals, and marketing email).",
|
|
76
|
+
setup: [
|
|
77
|
+
"In HubSpot, go to Settings \u2192 Integrations \u2192 Private Apps and create a private app.",
|
|
78
|
+
"Grant read scopes for the resources you intend to sync (CRM contacts, companies, deals, and marketing email).",
|
|
79
|
+
"Copy the generated access token (starts with `pat-`).",
|
|
80
|
+
'Store it as a secret and reference it from the connector config as `accessToken: secret("HUBSPOT_ACCESS_TOKEN")`.'
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
rateLimit: "HubSpot allows 100 requests / 10s; the Search API caps results at 10,000 per query.",
|
|
84
|
+
limitations: [
|
|
85
|
+
"Deal stage-change events are rewritten on every sync because the deal list endpoint has no incremental `since` filter.",
|
|
86
|
+
"Marketing email campaign data comes from the legacy email campaigns API and is only available for marketing emails.",
|
|
87
|
+
"Very large CRM portfolios may not backfill in full because the Search API caps at 10,000 results per query."
|
|
88
|
+
]
|
|
89
|
+
});
|
|
61
90
|
var hubspotCredentials = {
|
|
62
91
|
accessToken: {
|
|
63
92
|
description: "HubSpot private app access token",
|
|
@@ -117,20 +146,6 @@ var ENTITY_TYPE_BY_PHASE = {
|
|
|
117
146
|
};
|
|
118
147
|
var DEAL_STAGE_EVENT = "hubspot_deal_stage_change";
|
|
119
148
|
var EMAIL_STATS_METRIC = "hubspot_email_stats";
|
|
120
|
-
var COUNT_RESOURCE_TO_OBJECT = {
|
|
121
|
-
hubspot_contact: "contacts",
|
|
122
|
-
hubspot_company: "companies",
|
|
123
|
-
hubspot_deal: "deals"
|
|
124
|
-
};
|
|
125
|
-
var FILTER_OP_TO_HUBSPOT = {
|
|
126
|
-
eq: "EQ",
|
|
127
|
-
neq: "NEQ",
|
|
128
|
-
gt: "GT",
|
|
129
|
-
gte: "GTE",
|
|
130
|
-
lt: "LT",
|
|
131
|
-
lte: "LTE",
|
|
132
|
-
contains: "CONTAINS_TOKEN"
|
|
133
|
-
};
|
|
134
149
|
function finiteNumberOrNull(value) {
|
|
135
150
|
if (value === null || value === void 0 || value.trim() === "") {
|
|
136
151
|
return null;
|
|
@@ -141,11 +156,6 @@ function finiteNumberOrNull(value) {
|
|
|
141
156
|
function counterValue(value) {
|
|
142
157
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
143
158
|
}
|
|
144
|
-
function unsupportedAggregate(req) {
|
|
145
|
-
return new Error(
|
|
146
|
-
`HubSpot aggregate: unsupported ${req.fn} for resource=${req.resource}`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
159
|
var idString = z.string().min(1);
|
|
150
160
|
var contactProperties = z.object({
|
|
151
161
|
email: z.string().nullish(),
|
|
@@ -211,16 +221,68 @@ var campaignDetailSchema = z.object({
|
|
|
211
221
|
unsubscribed: z.number().optional()
|
|
212
222
|
}).optional()
|
|
213
223
|
});
|
|
224
|
+
var contactsSchema = z.array(crmRecordSchema(contactProperties));
|
|
225
|
+
var companiesSchema = z.array(crmRecordSchema(companyProperties));
|
|
226
|
+
var dealsSchema = z.array(crmRecordSchema(dealProperties));
|
|
227
|
+
var dealEventsSchema = z.array(dealHistoryRecordSchema);
|
|
228
|
+
var campaignsSchema = z.array(campaignDetailSchema);
|
|
229
|
+
var hubspotResources = defineResources({
|
|
230
|
+
hubspot_contact: {
|
|
231
|
+
shape: "entity",
|
|
232
|
+
description: "CRM contacts with email, lifecycle stage, lead status, owner, and creation time.",
|
|
233
|
+
endpoint: "POST /crm/v3/objects/contacts/search",
|
|
234
|
+
responses: { contacts: contactsSchema }
|
|
235
|
+
},
|
|
236
|
+
hubspot_company: {
|
|
237
|
+
shape: "entity",
|
|
238
|
+
description: "CRM companies with name, domain, industry, lifecycle stage, and creation time.",
|
|
239
|
+
endpoint: "POST /crm/v3/objects/companies/search",
|
|
240
|
+
responses: { companies: companiesSchema }
|
|
241
|
+
},
|
|
242
|
+
hubspot_deal: {
|
|
243
|
+
shape: "entity",
|
|
244
|
+
description: "CRM deals with name, stage, pipeline, amount, close date, owner, and creation time.",
|
|
245
|
+
endpoint: "POST /crm/v3/objects/deals/search",
|
|
246
|
+
responses: { deals: dealsSchema }
|
|
247
|
+
},
|
|
248
|
+
hubspot_deal_stage_change: {
|
|
249
|
+
shape: "event",
|
|
250
|
+
description: "Deal stage-change events derived from deal property history, one event per stage transition.",
|
|
251
|
+
endpoint: "GET /crm/v3/objects/deals?propertiesWithHistory=dealstage",
|
|
252
|
+
responses: { deal_events: dealEventsSchema }
|
|
253
|
+
},
|
|
254
|
+
hubspot_email_campaign: {
|
|
255
|
+
shape: "entity",
|
|
256
|
+
description: "Marketing email campaigns with name, subject, sender, type, send date, and recipient count.",
|
|
257
|
+
endpoint: "GET /email/public/v1/campaigns",
|
|
258
|
+
responses: { email_campaigns: campaignsSchema }
|
|
259
|
+
},
|
|
260
|
+
hubspot_email_stats: {
|
|
261
|
+
shape: "metric",
|
|
262
|
+
description: "Per-campaign marketing email engagement stats (sent, delivered, opened, clicked, bounced, unsubscribed) timestamped at the campaign send time.",
|
|
263
|
+
endpoint: "GET /email/public/v1/campaigns/{id}",
|
|
264
|
+
unit: "emails",
|
|
265
|
+
notes: "One sample per campaign; value is the sent count, and every counter (delivered, opened, clicked, bounced, unsubscribed) is also exposed in attributes.",
|
|
266
|
+
dimensions: [
|
|
267
|
+
{ name: "campaignId", description: "HubSpot campaign id." },
|
|
268
|
+
{ name: "campaignName", description: "Campaign name." },
|
|
269
|
+
{ name: "delivered", description: "Number of emails delivered." },
|
|
270
|
+
{ name: "opened", description: "Number of emails opened." },
|
|
271
|
+
{ name: "clicked", description: "Number of emails clicked." },
|
|
272
|
+
{ name: "bounced", description: "Number of emails bounced." },
|
|
273
|
+
{
|
|
274
|
+
name: "unsubscribed",
|
|
275
|
+
description: "Number of recipients who unsubscribed."
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
responses: { email_stats: campaignsSchema }
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
var id = "hubspot";
|
|
214
282
|
var HubSpotConnector = class _HubSpotConnector extends BaseConnector {
|
|
215
|
-
static id =
|
|
216
|
-
static
|
|
217
|
-
|
|
218
|
-
companies: z.array(crmRecordSchema(companyProperties)),
|
|
219
|
-
deals: z.array(crmRecordSchema(dealProperties)),
|
|
220
|
-
deal_events: z.array(dealHistoryRecordSchema),
|
|
221
|
-
email_campaigns: z.array(campaignDetailSchema),
|
|
222
|
-
email_stats: z.array(campaignDetailSchema)
|
|
223
|
-
};
|
|
283
|
+
static id = id;
|
|
284
|
+
static resources = hubspotResources;
|
|
285
|
+
static schemas = schemasFromResources(hubspotResources);
|
|
224
286
|
static create(input, ctx) {
|
|
225
287
|
const parsed = configFields.parse(input);
|
|
226
288
|
return new _HubSpotConnector(
|
|
@@ -229,7 +291,7 @@ var HubSpotConnector = class _HubSpotConnector extends BaseConnector {
|
|
|
229
291
|
ctx
|
|
230
292
|
);
|
|
231
293
|
}
|
|
232
|
-
id =
|
|
294
|
+
id = id;
|
|
233
295
|
credentials = hubspotCredentials;
|
|
234
296
|
buildHeaders() {
|
|
235
297
|
return {
|
|
@@ -383,9 +445,9 @@ var HubSpotConnector = class _HubSpotConnector extends BaseConnector {
|
|
|
383
445
|
// -------------------------------------------------------------------------
|
|
384
446
|
// Marketing email campaigns + stats (legacy email campaigns API)
|
|
385
447
|
// -------------------------------------------------------------------------
|
|
386
|
-
async fetchCampaignDetail(
|
|
448
|
+
async fetchCampaignDetail(id2, resource, signal) {
|
|
387
449
|
const res = await this.apiGet(
|
|
388
|
-
`${BASE_URL}/email/public/v1/campaigns/${
|
|
450
|
+
`${BASE_URL}/email/public/v1/campaigns/${id2}`,
|
|
389
451
|
resource,
|
|
390
452
|
signal
|
|
391
453
|
);
|
|
@@ -525,69 +587,6 @@ var HubSpotConnector = class _HubSpotConnector extends BaseConnector {
|
|
|
525
587
|
}
|
|
526
588
|
});
|
|
527
589
|
}
|
|
528
|
-
// -------------------------------------------------------------------------
|
|
529
|
-
// Aggregates — count via the CRM Search API `total` (one request)
|
|
530
|
-
// -------------------------------------------------------------------------
|
|
531
|
-
async aggregate(req, signal) {
|
|
532
|
-
if (req.fn !== "count") {
|
|
533
|
-
throw unsupportedAggregate(req);
|
|
534
|
-
}
|
|
535
|
-
const object = COUNT_RESOURCE_TO_OBJECT[req.resource];
|
|
536
|
-
if (!object) {
|
|
537
|
-
throw unsupportedAggregate(req);
|
|
538
|
-
}
|
|
539
|
-
const filterGroups = this.translateCountFilter(req.filter);
|
|
540
|
-
const res = await this.apiPost(
|
|
541
|
-
`${BASE_URL}/crm/v3/objects/${object}/search`,
|
|
542
|
-
object,
|
|
543
|
-
{ filterGroups, properties: [], limit: 1 },
|
|
544
|
-
signal
|
|
545
|
-
);
|
|
546
|
-
const value = res.body.total ?? 0;
|
|
547
|
-
this.logger.info("aggregate", {
|
|
548
|
-
fn: "count",
|
|
549
|
-
resource: req.resource,
|
|
550
|
-
filter: req.filter,
|
|
551
|
-
value,
|
|
552
|
-
via: "CRM search API"
|
|
553
|
-
});
|
|
554
|
-
return value;
|
|
555
|
-
}
|
|
556
|
-
validateCountFilter(resource, filter) {
|
|
557
|
-
if (!COUNT_RESOURCE_TO_OBJECT[resource]) {
|
|
558
|
-
throw new Error(
|
|
559
|
-
`HubSpot aggregate count: unsupported resource=${resource}`
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
this.translateCountFilter(filter);
|
|
563
|
-
}
|
|
564
|
-
// Translates flat AND filter conditions into HubSpot search `filterGroups`.
|
|
565
|
-
// OR clauses aren't expressible alongside the rest of the group model, so
|
|
566
|
-
// they throw "unsupported" and the runner falls back to storage rows.
|
|
567
|
-
translateCountFilter(filter) {
|
|
568
|
-
if (!filter || filter.length === 0) {
|
|
569
|
-
return [];
|
|
570
|
-
}
|
|
571
|
-
const filters = filter.map((clause) => {
|
|
572
|
-
if ("or" in clause) {
|
|
573
|
-
throw new Error(
|
|
574
|
-
"HubSpot aggregate count: OR filter clauses are not supported"
|
|
575
|
-
);
|
|
576
|
-
}
|
|
577
|
-
const operator = FILTER_OP_TO_HUBSPOT[clause.op];
|
|
578
|
-
if (!operator) {
|
|
579
|
-
throw new Error(
|
|
580
|
-
`HubSpot aggregate count: unsupported filter operator ${clause.op}`
|
|
581
|
-
);
|
|
582
|
-
}
|
|
583
|
-
return {
|
|
584
|
-
propertyName: clause.field,
|
|
585
|
-
operator,
|
|
586
|
-
value: String(clause.value)
|
|
587
|
-
};
|
|
588
|
-
});
|
|
589
|
-
return [{ filters }];
|
|
590
|
-
}
|
|
591
590
|
};
|
|
592
591
|
|
|
593
592
|
// src/index.ts
|
|
@@ -595,6 +594,9 @@ var index_default = HubSpotConnector;
|
|
|
595
594
|
export {
|
|
596
595
|
HubSpotConnector,
|
|
597
596
|
configFields,
|
|
598
|
-
index_default as default
|
|
597
|
+
index_default as default,
|
|
598
|
+
doc,
|
|
599
|
+
id,
|
|
600
|
+
hubspotResources as resources
|
|
599
601
|
};
|
|
600
602
|
//# sourceMappingURL=index.js.map
|