@squadbase/vite-server 0.1.8 → 0.1.9-dev.3841401

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 (86) hide show
  1. package/dist/cli/index.js +73422 -59588
  2. package/dist/connectors/airtable-oauth.js +3 -0
  3. package/dist/connectors/airtable.js +3 -0
  4. package/dist/connectors/amplitude.js +3 -0
  5. package/dist/connectors/anthropic.js +3 -0
  6. package/dist/connectors/asana.js +18 -2
  7. package/dist/connectors/attio.js +3 -0
  8. package/dist/connectors/aws-billing.d.ts +5 -0
  9. package/dist/connectors/aws-billing.js +29843 -0
  10. package/dist/connectors/azure-sql.d.ts +5 -0
  11. package/dist/connectors/azure-sql.js +668 -0
  12. package/dist/connectors/backlog-api-key.js +3 -0
  13. package/dist/connectors/clickup.d.ts +5 -0
  14. package/dist/connectors/clickup.js +850 -0
  15. package/dist/connectors/customerio.js +3 -0
  16. package/dist/connectors/dbt.js +3 -0
  17. package/dist/connectors/freshdesk.d.ts +5 -0
  18. package/dist/connectors/freshdesk.js +842 -0
  19. package/dist/connectors/freshsales.d.ts +5 -0
  20. package/dist/connectors/freshsales.js +867 -0
  21. package/dist/connectors/freshservice.d.ts +5 -0
  22. package/dist/connectors/freshservice.js +813 -0
  23. package/dist/connectors/gamma.js +3 -0
  24. package/dist/connectors/gemini.js +3 -0
  25. package/dist/connectors/github.d.ts +5 -0
  26. package/dist/connectors/github.js +963 -0
  27. package/dist/connectors/gmail-oauth.js +18 -2
  28. package/dist/connectors/gmail.js +34 -16
  29. package/dist/connectors/google-ads.js +3 -0
  30. package/dist/connectors/google-analytics-oauth.js +3 -0
  31. package/dist/connectors/google-analytics.js +3 -0
  32. package/dist/connectors/google-audit-log.d.ts +5 -0
  33. package/dist/connectors/google-audit-log.js +813 -0
  34. package/dist/connectors/google-calendar-oauth.js +21 -2
  35. package/dist/connectors/google-calendar.js +140 -73
  36. package/dist/connectors/google-docs.js +21 -2
  37. package/dist/connectors/google-drive.js +18 -2
  38. package/dist/connectors/google-search-console-oauth.d.ts +5 -0
  39. package/dist/connectors/google-search-console-oauth.js +954 -0
  40. package/dist/connectors/google-sheets.js +21 -2
  41. package/dist/connectors/google-slides.js +21 -2
  42. package/dist/connectors/grafana.js +3 -0
  43. package/dist/connectors/hubspot-oauth.js +3 -0
  44. package/dist/connectors/hubspot.js +3 -0
  45. package/dist/connectors/influxdb.js +3 -0
  46. package/dist/connectors/intercom-oauth.js +3 -0
  47. package/dist/connectors/intercom.js +3 -0
  48. package/dist/connectors/jdbc.d.ts +5 -0
  49. package/dist/connectors/jdbc.js +21509 -0
  50. package/dist/connectors/jira-api-key.js +3 -0
  51. package/dist/connectors/kintone-api-token.js +3 -0
  52. package/dist/connectors/kintone.js +3 -0
  53. package/dist/connectors/linear.js +3 -0
  54. package/dist/connectors/linkedin-ads.js +3 -0
  55. package/dist/connectors/mailchimp-oauth.js +3 -0
  56. package/dist/connectors/mailchimp.js +3 -0
  57. package/dist/connectors/meta-ads-oauth.js +3 -0
  58. package/dist/connectors/meta-ads.js +3 -0
  59. package/dist/connectors/mixpanel.js +3 -0
  60. package/dist/connectors/monday.d.ts +5 -0
  61. package/dist/connectors/monday.js +853 -0
  62. package/dist/connectors/notion-oauth.js +3 -0
  63. package/dist/connectors/notion.js +3 -0
  64. package/dist/connectors/openai.js +3 -0
  65. package/dist/connectors/oracle.d.ts +5 -0
  66. package/dist/connectors/oracle.js +676 -0
  67. package/dist/connectors/salesforce.js +3 -0
  68. package/dist/connectors/semrush.d.ts +5 -0
  69. package/dist/connectors/semrush.js +812 -0
  70. package/dist/connectors/sentry.js +3 -0
  71. package/dist/connectors/shopify-oauth.js +3 -0
  72. package/dist/connectors/shopify.js +3 -0
  73. package/dist/connectors/sqlserver.d.ts +5 -0
  74. package/dist/connectors/sqlserver.js +667 -0
  75. package/dist/connectors/stripe-api-key.js +3 -0
  76. package/dist/connectors/stripe-oauth.js +3 -0
  77. package/dist/connectors/supabase.d.ts +5 -0
  78. package/dist/connectors/supabase.js +582 -0
  79. package/dist/connectors/tiktok-ads.js +18 -2
  80. package/dist/connectors/wix-store.js +3 -0
  81. package/dist/connectors/zendesk-oauth.js +3 -0
  82. package/dist/connectors/zendesk.js +3 -0
  83. package/dist/index.js +70184 -56350
  84. package/dist/main.js +70178 -56344
  85. package/dist/vite-plugin.js +71935 -58101
  86. package/package.json +64 -2
