@squadbase/vite-server 0.1.9-dev.08f5c5f → 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.
package/dist/cli/index.js CHANGED
@@ -116968,8 +116968,8 @@ var mondayConnector = new ConnectorPlugin({
116968
116968
  The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
116969
116969
 
116970
116970
  SDK methods (client created via \`connection(connectionId)\`):
116971
- - \`client.graphql(query, variables?)\` \u2014 send any GraphQL query/mutation and get typed data back
116972
- - \`client.request(init?)\` \u2014 low-level authenticated fetch to the GraphQL endpoint
116971
+ - \`client.graphql(query, variables?)\` \u2014 send any GraphQL query/mutation. **Returns the GraphQL \`data\` payload directly with the outer \`{ data, errors }\` envelope already stripped.** For \`{ boards { ... } }\` you get \`{ boards: [...] }\`, NOT \`{ data: { boards: [...] } }\`. Access fields as \`result.boards\`, never \`result.data.boards\`. Errors are thrown automatically.
116972
+ - \`client.request(init?)\` \u2014 low-level authenticated fetch to the GraphQL endpoint (returns the raw \`Response\`; you parse the full \`{ data, errors }\` envelope yourself)
116973
116973
  - \`client.me()\` \u2014 get the authenticated user and account
116974
116974
  - \`client.listBoards(options?)\` \u2014 list boards with optional ids, workspaceIds, state, page, limit
116975
116975
  - \`client.getBoard(boardId)\` \u2014 fetch a single board with columns, groups, owners, tags
@@ -116998,6 +116998,26 @@ export default async function handler(c: Context) {
116998
116998
  }
116999
116999
  \`\`\`
117000
117000
 
117001
+ #### \`client.graphql()\` return shape (common pitfall)
117002
+
117003
+ \`client.graphql()\` already unwraps the GraphQL response envelope. **Do not access \`.data\` on the return value** \u2014 it is always \`undefined\` and will silently produce empty results.
117004
+
117005
+ \`\`\`ts
117006
+ // \u2705 Correct \u2014 fields are at the top level
117007
+ const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
117008
+ \`query($ids: [ID!], $limit: Int) {
117009
+ boards(ids: $ids) {
117010
+ items_page(limit: $limit) { cursor items { id name } }
117011
+ }
117012
+ }\`,
117013
+ { ids: [boardId], limit: 100 },
117014
+ );
117015
+ const items = res.boards?.[0]?.items_page?.items ?? [];
117016
+
117017
+ // \u274C Wrong \u2014 \`res.data\` is undefined; \`.data\` was already stripped by the SDK
117018
+ const items = res.data?.boards?.[0]?.items_page?.items; // always undefined!
117019
+ \`\`\`
117020
+
117001
117021
  ### monday.com GraphQL API Reference
117002
117022
 
117003
117023
  - Endpoint: \`https://api.monday.com/v2\`
@@ -117038,8 +117058,8 @@ export default async function handler(c: Context) {
117038
117058
  \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
117039
117059
 
117040
117060
  SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
117041
- - \`client.graphql(query, variables?)\` \u2014 \u4EFB\u610F\u306EGraphQL\u30AF\u30A8\u30EA/\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u3092\u9001\u4FE1\u3057\u578B\u4ED8\u304D\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
117042
- - \`client.request(init?)\` \u2014 GraphQL\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3078\u306E\u4F4E\u30EC\u30D9\u30EB\u8A8D\u8A3C\u4ED8\u304Dfetch
117061
+ - \`client.graphql(query, variables?)\` \u2014 \u4EFB\u610F\u306EGraphQL\u30AF\u30A8\u30EA/\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u3092\u9001\u4FE1\u3002**\u623B\u308A\u5024\u306F GraphQL \u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`data\` \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u65E2\u306B\u30A2\u30F3\u30E9\u30C3\u30D7\u3057\u305F\u3082\u306E**\u3002\`{ boards { ... } }\` \u3092\u6295\u3052\u305F\u5834\u5408\u306E\u623B\u308A\u5024\u306F \`{ boards: [...] }\` \u3067\u3042\u308A\u3001\`{ data: { boards: [...] } }\` \u3067\u306F\u306A\u3044\u3002\`result.boards\` \u306E\u3088\u3046\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u3001\`result.data.boards\` \u306E\u3088\u3046\u306B \`.data\` \u3092\u7D4C\u7531\u3057\u3066\u306F\u3044\u3051\u306A\u3044\u3002\u30A8\u30E9\u30FC\u306F\u81EA\u52D5\u3067\u4F8B\u5916\u3068\u3057\u3066\u6295\u3052\u3089\u308C\u308B\u3002
117062
+ - \`client.request(init?)\` \u2014 GraphQL\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3078\u306E\u4F4E\u30EC\u30D9\u30EB\u8A8D\u8A3C\u4ED8\u304Dfetch\uFF08\u751F\u306E \`Response\` \u3092\u8FD4\u3059\u3002\`{ data, errors }\` \u30A8\u30F3\u30D9\u30ED\u30FC\u30D7\u3092\u81EA\u5206\u3067\u30D1\u30FC\u30B9\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\uFF09
117043
117063
  - \`client.me()\` \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u3068\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u53D6\u5F97
117044
117064
  - \`client.listBoards(options?)\` \u2014 ids/workspaceIds/state/page/limit \u3067\u30DC\u30FC\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
117045
117065
  - \`client.getBoard(boardId)\` \u2014 1\u3064\u306E\u30DC\u30FC\u30C9\u3092 columns/groups/owners/tags \u4ED8\u304D\u3067\u53D6\u5F97
@@ -117068,6 +117088,26 @@ export default async function handler(c: Context) {
117068
117088
  }
117069
117089
  \`\`\`
117070
117090
 
117091
+ #### \`client.graphql()\` \u306E\u623B\u308A\u5024\uFF08\u3088\u304F\u3042\u308B\u9593\u9055\u3044\uFF09
117092
+
117093
+ \`client.graphql()\` \u306F GraphQL \u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`data\` \u3092\u3059\u3067\u306B\u30A2\u30F3\u30E9\u30C3\u30D7\u3057\u3066\u3044\u308B\u3002**\u623B\u308A\u5024\u306B\u5BFE\u3057\u3066 \`.data\` \u3092\u7D4C\u7531\u3057\u3066\u306F\u3044\u3051\u306A\u3044** \u2014 \u5E38\u306B \`undefined\` \u3068\u306A\u308A\u3001\u7D50\u679C\u304C\u7121\u97F3\u3067\u7A7A\u306B\u306A\u308B\u3002
117094
+
117095
+ \`\`\`ts
117096
+ // \u2705 \u6B63\u3057\u3044 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u306B\u3042\u308B
117097
+ const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
117098
+ \`query($ids: [ID!], $limit: Int) {
117099
+ boards(ids: $ids) {
117100
+ items_page(limit: $limit) { cursor items { id name } }
117101
+ }
117102
+ }\`,
117103
+ { ids: [boardId], limit: 100 },
117104
+ );
117105
+ const items = res.boards?.[0]?.items_page?.items ?? [];
117106
+
117107
+ // \u274C \u8AA4\u308A \u2014 \`res.data\` \u306F undefined\uFF08SDK\u304C\u65E2\u306B \`.data\` \u3092\u5265\u304C\u3057\u3066\u3044\u308B\uFF09
117108
+ const items = res.data?.boards?.[0]?.items_page?.items; // \u5E38\u306B undefined\uFF01
117109
+ \`\`\`
117110
+
117071
117111
  ### monday.com GraphQL API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
117072
117112
 
117073
117113
  - \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8: \`https://api.monday.com/v2\`
@@ -117103,6 +117143,230 @@ export default async function handler(c: Context) {
117103
117143
  tools: tools66
117104
117144
  });
117105
117145
 
117146
+ // ../connectors/src/connectors/sqlserver/utils.ts
117147
+ var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
117148
+ var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
117149
+ var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
117150
+ function parseBoolean(value) {
117151
+ if (value == null) return void 0;
117152
+ const lower = value.toLowerCase();
117153
+ if (TRUE_VALUES.has(lower)) return true;
117154
+ if (FALSE_VALUES.has(lower)) return false;
117155
+ return void 0;
117156
+ }
117157
+ function parseSqlServerJdbcUrl(jdbcUrl, options = {}) {
117158
+ const trimmed = jdbcUrl.trim();
117159
+ if (!SQLSERVER_PREFIX_RE.test(trimmed)) {
117160
+ throw new Error(
117161
+ `Unsupported SQL Server URL "${redactSqlServerUrl(trimmed)}". Expected prefix: jdbc:sqlserver:// or sqlserver://.`
117162
+ );
117163
+ }
117164
+ const withoutPrefix = trimmed.replace(SQLSERVER_PREFIX_RE, "");
117165
+ const [hostAndPath, ...propertySegments] = withoutPrefix.split(";");
117166
+ const props = {};
117167
+ for (const segment of propertySegments) {
117168
+ if (!segment) continue;
117169
+ const eqIdx = segment.indexOf("=");
117170
+ if (eqIdx === -1) continue;
117171
+ const key = segment.slice(0, eqIdx).trim().toLowerCase();
117172
+ const value = segment.slice(eqIdx + 1).trim();
117173
+ if (key) props[key] = value;
117174
+ }
117175
+ const url = new URL(`mssql://${hostAndPath}`);
117176
+ for (const [key, value] of url.searchParams.entries()) {
117177
+ if (!(key.toLowerCase() in props)) {
117178
+ props[key.toLowerCase()] = value;
117179
+ }
117180
+ }
117181
+ const server = url.hostname;
117182
+ const port = url.port ? Number(url.port) : 1433;
117183
+ const pathname = url.pathname.replace(/^\//, "");
117184
+ const database = pathname || props["database"] || props["databasename"];
117185
+ const user = props["user"] || props["username"] || props["userid"] || options.username;
117186
+ const password = props["password"] || options.password;
117187
+ return {
117188
+ server,
117189
+ port,
117190
+ database,
117191
+ user,
117192
+ password,
117193
+ options: props
117194
+ };
117195
+ }
117196
+ function toMssqlConfig(parsed, defaults = {}) {
117197
+ const encrypt = parseBoolean(parsed.options["encrypt"]) ?? defaults.encrypt ?? false;
117198
+ const trustServerCertificate = parseBoolean(parsed.options["trustservercertificate"]) ?? !encrypt;
117199
+ return {
117200
+ server: parsed.server,
117201
+ port: parsed.port,
117202
+ database: parsed.database,
117203
+ user: parsed.user,
117204
+ password: parsed.password,
117205
+ connectionTimeout: 1e4,
117206
+ requestTimeout: 6e4,
117207
+ options: {
117208
+ encrypt,
117209
+ trustServerCertificate
117210
+ }
117211
+ };
117212
+ }
117213
+ function redactSqlServerUrl(jdbcUrl) {
117214
+ return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
117215
+ }
117216
+
117217
+ // ../connectors/src/lib/mssql-runner.ts
117218
+ async function importMssql() {
117219
+ const mod = await import("mssql");
117220
+ return mod.default ?? mod;
117221
+ }
117222
+ async function runMssqlQuery(parsed, sql, options = {}) {
117223
+ const sqlMod = await importMssql();
117224
+ const config = toMssqlConfig(parsed, {
117225
+ encrypt: options.forceEncrypt
117226
+ });
117227
+ const pool = new sqlMod.ConnectionPool(config);
117228
+ await pool.connect();
117229
+ try {
117230
+ const result = await pool.request().query(sql);
117231
+ const recordset = result.recordset ?? [];
117232
+ return { rows: recordset };
117233
+ } finally {
117234
+ await pool.close();
117235
+ }
117236
+ }
117237
+ async function checkMssqlConnection(url, credentials, options = {}) {
117238
+ let parsed;
117239
+ try {
117240
+ parsed = parseSqlServerJdbcUrl(url, credentials);
117241
+ } catch (err) {
117242
+ return {
117243
+ success: false,
117244
+ error: err instanceof Error ? err.message : String(err)
117245
+ };
117246
+ }
117247
+ try {
117248
+ await runMssqlQuery(parsed, "SELECT 1 AS one", options);
117249
+ return { success: true };
117250
+ } catch (err) {
117251
+ let msg = err instanceof Error ? err.message : String(err);
117252
+ msg = msg.replaceAll(url, redactSqlServerUrl(url));
117253
+ return { success: false, error: msg };
117254
+ }
117255
+ }
117256
+
117257
+ // ../connectors/src/connectors/oracle/utils.ts
117258
+ var JDBC_THIN_PREFIX_RE = /^jdbc:oracle:thin:/i;
117259
+ var JDBC_OCI_PREFIX_RE = /^jdbc:oracle:oci/i;
117260
+ var URL_PREFIX_RE = /^oracle:\/\//i;
117261
+ function parseOracleJdbcUrl(jdbcUrl, options = {}) {
117262
+ const trimmed = jdbcUrl.trim();
117263
+ if (JDBC_OCI_PREFIX_RE.test(trimmed)) {
117264
+ throw new Error(
117265
+ "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
117266
+ );
117267
+ }
117268
+ if (URL_PREFIX_RE.test(trimmed)) {
117269
+ const url = new URL(trimmed);
117270
+ const path5 = url.pathname.replace(/^\//, "");
117271
+ if (!url.hostname || !path5) {
117272
+ throw new Error(
117273
+ `Invalid Oracle URL "${redactOracleUrl(trimmed)}". Expected oracle://[user:password@]host:port/service`
117274
+ );
117275
+ }
117276
+ const port = url.port || "1521";
117277
+ return {
117278
+ connectString: `${url.hostname}:${port}/${path5}`,
117279
+ user: url.username ? decodeURIComponent(url.username) : options.username,
117280
+ password: url.password ? decodeURIComponent(url.password) : options.password
117281
+ };
117282
+ }
117283
+ if (!JDBC_THIN_PREFIX_RE.test(trimmed)) {
117284
+ throw new Error(
117285
+ `Unsupported Oracle URL "${redactOracleUrl(trimmed)}". Expected prefix: jdbc:oracle:thin:@ or oracle://`
117286
+ );
117287
+ }
117288
+ const afterPrefix = trimmed.replace(JDBC_THIN_PREFIX_RE, "");
117289
+ const atIdx = afterPrefix.indexOf("@");
117290
+ if (atIdx === -1) {
117291
+ throw new Error(
117292
+ `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Expected '@' separator before host.`
117293
+ );
117294
+ }
117295
+ const credentialsPart = afterPrefix.slice(0, atIdx);
117296
+ const target = afterPrefix.slice(atIdx + 1).replace(/^\/\//, "");
117297
+ let user = options.username;
117298
+ let password = options.password;
117299
+ if (credentialsPart) {
117300
+ const slashIdx = credentialsPart.indexOf("/");
117301
+ if (slashIdx === -1) {
117302
+ user = credentialsPart || user;
117303
+ } else {
117304
+ user = credentialsPart.slice(0, slashIdx) || user;
117305
+ password = credentialsPart.slice(slashIdx + 1) || password;
117306
+ }
117307
+ }
117308
+ if (!target) {
117309
+ throw new Error(
117310
+ `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Missing host portion after '@'.`
117311
+ );
117312
+ }
117313
+ return {
117314
+ connectString: target,
117315
+ user,
117316
+ password
117317
+ };
117318
+ }
117319
+ function redactOracleUrl(jdbcUrl) {
117320
+ return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(thin:)([^@]+)@/i, "$1***@");
117321
+ }
117322
+
117323
+ // ../connectors/src/lib/oracle-runner.ts
117324
+ async function importOracleDb() {
117325
+ const mod = await import("oracledb");
117326
+ return mod.default ?? mod;
117327
+ }
117328
+ async function runOracleQuery(parsed, sql) {
117329
+ const oracledb = await importOracleDb();
117330
+ const connection = await oracledb.getConnection({
117331
+ user: parsed.user,
117332
+ password: parsed.password,
117333
+ connectString: parsed.connectString
117334
+ });
117335
+ try {
117336
+ const result = await connection.execute(sql, [], {
117337
+ outFormat: oracledb.OUT_FORMAT_OBJECT,
117338
+ // Bound by the connector's own row cap, but keep the driver from
117339
+ // streaming arbitrarily large result sets.
117340
+ maxRows: 5e3
117341
+ });
117342
+ return { rows: result.rows ?? [] };
117343
+ } finally {
117344
+ try {
117345
+ await connection.close();
117346
+ } catch {
117347
+ }
117348
+ }
117349
+ }
117350
+ async function checkOracleConnection(url, credentials) {
117351
+ let parsed;
117352
+ try {
117353
+ parsed = parseOracleJdbcUrl(url, credentials);
117354
+ } catch (err) {
117355
+ return {
117356
+ success: false,
117357
+ error: err instanceof Error ? err.message : String(err)
117358
+ };
117359
+ }
117360
+ try {
117361
+ await runOracleQuery(parsed, "SELECT 1 FROM DUAL");
117362
+ return { success: true };
117363
+ } catch (err) {
117364
+ let msg = err instanceof Error ? err.message : String(err);
117365
+ msg = msg.replaceAll(url, redactOracleUrl(url));
117366
+ return { success: false, error: msg };
117367
+ }
117368
+ }
117369
+
117106
117370
  // ../connectors/src/connectors/jdbc/setup.ts
117107
117371
  var jdbcOnboarding = new ConnectorOnboarding({
117108
117372
  dataOverviewInstructions: {
@@ -117157,20 +117421,82 @@ var parameters67 = {
117157
117421
  import { z as z82 } from "zod";
117158
117422
 
117159
117423
  // ../connectors/src/connectors/jdbc/utils.ts
117160
- var JDBC_PREFIX_RE = /^jdbc:(postgresql|postgres|mysql|mariadb):\/\//i;
117424
+ var POSTGRES_PREFIX_RE = /^jdbc:(postgresql|postgres):\/\//i;
117425
+ var MYSQL_PREFIX_RE = /^jdbc:(mysql|mariadb):\/\//i;
117426
+ var REDSHIFT_PREFIX_RE = /^jdbc:redshift:\/\//i;
117427
+ var SQLSERVER_PREFIX_RE2 = /^jdbc:sqlserver:\/\//i;
117428
+ var ORACLE_PREFIX_RE = /^jdbc:oracle:thin:/i;
117429
+ var KNOWN_UNSUPPORTED = [
117430
+ {
117431
+ prefix: /^jdbc:snowflake:\/\//i,
117432
+ message: "Snowflake JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `snowflake` connector."
117433
+ },
117434
+ {
117435
+ prefix: /^jdbc:bigquery:\/\//i,
117436
+ message: "BigQuery JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `bigquery` connector."
117437
+ },
117438
+ {
117439
+ prefix: /^jdbc:databricks:\/\//i,
117440
+ message: "Databricks JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `databricks` connector."
117441
+ },
117442
+ {
117443
+ prefix: /^jdbc:(trino|presto):\/\//i,
117444
+ message: "Trino/Presto JDBC URLs are not yet supported by the `jdbc` connector (no Node.js client bundled)."
117445
+ },
117446
+ {
117447
+ prefix: /^jdbc:td:\/\//i,
117448
+ message: "Treasure Data JDBC URLs are not yet supported by the `jdbc` connector (no Node.js client bundled). The TD JDBC driver speaks Presto under the hood; Trino/Presto support is the same prerequisite."
117449
+ },
117450
+ {
117451
+ prefix: /^jdbc:oracle:oci/i,
117452
+ message: "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
117453
+ },
117454
+ {
117455
+ prefix: /^jdbc:db2:\/\//i,
117456
+ message: "DB2 JDBC URLs are not yet supported by the `jdbc` connector."
117457
+ },
117458
+ {
117459
+ prefix: /^jdbc:(sybase|h2|hsqldb|derby|firebird|sqlite):/i,
117460
+ message: "This JDBC dialect is not supported by the `jdbc` connector."
117461
+ }
117462
+ ];
117161
117463
  function parseJdbcUrl(jdbcUrl, options = {}) {
117162
117464
  const trimmed = jdbcUrl.trim();
117163
- const match = JDBC_PREFIX_RE.exec(trimmed);
117164
- if (!match) {
117465
+ if (SQLSERVER_PREFIX_RE2.test(trimmed)) {
117466
+ return { driver: "sqlserver", originalUrl: trimmed };
117467
+ }
117468
+ if (ORACLE_PREFIX_RE.test(trimmed)) {
117469
+ return { driver: "oracle", originalUrl: trimmed };
117470
+ }
117471
+ let driver;
117472
+ let defaultPort;
117473
+ let forceSsl = false;
117474
+ let nativeProtocol;
117475
+ let withoutPrefix;
117476
+ if (POSTGRES_PREFIX_RE.test(trimmed)) {
117477
+ driver = "postgresql";
117478
+ defaultPort = 5432;
117479
+ nativeProtocol = "postgresql://";
117480
+ withoutPrefix = trimmed.replace(POSTGRES_PREFIX_RE, nativeProtocol);
117481
+ } else if (REDSHIFT_PREFIX_RE.test(trimmed)) {
117482
+ driver = "postgresql";
117483
+ defaultPort = 5439;
117484
+ forceSsl = true;
117485
+ nativeProtocol = "postgresql://";
117486
+ withoutPrefix = trimmed.replace(REDSHIFT_PREFIX_RE, nativeProtocol);
117487
+ } else if (MYSQL_PREFIX_RE.test(trimmed)) {
117488
+ driver = "mysql";
117489
+ defaultPort = 3306;
117490
+ nativeProtocol = "mysql://";
117491
+ withoutPrefix = trimmed.replace(MYSQL_PREFIX_RE, nativeProtocol);
117492
+ } else {
117493
+ for (const { prefix, message } of KNOWN_UNSUPPORTED) {
117494
+ if (prefix.test(trimmed)) throw new Error(message);
117495
+ }
117165
117496
  throw new Error(
117166
- `Unsupported JDBC URL "${redactJdbcUrl(trimmed)}". Supported prefixes: jdbc:postgresql://, jdbc:mysql://, jdbc:mariadb://.`
117497
+ `Unsupported JDBC URL "${redactJdbcUrl(trimmed)}". Supported prefixes: jdbc:postgresql://, jdbc:postgres://, jdbc:mysql://, jdbc:mariadb://, jdbc:sqlserver://, jdbc:oracle:thin:@, jdbc:redshift://.`
117167
117498
  );
117168
117499
  }
117169
- const subProtocol = match[1].toLowerCase();
117170
- const driver = subProtocol === "mysql" || subProtocol === "mariadb" ? "mysql" : "postgresql";
117171
- const defaultPort = driver === "postgresql" ? 5432 : 3306;
117172
- const nativeProtocol = driver === "postgresql" ? "postgresql://" : "mysql://";
117173
- const withoutPrefix = trimmed.replace(JDBC_PREFIX_RE, nativeProtocol);
117174
117500
  const url = new URL(withoutPrefix);
117175
117501
  if (options.username && !url.username) {
117176
117502
  url.username = encodeURIComponent(options.username);
@@ -117178,10 +117504,10 @@ function parseJdbcUrl(jdbcUrl, options = {}) {
117178
117504
  if (options.password && !url.password) {
117179
117505
  url.password = encodeURIComponent(options.password);
117180
117506
  }
117181
- return { driver, nativeUrl: url.toString(), defaultPort };
117507
+ return { driver, nativeUrl: url.toString(), defaultPort, forceSsl };
117182
117508
  }
117183
117509
  function redactJdbcUrl(jdbcUrl) {
117184
- return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@");
117510
+ return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(password\s*=\s*)([^;&]+)/gi, "$1***");
117185
117511
  }
117186
117512
 
117187
117513
  // ../connectors/src/connectors/jdbc/tools/execute-query.ts
@@ -117194,7 +117520,7 @@ var inputSchema82 = z82.object({
117194
117520
  ),
117195
117521
  connectionId: z82.string().describe("ID of the JDBC connection to use"),
117196
117522
  sql: z82.string().describe(
117197
- "SQL query to execute. Use the dialect that matches the JDBC URL (PostgreSQL or MySQL/MariaDB). Always include LIMIT."
117523
+ "SQL query to execute. Use the dialect that matches the JDBC URL prefix (PostgreSQL / Redshift: LIMIT N; MySQL/MariaDB: LIMIT N; SQL Server: TOP N; Oracle: FETCH FIRST N ROWS ONLY). Always bound the row count."
117198
117524
  )
117199
117525
  });
117200
117526
  var outputSchema82 = z82.discriminatedUnion("success", [
@@ -117212,9 +117538,10 @@ var outputSchema82 = z82.discriminatedUnion("success", [
117212
117538
  var executeQueryTool12 = new ConnectorTool({
117213
117539
  name: "executeQuery",
117214
117540
  description: `Execute a SQL query through the JDBC connector. Returns up to ${MAX_ROWS12} rows.
117215
- Use for: schema exploration via \`information_schema\`, data sampling, analytical queries.
117216
- The connector dispatches by JDBC URL prefix to the matching driver (PostgreSQL or MySQL/MariaDB),
117217
- so use the dialect that matches the connection. Always include LIMIT.`,
117541
+ Use for: schema exploration via \`information_schema\` (or USER_TABLES on Oracle), data sampling, analytical queries.
117542
+ The connector dispatches by JDBC URL prefix to the matching driver
117543
+ (PostgreSQL / Redshift / MySQL / MariaDB / SQL Server / Oracle), so use the dialect that matches the connection.
117544
+ Always bound results: LIMIT for PG/MySQL/Redshift, TOP for SQL Server, FETCH FIRST for Oracle.`,
117218
117545
  inputSchema: inputSchema82,
117219
117546
  outputSchema: outputSchema82,
117220
117547
  async execute({ connectionId, sql }, connections) {
@@ -117240,87 +117567,121 @@ so use the dialect that matches the connection. Always include LIMIT.`,
117240
117567
  error: err instanceof Error ? err.message : String(err)
117241
117568
  };
117242
117569
  }
117243
- let tunnel;
117244
117570
  try {
117245
- tunnel = await maybeOpenSshTunnel(
117246
- connectionParamsToRecord(connection),
117247
- parsed.nativeUrl,
117248
- parsed.defaultPort
117249
- );
117250
- if (parsed.driver === "postgresql") {
117251
- const { Pool } = await import("pg");
117252
- const pool2 = new Pool({
117253
- connectionString: tunnel.connectionUrl,
117254
- ssl: { rejectUnauthorized: false },
117255
- connectionTimeoutMillis: CONNECT_TIMEOUT_MS7,
117256
- statement_timeout: STATEMENT_TIMEOUT_MS3
117571
+ if (parsed.driver === "sqlserver") {
117572
+ const mssqlParsed = parseSqlServerJdbcUrl(parsed.originalUrl, {
117573
+ username,
117574
+ password
117575
+ });
117576
+ const result = await runMssqlQuery(mssqlParsed, sql);
117577
+ const rows = result.rows;
117578
+ return {
117579
+ success: true,
117580
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117581
+ truncated: rows.length > MAX_ROWS12,
117582
+ rows: rows.slice(0, MAX_ROWS12)
117583
+ };
117584
+ }
117585
+ if (parsed.driver === "oracle") {
117586
+ const oracleParsed = parseOracleJdbcUrl(parsed.originalUrl, {
117587
+ username,
117588
+ password
117589
+ });
117590
+ const cleanSql = sql.replace(/;\s*$/, "");
117591
+ const result = await runOracleQuery(oracleParsed, cleanSql);
117592
+ const rows = result.rows;
117593
+ return {
117594
+ success: true,
117595
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117596
+ truncated: rows.length > MAX_ROWS12,
117597
+ rows: rows.slice(0, MAX_ROWS12)
117598
+ };
117599
+ }
117600
+ let tunnel;
117601
+ try {
117602
+ tunnel = await maybeOpenSshTunnel(
117603
+ connectionParamsToRecord(connection),
117604
+ parsed.nativeUrl,
117605
+ parsed.defaultPort
117606
+ );
117607
+ if (parsed.driver === "postgresql") {
117608
+ const { Pool } = await import("pg");
117609
+ const pool2 = new Pool({
117610
+ connectionString: tunnel.connectionUrl,
117611
+ ssl: { rejectUnauthorized: false },
117612
+ connectionTimeoutMillis: CONNECT_TIMEOUT_MS7,
117613
+ statement_timeout: STATEMENT_TIMEOUT_MS3
117614
+ });
117615
+ try {
117616
+ const result = await pool2.query(sql);
117617
+ const rows = result.rows;
117618
+ const truncated = rows.length > MAX_ROWS12;
117619
+ return {
117620
+ success: true,
117621
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117622
+ truncated,
117623
+ rows: rows.slice(0, MAX_ROWS12)
117624
+ };
117625
+ } finally {
117626
+ await pool2.end();
117627
+ }
117628
+ }
117629
+ const mysql = await import("mysql2/promise");
117630
+ const pool = mysql.createPool({
117631
+ uri: tunnel.connectionUrl,
117632
+ connectTimeout: CONNECT_TIMEOUT_MS7
117257
117633
  });
117258
117634
  try {
117259
- const result = await pool2.query(sql);
117260
- const rows = result.rows;
117261
- const truncated = rows.length > MAX_ROWS12;
117635
+ const queryPromise = pool.query(sql);
117636
+ const timeoutPromise = new Promise(
117637
+ (_, reject) => setTimeout(
117638
+ () => reject(new Error("Query timed out after 60 seconds")),
117639
+ STATEMENT_TIMEOUT_MS3
117640
+ )
117641
+ );
117642
+ const [rows] = await Promise.race([queryPromise, timeoutPromise]);
117643
+ const resultRows = Array.isArray(rows) ? rows : [];
117644
+ const truncated = resultRows.length > MAX_ROWS12;
117262
117645
  return {
117263
117646
  success: true,
117264
- rowCount: Math.min(rows.length, MAX_ROWS12),
117647
+ rowCount: Math.min(resultRows.length, MAX_ROWS12),
117265
117648
  truncated,
117266
- rows: rows.slice(0, MAX_ROWS12)
117649
+ rows: resultRows.slice(0, MAX_ROWS12)
117267
117650
  };
117268
117651
  } finally {
117269
- await pool2.end();
117652
+ await pool.end();
117270
117653
  }
117271
- }
117272
- const mysql = await import("mysql2/promise");
117273
- const pool = mysql.createPool({
117274
- uri: tunnel.connectionUrl,
117275
- connectTimeout: CONNECT_TIMEOUT_MS7
117276
- });
117277
- try {
117278
- const queryPromise = pool.query(sql);
117279
- const timeoutPromise = new Promise(
117280
- (_, reject) => setTimeout(
117281
- () => reject(new Error("Query timed out after 60 seconds")),
117282
- STATEMENT_TIMEOUT_MS3
117283
- )
117284
- );
117285
- const [rows] = await Promise.race([queryPromise, timeoutPromise]);
117286
- const resultRows = Array.isArray(rows) ? rows : [];
117287
- const truncated = resultRows.length > MAX_ROWS12;
117288
- return {
117289
- success: true,
117290
- rowCount: Math.min(resultRows.length, MAX_ROWS12),
117291
- truncated,
117292
- rows: resultRows.slice(0, MAX_ROWS12)
117293
- };
117294
117654
  } finally {
117295
- await pool.end();
117655
+ await tunnel?.close();
117296
117656
  }
117297
117657
  } catch (err) {
117298
117658
  let msg = err instanceof Error ? err.message : String(err);
117299
- msg = msg.replaceAll(parsed.nativeUrl, redactJdbcUrl(jdbcUrl));
117659
+ if (parsed.driver === "postgresql" || parsed.driver === "mysql") {
117660
+ msg = msg.replaceAll(parsed.nativeUrl, redactJdbcUrl(jdbcUrl));
117661
+ }
117300
117662
  msg = msg.replaceAll(jdbcUrl, redactJdbcUrl(jdbcUrl));
117301
117663
  return { success: false, error: msg };
117302
- } finally {
117303
- await tunnel?.close();
117304
117664
  }
117305
117665
  }
117306
117666
  });
117307
117667
 
117308
117668
  // ../connectors/src/connectors/jdbc/index.ts
117309
117669
  var tools67 = { executeQuery: executeQueryTool12 };
117670
+ var SAMPLE_WRAPPER_RE = /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i;
117310
117671
  var jdbcConnector = new ConnectorPlugin({
117311
117672
  slug: "jdbc",
117312
117673
  authType: AUTH_TYPES.USER_PASSWORD,
117313
117674
  name: "JDBC",
117314
- description: "Generic JDBC-style connection. Accepts a JDBC URL and dispatches to the matching driver (PostgreSQL, MySQL, MariaDB).",
117675
+ description: "Generic JDBC-style connection. Accepts a JDBC URL and dispatches to the matching driver (PostgreSQL, MySQL/MariaDB, SQL Server, Oracle, Redshift).",
117315
117676
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4Hgb5qQffrdu5nOkc49WtM/76d82ef6b108c7780e42998137c61b83/jdbc-icon.png",
117316
117677
  parameters: parameters67,
117317
- releaseFlag: { dev1: true, dev2: false, prod: false },
117678
+ releaseFlag: { dev1: true, dev2: true, prod: true },
117318
117679
  categories: ["database"],
117319
117680
  onboarding: jdbcOnboarding,
117320
117681
  systemPrompt: {
117321
117682
  en: `### Tools
117322
117683
 
117323
- - \`jdbc_executeQuery\`: Executes a SQL query through a JDBC URL and returns rows. The connector dispatches by URL prefix to the matching driver (PostgreSQL or MySQL/MariaDB), so use the dialect that matches the connection. Use this for schema exploration via \`information_schema\` and for sampling data. See the SQL Reference below.
117684
+ - \`jdbc_executeQuery\`: Executes a SQL query through a JDBC URL and returns rows. The connector dispatches by URL prefix to the matching native driver, so use the dialect that matches the connection. Use this for schema exploration via \`information_schema\` (or vendor equivalent) and for sampling data. See the SQL Reference below.
117324
117685
 
117325
117686
  ### Business Logic
117326
117687
 
@@ -117330,16 +117691,29 @@ The business logic type for this connector is "sql".
117330
117691
 
117331
117692
  The dialect depends on the JDBC URL prefix:
117332
117693
 
117333
- - \`jdbc:postgresql://...\` \u2192 PostgreSQL dialect
117694
+ - \`jdbc:postgresql://...\` / \`jdbc:postgres://...\` \u2192 PostgreSQL (driver: \`pg\`). \`LIMIT N\` is native.
117334
117695
  - List tables: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
117335
117696
  - List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
117336
- - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL dialect
117697
+ - \`jdbc:redshift://...\` \u2192 Amazon Redshift (driver: \`pg\` with SSL forced; default port 5439). PostgreSQL-compatible wire protocol; \`LIMIT N\` is native.
117698
+ - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL / MariaDB (driver: \`mysql2\`). \`LIMIT N\` is native.
117337
117699
  - List tables: \`SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()\`
117338
117700
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
117339
- - Always include LIMIT in queries`,
117701
+ - \`jdbc:sqlserver://...\` \u2192 Microsoft SQL Server / Azure SQL (driver: \`mssql\` / \`tedious\`). T-SQL dialect. **Use \`TOP N\` instead of \`LIMIT N\`** in queries you write.
117702
+ - List tables: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'\`
117703
+ - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'xxx'\`
117704
+ - \`jdbc:oracle:thin:@host:port/service\` (or \`@//host:port/service\` / \`@host:port:sid\`) \u2192 Oracle Database (driver: \`oracledb\` thin). Oracle SQL. **No \`LIMIT\` keyword** \u2014 use \`FETCH FIRST N ROWS ONLY\`, \`OFFSET m ROWS FETCH NEXT N ROWS ONLY\`, or \`ROWNUM\` filters.
117705
+ - List tables: \`SELECT TABLE_NAME FROM USER_TABLES\`
117706
+ - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = UPPER('xxx')\`
117707
+
117708
+ Explicitly **not** supported via this connector \u2014 use the dedicated connector or open a request:
117709
+ \`jdbc:snowflake://\` (use \`snowflake\`), \`jdbc:bigquery://\` (use \`bigquery\`), \`jdbc:databricks://\` (use \`databricks\`), \`jdbc:trino://\` / \`jdbc:presto://\` / \`jdbc:td://\` (Treasure Data) \u2014 no Node.js client bundled.
117710
+
117711
+ ### Row-limit compatibility (server-logic schema inference)
117712
+
117713
+ The platform's server-logic schema inference may wrap your query as \`SELECT * FROM (<inner>) AS _sq LIMIT N\` (PostgreSQL/MySQL syntax). For PostgreSQL / Redshift / MySQL routes this executes natively. For \`jdbc:sqlserver://\` and \`jdbc:oracle:thin:\` routes, the connector detects this exact wrapper at \`query()\` time, executes \`<inner>\` directly via the dialect-specific driver, and slices the first N rows in JS. You do not need to handle this \u2014 but in queries **you author**, do not use \`LIMIT\` for the SQL Server / Oracle routes; use \`TOP\` / \`FETCH FIRST\` as listed above.`,
117340
117714
  ja: `### \u30C4\u30FC\u30EB
117341
117715
 
117342
- - \`jdbc_executeQuery\`: JDBC URL \u7D4C\u7531\u3067 SQL \u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\u30B3\u30CD\u30AF\u30BF\u306F URL \u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u304B\u3089\u5BFE\u5FDC\u3059\u308B\u30C9\u30E9\u30A4\u30D0\uFF08PostgreSQL \u307E\u305F\u306F MySQL/MariaDB\uFF09\u306B\u632F\u308A\u5206\u3051\u308B\u305F\u3081\u3001\u63A5\u7D9A\u5148\u306B\u5408\u3063\u305F\u65B9\u8A00\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\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\u3002\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
117716
+ - \`jdbc_executeQuery\`: JDBC URL \u7D4C\u7531\u3067 SQL \u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\u30B3\u30CD\u30AF\u30BF\u306F URL \u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u304B\u3089\u5BFE\u5FDC\u3059\u308B\u30CD\u30A4\u30C6\u30A3\u30D6\u30C9\u30E9\u30A4\u30D0\u3078\u632F\u308A\u5206\u3051\u308B\u305F\u3081\u3001\u63A5\u7D9A\u5148\u306B\u5408\u3063\u305F\u65B9\u8A00\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\`information_schema\`\uFF08\u307E\u305F\u306F\u5404 DB \u306E\u540C\u7B49\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u30D3\u30E5\u30FC\uFF09\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\u3002\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
117343
117717
 
117344
117718
  ### Business Logic
117345
117719
 
@@ -117349,13 +117723,26 @@ The dialect depends on the JDBC URL prefix:
117349
117723
 
117350
117724
  JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B9\u8A00\u304C\u6C7A\u307E\u308A\u307E\u3059:
117351
117725
 
117352
- - \`jdbc:postgresql://...\` \u2192 PostgreSQL \u65B9\u8A00
117726
+ - \`jdbc:postgresql://...\` / \`jdbc:postgres://...\` \u2192 PostgreSQL\uFF08\u30C9\u30E9\u30A4\u30D0: \`pg\`\uFF09\u3002\`LIMIT N\` \u304C\u30CD\u30A4\u30C6\u30A3\u30D6\u3067\u4F7F\u3048\u307E\u3059\u3002
117353
117727
  - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
117354
117728
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
117355
- - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL \u65B9\u8A00
117729
+ - \`jdbc:redshift://...\` \u2192 Amazon Redshift\uFF08\u30C9\u30E9\u30A4\u30D0: \`pg\`\u3001SSL \u5F37\u5236\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u30DD\u30FC\u30C8 5439\uFF09\u3002PostgreSQL \u30EF\u30A4\u30E4\u4E92\u63DB\u306E\u305F\u3081 \`LIMIT N\` \u304C\u305D\u306E\u307E\u307E\u4F7F\u3048\u307E\u3059\u3002
117730
+ - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL / MariaDB\uFF08\u30C9\u30E9\u30A4\u30D0: \`mysql2\`\uFF09\u3002\`LIMIT N\` \u304C\u30CD\u30A4\u30C6\u30A3\u30D6\u3067\u4F7F\u3048\u307E\u3059\u3002
117356
117731
  - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()\`
117357
117732
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
117358
- - \u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A LIMIT \u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044`
117733
+ - \`jdbc:sqlserver://...\` \u2192 Microsoft SQL Server / Azure SQL\uFF08\u30C9\u30E9\u30A4\u30D0: \`mssql\` / \`tedious\`\uFF09\u3002T-SQL \u65B9\u8A00\u3002**\u81EA\u5206\u3067\u66F8\u304F SQL \u3067\u306F \`LIMIT N\` \u3067\u306F\u306A\u304F \`TOP N\` \u3092\u4F7F\u3046\u3053\u3068**\u3002
117734
+ - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'\`
117735
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'xxx'\`
117736
+ - \`jdbc:oracle:thin:@host:port/service\`\uFF08\`@//host:port/service\` / \`@host:port:sid\` \u3082\u53EF\uFF09\u2192 Oracle Database\uFF08\u30C9\u30E9\u30A4\u30D0: \`oracledb\` thin\uFF09\u3002Oracle SQL\u3002**\`LIMIT\` \u30AD\u30FC\u30EF\u30FC\u30C9\u306F\u5B58\u5728\u3057\u307E\u305B\u3093** \u2014 \`FETCH FIRST N ROWS ONLY\` / \`OFFSET m ROWS FETCH NEXT N ROWS ONLY\` / \`ROWNUM\` \u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
117737
+ - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_NAME FROM USER_TABLES\`
117738
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = UPPER('xxx')\`
117739
+
117740
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u3067\u306F **\u30B5\u30DD\u30FC\u30C8\u5916**\uFF08\u5C02\u7528\u30B3\u30CD\u30AF\u30BF\u3092\u4F7F\u3046\u304B\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\uFF09:
117741
+ \`jdbc:snowflake://\`\uFF08\`snowflake\` \u3092\u4F7F\u7528\uFF09\u3001\`jdbc:bigquery://\`\uFF08\`bigquery\` \u3092\u4F7F\u7528\uFF09\u3001\`jdbc:databricks://\`\uFF08\`databricks\` \u3092\u4F7F\u7528\uFF09\u3001\`jdbc:trino://\` / \`jdbc:presto://\` / \`jdbc:td://\`\uFF08Treasure Data\uFF09\u2014 Node.js \u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u3092\u540C\u68B1\u3057\u3066\u3044\u307E\u305B\u3093\u3002
117742
+
117743
+ ### \u884C\u6570\u5236\u9650\u306E\u4E92\u63DB\u6027\uFF08server-logic \u30B9\u30AD\u30FC\u30DE\u63A8\u8AD6\uFF09
117744
+
117745
+ \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\`\uFF08PostgreSQL/MySQL \u69CB\u6587\uFF09\u306E\u5F62\u3067\u30E9\u30C3\u30D7\u3057\u3066\u304F\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002PostgreSQL / Redshift / MySQL \u30EB\u30FC\u30C8\u3067\u306F\u305D\u306E\u307E\u307E\u5B9F\u884C\u3055\u308C\u307E\u3059\u3002\`jdbc:sqlserver://\` \u304A\u3088\u3073 \`jdbc:oracle:thin:\` \u30EB\u30FC\u30C8\u3067\u306F\u3001\u30B3\u30CD\u30AF\u30BF\u304C \`query()\` \u5185\u3067\u3053\u306E\u30E9\u30C3\u30D1\u3092\u691C\u51FA\u3057\u3001\`<inner>\` \u3092\u65B9\u8A00\u56FA\u6709\u306E\u30C9\u30E9\u30A4\u30D0\u3067\u76F4\u63A5\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 SQL Server / Oracle \u30EB\u30FC\u30C8\u3067 \`LIMIT\` \u3092\u4F7F\u308F\u305A\u3001\u4E0A\u8A18\u306E \`TOP\` / \`FETCH FIRST\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
117359
117746
  },
117360
117747
  tools: tools67,
117361
117748
  async checkConnection(params, _config) {
@@ -117371,6 +117758,12 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117371
117758
  error: e7 instanceof Error ? e7.message : String(e7)
117372
117759
  };
117373
117760
  }
117761
+ if (parsed.driver === "sqlserver") {
117762
+ return checkMssqlConnection(parsed.originalUrl, { username, password });
117763
+ }
117764
+ if (parsed.driver === "oracle") {
117765
+ return checkOracleConnection(parsed.originalUrl, { username, password });
117766
+ }
117374
117767
  const tunnel = await maybeOpenSshTunnel(
117375
117768
  params,
117376
117769
  parsed.nativeUrl,
@@ -117380,7 +117773,7 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117380
117773
  const { Pool } = await import("pg");
117381
117774
  const pool2 = new Pool({
117382
117775
  connectionString: tunnel.connectionUrl,
117383
- ssl: { rejectUnauthorized: false },
117776
+ ssl: parsed.forceSsl ? { rejectUnauthorized: false } : { rejectUnauthorized: false },
117384
117777
  connectionTimeoutMillis: 1e4
117385
117778
  });
117386
117779
  try {
@@ -117419,6 +117812,35 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117419
117812
  const username = params[parameters67.username.slug];
117420
117813
  const password = params[parameters67.password.slug];
117421
117814
  const parsed = parseJdbcUrl(jdbcUrl, { username, password });
117815
+ if (parsed.driver === "sqlserver") {
117816
+ const mssqlParsed = parseSqlServerJdbcUrl(parsed.originalUrl, {
117817
+ username,
117818
+ password
117819
+ });
117820
+ const wrapper = sql.match(SAMPLE_WRAPPER_RE);
117821
+ if (wrapper) {
117822
+ const inner = wrapper[1].trim();
117823
+ const limit = Number.parseInt(wrapper[2], 10);
117824
+ const result = await runMssqlQuery(mssqlParsed, inner);
117825
+ return { rows: result.rows.slice(0, limit) };
117826
+ }
117827
+ return runMssqlQuery(mssqlParsed, sql);
117828
+ }
117829
+ if (parsed.driver === "oracle") {
117830
+ const oracleParsed = parseOracleJdbcUrl(parsed.originalUrl, {
117831
+ username,
117832
+ password
117833
+ });
117834
+ const wrapper = sql.match(SAMPLE_WRAPPER_RE);
117835
+ if (wrapper) {
117836
+ const inner = wrapper[1].trim().replace(/;\s*$/, "");
117837
+ const limit = Number.parseInt(wrapper[2], 10);
117838
+ const result = await runOracleQuery(oracleParsed, inner);
117839
+ return { rows: result.rows.slice(0, limit) };
117840
+ }
117841
+ const cleanSql = sql.replace(/;\s*$/, "");
117842
+ return runOracleQuery(oracleParsed, cleanSql);
117843
+ }
117422
117844
  const tunnel = await maybeOpenSshTunnel(
117423
117845
  params,
117424
117846
  parsed.nativeUrl,
@@ -117429,7 +117851,7 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117429
117851
  const cleanSql = sql.replace(/;\s*$/, "");
117430
117852
  const pool2 = new Pool({
117431
117853
  connectionString: tunnel.connectionUrl,
117432
- ssl: { rejectUnauthorized: false },
117854
+ ssl: parsed.forceSsl ? { rejectUnauthorized: false } : { rejectUnauthorized: false },
117433
117855
  connectionTimeoutMillis: 1e4,
117434
117856
  statement_timeout: 6e4
117435
117857
  });
@@ -118155,7 +118577,7 @@ var googleSearchConsoleOauthConnector = new ConnectorPlugin({
118155
118577
  description: "Connect to Google Search Console for search performance, indexing, and sitemap data using OAuth.",
118156
118578
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/3rPusKosno7i1emOCmskTp/9ed092a4dc95efb74e34e83098ef3905/google-search-console-icon.webp",
118157
118579
  parameters: parameters69,
118158
- releaseFlag: { dev1: true, dev2: false, prod: false },
118580
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118159
118581
  categories: ["marketing"],
118160
118582
  onboarding: googleSearchConsoleOauthOnboarding,
118161
118583
  proxyPolicy: {
@@ -118218,7 +118640,7 @@ The business logic type for this connector is "typescript". Write handler code u
118218
118640
  SDK surface (client created via \`connection(connectionId)\`):
118219
118641
  - \`client.request(path, init?)\` \u2014 low-level authenticated fetch (\`path\` is appended to \`https://searchconsole.googleapis.com/webmasters/v3\`; \`{siteUrl}\` placeholders are auto-replaced and URL-encoded).
118220
118642
  - \`client.listSites()\` \u2014 list sites accessible by the OAuth user.
118221
- - \`client.querySearchAnalytics(request, siteUrl?)\` \u2014 query Search Analytics performance data.
118643
+ - \`client.querySearchAnalytics(args)\` \u2014 query Search Analytics performance data. Pass a single object: \`{ startDate, endDate, dimensions?, rowLimit?, ... }\`. \`siteUrl\` may be set on the same object to override the connection default. The googleapis-style envelope \`{ siteUrl?, requestBody: { startDate, endDate, ... } }\` is also accepted. \`startDate\` and \`endDate\` (\`YYYY-MM-DD\`) are required.
118222
118644
  - \`client.listSitemaps(siteUrl?)\` \u2014 list sitemaps submitted for a site.
118223
118645
 
118224
118646
  If a handler test fails with \`Connection proxy is not configured\`, retry \u2014 the sandbox is still initializing. Do NOT abandon the SDK and construct OAuth proxy URLs manually.
@@ -118234,7 +118656,7 @@ const gsc = connection("<connectionId>");
118234
118656
  const sites = await gsc.listSites();
118235
118657
  console.log(sites.map(s => \`\${s.siteUrl} (\${s.permissionLevel})\`));
118236
118658
 
118237
- // Top queries for the last 28 days
118659
+ // Top queries for the last 28 days \u2014 flat shape (recommended)
118238
118660
  const { rows } = await gsc.querySearchAnalytics({
118239
118661
  startDate: "2024-01-01",
118240
118662
  endDate: "2024-01-28",
@@ -118243,6 +118665,12 @@ const { rows } = await gsc.querySearchAnalytics({
118243
118665
  });
118244
118666
  rows?.forEach(r => console.log(r.keys?.[0], r.clicks, r.impressions));
118245
118667
 
118668
+ // Override the configured site (also accepts requestBody envelope)
118669
+ await gsc.querySearchAnalytics({
118670
+ siteUrl: "sc-domain:example.com",
118671
+ requestBody: { startDate: "2024-01-01", endDate: "2024-01-28", dimensions: ["page"] },
118672
+ });
118673
+
118246
118674
  // List sitemaps
118247
118675
  const sitemaps = await gsc.listSitemaps();
118248
118676
  sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
@@ -118298,7 +118726,7 @@ sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
118298
118726
  SDK\uFF08\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\uFF09:
118299
118727
  - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304D fetch\uFF08\`path\` \u306F \`https://searchconsole.googleapis.com/webmasters/v3\` \u306B\u8FFD\u52A0\u3055\u308C\u3001\`{siteUrl}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u306F\u81EA\u52D5\u7684\u306BURL\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u7F6E\u63DB\u3055\u308C\u307E\u3059\uFF09\u3002
118300
118728
  - \`client.listSites()\` \u2014 OAuth \u30E6\u30FC\u30B6\u30FC\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30B5\u30A4\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3002
118301
- - \`client.querySearchAnalytics(request, siteUrl?)\` \u2014 \u691C\u7D22\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3002
118729
+ - \`client.querySearchAnalytics(args)\` \u2014 \u691C\u7D22\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3002\u5F15\u6570\u306F\u5358\u4E00\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3067 \`{ startDate, endDate, dimensions?, rowLimit?, ... }\` \u3092\u6E21\u3057\u307E\u3059\u3002\`siteUrl\` \u3092\u540C\u3058\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306B\u542B\u3081\u308B\u3068\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u4E0A\u66F8\u304D\u3067\u304D\u307E\u3059\u3002googleapis \u5F62\u5F0F\u306E \`{ siteUrl?, requestBody: { startDate, endDate, ... } }\` \u3082\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002\`startDate\` \u3068 \`endDate\`\uFF08\`YYYY-MM-DD\` \u5F62\u5F0F\uFF09\u306F\u5FC5\u9808\u3067\u3059\u3002
118302
118730
  - \`client.listSitemaps(siteUrl?)\` \u2014 \u30B5\u30A4\u30C8\u306B\u63D0\u51FA\u6E08\u307F\u306E\u30B5\u30A4\u30C8\u30DE\u30C3\u30D7\u4E00\u89A7\u3092\u53D6\u5F97\u3002
118303
118731
 
118304
118732
  \u30CF\u30F3\u30C9\u30E9\u306E\u30C6\u30B9\u30C8\u304C \`Connection proxy is not configured\` \u3067\u5931\u6557\u3059\u308B\u5834\u5408\u306F\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u901A\u5E38\u306F\u30B5\u30F3\u30C9\u30DC\u30C3\u30AF\u30B9\u306E\u521D\u671F\u5316\u4E2D\u306B\u8D77\u304D\u307E\u3059\u3002SDK \u3092\u8AE6\u3081\u3066 OAuth \u30D7\u30ED\u30AD\u30B7\u306E URL \u3092\u81EA\u5206\u3067\u7D44\u307F\u7ACB\u3066\u308B\u3053\u3068\u306F **\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044**\u3002
@@ -118314,7 +118742,7 @@ const gsc = connection("<connectionId>");
118314
118742
  const sites = await gsc.listSites();
118315
118743
  console.log(sites.map(s => \`\${s.siteUrl} (\${s.permissionLevel})\`));
118316
118744
 
118317
- // Top queries for the last 28 days
118745
+ // Top queries for the last 28 days \u2014 \u30D5\u30E9\u30C3\u30C8\u5F62\u5F0F\uFF08\u63A8\u5968\uFF09
118318
118746
  const { rows } = await gsc.querySearchAnalytics({
118319
118747
  startDate: "2024-01-01",
118320
118748
  endDate: "2024-01-28",
@@ -118323,6 +118751,12 @@ const { rows } = await gsc.querySearchAnalytics({
118323
118751
  });
118324
118752
  rows?.forEach(r => console.log(r.keys?.[0], r.clicks, r.impressions));
118325
118753
 
118754
+ // siteUrl \u3092\u4E0A\u66F8\u304D\u3059\u308B\u5834\u5408\uFF08requestBody \u30A8\u30F3\u30D9\u30ED\u30FC\u30D7\u3082\u53EF\uFF09
118755
+ await gsc.querySearchAnalytics({
118756
+ siteUrl: "sc-domain:example.com",
118757
+ requestBody: { startDate: "2024-01-01", endDate: "2024-01-28", dimensions: ["page"] },
118758
+ });
118759
+
118326
118760
  // List sitemaps
118327
118761
  const sitemaps = await gsc.listSitemaps();
118328
118762
  sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
@@ -118466,7 +118900,7 @@ var supabaseConnector = new ConnectorPlugin({
118466
118900
  description: "Connect to a Supabase project's Postgres database to query application tables and Supabase-managed schemas (auth, storage).",
118467
118901
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/14k0U6F9PVovVjYjWyNzKb/2c4ff53adbe9334a63fee0a13d9f050a/supabase-icon.webp",
118468
118902
  parameters: parameters70,
118469
- releaseFlag: { dev1: true, dev2: false, prod: false },
118903
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118470
118904
  categories: ["database"],
118471
118905
  onboarding: supabaseOnboarding,
118472
118906
  systemPrompt: {
@@ -118693,7 +119127,7 @@ var clickupConnector = new ConnectorPlugin({
118693
119127
  description: "Connect to ClickUp for project management, task tracking, time tracking, and team collaboration data via Personal API Token.",
118694
119128
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5bzXkRjOeFJ7KoWdN55RAK/8b9270e4b09a9760912edae36d805fe4/clickup-icon.webp",
118695
119129
  parameters: parameters71,
118696
- releaseFlag: { dev1: true, dev2: false, prod: false },
119130
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118697
119131
  categories: ["productivity"],
118698
119132
  onboarding: clickupOnboarding,
118699
119133
  systemPrompt: {
@@ -118873,117 +119307,6 @@ export default async function handler(c: Context) {
118873
119307
  tools: tools71
118874
119308
  });
118875
119309
 
118876
- // ../connectors/src/connectors/sqlserver/utils.ts
118877
- var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
118878
- var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
118879
- var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
118880
- function parseBoolean(value) {
118881
- if (value == null) return void 0;
118882
- const lower = value.toLowerCase();
118883
- if (TRUE_VALUES.has(lower)) return true;
118884
- if (FALSE_VALUES.has(lower)) return false;
118885
- return void 0;
118886
- }
118887
- function parseSqlServerJdbcUrl(jdbcUrl, options = {}) {
118888
- const trimmed = jdbcUrl.trim();
118889
- if (!SQLSERVER_PREFIX_RE.test(trimmed)) {
118890
- throw new Error(
118891
- `Unsupported SQL Server URL "${redactSqlServerUrl(trimmed)}". Expected prefix: jdbc:sqlserver:// or sqlserver://.`
118892
- );
118893
- }
118894
- const withoutPrefix = trimmed.replace(SQLSERVER_PREFIX_RE, "");
118895
- const [hostAndPath, ...propertySegments] = withoutPrefix.split(";");
118896
- const props = {};
118897
- for (const segment of propertySegments) {
118898
- if (!segment) continue;
118899
- const eqIdx = segment.indexOf("=");
118900
- if (eqIdx === -1) continue;
118901
- const key = segment.slice(0, eqIdx).trim().toLowerCase();
118902
- const value = segment.slice(eqIdx + 1).trim();
118903
- if (key) props[key] = value;
118904
- }
118905
- const url = new URL(`mssql://${hostAndPath}`);
118906
- for (const [key, value] of url.searchParams.entries()) {
118907
- if (!(key.toLowerCase() in props)) {
118908
- props[key.toLowerCase()] = value;
118909
- }
118910
- }
118911
- const server = url.hostname;
118912
- const port = url.port ? Number(url.port) : 1433;
118913
- const pathname = url.pathname.replace(/^\//, "");
118914
- const database = pathname || props["database"] || props["databasename"];
118915
- const user = props["user"] || props["username"] || props["userid"] || options.username;
118916
- const password = props["password"] || options.password;
118917
- return {
118918
- server,
118919
- port,
118920
- database,
118921
- user,
118922
- password,
118923
- options: props
118924
- };
118925
- }
118926
- function toMssqlConfig(parsed, defaults = {}) {
118927
- const encrypt = parseBoolean(parsed.options["encrypt"]) ?? defaults.encrypt ?? false;
118928
- const trustServerCertificate = parseBoolean(parsed.options["trustservercertificate"]) ?? !encrypt;
118929
- return {
118930
- server: parsed.server,
118931
- port: parsed.port,
118932
- database: parsed.database,
118933
- user: parsed.user,
118934
- password: parsed.password,
118935
- connectionTimeout: 1e4,
118936
- requestTimeout: 6e4,
118937
- options: {
118938
- encrypt,
118939
- trustServerCertificate
118940
- }
118941
- };
118942
- }
118943
- function redactSqlServerUrl(jdbcUrl) {
118944
- return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
118945
- }
118946
-
118947
- // ../connectors/src/lib/mssql-runner.ts
118948
- async function importMssql() {
118949
- const mod = await import("mssql");
118950
- return mod.default ?? mod;
118951
- }
118952
- async function runMssqlQuery(parsed, sql, options = {}) {
118953
- const sqlMod = await importMssql();
118954
- const config = toMssqlConfig(parsed, {
118955
- encrypt: options.forceEncrypt
118956
- });
118957
- const pool = new sqlMod.ConnectionPool(config);
118958
- await pool.connect();
118959
- try {
118960
- const result = await pool.request().query(sql);
118961
- const recordset = result.recordset ?? [];
118962
- return { rows: recordset };
118963
- } finally {
118964
- await pool.close();
118965
- }
118966
- }
118967
- async function checkMssqlConnection(url, credentials, options = {}) {
118968
- let parsed;
118969
- try {
118970
- parsed = parseSqlServerJdbcUrl(url, credentials);
118971
- } catch (err) {
118972
- return {
118973
- success: false,
118974
- error: err instanceof Error ? err.message : String(err)
118975
- };
118976
- }
118977
- try {
118978
- await runMssqlQuery(parsed, "SELECT 1 AS one", options);
118979
- return { success: true };
118980
- } catch (err) {
118981
- let msg = err instanceof Error ? err.message : String(err);
118982
- msg = msg.replaceAll(url, redactSqlServerUrl(url));
118983
- return { success: false, error: msg };
118984
- }
118985
- }
118986
-
118987
119310
  // ../connectors/src/connectors/sqlserver/setup.ts
118988
119311
  var sqlserverOnboarding = new ConnectorOnboarding({
118989
119312
  dataOverviewInstructions: {
@@ -119129,7 +119452,8 @@ The business logic type for this connector is "sql".
119129
119452
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119130
119453
  - Use \`TOP n\` instead of \`LIMIT n\` (e.g. \`SELECT TOP 100 * FROM ...\`).
119131
119454
  - Identifiers can be quoted with square brackets, e.g. \`[Order Details]\`.
119132
- - Always bound results with \`TOP\` in queries.`,
119455
+ - Always bound results with \`TOP\` in queries.
119456
+ - 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.`,
119133
119457
  ja: `### \u30C4\u30FC\u30EB
119134
119458
 
119135
119459
  - \`sqlserver_executeQuery\`: Microsoft SQL Server \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\u3002SQL Server \u56FA\u6709\u306E\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
@@ -119145,7 +119469,8 @@ The business logic type for this connector is "sql".
119145
119469
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119146
119470
  - \`LIMIT n\` \u3067\u306F\u306A\u304F \`TOP n\` \u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08\u4F8B: \`SELECT TOP 100 * FROM ...\`\uFF09\u3002
119147
119471
  - \u8B58\u5225\u5B50\u306F\u89D2\u62EC\u5F27\u3067\u56F2\u3081\u307E\u3059\uFF08\u4F8B: \`[Order Details]\`\uFF09\u3002
119148
- - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
119472
+ - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002
119473
+ - \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`
119149
119474
  },
119150
119475
  tools: tools72,
119151
119476
  async checkConnection(params, _config) {
@@ -119162,6 +119487,15 @@ The business logic type for this connector is "sql".
119162
119487
  username: params[parameters72.username.slug],
119163
119488
  password: params[parameters72.password.slug]
119164
119489
  });
119490
+ const wrapper = sql.match(
119491
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119492
+ );
119493
+ if (wrapper) {
119494
+ const inner = wrapper[1].trim();
119495
+ const limit = Number.parseInt(wrapper[2], 10);
119496
+ const result = await runMssqlQuery(parsed, inner);
119497
+ return { rows: result.rows.slice(0, limit) };
119498
+ }
119165
119499
  return runMssqlQuery(parsed, sql);
119166
119500
  }
119167
119501
  });
@@ -119311,7 +119645,8 @@ The business logic type for this connector is "sql".
119311
119645
  - 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')\`
119312
119646
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119313
119647
  - Cross-database queries are not supported on Azure SQL Database (single-DB scope per connection); always reference objects within the connected database.
119314
- - Always bound results with \`TOP\` in queries.`,
119648
+ - Always bound results with \`TOP\` in queries.
119649
+ - 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.`,
119315
119650
  ja: `### \u30C4\u30FC\u30EB
119316
119651
 
119317
119652
  - \`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
@@ -119327,7 +119662,8 @@ The business logic type for this connector is "sql".
119327
119662
  - \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')\`
119328
119663
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119329
119664
  - 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
119330
- - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
119665
+ - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002
119666
+ - \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`
119331
119667
  },
119332
119668
  tools: tools73,
119333
119669
  async checkConnection(params, _config) {
@@ -119345,122 +119681,18 @@ The business logic type for this connector is "sql".
119345
119681
  username: params[parameters73.username.slug],
119346
119682
  password: params[parameters73.password.slug]
119347
119683
  });
119348
- return runMssqlQuery(parsed, sql, { forceEncrypt: true });
119349
- }
119350
- });
119351
-
119352
- // ../connectors/src/connectors/oracle/utils.ts
119353
- var JDBC_THIN_PREFIX_RE = /^jdbc:oracle:thin:/i;
119354
- var JDBC_OCI_PREFIX_RE = /^jdbc:oracle:oci/i;
119355
- var URL_PREFIX_RE = /^oracle:\/\//i;
119356
- function parseOracleJdbcUrl(jdbcUrl, options = {}) {
119357
- const trimmed = jdbcUrl.trim();
119358
- if (JDBC_OCI_PREFIX_RE.test(trimmed)) {
119359
- throw new Error(
119360
- "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
119361
- );
119362
- }
119363
- if (URL_PREFIX_RE.test(trimmed)) {
119364
- const url = new URL(trimmed);
119365
- const path5 = url.pathname.replace(/^\//, "");
119366
- if (!url.hostname || !path5) {
119367
- throw new Error(
119368
- `Invalid Oracle URL "${redactOracleUrl(trimmed)}". Expected oracle://[user:password@]host:port/service`
119369
- );
119370
- }
119371
- const port = url.port || "1521";
119372
- return {
119373
- connectString: `${url.hostname}:${port}/${path5}`,
119374
- user: url.username ? decodeURIComponent(url.username) : options.username,
119375
- password: url.password ? decodeURIComponent(url.password) : options.password
119376
- };
119377
- }
119378
- if (!JDBC_THIN_PREFIX_RE.test(trimmed)) {
119379
- throw new Error(
119380
- `Unsupported Oracle URL "${redactOracleUrl(trimmed)}". Expected prefix: jdbc:oracle:thin:@ or oracle://`
119684
+ const wrapper = sql.match(
119685
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119381
119686
  );
119382
- }
119383
- const afterPrefix = trimmed.replace(JDBC_THIN_PREFIX_RE, "");
119384
- const atIdx = afterPrefix.indexOf("@");
119385
- if (atIdx === -1) {
119386
- throw new Error(
119387
- `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Expected '@' separator before host.`
119388
- );
119389
- }
119390
- const credentialsPart = afterPrefix.slice(0, atIdx);
119391
- const target = afterPrefix.slice(atIdx + 1).replace(/^\/\//, "");
119392
- let user = options.username;
119393
- let password = options.password;
119394
- if (credentialsPart) {
119395
- const slashIdx = credentialsPart.indexOf("/");
119396
- if (slashIdx === -1) {
119397
- user = credentialsPart || user;
119398
- } else {
119399
- user = credentialsPart.slice(0, slashIdx) || user;
119400
- password = credentialsPart.slice(slashIdx + 1) || password;
119401
- }
119402
- }
119403
- if (!target) {
119404
- throw new Error(
119405
- `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Missing host portion after '@'.`
119406
- );
119407
- }
119408
- return {
119409
- connectString: target,
119410
- user,
119411
- password
119412
- };
119413
- }
119414
- function redactOracleUrl(jdbcUrl) {
119415
- return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(thin:)([^@]+)@/i, "$1***@");
119416
- }
119417
-
119418
- // ../connectors/src/lib/oracle-runner.ts
119419
- async function importOracleDb() {
119420
- const mod = await import("oracledb");
119421
- return mod.default ?? mod;
119422
- }
119423
- async function runOracleQuery(parsed, sql) {
119424
- const oracledb = await importOracleDb();
119425
- const connection = await oracledb.getConnection({
119426
- user: parsed.user,
119427
- password: parsed.password,
119428
- connectString: parsed.connectString
119429
- });
119430
- try {
119431
- const result = await connection.execute(sql, [], {
119432
- outFormat: oracledb.OUT_FORMAT_OBJECT,
119433
- // Bound by the connector's own row cap, but keep the driver from
119434
- // streaming arbitrarily large result sets.
119435
- maxRows: 5e3
119436
- });
119437
- return { rows: result.rows ?? [] };
119438
- } finally {
119439
- try {
119440
- await connection.close();
119441
- } catch {
119687
+ if (wrapper) {
119688
+ const inner = wrapper[1].trim();
119689
+ const limit = Number.parseInt(wrapper[2], 10);
119690
+ const result = await runMssqlQuery(parsed, inner, { forceEncrypt: true });
119691
+ return { rows: result.rows.slice(0, limit) };
119442
119692
  }
119693
+ return runMssqlQuery(parsed, sql, { forceEncrypt: true });
119443
119694
  }
119444
- }
119445
- async function checkOracleConnection(url, credentials) {
119446
- let parsed;
119447
- try {
119448
- parsed = parseOracleJdbcUrl(url, credentials);
119449
- } catch (err) {
119450
- return {
119451
- success: false,
119452
- error: err instanceof Error ? err.message : String(err)
119453
- };
119454
- }
119455
- try {
119456
- await runOracleQuery(parsed, "SELECT 1 FROM DUAL");
119457
- return { success: true };
119458
- } catch (err) {
119459
- let msg = err instanceof Error ? err.message : String(err);
119460
- msg = msg.replaceAll(url, redactOracleUrl(url));
119461
- return { success: false, error: msg };
119462
- }
119463
- }
119695
+ });
119464
119696
 
119465
119697
  // ../connectors/src/connectors/oracle/setup.ts
119466
119698
  var oracleOnboarding = new ConnectorOnboarding({
@@ -119613,7 +119845,8 @@ The business logic type for this connector is "sql".
119613
119845
  - Row limiting: there is **no** \`LIMIT\` keyword. Use \`FETCH FIRST n ROWS ONLY\` (12c+), \`OFFSET m ROWS FETCH NEXT n ROWS ONLY\`, or filter on the \`ROWNUM\` pseudo-column.
119614
119846
  - Identifier case: unquoted identifiers are folded to upper-case at parse time. \`employees\` and \`EMPLOYEES\` resolve to the same object, but \`"employees"\` (double-quoted) is a distinct, case-sensitive name.
119615
119847
  - Single-row table: use \`SELECT 1 FROM DUAL\` for connection probes \u2014 Oracle requires a \`FROM\` clause on every query.
119616
- - Do not terminate statements with a semicolon; the thin driver rejects trailing terminators.`,
119848
+ - Do not terminate statements with a semicolon; the thin driver rejects trailing terminators.
119849
+ - Row-limit compatibility: the platform's server-logic schema inference may wrap your query as \`SELECT * FROM (<inner>) AS _sq LIMIT N\`. Oracle has no \`LIMIT\` keyword, 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 \`FETCH FIRST N ROWS ONLY\`, \`OFFSET m ROWS FETCH NEXT N ROWS ONLY\`, or \`ROWNUM\` filters.`,
119617
119850
  ja: `### \u30C4\u30FC\u30EB
119618
119851
 
119619
119852
  - \`oracle_executeQuery\`: Oracle Database \u306B\u5BFE\u3057\u3066 SQL \u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`USER_TABLES\` / \`USER_TAB_COLUMNS\` / \`ALL_TABLES\` \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\u3002Oracle \u56FA\u6709\u306E\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
@@ -119631,7 +119864,8 @@ The business logic type for this connector is "sql".
119631
119864
  - \u884C\u6570\u5236\u9650: \`LIMIT\` \u30AD\u30FC\u30EF\u30FC\u30C9\u306F **\u5B58\u5728\u3057\u307E\u305B\u3093**\u3002\`FETCH FIRST n ROWS ONLY\`\uFF0812c\u4EE5\u964D\uFF09\u3001\`OFFSET m ROWS FETCH NEXT n ROWS ONLY\`\u3001\u307E\u305F\u306F \`ROWNUM\` \u7591\u4F3C\u5217\u3067\u30D5\u30A3\u30EB\u30BF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
119632
119865
  - \u8B58\u5225\u5B50\u306E\u5927\u6587\u5B57\u5C0F\u6587\u5B57: \u5F15\u7528\u7B26\u306A\u3057\u306E\u8B58\u5225\u5B50\u306F\u30D1\u30FC\u30B9\u6642\u306B\u5927\u6587\u5B57\u3078\u7573\u307F\u8FBC\u307E\u308C\u307E\u3059\u3002\`employees\` \u3068 \`EMPLOYEES\` \u306F\u540C\u3058\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u6307\u3057\u307E\u3059\u304C\u3001\`"employees"\`\uFF08\u30C0\u30D6\u30EB\u30AF\u30A9\u30FC\u30C8\uFF09\u306F\u5225\u306E case-sensitive \u306A\u540D\u524D\u3067\u3059\u3002
119633
119866
  - \u5358\u4E00\u884C\u30C6\u30FC\u30D6\u30EB: \u63A5\u7D9A\u78BA\u8A8D\u306B\u306F \`SELECT 1 FROM DUAL\` \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002Oracle \u306E\u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A \`FROM\` \u7BC0\u304C\u5FC5\u8981\u3067\u3059\u3002
119634
- - \u30B9\u30C6\u30FC\u30C8\u30E1\u30F3\u30C8\u672B\u5C3E\u306B\u30BB\u30DF\u30B3\u30ED\u30F3\u3092\u4ED8\u3051\u306A\u3044\u3067\u304F\u3060\u3055\u3044\uFF08thin \u30C9\u30E9\u30A4\u30D0\u304C\u62D2\u5426\u3057\u307E\u3059\uFF09\u3002`
119867
+ - \u30B9\u30C6\u30FC\u30C8\u30E1\u30F3\u30C8\u672B\u5C3E\u306B\u30BB\u30DF\u30B3\u30ED\u30F3\u3092\u4ED8\u3051\u306A\u3044\u3067\u304F\u3060\u3055\u3044\uFF08thin \u30C9\u30E9\u30A4\u30D0\u304C\u62D2\u5426\u3057\u307E\u3059\uFF09\u3002
119868
+ - \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\u3002Oracle \u306B\u306F \`LIMIT\` \u30AD\u30FC\u30EF\u30FC\u30C9\u304C\u5B58\u5728\u3057\u306A\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 \`FETCH FIRST N ROWS ONLY\` / \`OFFSET m ROWS FETCH NEXT N ROWS ONLY\` / \`ROWNUM\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
119635
119869
  },
119636
119870
  tools: tools74,
119637
119871
  async checkConnection(params, _config) {
@@ -119645,6 +119879,15 @@ The business logic type for this connector is "sql".
119645
119879
  username: params[parameters74.username.slug],
119646
119880
  password: params[parameters74.password.slug]
119647
119881
  });
119882
+ const wrapper = sql.match(
119883
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119884
+ );
119885
+ if (wrapper) {
119886
+ const inner = wrapper[1].trim().replace(/;\s*$/, "");
119887
+ const limit = Number.parseInt(wrapper[2], 10);
119888
+ const result = await runOracleQuery(parsed, inner);
119889
+ return { rows: result.rows.slice(0, limit) };
119890
+ }
119648
119891
  const cleanSql = sql.replace(/;\s*$/, "");
119649
119892
  return runOracleQuery(parsed, cleanSql);
119650
119893
  }
@@ -119819,7 +120062,7 @@ var freshserviceConnector = new ConnectorPlugin({
119819
120062
  description: "Connect to Freshservice (ITSM) for ticket, agent, asset, and ITIL workflow data via API key.",
119820
120063
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/6Tj64HZOoIrGgQYDayBosY/3f45b29d3479726b5d245ac38d5a7036/freshservice-icon.svg",
119821
120064
  parameters: parameters75,
119822
- releaseFlag: { dev1: true, dev2: false, prod: false },
120065
+ releaseFlag: { dev1: true, dev2: true, prod: true },
119823
120066
  categories: ["productivity"],
119824
120067
  onboarding: freshserviceOnboarding,
119825
120068
  systemPrompt: {
@@ -120148,8 +120391,8 @@ var freshdeskConnector = new ConnectorPlugin({
120148
120391
  description: "Connect to Freshdesk for customer support ticket, contact, and company data via API key.",
120149
120392
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1PSjIfQJgTYmiWriNTx4uE/26905f4120713bda0afd0b23d02a154e/freshdesk-icon.png",
120150
120393
  parameters: parameters76,
120151
- releaseFlag: { dev1: true, dev2: false, prod: false },
120152
- categories: ["productivity"],
120394
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120395
+ categories: ["crm"],
120153
120396
  onboarding: freshdeskOnboarding,
120154
120397
  systemPrompt: {
120155
120398
  en: `### Tools
@@ -120314,15 +120557,15 @@ export default async function handler(c: Context) {
120314
120557
  var freshsalesOnboarding = new ConnectorOnboarding({
120315
120558
  dataOverviewInstructions: {
120316
120559
  en: `1. Call freshsales_request with GET /selector/owners to confirm credentials and discover sales team members.
120317
- 2. Call freshsales_request with GET /contacts/view to list available contact views, then GET /contacts/view/{view_id} to fetch contacts in a view (paginated with \`page\` and \`per_page\`, default 25, max 100).
120318
- 3. Repeat the same pattern for accounts (GET /sales_accounts/view) and deals (GET /deals/view).
120560
+ 2. Call freshsales_request with GET /contacts/filters to list available contact views (filters), then GET /contacts/view/{view_id} to fetch contacts in a view (paginated with \`page\` and \`per_page\`, default 25, max 100).
120561
+ 3. Repeat the same pattern for accounts (GET /sales_accounts/filters \u2192 /sales_accounts/view/{view_id}) and deals (GET /deals/filters \u2192 /deals/view/{view_id}).
120319
120562
  4. To inspect deal pipeline metadata, call GET /selector/deal_pipelines and GET /selector/deal_stages.
120320
- 5. Use the search endpoints (POST /lookup or POST /search) to find specific records by attribute (e.g., look up a contact by email).`,
120563
+ 5. Use GET /lookup to find specific records by attribute (e.g., look up a contact by email).`,
120321
120564
  ja: `1. freshsales_request \u3067 GET /selector/owners \u3092\u547C\u3073\u51FA\u3057\u3001\u8A8D\u8A3C\u60C5\u5831\u306E\u78BA\u8A8D\u3068\u55B6\u696D\u30E1\u30F3\u30D0\u30FC\u306E\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002
120322
- 2. freshsales_request \u3067 GET /contacts/view \u3092\u547C\u3073\u51FA\u3057\u3066\u30D3\u30E5\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u3001GET /contacts/view/{view_id} \u3067\u5404\u30D3\u30E5\u30FC\u306E\u9023\u7D61\u5148\u3092\u53D6\u5F97\u3057\u307E\u3059\uFF08\`page\` \u3068 \`per_page\` \u3067\u30DA\u30FC\u30B8\u30F3\u30B0\u3001\u30C7\u30D5\u30A9\u30EB\u30C825\u3001\u6700\u5927100\uFF09\u3002
120323
- 3. \u540C\u3058\u30D1\u30BF\u30FC\u30F3\u3092\u53D6\u5F15\u5148\uFF08GET /sales_accounts/view\uFF09\u3001\u5546\u8AC7\uFF08GET /deals/view\uFF09\u306B\u3082\u9069\u7528\u3057\u307E\u3059\u3002
120565
+ 2. freshsales_request \u3067 GET /contacts/filters \u3092\u547C\u3073\u51FA\u3057\u3066\u30D3\u30E5\u30FC\uFF08filters\uFF09\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u3001GET /contacts/view/{view_id} \u3067\u5404\u30D3\u30E5\u30FC\u306E\u9023\u7D61\u5148\u3092\u53D6\u5F97\u3057\u307E\u3059\uFF08\`page\` \u3068 \`per_page\` \u3067\u30DA\u30FC\u30B8\u30F3\u30B0\u3001\u30C7\u30D5\u30A9\u30EB\u30C825\u3001\u6700\u5927100\uFF09\u3002
120566
+ 3. \u540C\u3058\u30D1\u30BF\u30FC\u30F3\u3092\u53D6\u5F15\u5148\uFF08GET /sales_accounts/filters \u2192 /sales_accounts/view/{view_id}\uFF09\u3001\u5546\u8AC7\uFF08GET /deals/filters \u2192 /deals/view/{view_id}\uFF09\u306B\u3082\u9069\u7528\u3057\u307E\u3059\u3002
120324
120567
  4. \u5546\u8AC7\u30D1\u30A4\u30D7\u30E9\u30A4\u30F3\u306E\u30E1\u30BF\u60C5\u5831\u306F GET /selector/deal_pipelines \u304A\u3088\u3073 GET /selector/deal_stages \u3067\u53D6\u5F97\u3057\u307E\u3059\u3002
120325
- 5. \u7279\u5B9A\u30EC\u30B3\u30FC\u30C9\u3092\u5C5E\u6027\u3067\u691C\u7D22\u3059\u308B\u306B\u306F\u691C\u7D22\u7CFB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08POST /lookup \u307E\u305F\u306F POST /search\uFF09\u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08\u4F8B: \u30E1\u30FC\u30EB\u3067\u9023\u7D61\u5148\u3092\u691C\u7D22\uFF09\u3002`
120568
+ 5. \u7279\u5B9A\u30EC\u30B3\u30FC\u30C9\u3092\u5C5E\u6027\u3067\u691C\u7D22\u3059\u308B\u306B\u306F GET /lookup \u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08\u4F8B: \u30E1\u30FC\u30EB\u3067\u9023\u7D61\u5148\u3092\u691C\u7D22\uFF09\u3002`
120326
120569
  }
120327
120570
  });
120328
120571
 
@@ -120363,10 +120606,10 @@ var inputSchema93 = z93.object({
120363
120606
  ),
120364
120607
  connectionId: z93.string().describe("ID of the Freshsales connection to use"),
120365
120608
  method: z93.enum(["GET", "POST", "PUT", "DELETE"]).describe(
120366
- "HTTP method. GET for reading resources, POST for creating or running search/lookup, PUT for updating, DELETE for removing."
120609
+ "HTTP method. GET for reading resources (including /lookup), POST for creating, PUT for updating, DELETE for removing."
120367
120610
  ),
120368
120611
  path: z93.string().describe(
120369
- "API path (e.g., '/contacts', '/contacts/view', '/contacts/view/{view_id}', '/deals/{id}', '/lookup'). Append query parameters such as '?page=1&per_page=100'."
120612
+ "API path (e.g., '/contacts', '/contacts/filters', '/contacts/view/{view_id}', '/deals/{id}', '/lookup'). Append query parameters such as '?page=1&per_page=100'."
120370
120613
  ),
120371
120614
  body: z93.record(z93.string(), z93.unknown()).optional().describe(
120372
120615
  'Request body (JSON). For creating a contact: { "contact": { "first_name": "...", "last_name": "...", "email": "..." } }. For lookup: { "q": "john@example.com", "f": "email", "entities": "contact" }.'
@@ -120393,20 +120636,20 @@ Authentication uses the \`Authorization: Token token=<API_KEY>\` header (handled
120393
120636
  Provide the API path relative to the base URL (https://<bundle>.myfreshworks.com/crm/sales/api).
120394
120637
 
120395
120638
  Common endpoints:
120396
- - GET /contacts/view \u2014 List contact views (saved filters)
120639
+ - GET /contacts/filters \u2014 List contact views (saved filters)
120397
120640
  - GET /contacts/view/{view_id} \u2014 List contacts in a view (paginated)
120398
120641
  - GET /contacts/{id} \u2014 Get a contact (use ?include=owner,creator,deals for related data)
120399
120642
  - POST /contacts \u2014 Create a contact (body: { "contact": { ... } })
120400
120643
  - PUT /contacts/{id} \u2014 Update a contact
120401
- - GET /sales_accounts/view \u2014 List account views
120644
+ - GET /sales_accounts/filters \u2014 List account views
120402
120645
  - GET /sales_accounts/view/{view_id} \u2014 Accounts in a view
120403
- - GET /deals/view \u2014 Deal views
120646
+ - GET /deals/filters \u2014 Deal views
120404
120647
  - GET /deals/view/{view_id} \u2014 Deals in a view
120405
120648
  - GET /deals/{id} \u2014 Get a deal
120406
120649
  - POST /deals \u2014 Create a deal
120407
- - GET /leads/view \u2014 Lead views (legacy / Sales Cloud only)
120650
+ - GET /leads/filters \u2014 Lead views (legacy / Sales Cloud only)
120408
120651
  - GET /sales_activities \u2014 List sales activities
120409
- - POST /lookup?q=...&f=email&entities=contact \u2014 Look up a record by attribute
120652
+ - GET /lookup?q=...&f=email&entities=contact \u2014 Look up a record by attribute
120410
120653
  - GET /selector/owners \u2014 Available owners (sales reps)
120411
120654
  - GET /selector/deal_pipelines \u2014 Deal pipelines
120412
120655
  - GET /selector/deal_stages \u2014 Deal stages
@@ -120477,8 +120720,8 @@ var freshsalesConnector = new ConnectorPlugin({
120477
120720
  description: "Connect to Freshsales / Freshworks CRM for contact, account, and deal data via API key.",
120478
120721
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4UDOrFPM6wOFekbMVljjgl/4acc6060c3a1ff703980e6f4e76a3cd4/629b6c6f7c5cd817694c321f.png",
120479
120722
  parameters: parameters77,
120480
- releaseFlag: { dev1: true, dev2: false, prod: false },
120481
- categories: ["productivity"],
120723
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120724
+ categories: ["crm"],
120482
120725
  onboarding: freshsalesOnboarding,
120483
120726
  systemPrompt: {
120484
120727
  en: `### Tools
@@ -120525,26 +120768,26 @@ export default async function handler(c: Context) {
120525
120768
  #### Resource Endpoints
120526
120769
 
120527
120770
  **Contacts**
120528
- - GET \`/contacts/view\` \u2014 List saved views
120771
+ - GET \`/contacts/filters\` \u2014 List saved views (a.k.a. filters)
120529
120772
  - GET \`/contacts/view/{view_id}\` \u2014 Contacts in a view (paginated)
120530
120773
  - GET \`/contacts/{id}\` \u2014 Get a contact (use \`?include=owner,creator,deals,sales_accounts\`)
120531
120774
  - POST \`/contacts\` \u2014 Create a contact (body: \`{ "contact": { ... } }\`)
120532
120775
  - PUT \`/contacts/{id}\` \u2014 Update a contact
120533
120776
 
120534
120777
  **Sales accounts (companies)**
120535
- - GET \`/sales_accounts/view\` \u2014 List saved views
120778
+ - GET \`/sales_accounts/filters\` \u2014 List saved views
120536
120779
  - GET \`/sales_accounts/view/{view_id}\` \u2014 Accounts in a view
120537
120780
  - GET \`/sales_accounts/{id}\` \u2014 Get an account
120538
120781
  - POST \`/sales_accounts\` / PUT \`/sales_accounts/{id}\` \u2014 Write
120539
120782
 
120540
120783
  **Deals**
120541
- - GET \`/deals/view\` \u2014 List saved views
120784
+ - GET \`/deals/filters\` \u2014 List saved views
120542
120785
  - GET \`/deals/view/{view_id}\` \u2014 Deals in a view
120543
120786
  - GET \`/deals/{id}\` \u2014 Get a deal (use \`?include=owner,deal_stage,sales_account,contacts\`)
120544
120787
  - POST \`/deals\` / PUT \`/deals/{id}\` \u2014 Write
120545
120788
 
120546
120789
  **Leads (Sales Cloud only)**
120547
- - GET \`/leads/view\` \u2014 Saved views
120790
+ - GET \`/leads/filters\` \u2014 Saved views
120548
120791
  - GET \`/leads/view/{view_id}\` \u2014 Leads in a view
120549
120792
  - GET \`/leads/{id}\` \u2014 Get a lead
120550
120793
 
@@ -120555,7 +120798,7 @@ export default async function handler(c: Context) {
120555
120798
  - POST \`/notes\` \u2014 Create a note (body references a target contact/account/deal)
120556
120799
 
120557
120800
  **Search & lookup**
120558
- - POST \`/lookup\` \u2014 Lookup a record by attribute. Query params: \`q\` (value), \`f\` (field \u2014 typically \`email\`/\`mobile_number\`), \`entities\` (\`contact\`/\`sales_account\`/\`deal\`/\`lead\`).
120801
+ - GET \`/lookup\` \u2014 Lookup a record by attribute. Query params: \`q\` (value), \`f\` (field \u2014 typically \`email\`/\`mobile_number\`), \`entities\` (\`contact\`/\`sales_account\`/\`deal\`/\`lead\`).
120559
120802
 
120560
120803
  **Selector metadata**
120561
120804
  - GET \`/selector/owners\` \u2014 Sales reps available as owners
@@ -120608,26 +120851,26 @@ export default async function handler(c: Context) {
120608
120851
  #### \u30EA\u30BD\u30FC\u30B9\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
120609
120852
 
120610
120853
  **\u9023\u7D61\u5148\uFF08Contacts\uFF09**
120611
- - GET \`/contacts/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120854
+ - GET \`/contacts/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7\uFF08filters\uFF09
120612
120855
  - GET \`/contacts/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u9023\u7D61\u5148\u4E00\u89A7\uFF08\u30DA\u30FC\u30B8\u30F3\u30B0\uFF09
120613
120856
  - GET \`/contacts/{id}\` \u2014 \u9023\u7D61\u5148\u306E\u53D6\u5F97\uFF08\`?include=owner,creator,deals,sales_accounts\` \u3067\u95A2\u9023\u5C55\u958B\uFF09
120614
120857
  - POST \`/contacts\` \u2014 \u9023\u7D61\u5148\u306E\u4F5C\u6210\uFF08body: \`{ "contact": { ... } }\`\uFF09
120615
120858
  - PUT \`/contacts/{id}\` \u2014 \u9023\u7D61\u5148\u306E\u66F4\u65B0
120616
120859
 
120617
120860
  **\u53D6\u5F15\u5148\uFF08Sales accounts / \u4F1A\u793E\uFF09**
120618
- - GET \`/sales_accounts/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120861
+ - GET \`/sales_accounts/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120619
120862
  - GET \`/sales_accounts/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u53D6\u5F15\u5148
120620
120863
  - GET \`/sales_accounts/{id}\` \u2014 \u53D6\u5F15\u5148\u306E\u53D6\u5F97
120621
120864
  - POST \`/sales_accounts\` / PUT \`/sales_accounts/{id}\` \u2014 \u4F5C\u6210\u30FB\u66F4\u65B0
120622
120865
 
120623
120866
  **\u5546\u8AC7\uFF08Deals\uFF09**
120624
- - GET \`/deals/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120867
+ - GET \`/deals/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120625
120868
  - GET \`/deals/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u5546\u8AC7
120626
120869
  - GET \`/deals/{id}\` \u2014 \u5546\u8AC7\u306E\u53D6\u5F97\uFF08\`?include=owner,deal_stage,sales_account,contacts\` \u3067\u95A2\u9023\u5C55\u958B\uFF09
120627
120870
  - POST \`/deals\` / PUT \`/deals/{id}\` \u2014 \u4F5C\u6210\u30FB\u66F4\u65B0
120628
120871
 
120629
120872
  **\u30EA\u30FC\u30C9\uFF08Leads \u2014 Sales Cloud \u306E\u307F\uFF09**
120630
- - GET \`/leads/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120873
+ - GET \`/leads/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120631
120874
  - GET \`/leads/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u30EA\u30FC\u30C9
120632
120875
  - GET \`/leads/{id}\` \u2014 \u30EA\u30FC\u30C9\u306E\u53D6\u5F97
120633
120876
 
@@ -120638,7 +120881,7 @@ export default async function handler(c: Context) {
120638
120881
  - POST \`/notes\` \u2014 \u30CE\u30FC\u30C8\u306E\u4F5C\u6210\uFF08body \u3067\u9023\u7D61\u5148/\u53D6\u5F15\u5148/\u5546\u8AC7\u3092\u53C2\u7167\uFF09
120639
120882
 
120640
120883
  **\u691C\u7D22 & \u30EB\u30C3\u30AF\u30A2\u30C3\u30D7**
120641
- - POST \`/lookup\` \u2014 \u5C5E\u6027\u306B\u3088\u308B\u30EC\u30B3\u30FC\u30C9\u691C\u7D22\u3002\u30AF\u30A8\u30EA: \`q\`\uFF08\u5024\uFF09\u3001\`f\`\uFF08\u30D5\u30A3\u30FC\u30EB\u30C9 \u2014 \u901A\u5E38 \`email\`/\`mobile_number\`\uFF09\u3001\`entities\`\uFF08\`contact\`/\`sales_account\`/\`deal\`/\`lead\`\uFF09\u3002
120884
+ - GET \`/lookup\` \u2014 \u5C5E\u6027\u306B\u3088\u308B\u30EC\u30B3\u30FC\u30C9\u691C\u7D22\u3002\u30AF\u30A8\u30EA: \`q\`\uFF08\u5024\uFF09\u3001\`f\`\uFF08\u30D5\u30A3\u30FC\u30EB\u30C9 \u2014 \u901A\u5E38 \`email\`/\`mobile_number\`\uFF09\u3001\`entities\`\uFF08\`contact\`/\`sales_account\`/\`deal\`/\`lead\`\uFF09\u3002
120642
120885
 
120643
120886
  **\u30BB\u30EC\u30AF\u30BF\u30FC\u30E1\u30BF\u60C5\u5831**
120644
120887
  - GET \`/selector/owners\` \u2014 \u30AA\u30FC\u30CA\u30FC\uFF08\u55B6\u696D\u62C5\u5F53\uFF09\u4E00\u89A7
@@ -120833,7 +121076,7 @@ var githubConnector = new ConnectorPlugin({
120833
121076
  description: "Connect to GitHub for repository, issue, pull request, commit, and search data via Personal Access Token (Classic or fine-grained).",
120834
121077
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2flOAufkhDrLKuOQqEVS3/1f9dcf145680ef77aef149709263e2d4/github-icon.svg",
120835
121078
  parameters: parameters78,
120836
- releaseFlag: { dev1: true, dev2: false, prod: false },
121079
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120837
121080
  categories: ["productivity"],
120838
121081
  onboarding: githubOnboarding,
120839
121082
  systemPrompt: {