@squadbase/vite-server 0.1.2 → 0.1.3-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +13609 -3797
- package/dist/connectors/airtable-oauth.js +12 -4
- package/dist/connectors/amplitude.js +335 -32
- package/dist/connectors/asana.d.ts +5 -0
- package/dist/connectors/asana.js +661 -0
- package/dist/connectors/attio.js +304 -36
- package/dist/connectors/customerio.d.ts +5 -0
- package/dist/connectors/customerio.js +633 -0
- package/dist/connectors/gmail-oauth.d.ts +5 -0
- package/dist/connectors/gmail-oauth.js +639 -0
- package/dist/connectors/google-ads-oauth.js +14 -8
- package/dist/connectors/google-ads.d.ts +5 -0
- package/dist/connectors/google-ads.js +784 -0
- package/dist/connectors/google-analytics-oauth.js +16 -8
- package/dist/connectors/google-sheets-oauth.js +12 -4
- package/dist/connectors/google-sheets.d.ts +5 -0
- package/dist/connectors/google-sheets.js +598 -0
- package/dist/connectors/hubspot-oauth.js +12 -4
- package/dist/connectors/hubspot.d.ts +5 -0
- package/dist/connectors/hubspot.js +550 -0
- package/dist/connectors/intercom-oauth.d.ts +5 -0
- package/dist/connectors/intercom-oauth.js +510 -0
- package/dist/connectors/intercom.d.ts +5 -0
- package/dist/connectors/intercom.js +627 -0
- package/dist/connectors/jira-api-key.d.ts +5 -0
- package/dist/connectors/jira-api-key.js +523 -0
- package/dist/connectors/kintone-api-token.js +16 -20
- package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
- package/dist/connectors/linkedin-ads-oauth.js +774 -0
- package/dist/connectors/linkedin-ads.d.ts +5 -0
- package/dist/connectors/linkedin-ads.js +782 -0
- package/dist/connectors/mailchimp-oauth.d.ts +5 -0
- package/dist/connectors/mailchimp-oauth.js +539 -0
- package/dist/connectors/mailchimp.d.ts +5 -0
- package/dist/connectors/mailchimp.js +646 -0
- package/dist/connectors/shopify-oauth.js +12 -4
- package/dist/connectors/shopify.js +500 -80
- package/dist/connectors/stripe-oauth.js +12 -4
- package/dist/connectors/zendesk-oauth.d.ts +5 -0
- package/dist/connectors/zendesk-oauth.js +505 -0
- package/dist/connectors/zendesk.d.ts +5 -0
- package/dist/connectors/zendesk.js +631 -0
- package/dist/index.js +13594 -3782
- package/dist/main.js +13596 -3784
- package/dist/vite-plugin.js +13596 -3784
- package/package.json +46 -2
|
@@ -296,9 +296,13 @@ var hubspotOauthConnector = new ConnectorPlugin({
|
|
|
296
296
|
]
|
|
297
297
|
},
|
|
298
298
|
systemPrompt: {
|
|
299
|
-
en: `###
|
|
299
|
+
en: `### Tools
|
|
300
300
|
|
|
301
|
-
|
|
301
|
+
- \`hubspot-oauth_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, and other CRM objects. Authentication is configured automatically via OAuth. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response.
|
|
302
|
+
|
|
303
|
+
### HubSpot API Reference
|
|
304
|
+
|
|
305
|
+
#### Available Endpoints
|
|
302
306
|
- GET \`/crm/v3/objects/contacts\` \u2014 List contacts
|
|
303
307
|
- GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 Get a contact
|
|
304
308
|
- GET \`/crm/v3/objects/deals\` \u2014 List deals
|
|
@@ -337,9 +341,13 @@ const hubspot = connection("<connectionId>");
|
|
|
337
341
|
const res = await hubspot.request("/crm/v3/objects/contacts?limit=10");
|
|
338
342
|
const data = await res.json();
|
|
339
343
|
\`\`\``,
|
|
340
|
-
ja: `###
|
|
344
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
345
|
+
|
|
346
|
+
- \`hubspot-oauth_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
347
|
+
|
|
348
|
+
### HubSpot API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
341
349
|
|
|
342
|
-
|
|
350
|
+
#### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
|
|
343
351
|
- GET \`/crm/v3/objects/contacts\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
|
|
344
352
|
- GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u53D6\u5F97
|
|
345
353
|
- GET \`/crm/v3/objects/deals\` \u2014 \u53D6\u5F15\u4E00\u89A7\u3092\u53D6\u5F97
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
// ../connectors/src/parameter-definition.ts
|
|
2
|
+
var ParameterDefinition = class {
|
|
3
|
+
slug;
|
|
4
|
+
name;
|
|
5
|
+
description;
|
|
6
|
+
envVarBaseKey;
|
|
7
|
+
type;
|
|
8
|
+
secret;
|
|
9
|
+
required;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.slug = config.slug;
|
|
12
|
+
this.name = config.name;
|
|
13
|
+
this.description = config.description;
|
|
14
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
15
|
+
this.type = config.type;
|
|
16
|
+
this.secret = config.secret;
|
|
17
|
+
this.required = config.required;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
21
|
+
*/
|
|
22
|
+
getValue(connection2) {
|
|
23
|
+
const param = connection2.parameters.find(
|
|
24
|
+
(p) => p.parameterSlug === this.slug
|
|
25
|
+
);
|
|
26
|
+
if (!param || param.value == null) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return param.value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
35
|
+
*/
|
|
36
|
+
tryGetValue(connection2) {
|
|
37
|
+
const param = connection2.parameters.find(
|
|
38
|
+
(p) => p.parameterSlug === this.slug
|
|
39
|
+
);
|
|
40
|
+
if (!param || param.value == null) return void 0;
|
|
41
|
+
return param.value;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ../connectors/src/connectors/hubspot/parameters.ts
|
|
46
|
+
var parameters = {
|
|
47
|
+
apiKey: new ParameterDefinition({
|
|
48
|
+
slug: "api-key",
|
|
49
|
+
name: "Personal Access Key",
|
|
50
|
+
description: "Your HubSpot Personal Access Key for authentication (starts with pat-).",
|
|
51
|
+
envVarBaseKey: "HUBSPOT_API_KEY",
|
|
52
|
+
type: "text",
|
|
53
|
+
secret: true,
|
|
54
|
+
required: true
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ../connectors/src/connectors/hubspot/sdk/index.ts
|
|
59
|
+
var BASE_URL = "https://api.hubapi.com";
|
|
60
|
+
function createClient(params) {
|
|
61
|
+
const apiKey = params[parameters.apiKey.slug];
|
|
62
|
+
if (!apiKey) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`hubspot: missing required parameter: ${parameters.apiKey.slug}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
function authHeaders(extra) {
|
|
68
|
+
const headers = new Headers(extra);
|
|
69
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
70
|
+
headers.set("Content-Type", "application/json");
|
|
71
|
+
return headers;
|
|
72
|
+
}
|
|
73
|
+
async function assertOk(res, label) {
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
const body = await res.text().catch(() => "(unreadable body)");
|
|
76
|
+
throw new Error(
|
|
77
|
+
`hubspot ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
request(path2, init) {
|
|
83
|
+
const url = `${BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
84
|
+
const headers = new Headers(init?.headers);
|
|
85
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
86
|
+
headers.set("Content-Type", "application/json");
|
|
87
|
+
return fetch(url, { ...init, headers });
|
|
88
|
+
},
|
|
89
|
+
async listObjects(objectType, options) {
|
|
90
|
+
const params2 = new URLSearchParams();
|
|
91
|
+
if (options?.limit) params2.set("limit", String(options.limit));
|
|
92
|
+
if (options?.after) params2.set("after", options.after);
|
|
93
|
+
if (options?.properties)
|
|
94
|
+
params2.set("properties", options.properties.join(","));
|
|
95
|
+
if (options?.associations)
|
|
96
|
+
params2.set("associations", options.associations.join(","));
|
|
97
|
+
const qs = params2.toString();
|
|
98
|
+
const res = await fetch(
|
|
99
|
+
`${BASE_URL}/crm/v3/objects/${encodeURIComponent(objectType)}${qs ? `?${qs}` : ""}`,
|
|
100
|
+
{ method: "GET", headers: authHeaders() }
|
|
101
|
+
);
|
|
102
|
+
await assertOk(res, "listObjects");
|
|
103
|
+
return await res.json();
|
|
104
|
+
},
|
|
105
|
+
async getObject(objectType, objectId, options) {
|
|
106
|
+
const params2 = new URLSearchParams();
|
|
107
|
+
if (options?.properties)
|
|
108
|
+
params2.set("properties", options.properties.join(","));
|
|
109
|
+
if (options?.associations)
|
|
110
|
+
params2.set("associations", options.associations.join(","));
|
|
111
|
+
const qs = params2.toString();
|
|
112
|
+
const res = await fetch(
|
|
113
|
+
`${BASE_URL}/crm/v3/objects/${encodeURIComponent(objectType)}/${encodeURIComponent(objectId)}${qs ? `?${qs}` : ""}`,
|
|
114
|
+
{ method: "GET", headers: authHeaders() }
|
|
115
|
+
);
|
|
116
|
+
await assertOk(res, "getObject");
|
|
117
|
+
return await res.json();
|
|
118
|
+
},
|
|
119
|
+
async searchObjects(objectType, options) {
|
|
120
|
+
const body = {};
|
|
121
|
+
if (options?.filterGroups) body.filterGroups = options.filterGroups;
|
|
122
|
+
if (options?.sorts) body.sorts = options.sorts;
|
|
123
|
+
if (options?.properties) body.properties = options.properties;
|
|
124
|
+
if (options?.limit) body.limit = options.limit;
|
|
125
|
+
if (options?.after) body.after = options.after;
|
|
126
|
+
const res = await fetch(
|
|
127
|
+
`${BASE_URL}/crm/v3/objects/${encodeURIComponent(objectType)}/search`,
|
|
128
|
+
{
|
|
129
|
+
method: "POST",
|
|
130
|
+
headers: authHeaders(),
|
|
131
|
+
body: JSON.stringify(body)
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
await assertOk(res, "searchObjects");
|
|
135
|
+
return await res.json();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ../connectors/src/connector-onboarding.ts
|
|
141
|
+
var ConnectorOnboarding = class {
|
|
142
|
+
/** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
|
|
143
|
+
connectionSetupInstructions;
|
|
144
|
+
/** Phase 2: Data overview instructions */
|
|
145
|
+
dataOverviewInstructions;
|
|
146
|
+
constructor(config) {
|
|
147
|
+
this.connectionSetupInstructions = config.connectionSetupInstructions;
|
|
148
|
+
this.dataOverviewInstructions = config.dataOverviewInstructions;
|
|
149
|
+
}
|
|
150
|
+
getConnectionSetupPrompt(language) {
|
|
151
|
+
return this.connectionSetupInstructions?.[language] ?? null;
|
|
152
|
+
}
|
|
153
|
+
getDataOverviewInstructions(language) {
|
|
154
|
+
return this.dataOverviewInstructions[language];
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// ../connectors/src/connector-tool.ts
|
|
159
|
+
var ConnectorTool = class {
|
|
160
|
+
name;
|
|
161
|
+
description;
|
|
162
|
+
inputSchema;
|
|
163
|
+
outputSchema;
|
|
164
|
+
_execute;
|
|
165
|
+
constructor(config) {
|
|
166
|
+
this.name = config.name;
|
|
167
|
+
this.description = config.description;
|
|
168
|
+
this.inputSchema = config.inputSchema;
|
|
169
|
+
this.outputSchema = config.outputSchema;
|
|
170
|
+
this._execute = config.execute;
|
|
171
|
+
}
|
|
172
|
+
createTool(connections, config) {
|
|
173
|
+
return {
|
|
174
|
+
description: this.description,
|
|
175
|
+
inputSchema: this.inputSchema,
|
|
176
|
+
outputSchema: this.outputSchema,
|
|
177
|
+
execute: (input) => this._execute(input, connections, config)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// ../connectors/src/connector-plugin.ts
|
|
183
|
+
var ConnectorPlugin = class _ConnectorPlugin {
|
|
184
|
+
slug;
|
|
185
|
+
authType;
|
|
186
|
+
name;
|
|
187
|
+
description;
|
|
188
|
+
iconUrl;
|
|
189
|
+
parameters;
|
|
190
|
+
releaseFlag;
|
|
191
|
+
proxyPolicy;
|
|
192
|
+
experimentalAttributes;
|
|
193
|
+
onboarding;
|
|
194
|
+
systemPrompt;
|
|
195
|
+
tools;
|
|
196
|
+
query;
|
|
197
|
+
checkConnection;
|
|
198
|
+
constructor(config) {
|
|
199
|
+
this.slug = config.slug;
|
|
200
|
+
this.authType = config.authType;
|
|
201
|
+
this.name = config.name;
|
|
202
|
+
this.description = config.description;
|
|
203
|
+
this.iconUrl = config.iconUrl;
|
|
204
|
+
this.parameters = config.parameters;
|
|
205
|
+
this.releaseFlag = config.releaseFlag;
|
|
206
|
+
this.proxyPolicy = config.proxyPolicy;
|
|
207
|
+
this.experimentalAttributes = config.experimentalAttributes;
|
|
208
|
+
this.onboarding = config.onboarding;
|
|
209
|
+
this.systemPrompt = config.systemPrompt;
|
|
210
|
+
this.tools = config.tools;
|
|
211
|
+
this.query = config.query;
|
|
212
|
+
this.checkConnection = config.checkConnection;
|
|
213
|
+
}
|
|
214
|
+
get connectorKey() {
|
|
215
|
+
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Create tools for connections that belong to this connector.
|
|
219
|
+
* Filters connections by connectorKey internally.
|
|
220
|
+
* Returns tools keyed as `${connectorKey}_${toolName}`.
|
|
221
|
+
*/
|
|
222
|
+
createTools(connections, config) {
|
|
223
|
+
const myConnections = connections.filter(
|
|
224
|
+
(c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
|
|
225
|
+
);
|
|
226
|
+
const result = {};
|
|
227
|
+
for (const t of Object.values(this.tools)) {
|
|
228
|
+
result[`${this.connectorKey}_${t.name}`] = t.createTool(
|
|
229
|
+
myConnections,
|
|
230
|
+
config
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
static deriveKey(slug, authType) {
|
|
236
|
+
return authType ? `${slug}-${authType}` : slug;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// ../connectors/src/auth-types.ts
|
|
241
|
+
var AUTH_TYPES = {
|
|
242
|
+
OAUTH: "oauth",
|
|
243
|
+
API_KEY: "api-key",
|
|
244
|
+
JWT: "jwt",
|
|
245
|
+
SERVICE_ACCOUNT: "service-account",
|
|
246
|
+
PAT: "pat"
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// ../connectors/src/connectors/hubspot/setup.ts
|
|
250
|
+
var hubspotOnboarding = new ConnectorOnboarding({
|
|
251
|
+
dataOverviewInstructions: {
|
|
252
|
+
en: `1. Call hubspot_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
|
|
253
|
+
2. Call hubspot_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
|
|
254
|
+
3. Explore other object types (companies, tickets, etc.) as needed to understand available data`,
|
|
255
|
+
ja: `1. hubspot_request \u3067 GET /crm/v3/objects/contacts?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30B3\u30F3\u30BF\u30AF\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
256
|
+
2. hubspot_request \u3067 GET /crm/v3/objects/deals?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u53D6\u5F15\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
257
|
+
3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30BF\u30A4\u30D7\uFF08\u4F01\u696D\u3001\u30C1\u30B1\u30C3\u30C8\u306A\u3069\uFF09\u3092\u63A2\u7D22\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C7\u30FC\u30BF\u3092\u628A\u63E1`
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// ../connectors/src/connectors/hubspot/tools/request.ts
|
|
262
|
+
import { z } from "zod";
|
|
263
|
+
var BASE_URL2 = "https://api.hubapi.com";
|
|
264
|
+
var REQUEST_TIMEOUT_MS = 6e4;
|
|
265
|
+
var inputSchema = z.object({
|
|
266
|
+
toolUseIntent: z.string().optional().describe(
|
|
267
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
268
|
+
),
|
|
269
|
+
connectionId: z.string().describe("ID of the HubSpot connection to use"),
|
|
270
|
+
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).describe(
|
|
271
|
+
"HTTP method. GET for reading resources, POST for creating or searching, PATCH for updating, DELETE for removing."
|
|
272
|
+
),
|
|
273
|
+
path: z.string().describe(
|
|
274
|
+
"API path appended to https://api.hubapi.com (e.g., '/crm/v3/objects/contacts', '/crm/v3/objects/deals', '/crm/v3/objects/contacts/search')"
|
|
275
|
+
),
|
|
276
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PATCH requests")
|
|
277
|
+
});
|
|
278
|
+
var outputSchema = z.discriminatedUnion("success", [
|
|
279
|
+
z.object({
|
|
280
|
+
success: z.literal(true),
|
|
281
|
+
status: z.number(),
|
|
282
|
+
data: z.record(z.string(), z.unknown())
|
|
283
|
+
}),
|
|
284
|
+
z.object({
|
|
285
|
+
success: z.literal(false),
|
|
286
|
+
error: z.string()
|
|
287
|
+
})
|
|
288
|
+
]);
|
|
289
|
+
var requestTool = new ConnectorTool({
|
|
290
|
+
name: "request",
|
|
291
|
+
description: `Send authenticated requests to the HubSpot API.
|
|
292
|
+
Authentication is handled automatically using the Personal Access Key (Bearer token).
|
|
293
|
+
Use this tool for all HubSpot API interactions: querying contacts, deals, companies, tickets, and other CRM objects.
|
|
294
|
+
Use the search endpoint (POST /crm/v3/objects/{objectType}/search) for complex queries with filters.`,
|
|
295
|
+
inputSchema,
|
|
296
|
+
outputSchema,
|
|
297
|
+
async execute({ connectionId, method, path: path2, body }, connections) {
|
|
298
|
+
const connection2 = connections.find((c) => c.id === connectionId);
|
|
299
|
+
if (!connection2) {
|
|
300
|
+
return {
|
|
301
|
+
success: false,
|
|
302
|
+
error: `Connection ${connectionId} not found`
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
console.log(
|
|
306
|
+
`[connector-request] hubspot/${connection2.name}: ${method} ${path2}`
|
|
307
|
+
);
|
|
308
|
+
try {
|
|
309
|
+
const apiKey = parameters.apiKey.getValue(connection2);
|
|
310
|
+
const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
|
|
311
|
+
const controller = new AbortController();
|
|
312
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
313
|
+
try {
|
|
314
|
+
const response = await fetch(url, {
|
|
315
|
+
method,
|
|
316
|
+
headers: {
|
|
317
|
+
Authorization: `Bearer ${apiKey}`,
|
|
318
|
+
"Content-Type": "application/json"
|
|
319
|
+
},
|
|
320
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
321
|
+
signal: controller.signal
|
|
322
|
+
});
|
|
323
|
+
const data = await response.json();
|
|
324
|
+
if (!response.ok) {
|
|
325
|
+
const errorMessage = typeof data?.message === "string" ? data.message : typeof data?.error === "string" ? data.error : `HTTP ${response.status} ${response.statusText}`;
|
|
326
|
+
return { success: false, error: errorMessage };
|
|
327
|
+
}
|
|
328
|
+
return { success: true, status: response.status, data };
|
|
329
|
+
} finally {
|
|
330
|
+
clearTimeout(timeout);
|
|
331
|
+
}
|
|
332
|
+
} catch (err) {
|
|
333
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
334
|
+
return { success: false, error: msg };
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// ../connectors/src/connectors/hubspot/index.ts
|
|
340
|
+
var tools = { request: requestTool };
|
|
341
|
+
var hubspotConnector = new ConnectorPlugin({
|
|
342
|
+
slug: "hubspot",
|
|
343
|
+
authType: AUTH_TYPES.PAT,
|
|
344
|
+
name: "HubSpot",
|
|
345
|
+
description: "Connect to HubSpot CRM for contacts, deals, companies, and marketing data using a Personal Access Key.",
|
|
346
|
+
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5UcSkKkzhUMA4RsM45ynuo/43b967e36915ca0fc5d277684b204320/hubspot.svg",
|
|
347
|
+
parameters,
|
|
348
|
+
releaseFlag: { dev1: true, dev2: false, prod: false },
|
|
349
|
+
onboarding: hubspotOnboarding,
|
|
350
|
+
systemPrompt: {
|
|
351
|
+
en: `### Tools
|
|
352
|
+
|
|
353
|
+
- \`hubspot_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, tickets, and other CRM objects. Authentication (Bearer token) is configured automatically. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response. Use the search endpoint for complex queries with filters.
|
|
354
|
+
|
|
355
|
+
### Business Logic
|
|
356
|
+
|
|
357
|
+
The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
|
|
358
|
+
|
|
359
|
+
SDK methods (client created via \`connection(connectionId)\`):
|
|
360
|
+
- \`client.request(path, init?)\` \u2014 low-level authenticated fetch
|
|
361
|
+
- \`client.listObjects(objectType, options?)\` \u2014 list CRM objects with pagination (limit, after, properties, associations)
|
|
362
|
+
- \`client.getObject(objectType, objectId, options?)\` \u2014 fetch a single CRM object
|
|
363
|
+
- \`client.searchObjects(objectType, options?)\` \u2014 search CRM objects with filters, sorts, and pagination
|
|
364
|
+
|
|
365
|
+
\`\`\`ts
|
|
366
|
+
import type { Context } from "hono";
|
|
367
|
+
import { connection } from "@squadbase/vite-server/connectors/hubspot";
|
|
368
|
+
|
|
369
|
+
const hubspot = connection("<connectionId>");
|
|
370
|
+
|
|
371
|
+
export default async function handler(c: Context) {
|
|
372
|
+
const { limit = 10 } = await c.req.json<{ limit?: number }>();
|
|
373
|
+
|
|
374
|
+
const { results, paging } = await hubspot.listObjects("contacts", {
|
|
375
|
+
limit,
|
|
376
|
+
properties: ["email", "firstname", "lastname"],
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
return c.json({
|
|
380
|
+
contacts: results,
|
|
381
|
+
nextPage: paging?.next?.after,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
\`\`\`
|
|
385
|
+
|
|
386
|
+
### HubSpot API Reference
|
|
387
|
+
|
|
388
|
+
- Base URL: \`https://api.hubapi.com\`
|
|
389
|
+
- Authentication: Bearer token (handled automatically)
|
|
390
|
+
- Pagination: cursor-based with \`after\` parameter from \`paging.next.after\`
|
|
391
|
+
|
|
392
|
+
#### Common Endpoints
|
|
393
|
+
- GET \`/crm/v3/objects/contacts\` \u2014 List contacts
|
|
394
|
+
- GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 Get a contact
|
|
395
|
+
- GET \`/crm/v3/objects/deals\` \u2014 List deals
|
|
396
|
+
- GET \`/crm/v3/objects/deals/{dealId}\` \u2014 Get a deal
|
|
397
|
+
- GET \`/crm/v3/objects/companies\` \u2014 List companies
|
|
398
|
+
- GET \`/crm/v3/objects/companies/{companyId}\` \u2014 Get a company
|
|
399
|
+
- POST \`/crm/v3/objects/contacts\` \u2014 Create a contact
|
|
400
|
+
- POST \`/crm/v3/objects/deals\` \u2014 Create a deal
|
|
401
|
+
- PATCH \`/crm/v3/objects/contacts/{contactId}\` \u2014 Update a contact
|
|
402
|
+
- PATCH \`/crm/v3/objects/deals/{dealId}\` \u2014 Update a deal
|
|
403
|
+
- POST \`/crm/v3/objects/{objectType}/search\` \u2014 Search objects
|
|
404
|
+
|
|
405
|
+
#### Query Parameters
|
|
406
|
+
- \`limit\` \u2014 Number of results per page (max 100)
|
|
407
|
+
- \`after\` \u2014 Pagination cursor
|
|
408
|
+
- \`properties\` \u2014 Comma-separated list of properties to return
|
|
409
|
+
- \`associations\` \u2014 Comma-separated list of association types to include
|
|
410
|
+
|
|
411
|
+
#### Search Body (POST /crm/v3/objects/{objectType}/search)
|
|
412
|
+
- \`filterGroups\` \u2014 Array of filter groups with \`filters\` (propertyName, operator, value)
|
|
413
|
+
- \`sorts\` \u2014 Array of sort specifications
|
|
414
|
+
- \`properties\` \u2014 Array of properties to return
|
|
415
|
+
- \`limit\` \u2014 Max results per page (max 100)
|
|
416
|
+
- \`after\` \u2014 Pagination offset`,
|
|
417
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
418
|
+
|
|
419
|
+
- \`hubspot_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u30C1\u30B1\u30C3\u30C8\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Bearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u8907\u96D1\u306A\u30AF\u30A8\u30EA\u306B\u306F\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306Esearch\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
420
|
+
|
|
421
|
+
### Business Logic
|
|
422
|
+
|
|
423
|
+
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
424
|
+
|
|
425
|
+
SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
|
|
426
|
+
- \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
|
|
427
|
+
- \`client.listObjects(objectType, options?)\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067CRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u4E00\u89A7\u53D6\u5F97\uFF08limit, after, properties, associations\uFF09
|
|
428
|
+
- \`client.getObject(objectType, objectId, options?)\` \u2014 \u5358\u4E00CRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u53D6\u5F97
|
|
429
|
+
- \`client.searchObjects(objectType, options?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\u3001\u30BD\u30FC\u30C8\u3001\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067CRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u691C\u7D22
|
|
430
|
+
|
|
431
|
+
\`\`\`ts
|
|
432
|
+
import type { Context } from "hono";
|
|
433
|
+
import { connection } from "@squadbase/vite-server/connectors/hubspot";
|
|
434
|
+
|
|
435
|
+
const hubspot = connection("<connectionId>");
|
|
436
|
+
|
|
437
|
+
export default async function handler(c: Context) {
|
|
438
|
+
const { limit = 10 } = await c.req.json<{ limit?: number }>();
|
|
439
|
+
|
|
440
|
+
const { results, paging } = await hubspot.listObjects("contacts", {
|
|
441
|
+
limit,
|
|
442
|
+
properties: ["email", "firstname", "lastname"],
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
return c.json({
|
|
446
|
+
contacts: results,
|
|
447
|
+
nextPage: paging?.next?.after,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
\`\`\`
|
|
451
|
+
|
|
452
|
+
### HubSpot API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
453
|
+
|
|
454
|
+
- \u30D9\u30FC\u30B9URL: \`https://api.hubapi.com\`
|
|
455
|
+
- \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
|
|
456
|
+
- \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3: \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9
|
|
457
|
+
|
|
458
|
+
#### \u4E3B\u8981\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
|
|
459
|
+
- GET \`/crm/v3/objects/contacts\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
|
|
460
|
+
- GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u53D6\u5F97
|
|
461
|
+
- GET \`/crm/v3/objects/deals\` \u2014 \u53D6\u5F15\u4E00\u89A7\u3092\u53D6\u5F97
|
|
462
|
+
- GET \`/crm/v3/objects/deals/{dealId}\` \u2014 \u53D6\u5F15\u3092\u53D6\u5F97
|
|
463
|
+
- GET \`/crm/v3/objects/companies\` \u2014 \u4F1A\u793E\u4E00\u89A7\u3092\u53D6\u5F97
|
|
464
|
+
- GET \`/crm/v3/objects/companies/{companyId}\` \u2014 \u4F1A\u793E\u3092\u53D6\u5F97
|
|
465
|
+
- POST \`/crm/v3/objects/contacts\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u4F5C\u6210
|
|
466
|
+
- POST \`/crm/v3/objects/deals\` \u2014 \u53D6\u5F15\u3092\u4F5C\u6210
|
|
467
|
+
- PATCH \`/crm/v3/objects/contacts/{contactId}\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u66F4\u65B0
|
|
468
|
+
- PATCH \`/crm/v3/objects/deals/{dealId}\` \u2014 \u53D6\u5F15\u3092\u66F4\u65B0
|
|
469
|
+
- POST \`/crm/v3/objects/{objectType}/search\` \u2014 \u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u691C\u7D22
|
|
470
|
+
|
|
471
|
+
#### \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
|
|
472
|
+
- \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u7D50\u679C\u6570\uFF08\u6700\u5927100\uFF09
|
|
473
|
+
- \`after\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u30AB\u30FC\u30BD\u30EB
|
|
474
|
+
- \`properties\` \u2014 \u8FD4\u5374\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u30AB\u30F3\u30DE\u533A\u5207\u308A\u30EA\u30B9\u30C8
|
|
475
|
+
- \`associations\` \u2014 \u542B\u3081\u308B\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u30BF\u30A4\u30D7\u306E\u30AB\u30F3\u30DE\u533A\u5207\u308A\u30EA\u30B9\u30C8
|
|
476
|
+
|
|
477
|
+
#### \u691C\u7D22\u30DC\u30C7\u30A3 (POST /crm/v3/objects/{objectType}/search)
|
|
478
|
+
- \`filterGroups\` \u2014 \u30D5\u30A3\u30EB\u30BF\u30B0\u30EB\u30FC\u30D7\u306E\u914D\u5217\uFF08\`filters\`: propertyName, operator, value\uFF09
|
|
479
|
+
- \`sorts\` \u2014 \u30BD\u30FC\u30C8\u6307\u5B9A\u306E\u914D\u5217
|
|
480
|
+
- \`properties\` \u2014 \u8FD4\u5374\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u914D\u5217
|
|
481
|
+
- \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u6700\u5927\u7D50\u679C\u6570\uFF08\u6700\u5927100\uFF09
|
|
482
|
+
- \`after\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u30AA\u30D5\u30BB\u30C3\u30C8`
|
|
483
|
+
},
|
|
484
|
+
tools
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// src/connectors/create-connector-sdk.ts
|
|
488
|
+
import { readFileSync } from "fs";
|
|
489
|
+
import path from "path";
|
|
490
|
+
|
|
491
|
+
// src/connector-client/env.ts
|
|
492
|
+
function resolveEnvVar(entry, key, connectionId) {
|
|
493
|
+
const envVarName = entry.envVars[key];
|
|
494
|
+
if (!envVarName) {
|
|
495
|
+
throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
|
|
496
|
+
}
|
|
497
|
+
const value = process.env[envVarName];
|
|
498
|
+
if (!value) {
|
|
499
|
+
throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
|
|
500
|
+
}
|
|
501
|
+
return value;
|
|
502
|
+
}
|
|
503
|
+
function resolveEnvVarOptional(entry, key) {
|
|
504
|
+
const envVarName = entry.envVars[key];
|
|
505
|
+
if (!envVarName) return void 0;
|
|
506
|
+
return process.env[envVarName] || void 0;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/connectors/create-connector-sdk.ts
|
|
510
|
+
function loadConnectionsSync() {
|
|
511
|
+
const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
|
|
512
|
+
try {
|
|
513
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
514
|
+
return JSON.parse(raw);
|
|
515
|
+
} catch {
|
|
516
|
+
return {};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function createConnectorSdk(plugin, createClient2) {
|
|
520
|
+
return (connectionId) => {
|
|
521
|
+
const connections = loadConnectionsSync();
|
|
522
|
+
const entry = connections[connectionId];
|
|
523
|
+
if (!entry) {
|
|
524
|
+
throw new Error(
|
|
525
|
+
`Connection "${connectionId}" not found in .squadbase/connections.json`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
if (entry.connector.slug !== plugin.slug) {
|
|
529
|
+
throw new Error(
|
|
530
|
+
`Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
const params = {};
|
|
534
|
+
for (const param of Object.values(plugin.parameters)) {
|
|
535
|
+
if (param.required) {
|
|
536
|
+
params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
|
|
537
|
+
} else {
|
|
538
|
+
const val = resolveEnvVarOptional(entry, param.slug);
|
|
539
|
+
if (val !== void 0) params[param.slug] = val;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return createClient2(params);
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/connectors/entries/hubspot.ts
|
|
547
|
+
var connection = createConnectorSdk(hubspotConnector, createClient);
|
|
548
|
+
export {
|
|
549
|
+
connection
|
|
550
|
+
};
|