@squadbase/vite-server 0.1.3-dev.0 → 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.
Files changed (34) hide show
  1. package/dist/cli/index.js +13282 -4299
  2. package/dist/connectors/asana.d.ts +5 -0
  3. package/dist/connectors/asana.js +661 -0
  4. package/dist/connectors/customerio.d.ts +5 -0
  5. package/dist/connectors/customerio.js +633 -0
  6. package/dist/connectors/gmail-oauth.d.ts +5 -0
  7. package/dist/connectors/gmail-oauth.js +639 -0
  8. package/dist/connectors/google-ads.d.ts +5 -0
  9. package/dist/connectors/google-ads.js +784 -0
  10. package/dist/connectors/google-sheets.d.ts +5 -0
  11. package/dist/connectors/google-sheets.js +598 -0
  12. package/dist/connectors/hubspot.js +14 -5
  13. package/dist/connectors/intercom-oauth.d.ts +5 -0
  14. package/dist/connectors/intercom-oauth.js +510 -0
  15. package/dist/connectors/intercom.d.ts +5 -0
  16. package/dist/connectors/intercom.js +627 -0
  17. package/dist/connectors/jira-api-key.d.ts +5 -0
  18. package/dist/connectors/jira-api-key.js +523 -0
  19. package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
  20. package/dist/connectors/linkedin-ads-oauth.js +774 -0
  21. package/dist/connectors/linkedin-ads.d.ts +5 -0
  22. package/dist/connectors/linkedin-ads.js +782 -0
  23. package/dist/connectors/mailchimp-oauth.d.ts +5 -0
  24. package/dist/connectors/mailchimp-oauth.js +539 -0
  25. package/dist/connectors/mailchimp.d.ts +5 -0
  26. package/dist/connectors/mailchimp.js +646 -0
  27. package/dist/connectors/zendesk-oauth.d.ts +5 -0
  28. package/dist/connectors/zendesk-oauth.js +505 -0
  29. package/dist/connectors/zendesk.d.ts +5 -0
  30. package/dist/connectors/zendesk.js +631 -0
  31. package/dist/index.js +13238 -4255
  32. package/dist/main.js +13240 -4257
  33. package/dist/vite-plugin.js +13240 -4257
  34. package/package.json +42 -2
