@squadbase/vite-server 0.1.3-dev.9 → 0.1.4-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.
Files changed (63) hide show
  1. package/dist/cli/index.js +14539 -29447
  2. package/dist/connectors/airtable-oauth.js +43 -6
  3. package/dist/connectors/airtable.js +43 -6
  4. package/dist/connectors/amplitude.js +43 -6
  5. package/dist/connectors/anthropic.js +43 -6
  6. package/dist/connectors/asana.js +43 -6
  7. package/dist/connectors/attio.js +522 -118
  8. package/dist/connectors/{google-ads-oauth.d.ts → backlog-api-key.d.ts} +1 -1
  9. package/dist/connectors/backlog-api-key.js +629 -0
  10. package/dist/connectors/customerio.js +43 -6
  11. package/dist/connectors/dbt.js +43 -6
  12. package/dist/connectors/{google-sheets-oauth.d.ts → gamma.d.ts} +1 -1
  13. package/dist/connectors/gamma.js +866 -0
  14. package/dist/connectors/gemini.js +43 -6
  15. package/dist/connectors/gmail-oauth.js +65 -8
  16. package/dist/connectors/gmail.js +104 -44
  17. package/dist/connectors/google-ads.d.ts +1 -1
  18. package/dist/connectors/google-ads.js +410 -332
  19. package/dist/connectors/google-analytics-oauth.js +61 -8
  20. package/dist/connectors/google-analytics.js +107 -292
  21. package/dist/connectors/google-calendar-oauth.js +61 -8
  22. package/dist/connectors/google-calendar.js +111 -58
  23. package/dist/connectors/{linkedin-ads-oauth.d.ts → google-docs.d.ts} +1 -1
  24. package/dist/connectors/google-docs.js +631 -0
  25. package/dist/connectors/google-drive.d.ts +5 -0
  26. package/dist/connectors/google-drive.js +875 -0
  27. package/dist/connectors/google-sheets.d.ts +1 -1
  28. package/dist/connectors/google-sheets.js +267 -285
  29. package/dist/connectors/google-slides.d.ts +5 -0
  30. package/dist/connectors/google-slides.js +663 -0
  31. package/dist/connectors/grafana.js +43 -6
  32. package/dist/connectors/hubspot-oauth.js +43 -6
  33. package/dist/connectors/hubspot.js +43 -6
  34. package/dist/connectors/intercom-oauth.js +43 -6
  35. package/dist/connectors/intercom.js +43 -6
  36. package/dist/connectors/jira-api-key.js +43 -6
  37. package/dist/connectors/kintone-api-token.js +256 -82
  38. package/dist/connectors/kintone.js +43 -6
  39. package/dist/connectors/linkedin-ads.js +188 -168
  40. package/dist/connectors/mailchimp-oauth.js +43 -6
  41. package/dist/connectors/mailchimp.js +43 -6
  42. package/dist/connectors/mixpanel.d.ts +5 -0
  43. package/dist/connectors/mixpanel.js +779 -0
  44. package/dist/connectors/notion-oauth.js +43 -6
  45. package/dist/connectors/notion.js +43 -6
  46. package/dist/connectors/openai.js +43 -6
  47. package/dist/connectors/sentry.d.ts +5 -0
  48. package/dist/connectors/sentry.js +761 -0
  49. package/dist/connectors/shopify-oauth.js +43 -6
  50. package/dist/connectors/shopify.js +43 -6
  51. package/dist/connectors/stripe-api-key.js +46 -7
  52. package/dist/connectors/stripe-oauth.js +43 -6
  53. package/dist/connectors/wix-store.js +43 -6
  54. package/dist/connectors/zendesk-oauth.js +43 -6
  55. package/dist/connectors/zendesk.js +43 -6
  56. package/dist/index.d.ts +1 -1
  57. package/dist/index.js +4574 -3863
  58. package/dist/main.js +4572 -3862
  59. package/dist/vite-plugin.js +4572 -3862
  60. package/package.json +30 -12
  61. package/dist/connectors/google-ads-oauth.js +0 -890
  62. package/dist/connectors/google-sheets-oauth.js +0 -718
  63. package/dist/connectors/linkedin-ads-oauth.js +0 -848
