@squadbase/vite-server 0.1.2 → 0.1.3-dev.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.
@@ -0,0 +1,541 @@
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: "HubSpot Private App Access Token",
50
+ description: "The HubSpot private app access token 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/connectors/hubspot/setup.ts
241
+ var hubspotOnboarding = new ConnectorOnboarding({
242
+ dataOverviewInstructions: {
243
+ en: `1. Call hubspot_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
244
+ 2. Call hubspot_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
245
+ 3. Explore other object types (companies, tickets, etc.) as needed to understand available data`,
246
+ 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
247
+ 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
248
+ 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`
249
+ }
250
+ });
251
+
252
+ // ../connectors/src/connectors/hubspot/tools/request.ts
253
+ import { z } from "zod";
254
+ var BASE_URL2 = "https://api.hubapi.com";
255
+ var REQUEST_TIMEOUT_MS = 6e4;
256
+ var inputSchema = z.object({
257
+ toolUseIntent: z.string().optional().describe(
258
+ "Brief description of what you intend to accomplish with this tool call"
259
+ ),
260
+ connectionId: z.string().describe("ID of the HubSpot connection to use"),
261
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).describe(
262
+ "HTTP method. GET for reading resources, POST for creating or searching, PATCH for updating, DELETE for removing."
263
+ ),
264
+ path: z.string().describe(
265
+ "API path appended to https://api.hubapi.com (e.g., '/crm/v3/objects/contacts', '/crm/v3/objects/deals', '/crm/v3/objects/contacts/search')"
266
+ ),
267
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PATCH requests")
268
+ });
269
+ var outputSchema = z.discriminatedUnion("success", [
270
+ z.object({
271
+ success: z.literal(true),
272
+ status: z.number(),
273
+ data: z.record(z.string(), z.unknown())
274
+ }),
275
+ z.object({
276
+ success: z.literal(false),
277
+ error: z.string()
278
+ })
279
+ ]);
280
+ var requestTool = new ConnectorTool({
281
+ name: "request",
282
+ description: `Send authenticated requests to the HubSpot API.
283
+ Authentication is handled automatically using the Private App Access Token (Bearer token).
284
+ Use this tool for all HubSpot API interactions: querying contacts, deals, companies, tickets, and other CRM objects.
285
+ Use the search endpoint (POST /crm/v3/objects/{objectType}/search) for complex queries with filters.`,
286
+ inputSchema,
287
+ outputSchema,
288
+ async execute({ connectionId, method, path: path2, body }, connections) {
289
+ const connection2 = connections.find((c) => c.id === connectionId);
290
+ if (!connection2) {
291
+ return {
292
+ success: false,
293
+ error: `Connection ${connectionId} not found`
294
+ };
295
+ }
296
+ console.log(
297
+ `[connector-request] hubspot/${connection2.name}: ${method} ${path2}`
298
+ );
299
+ try {
300
+ const apiKey = parameters.apiKey.getValue(connection2);
301
+ const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
302
+ const controller = new AbortController();
303
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
304
+ try {
305
+ const response = await fetch(url, {
306
+ method,
307
+ headers: {
308
+ Authorization: `Bearer ${apiKey}`,
309
+ "Content-Type": "application/json"
310
+ },
311
+ body: body ? JSON.stringify(body) : void 0,
312
+ signal: controller.signal
313
+ });
314
+ const data = await response.json();
315
+ if (!response.ok) {
316
+ const errorMessage = typeof data?.message === "string" ? data.message : typeof data?.error === "string" ? data.error : `HTTP ${response.status} ${response.statusText}`;
317
+ return { success: false, error: errorMessage };
318
+ }
319
+ return { success: true, status: response.status, data };
320
+ } finally {
321
+ clearTimeout(timeout);
322
+ }
323
+ } catch (err) {
324
+ const msg = err instanceof Error ? err.message : String(err);
325
+ return { success: false, error: msg };
326
+ }
327
+ }
328
+ });
329
+
330
+ // ../connectors/src/connectors/hubspot/index.ts
331
+ var tools = { request: requestTool };
332
+ var hubspotConnector = new ConnectorPlugin({
333
+ slug: "hubspot",
334
+ authType: null,
335
+ name: "HubSpot",
336
+ description: "Connect to HubSpot CRM for contacts, deals, companies, and marketing data using a Private App Access Token.",
337
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5UcSkKkzhUMA4RsM45ynuo/43b967e36915ca0fc5d277684b204320/hubspot.svg",
338
+ parameters,
339
+ releaseFlag: { dev1: true, dev2: false, prod: false },
340
+ onboarding: hubspotOnboarding,
341
+ systemPrompt: {
342
+ en: `### Tools
343
+
344
+ - \`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.
345
+
346
+ ### Business Logic
347
+
348
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
349
+
350
+ SDK methods (client created via \`connection(connectionId)\`):
351
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
352
+ - \`client.listObjects(objectType, options?)\` \u2014 list CRM objects with pagination (limit, after, properties, associations)
353
+ - \`client.getObject(objectType, objectId, options?)\` \u2014 fetch a single CRM object
354
+ - \`client.searchObjects(objectType, options?)\` \u2014 search CRM objects with filters, sorts, and pagination
355
+
356
+ \`\`\`ts
357
+ import type { Context } from "hono";
358
+ import { connection } from "@squadbase/vite-server/connectors/hubspot";
359
+
360
+ const hubspot = connection("<connectionId>");
361
+
362
+ export default async function handler(c: Context) {
363
+ const { limit = 10 } = await c.req.json<{ limit?: number }>();
364
+
365
+ const { results, paging } = await hubspot.listObjects("contacts", {
366
+ limit,
367
+ properties: ["email", "firstname", "lastname"],
368
+ });
369
+
370
+ return c.json({
371
+ contacts: results,
372
+ nextPage: paging?.next?.after,
373
+ });
374
+ }
375
+ \`\`\`
376
+
377
+ ### HubSpot API Reference
378
+
379
+ - Base URL: \`https://api.hubapi.com\`
380
+ - Authentication: Bearer token (handled automatically)
381
+ - Pagination: cursor-based with \`after\` parameter from \`paging.next.after\`
382
+
383
+ #### Common Endpoints
384
+ - GET \`/crm/v3/objects/contacts\` \u2014 List contacts
385
+ - GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 Get a contact
386
+ - GET \`/crm/v3/objects/deals\` \u2014 List deals
387
+ - GET \`/crm/v3/objects/deals/{dealId}\` \u2014 Get a deal
388
+ - GET \`/crm/v3/objects/companies\` \u2014 List companies
389
+ - GET \`/crm/v3/objects/companies/{companyId}\` \u2014 Get a company
390
+ - POST \`/crm/v3/objects/contacts\` \u2014 Create a contact
391
+ - POST \`/crm/v3/objects/deals\` \u2014 Create a deal
392
+ - PATCH \`/crm/v3/objects/contacts/{contactId}\` \u2014 Update a contact
393
+ - PATCH \`/crm/v3/objects/deals/{dealId}\` \u2014 Update a deal
394
+ - POST \`/crm/v3/objects/{objectType}/search\` \u2014 Search objects
395
+
396
+ #### Query Parameters
397
+ - \`limit\` \u2014 Number of results per page (max 100)
398
+ - \`after\` \u2014 Pagination cursor
399
+ - \`properties\` \u2014 Comma-separated list of properties to return
400
+ - \`associations\` \u2014 Comma-separated list of association types to include
401
+
402
+ #### Search Body (POST /crm/v3/objects/{objectType}/search)
403
+ - \`filterGroups\` \u2014 Array of filter groups with \`filters\` (propertyName, operator, value)
404
+ - \`sorts\` \u2014 Array of sort specifications
405
+ - \`properties\` \u2014 Array of properties to return
406
+ - \`limit\` \u2014 Max results per page (max 100)
407
+ - \`after\` \u2014 Pagination offset`,
408
+ ja: `### \u30C4\u30FC\u30EB
409
+
410
+ - \`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
411
+
412
+ ### Business Logic
413
+
414
+ \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
415
+
416
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
417
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
418
+ - \`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
419
+ - \`client.getObject(objectType, objectId, options?)\` \u2014 \u5358\u4E00CRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u53D6\u5F97
420
+ - \`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
421
+
422
+ \`\`\`ts
423
+ import type { Context } from "hono";
424
+ import { connection } from "@squadbase/vite-server/connectors/hubspot";
425
+
426
+ const hubspot = connection("<connectionId>");
427
+
428
+ export default async function handler(c: Context) {
429
+ const { limit = 10 } = await c.req.json<{ limit?: number }>();
430
+
431
+ const { results, paging } = await hubspot.listObjects("contacts", {
432
+ limit,
433
+ properties: ["email", "firstname", "lastname"],
434
+ });
435
+
436
+ return c.json({
437
+ contacts: results,
438
+ nextPage: paging?.next?.after,
439
+ });
440
+ }
441
+ \`\`\`
442
+
443
+ ### HubSpot API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
444
+
445
+ - \u30D9\u30FC\u30B9URL: \`https://api.hubapi.com\`
446
+ - \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
447
+ - \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
448
+
449
+ #### \u4E3B\u8981\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
450
+ - GET \`/crm/v3/objects/contacts\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
451
+ - GET \`/crm/v3/objects/contacts/{contactId}\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u53D6\u5F97
452
+ - GET \`/crm/v3/objects/deals\` \u2014 \u53D6\u5F15\u4E00\u89A7\u3092\u53D6\u5F97
453
+ - GET \`/crm/v3/objects/deals/{dealId}\` \u2014 \u53D6\u5F15\u3092\u53D6\u5F97
454
+ - GET \`/crm/v3/objects/companies\` \u2014 \u4F1A\u793E\u4E00\u89A7\u3092\u53D6\u5F97
455
+ - GET \`/crm/v3/objects/companies/{companyId}\` \u2014 \u4F1A\u793E\u3092\u53D6\u5F97
456
+ - POST \`/crm/v3/objects/contacts\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u4F5C\u6210
457
+ - POST \`/crm/v3/objects/deals\` \u2014 \u53D6\u5F15\u3092\u4F5C\u6210
458
+ - PATCH \`/crm/v3/objects/contacts/{contactId}\` \u2014 \u30B3\u30F3\u30BF\u30AF\u30C8\u3092\u66F4\u65B0
459
+ - PATCH \`/crm/v3/objects/deals/{dealId}\` \u2014 \u53D6\u5F15\u3092\u66F4\u65B0
460
+ - POST \`/crm/v3/objects/{objectType}/search\` \u2014 \u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u691C\u7D22
461
+
462
+ #### \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
463
+ - \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u7D50\u679C\u6570\uFF08\u6700\u5927100\uFF09
464
+ - \`after\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u30AB\u30FC\u30BD\u30EB
465
+ - \`properties\` \u2014 \u8FD4\u5374\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u30AB\u30F3\u30DE\u533A\u5207\u308A\u30EA\u30B9\u30C8
466
+ - \`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
467
+
468
+ #### \u691C\u7D22\u30DC\u30C7\u30A3 (POST /crm/v3/objects/{objectType}/search)
469
+ - \`filterGroups\` \u2014 \u30D5\u30A3\u30EB\u30BF\u30B0\u30EB\u30FC\u30D7\u306E\u914D\u5217\uFF08\`filters\`: propertyName, operator, value\uFF09
470
+ - \`sorts\` \u2014 \u30BD\u30FC\u30C8\u6307\u5B9A\u306E\u914D\u5217
471
+ - \`properties\` \u2014 \u8FD4\u5374\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u914D\u5217
472
+ - \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u6700\u5927\u7D50\u679C\u6570\uFF08\u6700\u5927100\uFF09
473
+ - \`after\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u30AA\u30D5\u30BB\u30C3\u30C8`
474
+ },
475
+ tools
476
+ });
477
+
478
+ // src/connectors/create-connector-sdk.ts
479
+ import { readFileSync } from "fs";
480
+ import path from "path";
481
+
482
+ // src/connector-client/env.ts
483
+ function resolveEnvVar(entry, key, connectionId) {
484
+ const envVarName = entry.envVars[key];
485
+ if (!envVarName) {
486
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
487
+ }
488
+ const value = process.env[envVarName];
489
+ if (!value) {
490
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
491
+ }
492
+ return value;
493
+ }
494
+ function resolveEnvVarOptional(entry, key) {
495
+ const envVarName = entry.envVars[key];
496
+ if (!envVarName) return void 0;
497
+ return process.env[envVarName] || void 0;
498
+ }
499
+
500
+ // src/connectors/create-connector-sdk.ts
501
+ function loadConnectionsSync() {
502
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
503
+ try {
504
+ const raw = readFileSync(filePath, "utf-8");
505
+ return JSON.parse(raw);
506
+ } catch {
507
+ return {};
508
+ }
509
+ }
510
+ function createConnectorSdk(plugin, createClient2) {
511
+ return (connectionId) => {
512
+ const connections = loadConnectionsSync();
513
+ const entry = connections[connectionId];
514
+ if (!entry) {
515
+ throw new Error(
516
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
517
+ );
518
+ }
519
+ if (entry.connector.slug !== plugin.slug) {
520
+ throw new Error(
521
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
522
+ );
523
+ }
524
+ const params = {};
525
+ for (const param of Object.values(plugin.parameters)) {
526
+ if (param.required) {
527
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
528
+ } else {
529
+ const val = resolveEnvVarOptional(entry, param.slug);
530
+ if (val !== void 0) params[param.slug] = val;
531
+ }
532
+ }
533
+ return createClient2(params);
534
+ };
535
+ }
536
+
537
+ // src/connectors/entries/hubspot.ts
538
+ var connection = createConnectorSdk(hubspotConnector, createClient);
539
+ export {
540
+ connection
541
+ };
@@ -288,12 +288,13 @@ var kintoneApiTokenConnector = new ConnectorPlugin({
288
288
  releaseFlag: { dev1: true, dev2: false, prod: false },
289
289
  onboarding: kintoneApiTokenOnboarding,
290
290
  systemPrompt: {
291
- en: `### kintone REST API (API Token)
292
- - Call the kintone REST API using the authenticated request tool
293
- - The base URL (e.g., https://example.cybozu.com) is automatically resolved
294
- - Authentication uses the kintone API token (scoped to specific apps)
291
+ en: `### Tools
295
292
 
296
- ### List Apps
293
+ - \`kintone-api-key_request\`: The only way to call the kintone REST API. Use it to list apps, get field definitions, query records, and create/update records. Authentication (API Token) and base URL are configured automatically. API tokens are scoped per app \u2014 combine multiple tokens with commas to access multiple apps.
294
+
295
+ ### kintone REST API Reference
296
+
297
+ #### List Apps
297
298
  - GET apps.json
298
299
 
299
300
  ### Get Field Definitions
@@ -303,20 +304,17 @@ var kintoneApiTokenConnector = new ConnectorPlugin({
303
304
  - GET records.json?app={appId}&query={query}
304
305
  - Query example: records.json?app=1&query=updatedTime > "2024-01-01" order by recordNumber asc limit 100
305
306
 
306
- ### Add Record
307
+ #### Add Record
307
308
  - POST record.json
308
309
  - Body: { "app": 1, "record": { "fieldName": { "value": "value" } } }
309
310
 
310
- ### kintone Query Syntax
311
+ #### kintone Query Syntax
311
312
  - Comparison: fieldName = "value", fieldName > 100
312
313
  - Operators: and, or, not
313
314
  - Sort: order by fieldName asc/desc
314
315
  - Limit: limit 100 offset 0
315
316
  - String: like "partial match"
316
317
 
317
- ### Tips
318
- - API tokens are scoped per app. If you need to access multiple apps, you can combine multiple tokens separated by commas.
319
-
320
318
  ### Business Logic
321
319
 
322
320
  The business logic type for this connector is "typescript". Write handler code using the connector SDK shown below. Do NOT access credentials directly from environment variables.
@@ -337,12 +335,13 @@ await kintone.request("/k/v1/record.json", {
337
335
  body: JSON.stringify({ app: 1, record: { title: { value: "Hello" } } }),
338
336
  });
339
337
  \`\`\``,
340
- ja: `### kintone REST API (API Token)
341
- - \u8A8D\u8A3C\u6E08\u307F\u30EA\u30AF\u30A8\u30B9\u30C8\u30C4\u30FC\u30EB\u3092\u4F7F\u7528\u3057\u3066kintone REST API\u3092\u547C\u3073\u51FA\u3057\u307E\u3059
342
- - \u30D9\u30FC\u30B9URL\uFF08\u4F8B: https://example.cybozu.com\uFF09\u306F\u81EA\u52D5\u7684\u306B\u89E3\u6C7A\u3055\u308C\u307E\u3059
343
- - \u8A8D\u8A3C\u306B\u306Fkintone API\u30C8\u30FC\u30AF\u30F3\uFF08\u7279\u5B9A\u306E\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u305F\u3082\u306E\uFF09\u3092\u4F7F\u7528\u3057\u307E\u3059
338
+ ja: `### \u30C4\u30FC\u30EB
344
339
 
345
- ### \u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97
340
+ - \`kintone-api-key_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API\u30C8\u30FC\u30AF\u30F3\uFF09\u3068\u30D9\u30FC\u30B9URL\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002API\u30C8\u30FC\u30AF\u30F3\u306F\u30A2\u30D7\u30EA\u3054\u3068\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059 \u2014 \u8907\u6570\u306E\u30A2\u30D7\u30EA\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3067\u30C8\u30FC\u30AF\u30F3\u3092\u7D44\u307F\u5408\u308F\u305B\u3066\u304F\u3060\u3055\u3044\u3002
341
+
342
+ ### kintone REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
343
+
344
+ #### \u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97
346
345
  - GET apps.json
347
346
 
348
347
  ### \u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97
@@ -352,20 +351,17 @@ await kintone.request("/k/v1/record.json", {
352
351
  - GET records.json?app={appId}&query={query}
353
352
  - \u30AF\u30A8\u30EA\u4F8B: records.json?app=1&query=updatedTime > "2024-01-01" order by recordNumber asc limit 100
354
353
 
355
- ### \u30EC\u30B3\u30FC\u30C9\u306E\u8FFD\u52A0
354
+ #### \u30EC\u30B3\u30FC\u30C9\u306E\u8FFD\u52A0
356
355
  - POST record.json
357
356
  - Body: { "app": 1, "record": { "fieldName": { "value": "value" } } }
358
357
 
359
- ### kintone \u30AF\u30A8\u30EA\u69CB\u6587
358
+ #### kintone \u30AF\u30A8\u30EA\u69CB\u6587
360
359
  - \u6BD4\u8F03: fieldName = "value", fieldName > 100
361
360
  - \u6F14\u7B97\u5B50: and, or, not
362
361
  - \u30BD\u30FC\u30C8: order by fieldName asc/desc
363
362
  - \u5236\u9650: limit 100 offset 0
364
363
  - \u6587\u5B57\u5217: like "\u90E8\u5206\u4E00\u81F4"
365
364
 
366
- ### \u30D2\u30F3\u30C8
367
- - API\u30C8\u30FC\u30AF\u30F3\u306F\u30A2\u30D7\u30EA\u3054\u3068\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u8907\u6570\u306E\u30A2\u30D7\u30EA\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\u3001\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3067\u8907\u6570\u306E\u30C8\u30FC\u30AF\u30F3\u3092\u7D44\u307F\u5408\u308F\u305B\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002
368
-
369
365
  ### Business Logic
370
366
 
371
367
  \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u4EE5\u4E0B\u306B\u793A\u3059\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u30CF\u30F3\u30C9\u30E9\u30B3\u30FC\u30C9\u3092\u8A18\u8FF0\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u76F4\u63A5\u8A8D\u8A3C\u60C5\u5831\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
@@ -293,9 +293,13 @@ var shopifyOauthConnector = new ConnectorPlugin({
293
293
  ]
294
294
  },
295
295
  systemPrompt: {
296
- en: `### Shopify API (OAuth)
296
+ en: `### Tools
297
297
 
298
- ### Available Endpoints (API version: 2024-10)
298
+ - \`shopify-oauth_request\`: The only way to call the Shopify Admin REST API. Use it to query products, orders, customers, inventory, collections, and more. Authentication is configured automatically via OAuth proxy. Shopify uses cursor-based pagination via the \`page_info\` query parameter (obtained from the Link header in the response).
299
+
300
+ ### Shopify Admin REST API Reference
301
+
302
+ #### Available Endpoints (API version: 2024-10)
299
303
  - GET \`/admin/api/2024-10/shop.json\` \u2014 Get shop info
300
304
  - GET \`/admin/api/2024-10/products.json\` \u2014 List products
301
305
  - GET \`/admin/api/2024-10/products/{id}.json\` \u2014 Get a product
@@ -336,9 +340,13 @@ const shopify = connection("<connectionId>");
336
340
  const res = await shopify.request("/admin/api/2024-10/products.json?limit=10");
337
341
  const data = await res.json();
338
342
  \`\`\``,
339
- ja: `### Shopify API (OAuth)
343
+ ja: `### \u30C4\u30FC\u30EB
344
+
345
+ - \`shopify-oauth_request\`: Shopify Admin REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u5546\u54C1\u3001\u6CE8\u6587\u3001\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306A\u3069\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u30D7\u30ED\u30AD\u30B7\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Shopify\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E Link \u30D8\u30C3\u30C0\u30FC\u304B\u3089\u53D6\u5F97\u3059\u308B \`page_info\` \u30AF\u30A8\u30EA\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
346
+
347
+ ### Shopify Admin REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
340
348
 
341
- ### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 (API\u30D0\u30FC\u30B8\u30E7\u30F3: 2024-10)
349
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 (API\u30D0\u30FC\u30B8\u30E7\u30F3: 2024-10)
342
350
  - GET \`/admin/api/2024-10/shop.json\` \u2014 \u30B7\u30E7\u30C3\u30D7\u60C5\u5831\u3092\u53D6\u5F97
343
351
  - GET \`/admin/api/2024-10/products.json\` \u2014 \u5546\u54C1\u4E00\u89A7\u3092\u53D6\u5F97
344
352
  - GET \`/admin/api/2024-10/products/{id}.json\` \u2014 \u5546\u54C1\u3092\u53D6\u5F97