@squadbase/connectors 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -52,6 +52,12 @@ interface ProxyPolicyRule {
52
52
  interface ProxyPolicy {
53
53
  allowlist: ProxyPolicyRule[];
54
54
  }
55
+ type ConnectionCheckResult = {
56
+ success: true;
57
+ } | {
58
+ success: false;
59
+ error: string;
60
+ };
55
61
  interface ConnectorToolsConfig {
56
62
  oauthProxy: {
57
63
  appApiKey: string;
@@ -97,6 +103,9 @@ declare class ConnectorPlugin<P extends Record<string, ParameterDefinition> = Re
97
103
  }) => Promise<{
98
104
  rows: Record<string, unknown>[];
99
105
  }>;
106
+ readonly checkConnection?: (params: Record<string, string>, config: {
107
+ proxyFetch: typeof fetch;
108
+ }) => Promise<ConnectionCheckResult>;
100
109
  constructor(config: {
101
110
  slug: string;
102
111
  authType: string | null;
@@ -115,6 +124,9 @@ declare class ConnectorPlugin<P extends Record<string, ParameterDefinition> = Re
115
124
  }) => Promise<{
116
125
  rows: Record<string, unknown>[];
117
126
  }>;
127
+ checkConnection?: (params: Record<string, string>, config: {
128
+ proxyFetch: typeof fetch;
129
+ }) => Promise<ConnectionCheckResult>;
118
130
  });
119
131
  get connectorKey(): string;