@@ -1,5 +1,5 @@
1
1
  import * as _squadbase_connectors_sdk from '@squadbase/connectors/sdk';
2
2
 
3
- declare const connection: (connectionId: string) => _squadbase_connectors_sdk.GoogleAdsConnectorSdk;
3
+ declare const connection: (connectionId: string) => _squadbase_connectors_sdk.BacklogConnectorSdk;
4
4
 
5
5
  export { connection };
@@ -0,0 +1,629 @@
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/backlog/parameters.ts
46
+ var parameters = {
47
+ spaceUrl: new ParameterDefinition({
48
+ slug: "space-url",
49
+ name: "Backlog Space URL",
50
+ description: "Your Backlog space URL \u2014 just the base address, without any trailing path. For example: https://your-space.backlog.com or https://your-space.backlog.jp",
51
+ envVarBaseKey: "BACKLOG_SPACE_URL",
52
+ type: "text",
53
+ secret: false,
54
+ required: true
55
+ }),
56
+ apiKey: new ParameterDefinition({
57
+ slug: "api-key",
58
+ name: "API Key",
59
+ description: "Your Backlog API key. You can generate one at: Your Space > Personal Settings > API (https://your-space.backlog.com/EditApiSettings.action).",
60
+ envVarBaseKey: "BACKLOG_API_KEY",
61
+ type: "text",
62
+ secret: true,
63
+ required: true
64
+ })
65
+ };
66
+
67
+ // ../connectors/src/connectors/backlog/sdk/index.ts
68
+ function createClient(params) {
69
+ const spaceUrl = params[parameters.spaceUrl.slug];
70
+ const apiKey = params[parameters.apiKey.slug];
71
+ if (!spaceUrl || !apiKey) {
72
+ const required = [
73
+ parameters.spaceUrl.slug,
74
+ parameters.apiKey.slug
75
+ ];
76
+ const missing = required.filter((s) => !params[s]);
77
+ throw new Error(
78
+ `backlog: missing required parameters: ${missing.join(", ")}`
79
+ );
80
+ }
81
+ return {
82
+ request(path2, init) {
83
+ const separator = path2.includes("?") ? "&" : "?";
84
+ const url = `${spaceUrl.replace(/\/+$/, "")}${path2}${separator}apiKey=${apiKey}`;
85
+ const headers = new Headers(init?.headers);
86
+ headers.set("Accept", "application/json");
87
+ if (init?.body) {
88
+ headers.set("Content-Type", "application/json");
89
+ }
90
+ return fetch(url, { ...init, headers });
91
+ }
92
+ };
93
+ }
94
+
95
+ // ../connectors/src/connector-onboarding.ts
96
+ var ConnectorOnboarding = class {
97
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
98
+ connectionSetupInstructions;
99
+ /** Phase 2: Data overview instructions */
100
+ dataOverviewInstructions;
101
+ constructor(config) {
102
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
103
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
104
+ }
105
+ getConnectionSetupPrompt(language) {
106
+ return this.connectionSetupInstructions?.[language] ?? null;
107
+ }
108
+ getDataOverviewInstructions(language) {
109
+ return this.dataOverviewInstructions[language];
110
+ }
111
+ };
112
+
113
+ // ../connectors/src/connector-tool.ts
114
+ var ConnectorTool = class {
115
+ name;
116
+ description;
117
+ inputSchema;
118
+ outputSchema;
119
+ _execute;
120
+ constructor(config) {
121
+ this.name = config.name;
122
+ this.description = config.description;
123
+ this.inputSchema = config.inputSchema;
124
+ this.outputSchema = config.outputSchema;
125
+ this._execute = config.execute;
126
+ }
127
+ createTool(connections, config) {
128
+ return {
129
+ description: this.description,
130
+ inputSchema: this.inputSchema,
131
+ outputSchema: this.outputSchema,
132
+ execute: (input) => this._execute(input, connections, config)
133
+ };
134
+ }
135
+ };
136
+
137
+ // ../connectors/src/connector-plugin.ts
138
+ var ConnectorPlugin = class _ConnectorPlugin {
139
+ slug;
140
+ authType;
141
+ name;
142
+ description;
143
+ iconUrl;
144
+ parameters;
145
+ releaseFlag;
146
+ proxyPolicy;
147
+ experimentalAttributes;
148
+ onboarding;
149
+ systemPrompt;
150
+ tools;
151
+ query;
152
+ checkConnection;
153
+ constructor(config) {
154
+ this.slug = config.slug;
155
+ this.authType = config.authType;
156
+ this.name = config.name;
157
+ this.description = config.description;
158
+ this.iconUrl = config.iconUrl;
159
+ this.parameters = config.parameters;
160
+ this.releaseFlag = config.releaseFlag;
161
+ this.proxyPolicy = config.proxyPolicy;
162
+ this.experimentalAttributes = config.experimentalAttributes;
163
+ this.onboarding = config.onboarding;
164
+ this.systemPrompt = config.systemPrompt;
165
+ this.tools = config.tools;
166
+ this.query = config.query;
167
+ this.checkConnection = config.checkConnection;
168
+ }
169
+ get connectorKey() {
170
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
171
+ }
172
+ /**
173
+ * Create tools for connections that belong to this connector.
174
+ * Filters connections by connectorKey internally.
175
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
176
+ */
177
+ createTools(connections, config, opts) {
178
+ const myConnections = connections.filter(
179
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
180
+ );
181
+ const result = {};
182
+ for (const t of Object.values(this.tools)) {
183
+ const tool = t.createTool(myConnections, config);
184
+ const originalToModelOutput = tool.toModelOutput;
185
+ result[`${this.connectorKey}_${t.name}`] = {
186
+ ...tool,
187
+ toModelOutput: async (options) => {
188
+ if (!originalToModelOutput) {
189
+ return opts.truncateOutput(options.output);
190
+ }
191
+ const modelOutput = await originalToModelOutput(options);
192
+ if (modelOutput.type === "text" || modelOutput.type === "json") {
193
+ return opts.truncateOutput(modelOutput.value);
194
+ }
195
+ return modelOutput;
196
+ }
197
+ };
198
+ }
199
+ return result;
200
+ }
201
+ static deriveKey(slug, authType) {
202
+ if (authType) return `${slug}-${authType}`;
203
+ const LEGACY_NULL_AUTH_TYPE_MAP = {
204
+ // user-password
205
+ "postgresql": "user-password",
206
+ "mysql": "user-password",
207
+ "clickhouse": "user-password",
208
+ "kintone": "user-password",
209
+ "squadbase-db": "user-password",
210
+ // service-account
211
+ "snowflake": "service-account",
212
+ "bigquery": "service-account",
213
+ "google-analytics": "service-account",
214
+ "google-calendar": "service-account",
215
+ "aws-athena": "service-account",
216
+ "redshift": "service-account",
217
+ // api-key
218
+ "databricks": "api-key",
219
+ "dbt": "api-key",
220
+ "airtable": "api-key",
221
+ "openai": "api-key",
222
+ "gemini": "api-key",
223
+ "anthropic": "api-key",
224
+ "wix-store": "api-key"
225
+ };
226
+ const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
227
+ if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
228
+ return slug;
229
+ }
230
+ };
231
+
232
+ // ../connectors/src/auth-types.ts
233
+ var AUTH_TYPES = {
234
+ OAUTH: "oauth",
235
+ API_KEY: "api-key",
236
+ JWT: "jwt",
237
+ SERVICE_ACCOUNT: "service-account",
238
+ PAT: "pat",
239
+ USER_PASSWORD: "user-password"
240
+ };
241
+
242
+ // ../connectors/src/connectors/backlog/setup.ts
243
+ var backlogOnboarding = new ConnectorOnboarding({
244
+ dataOverviewInstructions: {
245
+ en: `1. Call backlog-api-key_request with GET space to verify the connection and get space information
246
+ 2. Call backlog-api-key_request with GET projects to list all accessible projects
247
+ 3. For key projects, call backlog-api-key_request with GET issues?projectId[]={projectId}&count=5&order=desc to retrieve recent issues
248
+ 4. Call backlog-api-key_request with GET projects/{projectIdOrKey}/statuses to understand the workflow statuses`,
249
+ ja: `1. backlog-api-key_request \u3067 GET space \u3092\u547C\u3073\u51FA\u3057\u3001\u63A5\u7D9A\u78BA\u8A8D\u3068\u30B9\u30DA\u30FC\u30B9\u60C5\u5831\u3092\u53D6\u5F97
250
+ 2. backlog-api-key_request \u3067 GET projects \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
251
+ 3. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066 backlog-api-key_request \u3067 GET issues?projectId[]={projectId}&count=5&order=desc \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306E\u8AB2\u984C\u3092\u53D6\u5F97
252
+ 4. backlog-api-key_request \u3067 GET projects/{projectIdOrKey}/statuses \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u306E\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u78BA\u8A8D`
253
+ }
254
+ });
255
+
256
+ // ../connectors/src/connectors/backlog/tools/request.ts
257
+ import { z } from "zod";
258
+ var REQUEST_TIMEOUT_MS = 6e4;
259
+ var inputSchema = z.object({
260
+ toolUseIntent: z.string().optional().describe("Brief description of what you intend to accomplish with this tool call"),
261
+ connectionId: z.string().describe("ID of the Backlog connection to use"),
262
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method. Use GET to read resources, POST to create, PATCH/PUT to update, DELETE to remove."),
263
+ path: z.string().describe("API path relative to /api/v2/ (e.g., 'space', 'projects', 'issues?projectId[]=12345'). Query parameters can be appended. The apiKey query parameter is added automatically \u2014 do NOT include it."),
264
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body as JSON object. Required for POST, PUT, and PATCH requests (e.g., issue creation, comment addition).")
265
+ });
266
+ var outputSchema = z.discriminatedUnion("success", [
267
+ z.object({
268
+ success: z.literal(true),
269
+ status: z.number(),
270
+ data: z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])
271
+ }),
272
+ z.object({
273
+ success: z.literal(false),
274
+ error: z.string()
275
+ })
276
+ ]);
277
+ var requestTool = new ConnectorTool({
278
+ name: "request",
279
+ description: `Send authenticated requests to the Backlog REST API (v2).
280
+ Authentication is handled automatically by appending the apiKey query parameter to every request.
281
+ Use this tool for all Backlog operations: listing projects, searching and creating issues, managing wikis, retrieving users, and more.
282
+ The base URL and API key are configured per connection \u2014 only specify the API path relative to /api/v2/.
283
+ Do NOT include the apiKey parameter yourself; it is injected automatically.`,
284
+ inputSchema,
285
+ outputSchema,
286
+ async execute({ connectionId, method, path: path2, body }, connections) {
287
+ const connection2 = connections.find((c) => c.id === connectionId);
288
+ if (!connection2) {
289
+ return { success: false, error: `Connection ${connectionId} not found` };
290
+ }
291
+ console.log(`[connector-request] backlog-api-key/${connection2.name}: ${method} ${path2}`);
292
+ try {
293
+ const spaceUrl = parameters.spaceUrl.getValue(connection2);
294
+ const apiKey = parameters.apiKey.getValue(connection2);
295
+ const separator = path2.includes("?") ? "&" : "?";
296
+ const url = `${spaceUrl.replace(/\/+$/, "")}/api/v2/${path2}${separator}apiKey=${apiKey}`;
297
+ const controller = new AbortController();
298
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
299
+ try {
300
+ const headers = {
301
+ Accept: "application/json"
302
+ };
303
+ if (body) {
304
+ headers["Content-Type"] = "application/json";
305
+ }
306
+ const response = await fetch(url, {
307
+ method,
308
+ headers,
309
+ body: body ? JSON.stringify(body) : void 0,
310
+ signal: controller.signal
311
+ });
312
+ if (response.status === 204) {
313
+ return { success: true, status: 204, data: {} };
314
+ }
315
+ const data = await response.json();
316
+ if (!response.ok) {
317
+ const errData = data;
318
+ const errors = errData?.errors;
319
+ const errorMessage = Array.isArray(errors) ? errors.map((e) => e.message).join("; ") : errData?.message ?? `HTTP ${response.status} ${response.statusText}`;
320
+ return { success: false, error: errorMessage };
321
+ }
322
+ return { success: true, status: response.status, data };
323
+ } finally {
324
+ clearTimeout(timeout);
325
+ }
326
+ } catch (err) {
327
+ const msg = err instanceof Error ? err.message : String(err);
328
+ return { success: false, error: msg };
329
+ }
330
+ }
331
+ });
332
+
333
+ // ../connectors/src/connectors/backlog/index.ts
334
+ var tools = { request: requestTool };
335
+ var backlogConnector = new ConnectorPlugin({
336
+ slug: "backlog",
337
+ authType: AUTH_TYPES.API_KEY,
338
+ name: "Backlog",
339
+ description: "Connect to Nulab Backlog for project management, issue tracking, and wiki data retrieval using API key authentication.",
340
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/6KcVBGf3mUHnuCOQgQMvtT/e8558c7990e40e3be46948e9476190fb/backlog-favicon.svg",
341
+ parameters,
342
+ releaseFlag: { dev1: true, dev2: true, prod: false },
343
+ onboarding: backlogOnboarding,
344
+ systemPrompt: {
345
+ en: `### Tools
346
+
347
+ - \`backlog-api-key_request\`: The only way to call the Backlog REST API (v2). Use it to list projects, search issues, get issue details, create/update issues, manage wikis, and retrieve users. Authentication (API key as query parameter) and space URL are configured automatically.
348
+
349
+ ### Business Logic
350
+
351
+ 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.
352
+
353
+ #### Example
354
+
355
+ \`\`\`ts
356
+ import { connection } from "@squadbase/vite-server/connectors/backlog-api-key";
357
+
358
+ const backlog = connection("<connectionId>");
359
+
360
+ // List projects
361
+ const res = await backlog.request("/api/v2/projects");
362
+ const projects = await res.json();
363
+
364
+ // Get issues for a project
365
+ const issuesRes = await backlog.request("/api/v2/issues?projectId[]=12345&count=20&sort=updated&order=desc");
366
+ const issues = await issuesRes.json();
367
+
368
+ // Create an issue
369
+ await backlog.request("/api/v2/issues", {
370
+ method: "POST",
371
+ body: JSON.stringify({
372
+ projectId: 12345,
373
+ summary: "New issue title",
374
+ issueTypeId: 67890,
375
+ priorityId: 3,
376
+ }),
377
+ });
378
+ \`\`\`
379
+
380
+ ### Backlog REST API v2 Reference
381
+
382
+ #### Space
383
+ - GET space \u2014 Get space information
384
+ - GET space/activities \u2014 Get recent activities in the space
385
+
386
+ #### Projects
387
+ - GET projects \u2014 List all projects (query params: archived, all)
388
+ - GET projects/{projectIdOrKey} \u2014 Get project details
389
+ - GET projects/{projectIdOrKey}/statuses \u2014 List issue statuses
390
+ - GET projects/{projectIdOrKey}/issueTypes \u2014 List issue types
391
+ - GET projects/{projectIdOrKey}/categories \u2014 List issue categories
392
+
393
+ #### Issues
394
+ - GET issues \u2014 Search issues (query params: projectId[], statusId[], assigneeId[], sort, order, count, offset, keyword)
395
+ - GET issues/{issueIdOrKey} \u2014 Get issue details
396
+ - GET issues/count \u2014 Get issue count
397
+ - POST issues \u2014 Create an issue (body: projectId, summary, issueTypeId, priorityId, and optional fields)
398
+ - PATCH issues/{issueIdOrKey} \u2014 Update an issue
399
+ - DELETE issues/{issueIdOrKey} \u2014 Delete an issue
400
+ - GET issues/{issueIdOrKey}/comments \u2014 List comments
401
+ - POST issues/{issueIdOrKey}/comments \u2014 Add a comment (body: { content: "comment text" })
402
+
403
+ #### Wiki
404
+ - GET wikis \u2014 List wiki pages (query params: projectIdOrKey, keyword)
405
+ - GET wikis/{wikiId} \u2014 Get wiki page details
406
+ - POST wikis \u2014 Create a wiki page (body: projectId, name, content)
407
+ - PATCH wikis/{wikiId} \u2014 Update a wiki page
408
+
409
+ #### Users
410
+ - GET users \u2014 List users in the space
411
+ - GET users/myself \u2014 Get authenticated user info
412
+
413
+ #### Pagination
414
+ - Use count (max 100, default 20) and offset parameters for pagination
415
+ - sort: "created", "updated", "issueType", "category", "priority", etc.
416
+ - order: "asc" or "desc"`,
417
+ ja: `### \u30C4\u30FC\u30EB
418
+
419
+ - \`backlog-api-key_request\`: Backlog REST API\uFF08v2\uFF09\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u8AB2\u984C\u306E\u691C\u7D22\u3001\u8AB2\u984C\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u8AB2\u984C\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u3001Wiki\u7BA1\u7406\u3001\u30E6\u30FC\u30B6\u30FC\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API\u30AD\u30FC\u3092\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u4ED8\u4E0E\uFF09\u3068\u30B9\u30DA\u30FC\u30B9URL\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\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\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
424
+
425
+ #### Example
426
+
427
+ \`\`\`ts
428
+ import { connection } from "@squadbase/vite-server/connectors/backlog-api-key";
429
+
430
+ const backlog = connection("<connectionId>");
431
+
432
+ // \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
433
+ const res = await backlog.request("/api/v2/projects");
434
+ const projects = await res.json();
435
+
436
+ // \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u8AB2\u984C\u3092\u53D6\u5F97
437
+ const issuesRes = await backlog.request("/api/v2/issues?projectId[]=12345&count=20&sort=updated&order=desc");
438
+ const issues = await issuesRes.json();
439
+
440
+ // \u8AB2\u984C\u3092\u4F5C\u6210
441
+ await backlog.request("/api/v2/issues", {
442
+ method: "POST",
443
+ body: JSON.stringify({
444
+ projectId: 12345,
445
+ summary: "\u65B0\u3057\u3044\u8AB2\u984C",
446
+ issueTypeId: 67890,
447
+ priorityId: 3,
448
+ }),
449
+ });
450
+ \`\`\`
451
+
452
+ ### Backlog REST API v2 \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
453
+
454
+ #### \u30B9\u30DA\u30FC\u30B9
455
+ - GET space \u2014 \u30B9\u30DA\u30FC\u30B9\u60C5\u5831\u306E\u53D6\u5F97
456
+ - GET space/activities \u2014 \u30B9\u30DA\u30FC\u30B9\u306E\u6700\u8FD1\u306E\u6D3B\u52D5\u3092\u53D6\u5F97
457
+
458
+ #### \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8
459
+ - GET projects \u2014 \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u306E\u53D6\u5F97\uFF08\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF: archived, all\uFF09
460
+ - GET projects/{projectIdOrKey} \u2014 \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u8A73\u7D30\u306E\u53D6\u5F97
461
+ - GET projects/{projectIdOrKey}/statuses \u2014 \u8AB2\u984C\u30B9\u30C6\u30FC\u30BF\u30B9\u4E00\u89A7
462
+ - GET projects/{projectIdOrKey}/issueTypes \u2014 \u8AB2\u984C\u7A2E\u5225\u4E00\u89A7
463
+ - GET projects/{projectIdOrKey}/categories \u2014 \u8AB2\u984C\u30AB\u30C6\u30B4\u30EA\u4E00\u89A7
464
+
465
+ #### \u8AB2\u984C
466
+ - GET issues \u2014 \u8AB2\u984C\u306E\u691C\u7D22\uFF08\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF: projectId[], statusId[], assigneeId[], sort, order, count, offset, keyword\uFF09
467
+ - GET issues/{issueIdOrKey} \u2014 \u8AB2\u984C\u8A73\u7D30\u306E\u53D6\u5F97
468
+ - GET issues/count \u2014 \u8AB2\u984C\u6570\u306E\u53D6\u5F97
469
+ - POST issues \u2014 \u8AB2\u984C\u306E\u4F5C\u6210\uFF08body: projectId, summary, issueTypeId, priorityId, \u305D\u306E\u4ED6\u30AA\u30D7\u30B7\u30E7\u30F3\u30D5\u30A3\u30FC\u30EB\u30C9\uFF09
470
+ - PATCH issues/{issueIdOrKey} \u2014 \u8AB2\u984C\u306E\u66F4\u65B0
471
+ - DELETE issues/{issueIdOrKey} \u2014 \u8AB2\u984C\u306E\u524A\u9664
472
+ - GET issues/{issueIdOrKey}/comments \u2014 \u30B3\u30E1\u30F3\u30C8\u4E00\u89A7
473
+ - POST issues/{issueIdOrKey}/comments \u2014 \u30B3\u30E1\u30F3\u30C8\u306E\u8FFD\u52A0\uFF08body: { content: "\u30B3\u30E1\u30F3\u30C8\u5185\u5BB9" }\uFF09
474
+
475
+ #### Wiki
476
+ - GET wikis \u2014 Wiki\u30DA\u30FC\u30B8\u4E00\u89A7\u306E\u53D6\u5F97\uFF08\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF: projectIdOrKey, keyword\uFF09
477
+ - GET wikis/{wikiId} \u2014 Wiki\u30DA\u30FC\u30B8\u8A73\u7D30\u306E\u53D6\u5F97
478
+ - POST wikis \u2014 Wiki\u30DA\u30FC\u30B8\u306E\u4F5C\u6210\uFF08body: projectId, name, content\uFF09
479
+ - PATCH wikis/{wikiId} \u2014 Wiki\u30DA\u30FC\u30B8\u306E\u66F4\u65B0
480
+
481
+ #### \u30E6\u30FC\u30B6\u30FC
482
+ - GET users \u2014 \u30B9\u30DA\u30FC\u30B9\u5185\u306E\u30E6\u30FC\u30B6\u30FC\u4E00\u89A7
483
+ - GET users/myself \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u306E\u53D6\u5F97
484
+
485
+ #### \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3
486
+ - count\uFF08\u6700\u5927100\u3001\u30C7\u30D5\u30A9\u30EB\u30C820\uFF09\u3068 offset \u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3
487
+ - sort: "created", "updated", "issueType", "category", "priority" \u7B49
488
+ - order: "asc" \u307E\u305F\u306F "desc"`
489
+ },
490
+ tools
491
+ });
492
+
493
+ // src/connectors/create-connector-sdk.ts
494
+ import { readFileSync } from "fs";
495
+ import path from "path";
496
+
497
+ // src/connector-client/env.ts
498
+ function resolveEnvVar(entry, key, connectionId) {
499
+ const envVarName = entry.envVars[key];
500
+ if (!envVarName) {
501
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
502
+ }
503
+ const value = process.env[envVarName];
504
+ if (!value) {
505
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
506
+ }
507
+ return value;
508
+ }
509
+ function resolveEnvVarOptional(entry, key) {
510
+ const envVarName = entry.envVars[key];
511
+ if (!envVarName) return void 0;
512
+ return process.env[envVarName] || void 0;
513
+ }
514
+
515
+ // src/connector-client/proxy-fetch.ts
516
+ import { getContext } from "hono/context-storage";
517
+ import { getCookie } from "hono/cookie";
518
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
519
+ function createSandboxProxyFetch(connectionId) {
520
+ return async (input, init) => {
521
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
522
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
523
+ if (!token || !sandboxId) {
524
+ throw new Error(
525
+ "Connection proxy is not configured. Please check your deployment settings."
526
+ );
527
+ }
528
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
529
+ const originalMethod = init?.method ?? "GET";
530
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
531
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
532
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
533
+ return fetch(proxyUrl, {
534
+ method: "POST",
535
+ headers: {
536
+ "Content-Type": "application/json",
537
+ Authorization: `Bearer ${token}`
538
+ },
539
+ body: JSON.stringify({
540
+ url: originalUrl,
541
+ method: originalMethod,
542
+ body: originalBody
543
+ })
544
+ });
545
+ };
546
+ }
547
+ function createDeployedAppProxyFetch(connectionId) {
548
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
549
+ if (!projectId) {
550
+ throw new Error(
551
+ "Connection proxy is not configured. Please check your deployment settings."
552
+ );
553
+ }
554
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
555
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
556
+ return async (input, init) => {
557
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
558
+ const originalMethod = init?.method ?? "GET";
559
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
560
+ const c = getContext();
561
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
562
+ if (!appSession) {
563
+ throw new Error(
564
+ "No authentication method available for connection proxy."
565
+ );
566
+ }
567
+ return fetch(proxyUrl, {
568
+ method: "POST",
569
+ headers: {
570
+ "Content-Type": "application/json",
571
+ Authorization: `Bearer ${appSession}`
572
+ },
573
+ body: JSON.stringify({
574
+ url: originalUrl,
575
+ method: originalMethod,
576
+ body: originalBody
577
+ })
578
+ });
579
+ };
580
+ }
581
+ function createProxyFetch(connectionId) {
582
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
583
+ return createSandboxProxyFetch(connectionId);
584
+ }
585
+ return createDeployedAppProxyFetch(connectionId);
586
+ }
587
+
588
+ // src/connectors/create-connector-sdk.ts
589
+ function loadConnectionsSync() {
590
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
591
+ try {
592
+ const raw = readFileSync(filePath, "utf-8");
593
+ return JSON.parse(raw);
594
+ } catch {
595
+ return {};
596
+ }
597
+ }
598
+ function createConnectorSdk(plugin, createClient2) {
599
+ return (connectionId) => {
600
+ const connections = loadConnectionsSync();
601
+ const entry = connections[connectionId];
602
+ if (!entry) {
603
+ throw new Error(
604
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
605
+ );
606
+ }
607
+ if (entry.connector.slug !== plugin.slug) {
608
+ throw new Error(
609
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
610
+ );
611
+ }
612
+ const params = {};
613
+ for (const param of Object.values(plugin.parameters)) {
614
+ if (param.required) {
615
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
616
+ } else {
617
+ const val = resolveEnvVarOptional(entry, param.slug);
618
+ if (val !== void 0) params[param.slug] = val;
619
+ }
620
+ }
621
+ return createClient2(params, createProxyFetch(connectionId));
622
+ };
623
+ }
624
+
625
+ // src/connectors/entries/backlog-api-key.ts
626
+ var connection = createConnectorSdk(backlogConnector, createClient);
627
+ export {
628
+ connection
629
+ };