@@ -0,0 +1,631 @@
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/zendesk/parameters.ts
46
+ var parameters = {
47
+ subdomain: new ParameterDefinition({
48
+ slug: "subdomain",
49
+ name: "Zendesk Subdomain",
50
+ description: 'Your Zendesk subdomain (e.g., "mycompany" for mycompany.zendesk.com).',
51
+ envVarBaseKey: "ZENDESK_SUBDOMAIN",
52
+ type: "text",
53
+ secret: false,
54
+ required: true
55
+ }),
56
+ email: new ParameterDefinition({
57
+ slug: "email",
58
+ name: "Email Address",
59
+ description: "The email address of the Zendesk agent used for API token authentication.",
60
+ envVarBaseKey: "ZENDESK_EMAIL",
61
+ type: "text",
62
+ secret: false,
63
+ required: true
64
+ }),
65
+ apiToken: new ParameterDefinition({
66
+ slug: "api-token",
67
+ name: "API Token",
68
+ description: "Your Zendesk API token (found in Admin > Apps and integrations > Zendesk API > Settings).",
69
+ envVarBaseKey: "ZENDESK_API_TOKEN",
70
+ type: "text",
71
+ secret: true,
72
+ required: true
73
+ })
74
+ };
75
+
76
+ // ../connectors/src/connectors/zendesk/sdk/index.ts
77
+ var API_VERSION = "v2";
78
+ function createClient(params) {
79
+ const subdomain = params[parameters.subdomain.slug];
80
+ const email = params[parameters.email.slug];
81
+ const apiToken = params[parameters.apiToken.slug];
82
+ if (!subdomain || !email || !apiToken) {
83
+ throw new Error("zendesk: missing required parameters (subdomain, email, api-token)");
84
+ }
85
+ const baseUrl = `https://${subdomain}.zendesk.com/api/${API_VERSION}`;
86
+ const authToken = Buffer.from(`${email}/token:${apiToken}`).toString("base64");
87
+ function authHeaders(extra) {
88
+ const headers = new Headers(extra);
89
+ headers.set("Authorization", `Basic ${authToken}`);
90
+ headers.set("Content-Type", "application/json");
91
+ return headers;
92
+ }
93
+ async function assertOk(res, label) {
94
+ if (!res.ok) {
95
+ const body = await res.text().catch(() => "(unreadable body)");
96
+ throw new Error(
97
+ `zendesk ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
98
+ );
99
+ }
100
+ }
101
+ return {
102
+ request(path2, init) {
103
+ const resolvedPath = path2.replace(/\{subdomain\}/g, subdomain);
104
+ const url = resolvedPath.startsWith("http") ? resolvedPath : `https://${subdomain}.zendesk.com${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
105
+ const headers = new Headers(init?.headers);
106
+ headers.set("Authorization", `Basic ${authToken}`);
107
+ headers.set("Content-Type", "application/json");
108
+ return fetch(url, { ...init, headers });
109
+ },
110
+ async listTickets(options) {
111
+ const searchParams = new URLSearchParams();
112
+ if (options?.status) searchParams.set("status", options.status);
113
+ if (options?.sort_by) searchParams.set("sort_by", options.sort_by);
114
+ if (options?.sort_order) searchParams.set("sort_order", options.sort_order);
115
+ if (options?.per_page) searchParams.set("page[size]", String(options.per_page));
116
+ if (options?.page_after) searchParams.set("page[after]", options.page_after);
117
+ const qs = searchParams.toString();
118
+ const res = await fetch(
119
+ `${baseUrl}/tickets.json${qs ? `?${qs}` : ""}`,
120
+ { method: "GET", headers: authHeaders() }
121
+ );
122
+ await assertOk(res, "listTickets");
123
+ return await res.json();
124
+ },
125
+ async getTicket(ticketId) {
126
+ const res = await fetch(
127
+ `${baseUrl}/tickets/${encodeURIComponent(String(ticketId))}.json`,
128
+ { method: "GET", headers: authHeaders() }
129
+ );
130
+ await assertOk(res, "getTicket");
131
+ return await res.json();
132
+ },
133
+ async listUsers(options) {
134
+ const searchParams = new URLSearchParams();
135
+ if (options?.role) searchParams.set("role", options.role);
136
+ if (options?.per_page) searchParams.set("page[size]", String(options.per_page));
137
+ if (options?.page_after) searchParams.set("page[after]", options.page_after);
138
+ const qs = searchParams.toString();
139
+ const res = await fetch(
140
+ `${baseUrl}/users.json${qs ? `?${qs}` : ""}`,
141
+ { method: "GET", headers: authHeaders() }
142
+ );
143
+ await assertOk(res, "listUsers");
144
+ return await res.json();
145
+ },
146
+ async getUser(userId) {
147
+ const res = await fetch(
148
+ `${baseUrl}/users/${encodeURIComponent(String(userId))}.json`,
149
+ { method: "GET", headers: authHeaders() }
150
+ );
151
+ await assertOk(res, "getUser");
152
+ return await res.json();
153
+ },
154
+ async search(query, options) {
155
+ const searchParams = new URLSearchParams();
156
+ searchParams.set("query", query);
157
+ if (options?.sort_by) searchParams.set("sort_by", options.sort_by);
158
+ if (options?.sort_order) searchParams.set("sort_order", options.sort_order);
159
+ if (options?.per_page) searchParams.set("per_page", String(options.per_page));
160
+ if (options?.page) searchParams.set("page", String(options.page));
161
+ const qs = searchParams.toString();
162
+ const res = await fetch(
163
+ `${baseUrl}/search.json?${qs}`,
164
+ { method: "GET", headers: authHeaders() }
165
+ );
166
+ await assertOk(res, "search");
167
+ return await res.json();
168
+ },
169
+ async listOrganizations(options) {
170
+ const searchParams = new URLSearchParams();
171
+ if (options?.per_page) searchParams.set("page[size]", String(options.per_page));
172
+ if (options?.page_after) searchParams.set("page[after]", options.page_after);
173
+ const qs = searchParams.toString();
174
+ const res = await fetch(
175
+ `${baseUrl}/organizations.json${qs ? `?${qs}` : ""}`,
176
+ { method: "GET", headers: authHeaders() }
177
+ );
178
+ await assertOk(res, "listOrganizations");
179
+ return await res.json();
180
+ }
181
+ };
182
+ }
183
+
184
+ // ../connectors/src/connector-onboarding.ts
185
+ var ConnectorOnboarding = class {
186
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
187
+ connectionSetupInstructions;
188
+ /** Phase 2: Data overview instructions */
189
+ dataOverviewInstructions;
190
+ constructor(config) {
191
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
192
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
193
+ }
194
+ getConnectionSetupPrompt(language) {
195
+ return this.connectionSetupInstructions?.[language] ?? null;
196
+ }
197
+ getDataOverviewInstructions(language) {
198
+ return this.dataOverviewInstructions[language];
199
+ }
200
+ };
201
+
202
+ // ../connectors/src/connector-tool.ts
203
+ var ConnectorTool = class {
204
+ name;
205
+ description;
206
+ inputSchema;
207
+ outputSchema;
208
+ _execute;
209
+ constructor(config) {
210
+ this.name = config.name;
211
+ this.description = config.description;
212
+ this.inputSchema = config.inputSchema;
213
+ this.outputSchema = config.outputSchema;
214
+ this._execute = config.execute;
215
+ }
216
+ createTool(connections, config) {
217
+ return {
218
+ description: this.description,
219
+ inputSchema: this.inputSchema,
220
+ outputSchema: this.outputSchema,
221
+ execute: (input) => this._execute(input, connections, config)
222
+ };
223
+ }
224
+ };
225
+
226
+ // ../connectors/src/connector-plugin.ts
227
+ var ConnectorPlugin = class _ConnectorPlugin {
228
+ slug;
229
+ authType;
230
+ name;
231
+ description;
232
+ iconUrl;
233
+ parameters;
234
+ releaseFlag;
235
+ proxyPolicy;
236
+ experimentalAttributes;
237
+ onboarding;
238
+ systemPrompt;
239
+ tools;
240
+ query;
241
+ checkConnection;
242
+ constructor(config) {
243
+ this.slug = config.slug;
244
+ this.authType = config.authType;
245
+ this.name = config.name;
246
+ this.description = config.description;
247
+ this.iconUrl = config.iconUrl;
248
+ this.parameters = config.parameters;
249
+ this.releaseFlag = config.releaseFlag;
250
+ this.proxyPolicy = config.proxyPolicy;
251
+ this.experimentalAttributes = config.experimentalAttributes;
252
+ this.onboarding = config.onboarding;
253
+ this.systemPrompt = config.systemPrompt;
254
+ this.tools = config.tools;
255
+ this.query = config.query;
256
+ this.checkConnection = config.checkConnection;
257
+ }
258
+ get connectorKey() {
259
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
260
+ }
261
+ /**
262
+ * Create tools for connections that belong to this connector.
263
+ * Filters connections by connectorKey internally.
264
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
265
+ */
266
+ createTools(connections, config) {
267
+ const myConnections = connections.filter(
268
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
269
+ );
270
+ const result = {};
271
+ for (const t of Object.values(this.tools)) {
272
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
273
+ myConnections,
274
+ config
275
+ );
276
+ }
277
+ return result;
278
+ }
279
+ static deriveKey(slug, authType) {
280
+ return authType ? `${slug}-${authType}` : slug;
281
+ }
282
+ };
283
+
284
+ // ../connectors/src/connectors/zendesk/setup.ts
285
+ var zendeskOnboarding = new ConnectorOnboarding({
286
+ dataOverviewInstructions: {
287
+ en: `1. Call zendesk_request with GET /api/v2/ticket_fields.json to list available ticket fields
288
+ 2. Call zendesk_request with GET /api/v2/tickets.json?page[size]=5 to explore ticket structure
289
+ 3. Call zendesk_request with GET /api/v2/users.json?page[size]=5 to explore user structure
290
+ 4. Call zendesk_request with GET /api/v2/organizations.json?page[size]=5 to explore organization structure`,
291
+ ja: `1. zendesk_request \u3067 GET /api/v2/ticket_fields.json \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C1\u30B1\u30C3\u30C8\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D
292
+ 2. zendesk_request \u3067 GET /api/v2/tickets.json?page[size]=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30B1\u30C3\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
293
+ 3. zendesk_request \u3067 GET /api/v2/users.json?page[size]=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u306E\u69CB\u9020\u3092\u78BA\u8A8D
294
+ 4. zendesk_request \u3067 GET /api/v2/organizations.json?page[size]=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u7D44\u7E54\u306E\u69CB\u9020\u3092\u78BA\u8A8D`
295
+ }
296
+ });
297
+
298
+ // ../connectors/src/connectors/zendesk/tools/request.ts
299
+ import { z } from "zod";
300
+ var REQUEST_TIMEOUT_MS = 6e4;
301
+ var inputSchema = z.object({
302
+ toolUseIntent: z.string().optional().describe(
303
+ "Brief description of what you intend to accomplish with this tool call"
304
+ ),
305
+ connectionId: z.string().describe("ID of the Zendesk connection to use"),
306
+ method: z.enum(["GET", "POST", "PUT", "DELETE"]).describe(
307
+ "HTTP method. GET for reading, POST for creating/searching, PUT for updating, DELETE for removing."
308
+ ),
309
+ path: z.string().describe(
310
+ "API path appended to https://{subdomain}.zendesk.com (e.g., '/api/v2/tickets.json', '/api/v2/search.json?query=status:open')"
311
+ ),
312
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT requests")
313
+ });
314
+ var outputSchema = z.discriminatedUnion("success", [
315
+ z.object({
316
+ success: z.literal(true),
317
+ status: z.number(),
318
+ data: z.record(z.string(), z.unknown())
319
+ }),
320
+ z.object({
321
+ success: z.literal(false),
322
+ error: z.string()
323
+ })
324
+ ]);
325
+ var requestTool = new ConnectorTool({
326
+ name: "request",
327
+ description: `Send authenticated requests to the Zendesk Support API.
328
+ Authentication is handled automatically using email/token Basic auth.
329
+ Use this tool for all Zendesk API interactions: querying tickets, users, organizations, groups, and searching.
330
+ Zendesk uses cursor-based pagination with page[size] and page[after] parameters. All endpoints return .json suffix.`,
331
+ inputSchema,
332
+ outputSchema,
333
+ async execute({ connectionId, method, path: path2, body }, connections) {
334
+ const connection2 = connections.find((c) => c.id === connectionId);
335
+ if (!connection2) {
336
+ return {
337
+ success: false,
338
+ error: `Connection ${connectionId} not found`
339
+ };
340
+ }
341
+ console.log(
342
+ `[connector-request] zendesk/${connection2.name}: ${method} ${path2}`
343
+ );
344
+ try {
345
+ const subdomain = parameters.subdomain.getValue(connection2);
346
+ const email = parameters.email.getValue(connection2);
347
+ const apiToken = parameters.apiToken.getValue(connection2);
348
+ const authToken = Buffer.from(`${email}/token:${apiToken}`).toString(
349
+ "base64"
350
+ );
351
+ const url = `https://${subdomain}.zendesk.com${path2.startsWith("/") ? "" : "/"}${path2}`;
352
+ const controller = new AbortController();
353
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
354
+ try {
355
+ const response = await fetch(url, {
356
+ method,
357
+ headers: {
358
+ Authorization: `Basic ${authToken}`,
359
+ "Content-Type": "application/json"
360
+ },
361
+ body: body ? JSON.stringify(body) : void 0,
362
+ signal: controller.signal
363
+ });
364
+ const data = await response.json();
365
+ if (!response.ok) {
366
+ const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.description === "string" ? data.description : `HTTP ${response.status} ${response.statusText}`;
367
+ return { success: false, error: errorMessage };
368
+ }
369
+ return { success: true, status: response.status, data };
370
+ } finally {
371
+ clearTimeout(timeout);
372
+ }
373
+ } catch (err) {
374
+ const msg = err instanceof Error ? err.message : String(err);
375
+ return { success: false, error: msg };
376
+ }
377
+ }
378
+ });
379
+
380
+ // ../connectors/src/connectors/zendesk/index.ts
381
+ var tools = { request: requestTool };
382
+ var zendeskConnector = new ConnectorPlugin({
383
+ slug: "zendesk",
384
+ authType: null,
385
+ name: "Zendesk",
386
+ description: "Connect to Zendesk Support for tickets, users, organizations, and customer service data using an API token.",
387
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4vJHzNjXZ5gPabCCjTMz7v/2afba49a2b7e901f1e6c3cfa16d76e82/zendesk.svg",
388
+ parameters,
389
+ releaseFlag: { dev1: true, dev2: false, prod: false },
390
+ onboarding: zendeskOnboarding,
391
+ systemPrompt: {
392
+ en: `### Tools
393
+
394
+ - \`zendesk_request\`: The only way to call the Zendesk Support API. Use it to query tickets, users, organizations, groups, and perform searches. Authentication (Basic auth with email/token) is configured automatically. Zendesk uses cursor-based pagination with \`page[size]\` and \`page[after]\` parameters. All endpoint paths end with \`.json\`.
395
+
396
+ ### Business Logic
397
+
398
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
399
+
400
+ SDK methods (client created via \`connection(connectionId)\`):
401
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
402
+ - \`client.listTickets(options?)\` \u2014 list tickets with pagination (status, sort_by, sort_order, per_page, page_after)
403
+ - \`client.getTicket(ticketId)\` \u2014 fetch a single ticket
404
+ - \`client.listUsers(options?)\` \u2014 list users with pagination (role, per_page, page_after)
405
+ - \`client.getUser(userId)\` \u2014 fetch a single user
406
+ - \`client.search(query, options?)\` \u2014 search using Zendesk query syntax
407
+ - \`client.listOrganizations(options?)\` \u2014 list organizations with pagination
408
+
409
+ \`\`\`ts
410
+ import type { Context } from "hono";
411
+ import { connection } from "@squadbase/vite-server/connectors/zendesk";
412
+
413
+ const zendesk = connection("<connectionId>");
414
+
415
+ export default async function handler(c: Context) {
416
+ const { tickets, meta } = await zendesk.listTickets({
417
+ status: "open",
418
+ sort_by: "updated_at",
419
+ sort_order: "desc",
420
+ per_page: 100,
421
+ });
422
+
423
+ return c.json({ tickets, hasMore: meta?.has_more });
424
+ }
425
+ \`\`\`
426
+
427
+ ### Zendesk API Reference
428
+
429
+ - Base URL: \`https://{subdomain}.zendesk.com\`
430
+ - Authentication: Basic auth with \`{email}/token:{api_token}\` (handled automatically)
431
+ - Pagination: Cursor-based with \`page[size]\` (max 100) and \`page[after]\` parameters
432
+
433
+ #### Tickets
434
+ - GET \`/api/v2/tickets.json\` \u2014 List tickets
435
+ - GET \`/api/v2/tickets/{id}.json\` \u2014 Get a ticket
436
+ - POST \`/api/v2/tickets.json\` \u2014 Create a ticket (body: \`{ "ticket": { "subject": "...", "comment": { "body": "..." } } }\`)
437
+ - PUT \`/api/v2/tickets/{id}.json\` \u2014 Update a ticket
438
+ - DELETE \`/api/v2/tickets/{id}.json\` \u2014 Delete a ticket
439
+ - GET \`/api/v2/tickets/{id}/comments.json\` \u2014 List ticket comments
440
+
441
+ #### Users
442
+ - GET \`/api/v2/users.json\` \u2014 List users
443
+ - GET \`/api/v2/users/{id}.json\` \u2014 Get a user
444
+ - POST \`/api/v2/users.json\` \u2014 Create a user
445
+ - GET \`/api/v2/users/{id}/identities.json\` \u2014 List user identities
446
+
447
+ #### Organizations
448
+ - GET \`/api/v2/organizations.json\` \u2014 List organizations
449
+ - GET \`/api/v2/organizations/{id}.json\` \u2014 Get an organization
450
+ - GET \`/api/v2/organizations/{id}/tickets.json\` \u2014 List organization tickets
451
+
452
+ #### Groups
453
+ - GET \`/api/v2/groups.json\` \u2014 List groups
454
+ - GET \`/api/v2/groups/{id}.json\` \u2014 Get a group
455
+
456
+ #### Search
457
+ - GET \`/api/v2/search.json?query={query}\` \u2014 Search tickets, users, organizations
458
+ - Query params: \`sort_by\` (updated_at, created_at, priority, status), \`sort_order\` (asc, desc)
459
+
460
+ #### Ticket Fields & Forms
461
+ - GET \`/api/v2/ticket_fields.json\` \u2014 List ticket fields
462
+ - GET \`/api/v2/ticket_forms.json\` \u2014 List ticket forms
463
+
464
+ #### Views
465
+ - GET \`/api/v2/views.json\` \u2014 List views
466
+ - GET \`/api/v2/views/{id}/tickets.json\` \u2014 List tickets in a view
467
+
468
+ #### Tags
469
+ - GET \`/api/v2/tags.json\` \u2014 List tags
470
+
471
+ #### Common Search Queries
472
+ - \`type:ticket status:open\` \u2014 Open tickets
473
+ - \`type:ticket priority:high\` \u2014 High priority tickets
474
+ - \`type:ticket assignee:{name}\` \u2014 Tickets assigned to a user
475
+ - \`type:ticket created>{date}\` \u2014 Tickets created after a date
476
+ - \`type:user role:agent\` \u2014 Agent users
477
+ - \`type:organization {name}\` \u2014 Organizations matching a name`,
478
+ ja: `### \u30C4\u30FC\u30EB
479
+
480
+ - \`zendesk_request\`: Zendesk Support API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C1\u30B1\u30C3\u30C8\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u7D44\u7E54\u3001\u30B0\u30EB\u30FC\u30D7\u306E\u30AF\u30A8\u30EA\u3084\u691C\u7D22\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08\u30E1\u30FC\u30EB/\u30C8\u30FC\u30AF\u30F3\u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Zendesk\u306F \`page[size]\` \u3068 \`page[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\u5168\u3066\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u30D1\u30B9\u306F \`.json\` \u3067\u7D42\u308F\u308A\u307E\u3059\u3002
481
+
482
+ ### Business Logic
483
+
484
+ \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
485
+
486
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
487
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
488
+ - \`client.listTickets(options?)\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u30C1\u30B1\u30C3\u30C8\u3092\u4E00\u89A7\u53D6\u5F97\uFF08status, sort_by, sort_order, per_page, page_after\uFF09
489
+ - \`client.getTicket(ticketId)\` \u2014 \u5358\u4E00\u30C1\u30B1\u30C3\u30C8\u3092\u53D6\u5F97
490
+ - \`client.listUsers(options?)\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u30E6\u30FC\u30B6\u30FC\u3092\u4E00\u89A7\u53D6\u5F97\uFF08role, per_page, page_after\uFF09
491
+ - \`client.getUser(userId)\` \u2014 \u5358\u4E00\u30E6\u30FC\u30B6\u30FC\u3092\u53D6\u5F97
492
+ - \`client.search(query, options?)\` \u2014 Zendesk\u691C\u7D22\u69CB\u6587\u3067\u691C\u7D22
493
+ - \`client.listOrganizations(options?)\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u7D44\u7E54\u3092\u4E00\u89A7\u53D6\u5F97
494
+
495
+ \`\`\`ts
496
+ import type { Context } from "hono";
497
+ import { connection } from "@squadbase/vite-server/connectors/zendesk";
498
+
499
+ const zendesk = connection("<connectionId>");
500
+
501
+ export default async function handler(c: Context) {
502
+ const { tickets, meta } = await zendesk.listTickets({
503
+ status: "open",
504
+ sort_by: "updated_at",
505
+ sort_order: "desc",
506
+ per_page: 100,
507
+ });
508
+
509
+ return c.json({ tickets, hasMore: meta?.has_more });
510
+ }
511
+ \`\`\`
512
+
513
+ ### Zendesk API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
514
+
515
+ - \u30D9\u30FC\u30B9URL: \`https://{subdomain}.zendesk.com\`
516
+ - \u8A8D\u8A3C: \`{email}/token:{api_token}\` \u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
517
+ - \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3: \`page[size]\`\uFF08\u6700\u5927100\uFF09\u3068 \`page[after]\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9
518
+
519
+ #### \u30C1\u30B1\u30C3\u30C8
520
+ - GET \`/api/v2/tickets.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
521
+ - GET \`/api/v2/tickets/{id}.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u3092\u53D6\u5F97
522
+ - POST \`/api/v2/tickets.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u3092\u4F5C\u6210\uFF08body: \`{ "ticket": { "subject": "...", "comment": { "body": "..." } } }\`\uFF09
523
+ - PUT \`/api/v2/tickets/{id}.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u3092\u66F4\u65B0
524
+ - DELETE \`/api/v2/tickets/{id}.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u3092\u524A\u9664
525
+ - GET \`/api/v2/tickets/{id}/comments.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u30B3\u30E1\u30F3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
526
+
527
+ #### \u30E6\u30FC\u30B6\u30FC
528
+ - GET \`/api/v2/users.json\` \u2014 \u30E6\u30FC\u30B6\u30FC\u4E00\u89A7\u3092\u53D6\u5F97
529
+ - GET \`/api/v2/users/{id}.json\` \u2014 \u30E6\u30FC\u30B6\u30FC\u3092\u53D6\u5F97
530
+ - POST \`/api/v2/users.json\` \u2014 \u30E6\u30FC\u30B6\u30FC\u3092\u4F5C\u6210
531
+ - GET \`/api/v2/users/{id}/identities.json\` \u2014 \u30E6\u30FC\u30B6\u30FCID\u3092\u4E00\u89A7\u53D6\u5F97
532
+
533
+ #### \u7D44\u7E54
534
+ - GET \`/api/v2/organizations.json\` \u2014 \u7D44\u7E54\u4E00\u89A7\u3092\u53D6\u5F97
535
+ - GET \`/api/v2/organizations/{id}.json\` \u2014 \u7D44\u7E54\u3092\u53D6\u5F97
536
+ - GET \`/api/v2/organizations/{id}/tickets.json\` \u2014 \u7D44\u7E54\u306E\u30C1\u30B1\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
537
+
538
+ #### \u30B0\u30EB\u30FC\u30D7
539
+ - GET \`/api/v2/groups.json\` \u2014 \u30B0\u30EB\u30FC\u30D7\u4E00\u89A7\u3092\u53D6\u5F97
540
+ - GET \`/api/v2/groups/{id}.json\` \u2014 \u30B0\u30EB\u30FC\u30D7\u3092\u53D6\u5F97
541
+
542
+ #### \u691C\u7D22
543
+ - GET \`/api/v2/search.json?query={query}\` \u2014 \u30C1\u30B1\u30C3\u30C8\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u7D44\u7E54\u3092\u691C\u7D22
544
+ - \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF: \`sort_by\`\uFF08updated_at, created_at, priority, status\uFF09\u3001\`sort_order\`\uFF08asc, desc\uFF09
545
+
546
+ #### \u30C1\u30B1\u30C3\u30C8\u30D5\u30A3\u30FC\u30EB\u30C9\u30FB\u30D5\u30A9\u30FC\u30E0
547
+ - GET \`/api/v2/ticket_fields.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u30D5\u30A3\u30FC\u30EB\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
548
+ - GET \`/api/v2/ticket_forms.json\` \u2014 \u30C1\u30B1\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4E00\u89A7\u3092\u53D6\u5F97
549
+
550
+ #### \u30D3\u30E5\u30FC
551
+ - GET \`/api/v2/views.json\` \u2014 \u30D3\u30E5\u30FC\u4E00\u89A7\u3092\u53D6\u5F97
552
+ - GET \`/api/v2/views/{id}/tickets.json\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u30C1\u30B1\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
553
+
554
+ #### \u30BF\u30B0
555
+ - GET \`/api/v2/tags.json\` \u2014 \u30BF\u30B0\u4E00\u89A7\u3092\u53D6\u5F97
556
+
557
+ #### \u3088\u304F\u4F7F\u3046\u691C\u7D22\u30AF\u30A8\u30EA
558
+ - \`type:ticket status:open\` \u2014 \u672A\u89E3\u6C7A\u30C1\u30B1\u30C3\u30C8
559
+ - \`type:ticket priority:high\` \u2014 \u9AD8\u512A\u5148\u5EA6\u30C1\u30B1\u30C3\u30C8
560
+ - \`type:ticket assignee:{name}\` \u2014 \u7279\u5B9A\u30E6\u30FC\u30B6\u30FC\u306B\u5272\u308A\u5F53\u3066\u3089\u308C\u305F\u30C1\u30B1\u30C3\u30C8
561
+ - \`type:ticket created>{date}\` \u2014 \u7279\u5B9A\u65E5\u4EE5\u964D\u306B\u4F5C\u6210\u3055\u308C\u305F\u30C1\u30B1\u30C3\u30C8
562
+ - \`type:user role:agent\` \u2014 \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30E6\u30FC\u30B6\u30FC
563
+ - \`type:organization {name}\` \u2014 \u540D\u524D\u304C\u4E00\u81F4\u3059\u308B\u7D44\u7E54`
564
+ },
565
+ tools
566
+ });
567
+
568
+ // src/connectors/create-connector-sdk.ts
569
+ import { readFileSync } from "fs";
570
+ import path from "path";
571
+
572
+ // src/connector-client/env.ts
573
+ function resolveEnvVar(entry, key, connectionId) {
574
+ const envVarName = entry.envVars[key];
575
+ if (!envVarName) {
576
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
577
+ }
578
+ const value = process.env[envVarName];
579
+ if (!value) {
580
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
581
+ }
582
+ return value;
583
+ }
584
+ function resolveEnvVarOptional(entry, key) {
585
+ const envVarName = entry.envVars[key];
586
+ if (!envVarName) return void 0;
587
+ return process.env[envVarName] || void 0;
588
+ }
589
+
590
+ // src/connectors/create-connector-sdk.ts
591
+ function loadConnectionsSync() {
592
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
593
+ try {
594
+ const raw = readFileSync(filePath, "utf-8");
595
+ return JSON.parse(raw);
596
+ } catch {
597
+ return {};
598
+ }
599
+ }
600
+ function createConnectorSdk(plugin, createClient2) {
601
+ return (connectionId) => {
602
+ const connections = loadConnectionsSync();
603
+ const entry = connections[connectionId];
604
+ if (!entry) {
605
+ throw new Error(
606
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
607
+ );
608
+ }
609
+ if (entry.connector.slug !== plugin.slug) {
610
+ throw new Error(
611
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
612
+ );
613
+ }
614
+ const params = {};
615
+ for (const param of Object.values(plugin.parameters)) {
616
+ if (param.required) {
617
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
618
+ } else {
619
+ const val = resolveEnvVarOptional(entry, param.slug);
620
+ if (val !== void 0) params[param.slug] = val;
621
+ }
622
+ }
623
+ return createClient2(params);
624
+ };
625
+ }
626
+
627
+ // src/connectors/entries/zendesk.ts
628
+ var connection = createConnectorSdk(zendeskConnector, createClient);
629
+ export {
630
+ connection
631
+ };