120
132
  /**
@@ -790,4 +802,4 @@ declare const squadbaseDbConnector: ConnectorPlugin<{
790
802
  }>;
791
803
  }>;
792
804
 
793
- export { AUTH_TYPES, ConnectorPlugin, ConnectorSetup, ConnectorTool, type ConnectorToolsConfig, ParameterDefinition, type ProxyPolicy, type ProxyPolicyRule, type ReleaseFlag, type SetupLanguage, airtableConnector, awsAthenaConnector, bigqueryConnector, bigqueryOauthConnector, connectors, databricksConnector, dbtConnector, googleAnalyticsConnector, kintoneConnector, mysqlConnector, postgresqlConnector, redshiftConnector, snowflakeConnector, snowflakePatConnector, squadbaseDbConnector, wixStoreConnector };
805
+ export { AUTH_TYPES, type ConnectionCheckResult, ConnectorPlugin, ConnectorSetup, ConnectorTool, type ConnectorToolsConfig, ParameterDefinition, type ProxyPolicy, type ProxyPolicyRule, type ReleaseFlag, type SetupLanguage, airtableConnector, awsAthenaConnector, bigqueryConnector, bigqueryOauthConnector, connectors, databricksConnector, dbtConnector, googleAnalyticsConnector, kintoneConnector, mysqlConnector, postgresqlConnector, redshiftConnector, snowflakeConnector, snowflakePatConnector, squadbaseDbConnector, wixStoreConnector };
package/dist/index.js CHANGED
@@ -92,6 +92,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
92
92
  systemPrompt;
93
93
  tools;
94
94
  query;
95
+ checkConnection;
95
96
  constructor(config) {
96
97
  this.slug = config.slug;
97
98
  this.authType = config.authType;
@@ -106,6 +107,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
106
107
  this.systemPrompt = config.systemPrompt;
107
108
  this.tools = config.tools;
108
109
  this.query = config.query;
110
+ this.checkConnection = config.checkConnection;
109
111
  }
110
112
  get connectorKey() {
111
113
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -439,6 +441,45 @@ var snowflakeConnector = new ConnectorPlugin({
439
441
  - List columns: \`DESCRIBE TABLE db_name.schema_name.table_name\`
440
442
  - INFORMATION_SCHEMA is also available: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``,
441
443
  tools,
444
+ async checkConnection(params, _config) {
445
+ try {
446
+ const snowflake = (await import("snowflake-sdk")).default;
447
+ snowflake.configure({ logLevel: "ERROR" });
448
+ const privateKey = Buffer.from(
449
+ params[parameters.privateKeyBase64.slug],
450
+ "base64"
451
+ ).toString("utf-8");
452
+ const conn = snowflake.createConnection({
453
+ account: params[parameters.account.slug],
454
+ username: params[parameters.user.slug],
455
+ role: params[parameters.role.slug],
456
+ warehouse: params[parameters.warehouse.slug],
457
+ authenticator: "SNOWFLAKE_JWT",
458
+ privateKey
459
+ });
460
+ await new Promise((resolve, reject) => {
461
+ conn.connect((err) => {
462
+ if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
463
+ else resolve();
464
+ });
465
+ });
466
+ await new Promise((resolve, reject) => {
467
+ conn.execute({
468
+ sqlText: "SELECT 1",
469
+ complete: (err) => {
470
+ if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
471
+ else resolve();
472
+ }
473
+ });
474
+ });
475
+ conn.destroy((err) => {
476
+ if (err) console.warn(`[connector-client] Snowflake destroy error: ${err.message}`);
477
+ });
478
+ return { success: true };
479
+ } catch (e) {
480
+ return { success: false, error: e instanceof Error ? e.message : String(e) };
481
+ }
482
+ },
442
483
  async query(params, sql, namedParams) {
443
484
  const resolvedSql = replaceLiteralParams(sql, namedParams);
444
485
  const snowflake = (await import("snowflake-sdk")).default;
@@ -653,6 +694,45 @@ var snowflakePatConnector = new ConnectorPlugin({
653
694
  - List columns: \`DESCRIBE TABLE db_name.schema_name.table_name\`
654
695
  - INFORMATION_SCHEMA is also available: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``,
655
696
  tools: tools2,
697
+ async checkConnection(params, _config) {
698
+ try {
699
+ const snowflake = (await import("snowflake-sdk")).default;
700
+ snowflake.configure({ logLevel: "ERROR" });
701
+ const conn = snowflake.createConnection({
702
+ account: params[parameters2.account.slug],
703
+ username: params[parameters2.user.slug],
704
+ role: params[parameters2.role.slug],
705
+ warehouse: params[parameters2.warehouse.slug],
706
+ password: params[parameters2.pat.slug]
707
+ });
708
+ await new Promise((resolve, reject) => {
709
+ conn.connect((err) => {
710
+ if (err)
711
+ reject(new Error(`Snowflake connect failed: ${err.message}`));
712
+ else resolve();
713
+ });
714
+ });
715
+ await new Promise((resolve, reject) => {
716
+ conn.execute({
717
+ sqlText: "SELECT 1",
718
+ complete: (err) => {
719
+ if (err)
720
+ reject(new Error(`Snowflake query failed: ${err.message}`));
721
+ else resolve();
722
+ }
723
+ });
724
+ });
725
+ conn.destroy((err) => {
726
+ if (err)
727
+ console.warn(
728
+ `[connector-client] Snowflake destroy error: ${err.message}`
729
+ );
730
+ });
731
+ return { success: true };
732
+ } catch (e) {
733
+ return { success: false, error: e instanceof Error ? e.message : String(e) };
734
+ }
735
+ },
656
736
  async query(params, sql, namedParams) {
657
737
  const resolvedSql = replaceLiteralParams(sql, namedParams);
658
738
  const snowflake = (await import("snowflake-sdk")).default;
@@ -797,6 +877,22 @@ var postgresqlConnector = new ConnectorPlugin({
797
877
  - List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
798
878
  - Always include LIMIT in queries`,
799
879
  tools: tools3,
880
+ async checkConnection(params, _config) {
881
+ const { Pool } = await import("pg");
882
+ const pool = new Pool({
883
+ connectionString: params[parameters3.connectionUrl.slug],
884
+ ssl: { rejectUnauthorized: false },
885
+ connectionTimeoutMillis: 1e4
886
+ });
887
+ try {
888
+ await pool.query("SELECT 1");
889
+ return { success: true };
890
+ } catch (error) {
891
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
892
+ } finally {
893
+ await pool.end();
894
+ }
895
+ },
800
896
  async query(params, sql, namedParams) {
801
897
  const { Pool } = await import("pg");
802
898
  const { text, values } = buildPositionalParams(sql, namedParams);
@@ -921,6 +1017,21 @@ var mysqlConnector = new ConnectorPlugin({
921
1017
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
922
1018
  - Always include LIMIT in queries`,
923
1019
  tools: tools4,
1020
+ async checkConnection(params, _config) {
1021
+ const mysql = await import("mysql2/promise");
1022
+ const pool = mysql.createPool({
1023
+ uri: params[parameters4.connectionUrl.slug],
1024
+ connectTimeout: 1e4
1025
+ });
1026
+ try {
1027
+ await pool.query("SELECT 1");
1028
+ return { success: true };
1029
+ } catch (e) {
1030
+ return { success: false, error: e instanceof Error ? e.message : String(e) };
1031
+ } finally {
1032
+ await pool.end();
1033
+ }
1034
+ },
924
1035
  async query(params, sql, namedParams) {
925
1036
  const mysql = await import("mysql2/promise");
926
1037
  const { text, values } = buildQuestionmarkParams(sql, namedParams);
@@ -1039,14 +1150,10 @@ var bigquerySetup = new ConnectorSetup({
1039
1150
 
1040
1151
  #### \u30B9\u30C6\u30C3\u30D71: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u9078\u629E
1041
1152
  1. \`${listProjectsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGCP\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
1042
- 2. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
1043
- - **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: false\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u629E\u3055\u305B\u308B\u3002\u9078\u629E\u80A2\u306E label \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u306B\u3059\u308B
1044
- - **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
1045
- 3. \`updateConnectionParameters\` \u3067\u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
1153
+ 2. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
1046
1154
  - \`parameterSlug\`: \`"project-id"\`
1047
- - \`value\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
1048
- - \`displayValue\`: \`"\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)"\`
1049
- 4. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
1155
+ - \`options\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
1156
+ 3. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
1050
1157
 
1051
1158
  #### \u30B9\u30C6\u30C3\u30D72: \u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u9078\u629E
1052
1159
  1. \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` \u3092\u5B9F\u884C\u3057\u3066\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
@@ -1081,14 +1188,10 @@ Follow these steps to set up the BigQuery connection.
1081
1188
 
1082
1189
  #### Step 1: Project Selection
1083
1190
  1. Call \`${listProjectsToolName}\` to get the list of GCP projects accessible with the service account credentials
1084
- 2. Branch based on results:
1085
- - **2 or more projects**: Present them to the user via \`askUserQuestion\` (multiSelect: false) and let them select a project. Format option labels as \`Project Name (id: project-id)\`
1086
- - **Exactly 1 project**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected project X" in one sentence
1087
- 3. Call \`updateConnectionParameters\` to save the selected project:
1191
+ 2. Call \`updateConnectionParameters\` to save the project:
1088
1192
  - \`parameterSlug\`: \`"project-id"\`
1089
- - \`value\`: the project ID
1090
- - \`displayValue\`: \`"Project Name (id: project-id)"\`
1091
- 4. After receiving the continuation message, proceed to Step 2
1193
+ - \`options\`: The project list. Each option's \`label\` should be \`Project Name (id: project-id)\`, \`value\` should be the project ID
1194
+ 3. After receiving the continuation message, proceed to Step 2
1092
1195
 
1093
1196
  #### Step 2: Dataset Selection
1094
1197
  1. Run \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` to get the list of datasets
@@ -1203,6 +1306,23 @@ var bigqueryConnector = new ConnectorPlugin({
1203
1306
  - List columns: \`SELECT column_name, data_type FROM \\\`project_id.dataset\\\`.INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'xxx'\`
1204
1307
  - Always specify project_id explicitly in queries`,
1205
1308
  tools: tools5,
1309
+ async checkConnection(params, _config) {
1310
+ const { BigQuery } = await import("@google-cloud/bigquery");
1311
+ const credentials = JSON.parse(
1312
+ Buffer.from(params[parameters5.serviceAccountKeyJsonBase64.slug], "base64").toString("utf-8")
1313
+ );
1314
+ const bq = new BigQuery({
1315
+ projectId: params[parameters5.projectId.slug],
1316
+ credentials
1317
+ });
1318
+ try {
1319
+ const [job] = await bq.createQueryJob({ query: "SELECT 1" });
1320
+ await job.getQueryResults();
1321
+ return { success: true };
1322
+ } catch (error) {
1323
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1324
+ }
1325
+ },
1206
1326
  async query(params, sql, namedParams) {
1207
1327
  const { BigQuery } = await import("@google-cloud/bigquery");
1208
1328
  const resolvedSql = replaceLiteralParams(sql, namedParams);
@@ -1337,14 +1457,10 @@ var bigquerySetup2 = new ConnectorSetup({
1337
1457
 
1338
1458
  #### \u30B9\u30C6\u30C3\u30D71: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u9078\u629E
1339
1459
  1. \`${listProjectsToolName2}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGCP\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
1340
- 2. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
1341
- - **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: false\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u629E\u3055\u305B\u308B\u3002\u9078\u629E\u80A2\u306E label \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u306B\u3059\u308B
1342
- - **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
1343
- 3. \`updateConnectionParameters\` \u3067\u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
1460
+ 2. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
1344
1461
  - \`parameterSlug\`: \`"project-id"\`
1345
- - \`value\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
1346
- - \`displayValue\`: \`"\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)"\`
1347
- 4. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
1462
+ - \`options\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
1463
+ 3. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
1348
1464
 
1349
1465
  #### \u30B9\u30C6\u30C3\u30D72: \u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u9078\u629E
1350
1466
  1. \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` \u3092\u5B9F\u884C\u3057\u3066\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
@@ -1379,14 +1495,10 @@ Follow these steps to set up the BigQuery connection.
1379
1495
 
1380
1496
  #### Step 1: Project Selection
1381
1497
  1. Call \`${listProjectsToolName2}\` to get the list of GCP projects accessible with the OAuth credentials
1382
- 2. Branch based on results:
1383
- - **2 or more projects**: Present them to the user via \`askUserQuestion\` (multiSelect: false) and let them select a project. Format option labels as \`Project Name (id: project-id)\`
1384
- - **Exactly 1 project**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected project X" in one sentence
1385
- 3. Call \`updateConnectionParameters\` to save the selected project:
1498
+ 2. Call \`updateConnectionParameters\` to save the project:
1386
1499
  - \`parameterSlug\`: \`"project-id"\`
1387
- - \`value\`: the project ID
1388
- - \`displayValue\`: \`"Project Name (id: project-id)"\`
1389
- 4. After receiving the continuation message, proceed to Step 2
1500
+ - \`options\`: The project list. Each option's \`label\` should be \`Project Name (id: project-id)\`, \`value\` should be the project ID
1501
+ 3. After receiving the continuation message, proceed to Step 2
1390
1502
 
1391
1503
  #### Step 2: Dataset Selection
1392
1504
  1. Run \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` to get the list of datasets
@@ -1594,6 +1706,25 @@ var bigqueryOauthConnector = new ConnectorPlugin({
1594
1706
  - List columns: \`SELECT column_name, data_type FROM \\\`project_id.dataset\\\`.INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'xxx'\`
1595
1707
  - Always specify project_id explicitly in queries`,
1596
1708
  tools: tools6,
1709
+ async checkConnection(params, config) {
1710
+ const { proxyFetch } = config;
1711
+ const projectId = params[parameters6.projectId.slug];
1712
+ const url = `https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/queries`;
1713
+ try {
1714
+ const res = await proxyFetch(url, {
1715
+ method: "POST",
1716
+ headers: { "Content-Type": "application/json" },
1717
+ body: JSON.stringify({ query: "SELECT 1", useLegacySql: false })
1718
+ });
1719
+ if (!res.ok) {
1720
+ const errorText = await res.text().catch(() => res.statusText);
1721
+ return { success: false, error: `BigQuery query failed: HTTP ${res.status} ${errorText}` };
1722
+ }
1723
+ return { success: true };
1724
+ } catch (error) {
1725
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1726
+ }
1727
+ },
1597
1728
  async query(params, sql, namedParams, context) {
1598
1729
  const { proxyFetch } = context;
1599
1730
  const projectId = params[parameters6.projectId.slug];
@@ -1798,6 +1929,62 @@ var awsAthenaConnector = new ConnectorPlugin({
1798
1929
  - Always include LIMIT in queries
1799
1930
  - Query execution is asynchronous and results may take time to retrieve`,
1800
1931
  tools: tools7,
1932
+ async checkConnection(params, _config) {
1933
+ try {
1934
+ const {
1935
+ AthenaClient,
1936
+ StartQueryExecutionCommand,
1937
+ GetQueryExecutionCommand
1938
+ } = await import("@aws-sdk/client-athena");
1939
+ const workgroup = params[parameters7.workgroup.slug];
1940
+ const outputLocation = params[parameters7.outputLocation.slug];
1941
+ if (!workgroup && !outputLocation) {
1942
+ return {
1943
+ success: false,
1944
+ error: "Either workgroup or output-location is required"
1945
+ };
1946
+ }
1947
+ const client = new AthenaClient({
1948
+ region: params[parameters7.awsRegion.slug],
1949
+ credentials: {
1950
+ accessKeyId: params[parameters7.awsAccessKeyId.slug],
1951
+ secretAccessKey: params[parameters7.awsSecretAccessKey.slug]
1952
+ }
1953
+ });
1954
+ const startParams = { QueryString: "SELECT 1" };
1955
+ if (workgroup) startParams.WorkGroup = workgroup;
1956
+ if (outputLocation) {
1957
+ startParams.ResultConfiguration = { OutputLocation: outputLocation };
1958
+ }
1959
+ const { QueryExecutionId } = await client.send(
1960
+ new StartQueryExecutionCommand(startParams)
1961
+ );
1962
+ const startTime = Date.now();
1963
+ while (true) {
1964
+ const exec = await client.send(
1965
+ new GetQueryExecutionCommand({ QueryExecutionId })
1966
+ );
1967
+ const state = exec.QueryExecution?.Status?.State;
1968
+ if (state === "SUCCEEDED") break;
1969
+ if (state === "FAILED" || state === "CANCELLED") {
1970
+ return {
1971
+ success: false,
1972
+ error: exec.QueryExecution?.Status?.StateChangeReason || `Query ${state}`
1973
+ };
1974
+ }
1975
+ if (Date.now() - startTime > 12e4) {
1976
+ return { success: false, error: "Query timed out after 120 seconds" };
1977
+ }
1978
+ await new Promise((r) => setTimeout(r, 1e3));
1979
+ }
1980
+ return { success: true };
1981
+ } catch (error) {
1982
+ return {
1983
+ success: false,
1984
+ error: error instanceof Error ? error.message : String(error)
1985
+ };
1986
+ }
1987
+ },
1801
1988
  async query(params, sql, namedParams) {
1802
1989
  const {
1803
1990
  AthenaClient,
@@ -2075,6 +2262,65 @@ var redshiftConnector = new ConnectorPlugin({
2075
2262
  - Always include LIMIT in queries
2076
2263
  - Query execution is asynchronous and results may take time to retrieve`,
2077
2264
  tools: tools8,
2265
+ async checkConnection(params, _config) {
2266
+ try {
2267
+ const {
2268
+ RedshiftDataClient,
2269
+ ExecuteStatementCommand,
2270
+ DescribeStatementCommand
2271
+ } = await import("@aws-sdk/client-redshift-data");
2272
+ const clusterIdentifier = params[parameters8.clusterIdentifier.slug];
2273
+ const workgroupName = params[parameters8.workgroupName.slug];
2274
+ const secretArn = params[parameters8.secretArn.slug];
2275
+ const dbUser = params[parameters8.dbUser.slug];
2276
+ if (!clusterIdentifier && !workgroupName) {
2277
+ return {
2278
+ success: false,
2279
+ error: "Either cluster-identifier or workgroup-name is required"
2280
+ };
2281
+ }
2282
+ const client = new RedshiftDataClient({
2283
+ region: params[parameters8.awsRegion.slug],
2284
+ credentials: {
2285
+ accessKeyId: params[parameters8.awsAccessKeyId.slug],
2286
+ secretAccessKey: params[parameters8.awsSecretAccessKey.slug]
2287
+ }
2288
+ });
2289
+ const { Id: statementId } = await client.send(
2290
+ new ExecuteStatementCommand({
2291
+ Database: params[parameters8.database.slug],
2292
+ Sql: "SELECT 1",
2293
+ ...clusterIdentifier && { ClusterIdentifier: clusterIdentifier },
2294
+ ...workgroupName && { WorkgroupName: workgroupName },
2295
+ ...secretArn && { SecretArn: secretArn },
2296
+ ...dbUser && { DbUser: dbUser }
2297
+ })
2298
+ );
2299
+ const startTime = Date.now();
2300
+ while (true) {
2301
+ const desc = await client.send(
2302
+ new DescribeStatementCommand({ Id: statementId })
2303
+ );
2304
+ if (desc.Status === "FINISHED") break;
2305
+ if (desc.Status === "FAILED" || desc.Status === "ABORTED") {
2306
+ return {
2307
+ success: false,
2308
+ error: desc.Error || `Statement ${desc.Status}`
2309
+ };
2310
+ }
2311
+ if (Date.now() - startTime > 12e4) {
2312
+ return { success: false, error: "Query timed out after 120 seconds" };
2313
+ }
2314
+ await new Promise((r) => setTimeout(r, 1e3));
2315
+ }
2316
+ return { success: true };
2317
+ } catch (error) {
2318
+ return {
2319
+ success: false,
2320
+ error: error instanceof Error ? error.message : String(error)
2321
+ };
2322
+ }
2323
+ },
2078
2324
  async query(params, sql, namedParams) {
2079
2325
  const {
2080
2326
  RedshiftDataClient,
@@ -2263,6 +2509,34 @@ var databricksConnector = new ConnectorPlugin({
2263
2509
  - List columns: \`DESCRIBE TABLE table_name\`
2264
2510
  - Always include LIMIT in queries`,
2265
2511
  tools: tools9,
2512
+ async checkConnection(params, _config) {
2513
+ const { DBSQLClient } = await import("@databricks/sql");
2514
+ const client = new DBSQLClient();
2515
+ await client.connect({
2516
+ host: params[parameters9.host.slug],
2517
+ path: params[parameters9.httpPath.slug],
2518
+ token: params[parameters9.token.slug]
2519
+ });
2520
+ let session;
2521
+ let operation;
2522
+ try {
2523
+ session = await client.openSession();
2524
+ operation = await session.executeStatement("SELECT 1", {
2525
+ runAsync: true
2526
+ });
2527
+ await operation.fetchAll();
2528
+ return { success: true };
2529
+ } catch (e) {
2530
+ return { success: false, error: e instanceof Error ? e.message : String(e) };
2531
+ } finally {
2532
+ if (operation) await operation.close().catch(() => {
2533
+ });
2534
+ if (session) await session.close().catch(() => {
2535
+ });
2536
+ await client.close().catch(() => {
2537
+ });
2538
+ }
2539
+ },
2266
2540
  async query(params, sql, namedParams) {
2267
2541
  const { DBSQLClient } = await import("@databricks/sql");
2268
2542
  const resolvedSql = replaceLiteralParams(sql, namedParams);
@@ -3124,6 +3398,22 @@ var squadbaseDbConnector = new ConnectorPlugin({
3124
3398
  - List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
3125
3399
  - Always include LIMIT in queries`,
3126
3400
  tools: tools15,
3401
+ async checkConnection(params, _config) {
3402
+ const { Pool } = await import("pg");
3403
+ const pool = new Pool({
3404
+ connectionString: params[parameters15.connectionUrl.slug],
3405
+ ssl: { rejectUnauthorized: false },
3406
+ connectionTimeoutMillis: 1e4
3407
+ });
3408
+ try {
3409
+ await pool.query("SELECT 1");
3410
+ return { success: true };
3411
+ } catch (error) {
3412
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
3413
+ } finally {
3414
+ await pool.end();
3415
+ }
3416
+ },
3127
3417
  async query(params, sql, namedParams) {
3128
3418
  const { Pool } = await import("pg");
3129
3419
  const { text, values } = buildPositionalParams(sql, namedParams);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squadbase/connectors",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Squadbase Connectors",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",