@@ -0,0 +1,5 @@
1
+ import * as _squadbase_connectors_sdk from '@squadbase/connectors/sdk';
2
+
3
+ declare const connection: (connectionId: string) => _squadbase_connectors_sdk.AzureSqlConnectorSdk;
4
+
5
+ export { connection };
@@ -0,0 +1,668 @@
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/sqlserver/utils.ts
46
+ var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
47
+ var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
48
+ var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
49
+ function parseBoolean(value) {
50
+ if (value == null) return void 0;
51
+ const lower = value.toLowerCase();
52
+ if (TRUE_VALUES.has(lower)) return true;
53
+ if (FALSE_VALUES.has(lower)) return false;
54
+ return void 0;
55
+ }
56
+ function parseSqlServerJdbcUrl(jdbcUrl, options = {}) {
57
+ const trimmed = jdbcUrl.trim();
58
+ if (!SQLSERVER_PREFIX_RE.test(trimmed)) {
59
+ throw new Error(
60
+ `Unsupported SQL Server URL "${redactSqlServerUrl(trimmed)}". Expected prefix: jdbc:sqlserver:// or sqlserver://.`
61
+ );
62
+ }
63
+ const withoutPrefix = trimmed.replace(SQLSERVER_PREFIX_RE, "");
64
+ const [hostAndPath, ...propertySegments] = withoutPrefix.split(";");
65
+ const props = {};
66
+ for (const segment of propertySegments) {
67
+ if (!segment) continue;
68
+ const eqIdx = segment.indexOf("=");
69
+ if (eqIdx === -1) continue;
70
+ const key = segment.slice(0, eqIdx).trim().toLowerCase();
71
+ const value = segment.slice(eqIdx + 1).trim();
72
+ if (key) props[key] = value;
73
+ }
74
+ const url = new URL(`mssql://${hostAndPath}`);
75
+ for (const [key, value] of url.searchParams.entries()) {
76
+ if (!(key.toLowerCase() in props)) {
77
+ props[key.toLowerCase()] = value;
78
+ }
79
+ }
80
+ const server = url.hostname;
81
+ const port = url.port ? Number(url.port) : 1433;
82
+ const pathname = url.pathname.replace(/^\//, "");
83
+ const database = pathname || props["database"] || props["databasename"];
84
+ const user = props["user"] || props["username"] || props["userid"] || options.username;
85
+ const password = props["password"] || options.password;
86
+ return {
87
+ server,
88
+ port,
89
+ database,
90
+ user,
91
+ password,
92
+ options: props
93
+ };
94
+ }
95
+ function toMssqlConfig(parsed, defaults = {}) {
96
+ const encrypt = parseBoolean(parsed.options["encrypt"]) ?? defaults.encrypt ?? false;
97
+ const trustServerCertificate = parseBoolean(parsed.options["trustservercertificate"]) ?? !encrypt;
98
+ return {
99
+ server: parsed.server,
100
+ port: parsed.port,
101
+ database: parsed.database,
102
+ user: parsed.user,
103
+ password: parsed.password,
104
+ connectionTimeout: 1e4,
105
+ requestTimeout: 6e4,
106
+ options: {
107
+ encrypt,
108
+ trustServerCertificate
109
+ }
110
+ };
111
+ }
112
+ function redactSqlServerUrl(jdbcUrl) {
113
+ return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
114
+ }
115
+
116
+ // ../connectors/src/lib/mssql-runner.ts
117
+ async function importMssql() {
118
+ const mod = await import("mssql");
119
+ return mod.default ?? mod;
120
+ }
121
+ async function runMssqlQuery(parsed, sql, options = {}) {
122
+ const sqlMod = await importMssql();
123
+ const config = toMssqlConfig(parsed, {
124
+ encrypt: options.forceEncrypt
125
+ });
126
+ const pool = new sqlMod.ConnectionPool(config);
127
+ await pool.connect();
128
+ try {
129
+ const result = await pool.request().query(sql);
130
+ const recordset = result.recordset ?? [];
131
+ return { rows: recordset };
132
+ } finally {
133
+ await pool.close();
134
+ }
135
+ }
136
+ async function checkMssqlConnection(url, credentials, options = {}) {
137
+ let parsed;
138
+ try {
139
+ parsed = parseSqlServerJdbcUrl(url, credentials);
140
+ } catch (err) {
141
+ return {
142
+ success: false,
143
+ error: err instanceof Error ? err.message : String(err)
144
+ };
145
+ }
146
+ try {
147
+ await runMssqlQuery(parsed, "SELECT 1 AS one", options);
148
+ return { success: true };
149
+ } catch (err) {
150
+ let msg = err instanceof Error ? err.message : String(err);
151
+ msg = msg.replaceAll(url, redactSqlServerUrl(url));
152
+ return { success: false, error: msg };
153
+ }
154
+ }
155
+
156
+ // ../connectors/src/connectors/azure-sql/parameters.ts
157
+ var parameters = {
158
+ jdbcUrl: new ParameterDefinition({
159
+ slug: "jdbc-url",
160
+ name: "Azure SQL JDBC URL",
161
+ description: "JDBC-style connection URL for Azure SQL Database (e.g. `jdbc:sqlserver://<server>.database.windows.net:1433;database=<db>;encrypt=true`). Encryption is enforced by Azure SQL \u2014 the connector defaults `encrypt=true` even when the URL omits it. The `jdbc:` prefix may be omitted (`sqlserver://...`).",
162
+ envVarBaseKey: "AZURE_SQL_JDBC_URL",
163
+ type: "text",
164
+ secret: true,
165
+ required: true
166
+ }),
167
+ username: new ParameterDefinition({
168
+ slug: "username",
169
+ name: "Username",
170
+ description: "Azure SQL login (typically `<user>@<server>`). Optional when embedded in the JDBC URL via `user=...`.",
171
+ envVarBaseKey: "AZURE_SQL_USERNAME",
172
+ type: "text",
173
+ secret: false,
174
+ required: false
175
+ }),
176
+ password: new ParameterDefinition({
177
+ slug: "password",
178
+ name: "Password",
179
+ description: "Azure SQL password. Optional when embedded in the JDBC URL via `password=...`.",
180
+ envVarBaseKey: "AZURE_SQL_PASSWORD",
181
+ type: "text",
182
+ secret: true,
183
+ required: false
184
+ })
185
+ };
186
+
187
+ // ../connectors/src/connectors/azure-sql/sdk/index.ts
188
+ function createClient(params) {
189
+ const jdbcUrl = params[parameters.jdbcUrl.slug];
190
+ if (!jdbcUrl) {
191
+ throw new Error(
192
+ `azure-sql: missing required parameter: ${parameters.jdbcUrl.slug}`
193
+ );
194
+ }
195
+ const username = params[parameters.username.slug];
196
+ const password = params[parameters.password.slug];
197
+ const parsed = parseSqlServerJdbcUrl(jdbcUrl, { username, password });
198
+ async function runQuery(sql) {
199
+ try {
200
+ const { rows } = await runMssqlQuery(parsed, sql, { forceEncrypt: true });
201
+ return rows;
202
+ } catch (err) {
203
+ const msg = err instanceof Error ? err.message : String(err);
204
+ throw new Error(msg.replaceAll(jdbcUrl, redactSqlServerUrl(jdbcUrl)));
205
+ }
206
+ }
207
+ return { query: runQuery };
208
+ }
209
+
210
+ // ../connectors/src/connector-onboarding.ts
211
+ var ConnectorOnboarding = class {
212
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
213
+ connectionSetupInstructions;
214
+ /** Phase 2: Data overview instructions */
215
+ dataOverviewInstructions;
216
+ constructor(config) {
217
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
218
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
219
+ }
220
+ getConnectionSetupPrompt(language) {
221
+ return this.connectionSetupInstructions?.[language] ?? null;
222
+ }
223
+ getDataOverviewInstructions(language) {
224
+ return this.dataOverviewInstructions[language];
225
+ }
226
+ };
227
+
228
+ // ../connectors/src/connector-tool.ts
229
+ var ConnectorTool = class {
230
+ name;
231
+ description;
232
+ inputSchema;
233
+ outputSchema;
234
+ _execute;
235
+ constructor(config) {
236
+ this.name = config.name;
237
+ this.description = config.description;
238
+ this.inputSchema = config.inputSchema;
239
+ this.outputSchema = config.outputSchema;
240
+ this._execute = config.execute;
241
+ }
242
+ createTool(connections, config) {
243
+ return {
244
+ description: this.description,
245
+ inputSchema: this.inputSchema,
246
+ outputSchema: this.outputSchema,
247
+ execute: (input) => this._execute(input, connections, config)
248
+ };
249
+ }
250
+ };
251
+
252
+ // ../connectors/src/connector-plugin.ts
253
+ var ConnectorPlugin = class _ConnectorPlugin {
254
+ slug;
255
+ authType;
256
+ name;
257
+ description;
258
+ iconUrl;
259
+ parameters;
260
+ releaseFlag;
261
+ proxyPolicy;
262
+ experimentalAttributes;
263
+ categories;
264
+ onboarding;
265
+ systemPrompt;
266
+ tools;
267
+ query;
268
+ checkConnection;
269
+ constructor(config) {
270
+ this.slug = config.slug;
271
+ this.authType = config.authType;
272
+ this.name = config.name;
273
+ this.description = config.description;
274
+ this.iconUrl = config.iconUrl;
275
+ this.parameters = config.parameters;
276
+ this.releaseFlag = config.releaseFlag;
277
+ this.proxyPolicy = config.proxyPolicy;
278
+ this.experimentalAttributes = config.experimentalAttributes;
279
+ this.categories = config.categories ?? [];
280
+ this.onboarding = config.onboarding;
281
+ this.systemPrompt = config.systemPrompt;
282
+ this.tools = config.tools;
283
+ this.query = config.query;
284
+ this.checkConnection = config.checkConnection;
285
+ }
286
+ get connectorKey() {
287
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
288
+ }
289
+ /**
290
+ * Create tools for connections that belong to this connector.
291
+ * Filters connections by connectorKey internally.
292
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
293
+ */
294
+ createTools(connections, config, opts) {
295
+ const myConnections = connections.filter(
296
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
297
+ );
298
+ const result = {};
299
+ for (const t of Object.values(this.tools)) {
300
+ const tool = t.createTool(myConnections, config);
301
+ const originalToModelOutput = tool.toModelOutput;
302
+ result[`${this.connectorKey}_${t.name}`] = {
303
+ ...tool,
304
+ toModelOutput: async (options) => {
305
+ if (!originalToModelOutput) {
306
+ return opts.truncateOutput(options.output);
307
+ }
308
+ const modelOutput = await originalToModelOutput(options);
309
+ if (modelOutput.type === "text" || modelOutput.type === "json") {
310
+ return opts.truncateOutput(modelOutput.value);
311
+ }
312
+ return modelOutput;
313
+ }
314
+ };
315
+ }
316
+ return result;
317
+ }
318
+ static deriveKey(slug, authType) {
319
+ if (authType) return `${slug}-${authType}`;
320
+ const LEGACY_NULL_AUTH_TYPE_MAP = {
321
+ // user-password
322
+ "postgresql": "user-password",
323
+ "mysql": "user-password",
324
+ "clickhouse": "user-password",
325
+ "kintone": "user-password",
326
+ "squadbase-db": "user-password",
327
+ // service-account
328
+ "snowflake": "service-account",
329
+ "bigquery": "service-account",
330
+ "google-analytics": "service-account",
331
+ "google-calendar": "service-account",
332
+ "aws-athena": "service-account",
333
+ "redshift": "service-account",
334
+ // api-key
335
+ "databricks": "api-key",
336
+ "dbt": "api-key",
337
+ "airtable": "api-key",
338
+ "openai": "api-key",
339
+ "gemini": "api-key",
340
+ "anthropic": "api-key",
341
+ "wix-store": "api-key"
342
+ };
343
+ const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
344
+ if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
345
+ return slug;
346
+ }
347
+ };
348
+
349
+ // ../connectors/src/auth-types.ts
350
+ var AUTH_TYPES = {
351
+ OAUTH: "oauth",
352
+ API_KEY: "api-key",
353
+ JWT: "jwt",
354
+ SERVICE_ACCOUNT: "service-account",
355
+ PAT: "pat",
356
+ USER_PASSWORD: "user-password"
357
+ };
358
+
359
+ // ../connectors/src/connectors/azure-sql/setup.ts
360
+ var azureSqlOnboarding = new ConnectorOnboarding({
361
+ dataOverviewInstructions: {
362
+ en: `1. Use azure-sql_executeQuery to confirm the database flavor: \`SELECT @@VERSION\` (Azure SQL returns "Microsoft SQL Azure \u2026")
363
+ 2. List user tables: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
364
+ 3. For key tables, fetch column info: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
365
+ 4. Sample up to 3 tables. Azure SQL is T-SQL, so use \`TOP\` rather than \`LIMIT\`: \`SELECT TOP 5 * FROM <schema>.<table_name>\``,
366
+ ja: `1. azure-sql_executeQuery \u3067\u30D5\u30EC\u30FC\u30D0\u30FC\u3092\u78BA\u8A8D: \`SELECT @@VERSION\`\uFF08Azure SQL \u306F "Microsoft SQL Azure \u2026" \u3092\u8FD4\u3057\u307E\u3059\uFF09
367
+ 2. \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
368
+ 3. \u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30AB\u30E9\u30E0\u60C5\u5831: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
369
+ 4. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u6700\u59273\u30C6\u30FC\u30D6\u30EB\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3002Azure SQL \u306F T-SQL \u306E\u305F\u3081 \`LIMIT\` \u3067\u306F\u306A\u304F \`TOP\` \u3092\u4F7F\u7528: \`SELECT TOP 5 * FROM <schema>.<table_name>\``
370
+ }
371
+ });
372
+
373
+ // ../connectors/src/connectors/azure-sql/tools/execute-query.ts
374
+ import { z } from "zod";
375
+ var MAX_ROWS = 500;
376
+ var inputSchema = z.object({
377
+ toolUseIntent: z.string().optional().describe(
378
+ "Brief description of what you intend to accomplish with this tool call"
379
+ ),
380
+ connectionId: z.string().describe("ID of the Azure SQL connection to use"),
381
+ sql: z.string().describe(
382
+ "T-SQL query to execute against Azure SQL. Use SQL Server syntax (e.g. `TOP n`, square-bracket identifiers). Always include `TOP` to bound result size."
383
+ )
384
+ });
385
+ var outputSchema = z.discriminatedUnion("success", [
386
+ z.object({
387
+ success: z.literal(true),
388
+ rowCount: z.number(),
389
+ truncated: z.boolean(),
390
+ rows: z.array(z.record(z.string(), z.unknown()))
391
+ }),
392
+ z.object({
393
+ success: z.literal(false),
394
+ error: z.string()
395
+ })
396
+ ]);
397
+ var executeQueryTool = new ConnectorTool({
398
+ name: "executeQuery",
399
+ description: `Execute a T-SQL query against Azure SQL Database. Returns up to ${MAX_ROWS} rows.
400
+ Use for: schema exploration via \`INFORMATION_SCHEMA\`, data sampling, and analytical queries.
401
+ Azure SQL is T-SQL: use \`TOP n\` instead of \`LIMIT n\`. Identifiers can be wrapped in square brackets.
402
+ Avoid loading large amounts of data; always include \`TOP\` in queries.`,
403
+ inputSchema,
404
+ outputSchema,
405
+ async execute({ connectionId, sql }, connections) {
406
+ const connection2 = connections.find((c) => c.id === connectionId);
407
+ if (!connection2) {
408
+ return {
409
+ success: false,
410
+ error: `Connection ${connectionId} not found`
411
+ };
412
+ }
413
+ const jdbcUrl = parameters.jdbcUrl.getValue(connection2);
414
+ const username = parameters.username.tryGetValue(connection2);
415
+ const password = parameters.password.tryGetValue(connection2);
416
+ console.log(
417
+ `[connector-query] azure-sql/${connection2.name} (${redactSqlServerUrl(jdbcUrl)}): ${sql}`
418
+ );
419
+ let parsed;
420
+ try {
421
+ parsed = parseSqlServerJdbcUrl(jdbcUrl, { username, password });
422
+ } catch (err) {
423
+ return {
424
+ success: false,
425
+ error: err instanceof Error ? err.message : String(err)
426
+ };
427
+ }
428
+ try {
429
+ const { rows } = await runMssqlQuery(parsed, sql, { forceEncrypt: true });
430
+ const truncated = rows.length > MAX_ROWS;
431
+ return {
432
+ success: true,
433
+ rowCount: Math.min(rows.length, MAX_ROWS),
434
+ truncated,
435
+ rows: rows.slice(0, MAX_ROWS)
436
+ };
437
+ } catch (err) {
438
+ let msg = err instanceof Error ? err.message : String(err);
439
+ msg = msg.replaceAll(jdbcUrl, redactSqlServerUrl(jdbcUrl));
440
+ return { success: false, error: msg };
441
+ }
442
+ }
443
+ });
444
+
445
+ // ../connectors/src/connectors/azure-sql/index.ts
446
+ var tools = { executeQuery: executeQueryTool };
447
+ var azureSqlConnector = new ConnectorPlugin({
448
+ slug: "azure-sql",
449
+ authType: AUTH_TYPES.USER_PASSWORD,
450
+ name: "Azure SQL",
451
+ description: "Connect to Azure SQL Database (managed) using a JDBC-style URL. Encryption is enforced automatically.",
452
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5TL0yBbxoLlk6jFZuiHl8w/55040f52d57bf0b77a2215c985c5a772/azure-sql-icon.png",
453
+ parameters,
454
+ releaseFlag: { dev1: true, dev2: false, prod: false },
455
+ categories: ["database"],
456
+ onboarding: azureSqlOnboarding,
457
+ systemPrompt: {
458
+ en: `### Tools
459
+
460
+ - \`azure-sql_executeQuery\`: Executes a T-SQL query against Azure SQL Database and returns rows. Use for schema exploration via \`INFORMATION_SCHEMA\` and data sampling. See the SQL Reference below for Azure SQL-specific notes.
461
+
462
+ ### Business Logic
463
+
464
+ The business logic type for this connector is "sql".
465
+
466
+ ### SQL Reference
467
+ - Dialect: T-SQL (same as on-premises SQL Server). Use \`TOP n\` instead of \`LIMIT n\`.
468
+ - Schema layout: user objects live in \`dbo\` by default; system objects in \`sys\` and \`INFORMATION_SCHEMA\`.
469
+ - Schema exploration:
470
+ - List user tables: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
471
+ - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
472
+ - Cross-database queries are not supported on Azure SQL Database (single-DB scope per connection); always reference objects within the connected database.
473
+ - Always bound results with \`TOP\` in queries.
474
+ - Row-limit compatibility: the platform's server-logic schema inference may wrap your query as \`SELECT * FROM (<inner>) AS _sq LIMIT N\`. T-SQL does not understand \`LIMIT\`, so the connector detects this exact wrapper at \`query()\` time, executes \`<inner>\` directly, and slices the first N rows in JS. You do not need to handle this \u2014 but do not author your own \`LIMIT\` clauses; use \`TOP\` / \`OFFSET ... FETCH NEXT\` in queries you write.`,
475
+ ja: `### \u30C4\u30FC\u30EB
476
+
477
+ - \`azure-sql_executeQuery\`: Azure SQL Database \u306B\u5BFE\u3057\u3066 T-SQL \u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`INFORMATION_SCHEMA\` \u3092\u4F7F\u3063\u305F\u30B9\u30AD\u30FC\u30DE\u63A2\u7D22\u3084\u30C7\u30FC\u30BF\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u306B\u4F7F\u3044\u307E\u3059\u3002Azure SQL \u56FA\u6709\u306E\u6CE8\u610F\u70B9\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
478
+
479
+ ### Business Logic
480
+
481
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "sql" \u3067\u3059\u3002
482
+
483
+ ### SQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
484
+ - \u65B9\u8A00: T-SQL\uFF08\u30AA\u30F3\u30D7\u30EC SQL Server \u3068\u5171\u901A\uFF09\u3002\`LIMIT n\` \u3067\u306F\u306A\u304F \`TOP n\` \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
485
+ - \u30B9\u30AD\u30FC\u30DE\u69CB\u6210: \u30E6\u30FC\u30B6\u30FC\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067 \`dbo\` \u306B\u914D\u7F6E\u3055\u308C\u307E\u3059\u3002\u30B7\u30B9\u30C6\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306F \`sys\` \u304A\u3088\u3073 \`INFORMATION_SCHEMA\` \u306B\u5B58\u5728\u3057\u307E\u3059\u3002
486
+ - \u30B9\u30AD\u30FC\u30DE\u63A2\u7D22:
487
+ - \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
488
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
489
+ - Azure SQL Database \u3067\u306F\u8907\u6570DB\u3092\u307E\u305F\u3044\u3060\u30AF\u30A8\u30EA\u306F\u3067\u304D\u307E\u305B\u3093\uFF08\u63A5\u7D9A\u5358\u4F4D\u30671DB\uFF09\u3002\u63A5\u7D9A\u4E2D\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u5185\u306E\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u307F\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
490
+ - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002
491
+ - \u884C\u6570\u5236\u9650\u306E\u4E92\u63DB\u6027: \u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306E server-logic \u30B9\u30AD\u30FC\u30DE\u63A8\u8AD6\u306F\u3001\u30AF\u30A8\u30EA\u3092 \`SELECT * FROM (<inner>) AS _sq LIMIT N\` \u306E\u5F62\u3067\u30E9\u30C3\u30D7\u3057\u3066\u304F\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002T-SQL \u306B\u306F \`LIMIT\` \u304C\u7121\u3044\u305F\u3081\u3001\u30B3\u30CD\u30AF\u30BF\u306F \`query()\` \u5185\u3067\u3053\u306E\u30E9\u30C3\u30D1\u3092\u691C\u51FA\u3057\u3001\`<inner>\` \u3092\u305D\u306E\u307E\u307E\u5B9F\u884C\u3057\u3066 JS \u5074\u3067\u5148\u982D N \u884C\u306B\u5207\u308A\u8A70\u3081\u307E\u3059\u3002\u5229\u7528\u8005\u5074\u3067\u5BFE\u51E6\u3059\u308B\u5FC5\u8981\u306F\u3042\u308A\u307E\u305B\u3093\u304C\u3001\u81EA\u5206\u3067\u66F8\u304F SQL \u3067\u306F \`LIMIT\` \u3092\u4F7F\u308F\u305A \`TOP\` / \`OFFSET ... FETCH NEXT\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
492
+ },
493
+ tools,
494
+ async checkConnection(params, _config) {
495
+ return checkMssqlConnection(
496
+ params[parameters.jdbcUrl.slug],
497
+ {
498
+ username: params[parameters.username.slug],
499
+ password: params[parameters.password.slug]
500
+ },
501
+ { forceEncrypt: true }
502
+ );
503
+ },
504
+ async query(params, sql, _namedParams) {
505
+ const parsed = parseSqlServerJdbcUrl(params[parameters.jdbcUrl.slug], {
506
+ username: params[parameters.username.slug],
507
+ password: params[parameters.password.slug]
508
+ });
509
+ const wrapper = sql.match(
510
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
511
+ );
512
+ if (wrapper) {
513
+ const inner = wrapper[1].trim();
514
+ const limit = Number.parseInt(wrapper[2], 10);
515
+ const result = await runMssqlQuery(parsed, inner, { forceEncrypt: true });
516
+ return { rows: result.rows.slice(0, limit) };
517
+ }
518
+ return runMssqlQuery(parsed, sql, { forceEncrypt: true });
519
+ }
520
+ });
521
+
522
+ // src/connectors/create-connector-sdk.ts
523
+ import { readFileSync } from "fs";
524
+ import path from "path";
525
+
526
+ // src/connector-client/env.ts
527
+ function resolveEnvVar(entry, key, connectionId) {
528
+ const envVarName = entry.envVars[key];
529
+ if (!envVarName) {
530
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
531
+ }
532
+ const value = process.env[envVarName];
533
+ if (!value) {
534
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
535
+ }
536
+ return value;
537
+ }
538
+ function resolveEnvVarOptional(entry, key) {
539
+ const envVarName = entry.envVars[key];
540
+ if (!envVarName) return void 0;
541
+ return process.env[envVarName] || void 0;
542
+ }
543
+
544
+ // src/connector-client/proxy-fetch.ts
545
+ import { getContext } from "hono/context-storage";
546
+ import { getCookie } from "hono/cookie";
547
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
548
+ function normalizeHeaders(input) {
549
+ const out = {};
550
+ if (!input) return out;
551
+ new Headers(input).forEach((value, key) => {
552
+ out[key] = value;
553
+ });
554
+ return out;
555
+ }
556
+ function createSandboxProxyFetch(connectionId) {
557
+ return async (input, init) => {
558
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
559
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
560
+ if (!token || !sandboxId) {
561
+ throw new Error(
562
+ "Connection proxy is not configured. Please check your deployment settings."
563
+ );
564
+ }
565
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
566
+ const originalMethod = init?.method ?? "GET";
567
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
568
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
569
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
570
+ return fetch(proxyUrl, {
571
+ method: "POST",
572
+ headers: {
573
+ "Content-Type": "application/json",
574
+ Authorization: `Bearer ${token}`
575
+ },
576
+ body: JSON.stringify({
577
+ url: originalUrl,
578
+ method: originalMethod,
579
+ headers: normalizeHeaders(init?.headers),
580
+ body: originalBody
581
+ })
582
+ });
583
+ };
584
+ }
585
+ function createDeployedAppProxyFetch(connectionId) {
586
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
587
+ if (!projectId) {
588
+ throw new Error(
589
+ "Connection proxy is not configured. Please check your deployment settings."
590
+ );
591
+ }
592
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
593
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
594
+ return async (input, init) => {
595
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
596
+ const originalMethod = init?.method ?? "GET";
597
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
598
+ const c = getContext();
599
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
600
+ if (!appSession) {
601
+ throw new Error(
602
+ "No authentication method available for connection proxy."
603
+ );
604
+ }
605
+ return fetch(proxyUrl, {
606
+ method: "POST",
607
+ headers: {
608
+ "Content-Type": "application/json",
609
+ Authorization: `Bearer ${appSession}`
610
+ },
611
+ body: JSON.stringify({
612
+ url: originalUrl,
613
+ method: originalMethod,
614
+ headers: normalizeHeaders(init?.headers),
615
+ body: originalBody
616
+ })
617
+ });
618
+ };
619
+ }
620
+ function createProxyFetch(connectionId) {
621
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
622
+ return createSandboxProxyFetch(connectionId);
623
+ }
624
+ return createDeployedAppProxyFetch(connectionId);
625
+ }
626
+
627
+ // src/connectors/create-connector-sdk.ts
628
+ function loadConnectionsSync() {
629
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
630
+ try {
631
+ const raw = readFileSync(filePath, "utf-8");
632
+ return JSON.parse(raw);
633
+ } catch {
634
+ return {};
635
+ }
636
+ }
637
+ function createConnectorSdk(plugin, createClient2) {
638
+ return (connectionId) => {
639
+ const connections = loadConnectionsSync();
640
+ const entry = connections[connectionId];
641
+ if (!entry) {
642
+ throw new Error(
643
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
644
+ );
645
+ }
646
+ if (entry.connector.slug !== plugin.slug) {
647
+ throw new Error(
648
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
649
+ );
650
+ }
651
+ const params = {};
652
+ for (const param of Object.values(plugin.parameters)) {
653
+ if (param.required) {
654
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
655
+ } else {
656
+ const val = resolveEnvVarOptional(entry, param.slug);
657
+ if (val !== void 0) params[param.slug] = val;
658
+ }
659
+ }
660
+ return createClient2(params, createProxyFetch(connectionId));
661
+ };
662
+ }
663
+
664
+ // src/connectors/entries/azure-sql.ts
665
+ var connection = createConnectorSdk(azureSqlConnector, createClient);
666
+ export {
667
+ connection
668
+ };
@@ -145,6 +145,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
145
145
  releaseFlag;
146
146
  proxyPolicy;
147
147
  experimentalAttributes;
148
+ categories;
148
149
  onboarding;
149
150
  systemPrompt;
150
151
  tools;
@@ -160,6 +161,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
160
161
  this.releaseFlag = config.releaseFlag;
161
162
  this.proxyPolicy = config.proxyPolicy;
162
163
  this.experimentalAttributes = config.experimentalAttributes;
164
+ this.categories = config.categories ?? [];
163
165
  this.onboarding = config.onboarding;
164
166
  this.systemPrompt = config.systemPrompt;
165
167
  this.tools = config.tools;
@@ -340,6 +342,7 @@ var backlogConnector = new ConnectorPlugin({
340
342
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/6KcVBGf3mUHnuCOQgQMvtT/e8558c7990e40e3be46948e9476190fb/backlog-favicon.svg",
341
343
  parameters,
342
344
  releaseFlag: { dev1: true, dev2: true, prod: true },
345
+ categories: ["productivity"],
343
346
  onboarding: backlogOnboarding,
344
347
  systemPrompt: {
345
348
  en: `### Tools