@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/index.js CHANGED
@@ -116903,8 +116903,8 @@ var mondayConnector = new ConnectorPlugin({
116903
116903
  The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
116904
116904
 
116905
116905
  SDK methods (client created via \`connection(connectionId)\`):
116906
- - \`client.graphql(query, variables?)\` \u2014 send any GraphQL query/mutation and get typed data back
116907
- - \`client.request(init?)\` \u2014 low-level authenticated fetch to the GraphQL endpoint
116906
+ - \`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.
116907
+ - \`client.request(init?)\` \u2014 low-level authenticated fetch to the GraphQL endpoint (returns the raw \`Response\`; you parse the full \`{ data, errors }\` envelope yourself)
116908
116908
  - \`client.me()\` \u2014 get the authenticated user and account
116909
116909
  - \`client.listBoards(options?)\` \u2014 list boards with optional ids, workspaceIds, state, page, limit
116910
116910
  - \`client.getBoard(boardId)\` \u2014 fetch a single board with columns, groups, owners, tags
@@ -116933,6 +116933,26 @@ export default async function handler(c: Context) {
116933
116933
  }
116934
116934
  \`\`\`
116935
116935
 
116936
+ #### \`client.graphql()\` return shape (common pitfall)
116937
+
116938
+ \`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.
116939
+
116940
+ \`\`\`ts
116941
+ // \u2705 Correct \u2014 fields are at the top level
116942
+ const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
116943
+ \`query($ids: [ID!], $limit: Int) {
116944
+ boards(ids: $ids) {
116945
+ items_page(limit: $limit) { cursor items { id name } }
116946
+ }
116947
+ }\`,
116948
+ { ids: [boardId], limit: 100 },
116949
+ );
116950
+ const items = res.boards?.[0]?.items_page?.items ?? [];
116951
+
116952
+ // \u274C Wrong \u2014 \`res.data\` is undefined; \`.data\` was already stripped by the SDK
116953
+ const items = res.data?.boards?.[0]?.items_page?.items; // always undefined!
116954
+ \`\`\`
116955
+
116936
116956
  ### monday.com GraphQL API Reference
116937
116957
 
116938
116958
  - Endpoint: \`https://api.monday.com/v2\`
@@ -116973,8 +116993,8 @@ export default async function handler(c: Context) {
116973
116993
  \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
116974
116994
 
116975
116995
  SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
116976
- - \`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
116977
- - \`client.request(init?)\` \u2014 GraphQL\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3078\u306E\u4F4E\u30EC\u30D9\u30EB\u8A8D\u8A3C\u4ED8\u304Dfetch
116996
+ - \`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
116997
+ - \`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
116978
116998
  - \`client.me()\` \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u3068\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u53D6\u5F97
116979
116999
  - \`client.listBoards(options?)\` \u2014 ids/workspaceIds/state/page/limit \u3067\u30DC\u30FC\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
116980
117000
  - \`client.getBoard(boardId)\` \u2014 1\u3064\u306E\u30DC\u30FC\u30C9\u3092 columns/groups/owners/tags \u4ED8\u304D\u3067\u53D6\u5F97
@@ -117003,6 +117023,26 @@ export default async function handler(c: Context) {
117003
117023
  }
117004
117024
  \`\`\`
117005
117025
 
117026
+ #### \`client.graphql()\` \u306E\u623B\u308A\u5024\uFF08\u3088\u304F\u3042\u308B\u9593\u9055\u3044\uFF09
117027
+
117028
+ \`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
117029
+
117030
+ \`\`\`ts
117031
+ // \u2705 \u6B63\u3057\u3044 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u306B\u3042\u308B
117032
+ const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
117033
+ \`query($ids: [ID!], $limit: Int) {
117034
+ boards(ids: $ids) {
117035
+ items_page(limit: $limit) { cursor items { id name } }
117036
+ }
117037
+ }\`,
117038
+ { ids: [boardId], limit: 100 },
117039
+ );
117040
+ const items = res.boards?.[0]?.items_page?.items ?? [];
117041
+
117042
+ // \u274C \u8AA4\u308A \u2014 \`res.data\` \u306F undefined\uFF08SDK\u304C\u65E2\u306B \`.data\` \u3092\u5265\u304C\u3057\u3066\u3044\u308B\uFF09
117043
+ const items = res.data?.boards?.[0]?.items_page?.items; // \u5E38\u306B undefined\uFF01
117044
+ \`\`\`
117045
+
117006
117046
  ### monday.com GraphQL API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
117007
117047
 
117008
117048
  - \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8: \`https://api.monday.com/v2\`
@@ -117038,6 +117078,230 @@ export default async function handler(c: Context) {
117038
117078
  tools: tools66
117039
117079
  });
117040
117080
 
117081
+ // ../connectors/src/connectors/sqlserver/utils.ts
117082
+ var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
117083
+ var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
117084
+ var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
117085
+ function parseBoolean(value) {
117086
+ if (value == null) return void 0;
117087
+ const lower = value.toLowerCase();
117088
+ if (TRUE_VALUES.has(lower)) return true;
117089
+ if (FALSE_VALUES.has(lower)) return false;
117090
+ return void 0;
117091
+ }
117092
+ function parseSqlServerJdbcUrl(jdbcUrl, options = {}) {
117093
+ const trimmed = jdbcUrl.trim();
117094
+ if (!SQLSERVER_PREFIX_RE.test(trimmed)) {
117095
+ throw new Error(
117096
+ `Unsupported SQL Server URL "${redactSqlServerUrl(trimmed)}". Expected prefix: jdbc:sqlserver:// or sqlserver://.`
117097
+ );
117098
+ }
117099
+ const withoutPrefix = trimmed.replace(SQLSERVER_PREFIX_RE, "");
117100
+ const [hostAndPath, ...propertySegments] = withoutPrefix.split(";");
117101
+ const props = {};
117102
+ for (const segment of propertySegments) {
117103
+ if (!segment) continue;
117104
+ const eqIdx = segment.indexOf("=");
117105
+ if (eqIdx === -1) continue;
117106
+ const key = segment.slice(0, eqIdx).trim().toLowerCase();
117107
+ const value = segment.slice(eqIdx + 1).trim();
117108
+ if (key) props[key] = value;
117109
+ }
117110
+ const url = new URL(`mssql://${hostAndPath}`);
117111
+ for (const [key, value] of url.searchParams.entries()) {
117112
+ if (!(key.toLowerCase() in props)) {
117113
+ props[key.toLowerCase()] = value;
117114
+ }
117115
+ }
117116
+ const server = url.hostname;
117117
+ const port = url.port ? Number(url.port) : 1433;
117118
+ const pathname = url.pathname.replace(/^\//, "");
117119
+ const database = pathname || props["database"] || props["databasename"];
117120
+ const user = props["user"] || props["username"] || props["userid"] || options.username;
117121
+ const password = props["password"] || options.password;
117122
+ return {
117123
+ server,
117124
+ port,
117125
+ database,
117126
+ user,
117127
+ password,
117128
+ options: props
117129
+ };
117130
+ }
117131
+ function toMssqlConfig(parsed, defaults = {}) {
117132
+ const encrypt = parseBoolean(parsed.options["encrypt"]) ?? defaults.encrypt ?? false;
117133
+ const trustServerCertificate = parseBoolean(parsed.options["trustservercertificate"]) ?? !encrypt;
117134
+ return {
117135
+ server: parsed.server,
117136
+ port: parsed.port,
117137
+ database: parsed.database,
117138
+ user: parsed.user,
117139
+ password: parsed.password,
117140
+ connectionTimeout: 1e4,
117141
+ requestTimeout: 6e4,
117142
+ options: {
117143
+ encrypt,
117144
+ trustServerCertificate
117145
+ }
117146
+ };
117147
+ }
117148
+ function redactSqlServerUrl(jdbcUrl) {
117149
+ return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
117150
+ }
117151
+
117152
+ // ../connectors/src/lib/mssql-runner.ts
117153
+ async function importMssql() {
117154
+ const mod = await import("mssql");
117155
+ return mod.default ?? mod;
117156
+ }
117157
+ async function runMssqlQuery(parsed, sql, options = {}) {
117158
+ const sqlMod = await importMssql();
117159
+ const config = toMssqlConfig(parsed, {
117160
+ encrypt: options.forceEncrypt
117161
+ });
117162
+ const pool = new sqlMod.ConnectionPool(config);
117163
+ await pool.connect();
117164
+ try {
117165
+ const result = await pool.request().query(sql);
117166
+ const recordset = result.recordset ?? [];
117167
+ return { rows: recordset };
117168
+ } finally {
117169
+ await pool.close();
117170
+ }
117171
+ }
117172
+ async function checkMssqlConnection(url, credentials, options = {}) {
117173
+ let parsed;
117174
+ try {
117175
+ parsed = parseSqlServerJdbcUrl(url, credentials);
117176
+ } catch (err) {
117177
+ return {
117178
+ success: false,
117179
+ error: err instanceof Error ? err.message : String(err)
117180
+ };
117181
+ }
117182
+ try {
117183
+ await runMssqlQuery(parsed, "SELECT 1 AS one", options);
117184
+ return { success: true };
117185
+ } catch (err) {
117186
+ let msg = err instanceof Error ? err.message : String(err);
117187
+ msg = msg.replaceAll(url, redactSqlServerUrl(url));
117188
+ return { success: false, error: msg };
117189
+ }
117190
+ }
117191
+
117192
+ // ../connectors/src/connectors/oracle/utils.ts
117193
+ var JDBC_THIN_PREFIX_RE = /^jdbc:oracle:thin:/i;
117194
+ var JDBC_OCI_PREFIX_RE = /^jdbc:oracle:oci/i;
117195
+ var URL_PREFIX_RE = /^oracle:\/\//i;
117196
+ function parseOracleJdbcUrl(jdbcUrl, options = {}) {
117197
+ const trimmed = jdbcUrl.trim();
117198
+ if (JDBC_OCI_PREFIX_RE.test(trimmed)) {
117199
+ throw new Error(
117200
+ "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
117201
+ );
117202
+ }
117203
+ if (URL_PREFIX_RE.test(trimmed)) {
117204
+ const url = new URL(trimmed);
117205
+ const path5 = url.pathname.replace(/^\//, "");
117206
+ if (!url.hostname || !path5) {
117207
+ throw new Error(
117208
+ `Invalid Oracle URL "${redactOracleUrl(trimmed)}". Expected oracle://[user:password@]host:port/service`
117209
+ );
117210
+ }
117211
+ const port = url.port || "1521";
117212
+ return {
117213
+ connectString: `${url.hostname}:${port}/${path5}`,
117214
+ user: url.username ? decodeURIComponent(url.username) : options.username,
117215
+ password: url.password ? decodeURIComponent(url.password) : options.password
117216
+ };
117217
+ }
117218
+ if (!JDBC_THIN_PREFIX_RE.test(trimmed)) {
117219
+ throw new Error(
117220
+ `Unsupported Oracle URL "${redactOracleUrl(trimmed)}". Expected prefix: jdbc:oracle:thin:@ or oracle://`
117221
+ );
117222
+ }
117223
+ const afterPrefix = trimmed.replace(JDBC_THIN_PREFIX_RE, "");
117224
+ const atIdx = afterPrefix.indexOf("@");
117225
+ if (atIdx === -1) {
117226
+ throw new Error(
117227
+ `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Expected '@' separator before host.`
117228
+ );
117229
+ }
117230
+ const credentialsPart = afterPrefix.slice(0, atIdx);
117231
+ const target = afterPrefix.slice(atIdx + 1).replace(/^\/\//, "");
117232
+ let user = options.username;
117233
+ let password = options.password;
117234
+ if (credentialsPart) {
117235
+ const slashIdx = credentialsPart.indexOf("/");
117236
+ if (slashIdx === -1) {
117237
+ user = credentialsPart || user;
117238
+ } else {
117239
+ user = credentialsPart.slice(0, slashIdx) || user;
117240
+ password = credentialsPart.slice(slashIdx + 1) || password;
117241
+ }
117242
+ }
117243
+ if (!target) {
117244
+ throw new Error(
117245
+ `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Missing host portion after '@'.`
117246
+ );
117247
+ }
117248
+ return {
117249
+ connectString: target,
117250
+ user,
117251
+ password
117252
+ };
117253
+ }
117254
+ function redactOracleUrl(jdbcUrl) {
117255
+ return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(thin:)([^@]+)@/i, "$1***@");
117256
+ }
117257
+
117258
+ // ../connectors/src/lib/oracle-runner.ts
117259
+ async function importOracleDb() {
117260
+ const mod = await import("oracledb");
117261
+ return mod.default ?? mod;
117262
+ }
117263
+ async function runOracleQuery(parsed, sql) {
117264
+ const oracledb = await importOracleDb();
117265
+ const connection2 = await oracledb.getConnection({
117266
+ user: parsed.user,
117267
+ password: parsed.password,
117268
+ connectString: parsed.connectString
117269
+ });
117270
+ try {
117271
+ const result = await connection2.execute(sql, [], {
117272
+ outFormat: oracledb.OUT_FORMAT_OBJECT,
117273
+ // Bound by the connector's own row cap, but keep the driver from
117274
+ // streaming arbitrarily large result sets.
117275
+ maxRows: 5e3
117276
+ });
117277
+ return { rows: result.rows ?? [] };
117278
+ } finally {
117279
+ try {
117280
+ await connection2.close();
117281
+ } catch {
117282
+ }
117283
+ }
117284
+ }
117285
+ async function checkOracleConnection(url, credentials) {
117286
+ let parsed;
117287
+ try {
117288
+ parsed = parseOracleJdbcUrl(url, credentials);
117289
+ } catch (err) {
117290
+ return {
117291
+ success: false,
117292
+ error: err instanceof Error ? err.message : String(err)
117293
+ };
117294
+ }
117295
+ try {
117296
+ await runOracleQuery(parsed, "SELECT 1 FROM DUAL");
117297
+ return { success: true };
117298
+ } catch (err) {
117299
+ let msg = err instanceof Error ? err.message : String(err);
117300
+ msg = msg.replaceAll(url, redactOracleUrl(url));
117301
+ return { success: false, error: msg };
117302
+ }
117303
+ }
117304
+
117041
117305
  // ../connectors/src/connectors/jdbc/setup.ts
117042
117306
  var jdbcOnboarding = new ConnectorOnboarding({
117043
117307
  dataOverviewInstructions: {
@@ -117092,20 +117356,82 @@ var parameters67 = {
117092
117356
  import { z as z82 } from "zod";
117093
117357
 
117094
117358
  // ../connectors/src/connectors/jdbc/utils.ts
117095
- var JDBC_PREFIX_RE = /^jdbc:(postgresql|postgres|mysql|mariadb):\/\//i;
117359
+ var POSTGRES_PREFIX_RE = /^jdbc:(postgresql|postgres):\/\//i;
117360
+ var MYSQL_PREFIX_RE = /^jdbc:(mysql|mariadb):\/\//i;
117361
+ var REDSHIFT_PREFIX_RE = /^jdbc:redshift:\/\//i;
117362
+ var SQLSERVER_PREFIX_RE2 = /^jdbc:sqlserver:\/\//i;
117363
+ var ORACLE_PREFIX_RE = /^jdbc:oracle:thin:/i;
117364
+ var KNOWN_UNSUPPORTED = [
117365
+ {
117366
+ prefix: /^jdbc:snowflake:\/\//i,
117367
+ message: "Snowflake JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `snowflake` connector."
117368
+ },
117369
+ {
117370
+ prefix: /^jdbc:bigquery:\/\//i,
117371
+ message: "BigQuery JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `bigquery` connector."
117372
+ },
117373
+ {
117374
+ prefix: /^jdbc:databricks:\/\//i,
117375
+ message: "Databricks JDBC URLs are not routable through the generic `jdbc` connector. Use the dedicated `databricks` connector."
117376
+ },
117377
+ {
117378
+ prefix: /^jdbc:(trino|presto):\/\//i,
117379
+ message: "Trino/Presto JDBC URLs are not yet supported by the `jdbc` connector (no Node.js client bundled)."
117380
+ },
117381
+ {
117382
+ prefix: /^jdbc:td:\/\//i,
117383
+ 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."
117384
+ },
117385
+ {
117386
+ prefix: /^jdbc:oracle:oci/i,
117387
+ message: "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
117388
+ },
117389
+ {
117390
+ prefix: /^jdbc:db2:\/\//i,
117391
+ message: "DB2 JDBC URLs are not yet supported by the `jdbc` connector."
117392
+ },
117393
+ {
117394
+ prefix: /^jdbc:(sybase|h2|hsqldb|derby|firebird|sqlite):/i,
117395
+ message: "This JDBC dialect is not supported by the `jdbc` connector."
117396
+ }
117397
+ ];
117096
117398
  function parseJdbcUrl(jdbcUrl, options = {}) {
117097
117399
  const trimmed = jdbcUrl.trim();
117098
- const match = JDBC_PREFIX_RE.exec(trimmed);
117099
- if (!match) {
117400
+ if (SQLSERVER_PREFIX_RE2.test(trimmed)) {
117401
+ return { driver: "sqlserver", originalUrl: trimmed };
117402
+ }
117403
+ if (ORACLE_PREFIX_RE.test(trimmed)) {
117404
+ return { driver: "oracle", originalUrl: trimmed };
117405
+ }
117406
+ let driver;
117407
+ let defaultPort;
117408
+ let forceSsl = false;
117409
+ let nativeProtocol;
117410
+ let withoutPrefix;
117411
+ if (POSTGRES_PREFIX_RE.test(trimmed)) {
117412
+ driver = "postgresql";
117413
+ defaultPort = 5432;
117414
+ nativeProtocol = "postgresql://";
117415
+ withoutPrefix = trimmed.replace(POSTGRES_PREFIX_RE, nativeProtocol);
117416
+ } else if (REDSHIFT_PREFIX_RE.test(trimmed)) {
117417
+ driver = "postgresql";
117418
+ defaultPort = 5439;
117419
+ forceSsl = true;
117420
+ nativeProtocol = "postgresql://";
117421
+ withoutPrefix = trimmed.replace(REDSHIFT_PREFIX_RE, nativeProtocol);
117422
+ } else if (MYSQL_PREFIX_RE.test(trimmed)) {
117423
+ driver = "mysql";
117424
+ defaultPort = 3306;
117425
+ nativeProtocol = "mysql://";
117426
+ withoutPrefix = trimmed.replace(MYSQL_PREFIX_RE, nativeProtocol);
117427
+ } else {
117428
+ for (const { prefix, message } of KNOWN_UNSUPPORTED) {
117429
+ if (prefix.test(trimmed)) throw new Error(message);
117430
+ }
117100
117431
  throw new Error(
117101
- `Unsupported JDBC URL "${redactJdbcUrl(trimmed)}". Supported prefixes: jdbc:postgresql://, jdbc:mysql://, jdbc:mariadb://.`
117432
+ `Unsupported JDBC URL "${redactJdbcUrl(trimmed)}". Supported prefixes: jdbc:postgresql://, jdbc:postgres://, jdbc:mysql://, jdbc:mariadb://, jdbc:sqlserver://, jdbc:oracle:thin:@, jdbc:redshift://.`
117102
117433
  );
117103
117434
  }
117104
- const subProtocol = match[1].toLowerCase();
117105
- const driver = subProtocol === "mysql" || subProtocol === "mariadb" ? "mysql" : "postgresql";
117106
- const defaultPort = driver === "postgresql" ? 5432 : 3306;
117107
- const nativeProtocol = driver === "postgresql" ? "postgresql://" : "mysql://";
117108
- const withoutPrefix = trimmed.replace(JDBC_PREFIX_RE, nativeProtocol);
117109
117435
  const url = new URL(withoutPrefix);
117110
117436
  if (options.username && !url.username) {
117111
117437
  url.username = encodeURIComponent(options.username);
@@ -117113,10 +117439,10 @@ function parseJdbcUrl(jdbcUrl, options = {}) {
117113
117439
  if (options.password && !url.password) {
117114
117440
  url.password = encodeURIComponent(options.password);
117115
117441
  }
117116
- return { driver, nativeUrl: url.toString(), defaultPort };
117442
+ return { driver, nativeUrl: url.toString(), defaultPort, forceSsl };
117117
117443
  }
117118
117444
  function redactJdbcUrl(jdbcUrl) {
117119
- return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@");
117445
+ return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(password\s*=\s*)([^;&]+)/gi, "$1***");
117120
117446
  }
117121
117447
 
117122
117448
  // ../connectors/src/connectors/jdbc/tools/execute-query.ts
@@ -117129,7 +117455,7 @@ var inputSchema82 = z82.object({
117129
117455
  ),
117130
117456
  connectionId: z82.string().describe("ID of the JDBC connection to use"),
117131
117457
  sql: z82.string().describe(
117132
- "SQL query to execute. Use the dialect that matches the JDBC URL (PostgreSQL or MySQL/MariaDB). Always include LIMIT."
117458
+ "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."
117133
117459
  )
117134
117460
  });
117135
117461
  var outputSchema82 = z82.discriminatedUnion("success", [
@@ -117147,9 +117473,10 @@ var outputSchema82 = z82.discriminatedUnion("success", [
117147
117473
  var executeQueryTool12 = new ConnectorTool({
117148
117474
  name: "executeQuery",
117149
117475
  description: `Execute a SQL query through the JDBC connector. Returns up to ${MAX_ROWS12} rows.
117150
- Use for: schema exploration via \`information_schema\`, data sampling, analytical queries.
117151
- The connector dispatches by JDBC URL prefix to the matching driver (PostgreSQL or MySQL/MariaDB),
117152
- so use the dialect that matches the connection. Always include LIMIT.`,
117476
+ Use for: schema exploration via \`information_schema\` (or USER_TABLES on Oracle), data sampling, analytical queries.
117477
+ The connector dispatches by JDBC URL prefix to the matching driver
117478
+ (PostgreSQL / Redshift / MySQL / MariaDB / SQL Server / Oracle), so use the dialect that matches the connection.
117479
+ Always bound results: LIMIT for PG/MySQL/Redshift, TOP for SQL Server, FETCH FIRST for Oracle.`,
117153
117480
  inputSchema: inputSchema82,
117154
117481
  outputSchema: outputSchema82,
117155
117482
  async execute({ connectionId, sql }, connections) {
@@ -117175,87 +117502,121 @@ so use the dialect that matches the connection. Always include LIMIT.`,
117175
117502
  error: err instanceof Error ? err.message : String(err)
117176
117503
  };
117177
117504
  }
117178
- let tunnel;
117179
117505
  try {
117180
- tunnel = await maybeOpenSshTunnel(
117181
- connectionParamsToRecord(connection2),
117182
- parsed.nativeUrl,
117183
- parsed.defaultPort
117184
- );
117185
- if (parsed.driver === "postgresql") {
117186
- const { Pool } = await import("pg");
117187
- const pool2 = new Pool({
117188
- connectionString: tunnel.connectionUrl,
117189
- ssl: { rejectUnauthorized: false },
117190
- connectionTimeoutMillis: CONNECT_TIMEOUT_MS7,
117191
- statement_timeout: STATEMENT_TIMEOUT_MS3
117506
+ if (parsed.driver === "sqlserver") {
117507
+ const mssqlParsed = parseSqlServerJdbcUrl(parsed.originalUrl, {
117508
+ username,
117509
+ password
117510
+ });
117511
+ const result = await runMssqlQuery(mssqlParsed, sql);
117512
+ const rows = result.rows;
117513
+ return {
117514
+ success: true,
117515
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117516
+ truncated: rows.length > MAX_ROWS12,
117517
+ rows: rows.slice(0, MAX_ROWS12)
117518
+ };
117519
+ }
117520
+ if (parsed.driver === "oracle") {
117521
+ const oracleParsed = parseOracleJdbcUrl(parsed.originalUrl, {
117522
+ username,
117523
+ password
117524
+ });
117525
+ const cleanSql = sql.replace(/;\s*$/, "");
117526
+ const result = await runOracleQuery(oracleParsed, cleanSql);
117527
+ const rows = result.rows;
117528
+ return {
117529
+ success: true,
117530
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117531
+ truncated: rows.length > MAX_ROWS12,
117532
+ rows: rows.slice(0, MAX_ROWS12)
117533
+ };
117534
+ }
117535
+ let tunnel;
117536
+ try {
117537
+ tunnel = await maybeOpenSshTunnel(
117538
+ connectionParamsToRecord(connection2),
117539
+ parsed.nativeUrl,
117540
+ parsed.defaultPort
117541
+ );
117542
+ if (parsed.driver === "postgresql") {
117543
+ const { Pool } = await import("pg");
117544
+ const pool2 = new Pool({
117545
+ connectionString: tunnel.connectionUrl,
117546
+ ssl: { rejectUnauthorized: false },
117547
+ connectionTimeoutMillis: CONNECT_TIMEOUT_MS7,
117548
+ statement_timeout: STATEMENT_TIMEOUT_MS3
117549
+ });
117550
+ try {
117551
+ const result = await pool2.query(sql);
117552
+ const rows = result.rows;
117553
+ const truncated = rows.length > MAX_ROWS12;
117554
+ return {
117555
+ success: true,
117556
+ rowCount: Math.min(rows.length, MAX_ROWS12),
117557
+ truncated,
117558
+ rows: rows.slice(0, MAX_ROWS12)
117559
+ };
117560
+ } finally {
117561
+ await pool2.end();
117562
+ }
117563
+ }
117564
+ const mysql = await import("mysql2/promise");
117565
+ const pool = mysql.createPool({
117566
+ uri: tunnel.connectionUrl,
117567
+ connectTimeout: CONNECT_TIMEOUT_MS7
117192
117568
  });
117193
117569
  try {
117194
- const result = await pool2.query(sql);
117195
- const rows = result.rows;
117196
- const truncated = rows.length > MAX_ROWS12;
117570
+ const queryPromise = pool.query(sql);
117571
+ const timeoutPromise = new Promise(
117572
+ (_, reject) => setTimeout(
117573
+ () => reject(new Error("Query timed out after 60 seconds")),
117574
+ STATEMENT_TIMEOUT_MS3
117575
+ )
117576
+ );
117577
+ const [rows] = await Promise.race([queryPromise, timeoutPromise]);
117578
+ const resultRows = Array.isArray(rows) ? rows : [];
117579
+ const truncated = resultRows.length > MAX_ROWS12;
117197
117580
  return {
117198
117581
  success: true,
117199
- rowCount: Math.min(rows.length, MAX_ROWS12),
117582
+ rowCount: Math.min(resultRows.length, MAX_ROWS12),
117200
117583
  truncated,
117201
- rows: rows.slice(0, MAX_ROWS12)
117584
+ rows: resultRows.slice(0, MAX_ROWS12)
117202
117585
  };
117203
117586
  } finally {
117204
- await pool2.end();
117587
+ await pool.end();
117205
117588
  }
117206
- }
117207
- const mysql = await import("mysql2/promise");
117208
- const pool = mysql.createPool({
117209
- uri: tunnel.connectionUrl,
117210
- connectTimeout: CONNECT_TIMEOUT_MS7
117211
- });
117212
- try {
117213
- const queryPromise = pool.query(sql);
117214
- const timeoutPromise = new Promise(
117215
- (_, reject) => setTimeout(
117216
- () => reject(new Error("Query timed out after 60 seconds")),
117217
- STATEMENT_TIMEOUT_MS3
117218
- )
117219
- );
117220
- const [rows] = await Promise.race([queryPromise, timeoutPromise]);
117221
- const resultRows = Array.isArray(rows) ? rows : [];
117222
- const truncated = resultRows.length > MAX_ROWS12;
117223
- return {
117224
- success: true,
117225
- rowCount: Math.min(resultRows.length, MAX_ROWS12),
117226
- truncated,
117227
- rows: resultRows.slice(0, MAX_ROWS12)
117228
- };
117229
117589
  } finally {
117230
- await pool.end();
117590
+ await tunnel?.close();
117231
117591
  }
117232
117592
  } catch (err) {
117233
117593
  let msg = err instanceof Error ? err.message : String(err);
117234
- msg = msg.replaceAll(parsed.nativeUrl, redactJdbcUrl(jdbcUrl));
117594
+ if (parsed.driver === "postgresql" || parsed.driver === "mysql") {
117595
+ msg = msg.replaceAll(parsed.nativeUrl, redactJdbcUrl(jdbcUrl));
117596
+ }
117235
117597
  msg = msg.replaceAll(jdbcUrl, redactJdbcUrl(jdbcUrl));
117236
117598
  return { success: false, error: msg };
117237
- } finally {
117238
- await tunnel?.close();
117239
117599
  }
117240
117600
  }
117241
117601
  });
117242
117602
 
117243
117603
  // ../connectors/src/connectors/jdbc/index.ts
117244
117604
  var tools67 = { executeQuery: executeQueryTool12 };
117605
+ var SAMPLE_WRAPPER_RE = /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i;
117245
117606
  var jdbcConnector = new ConnectorPlugin({
117246
117607
  slug: "jdbc",
117247
117608
  authType: AUTH_TYPES.USER_PASSWORD,
117248
117609
  name: "JDBC",
117249
- description: "Generic JDBC-style connection. Accepts a JDBC URL and dispatches to the matching driver (PostgreSQL, MySQL, MariaDB).",
117610
+ description: "Generic JDBC-style connection. Accepts a JDBC URL and dispatches to the matching driver (PostgreSQL, MySQL/MariaDB, SQL Server, Oracle, Redshift).",
117250
117611
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4Hgb5qQffrdu5nOkc49WtM/76d82ef6b108c7780e42998137c61b83/jdbc-icon.png",
117251
117612
  parameters: parameters67,
117252
- releaseFlag: { dev1: true, dev2: false, prod: false },
117613
+ releaseFlag: { dev1: true, dev2: true, prod: true },
117253
117614
  categories: ["database"],
117254
117615
  onboarding: jdbcOnboarding,
117255
117616
  systemPrompt: {
117256
117617
  en: `### Tools
117257
117618
 
117258
- - \`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.
117619
+ - \`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.
117259
117620
 
117260
117621
  ### Business Logic
117261
117622
 
@@ -117265,16 +117626,29 @@ The business logic type for this connector is "sql".
117265
117626
 
117266
117627
  The dialect depends on the JDBC URL prefix:
117267
117628
 
117268
- - \`jdbc:postgresql://...\` \u2192 PostgreSQL dialect
117629
+ - \`jdbc:postgresql://...\` / \`jdbc:postgres://...\` \u2192 PostgreSQL (driver: \`pg\`). \`LIMIT N\` is native.
117269
117630
  - List tables: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
117270
117631
  - List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
117271
- - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL dialect
117632
+ - \`jdbc:redshift://...\` \u2192 Amazon Redshift (driver: \`pg\` with SSL forced; default port 5439). PostgreSQL-compatible wire protocol; \`LIMIT N\` is native.
117633
+ - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL / MariaDB (driver: \`mysql2\`). \`LIMIT N\` is native.
117272
117634
  - List tables: \`SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()\`
117273
117635
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
117274
- - Always include LIMIT in queries`,
117636
+ - \`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.
117637
+ - List tables: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'\`
117638
+ - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'xxx'\`
117639
+ - \`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.
117640
+ - List tables: \`SELECT TABLE_NAME FROM USER_TABLES\`
117641
+ - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = UPPER('xxx')\`
117642
+
117643
+ Explicitly **not** supported via this connector \u2014 use the dedicated connector or open a request:
117644
+ \`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.
117645
+
117646
+ ### Row-limit compatibility (server-logic schema inference)
117647
+
117648
+ 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.`,
117275
117649
  ja: `### \u30C4\u30FC\u30EB
117276
117650
 
117277
- - \`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
117651
+ - \`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
117278
117652
 
117279
117653
  ### Business Logic
117280
117654
 
@@ -117284,13 +117658,26 @@ The dialect depends on the JDBC URL prefix:
117284
117658
 
117285
117659
  JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B9\u8A00\u304C\u6C7A\u307E\u308A\u307E\u3059:
117286
117660
 
117287
- - \`jdbc:postgresql://...\` \u2192 PostgreSQL \u65B9\u8A00
117661
+ - \`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
117288
117662
  - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
117289
117663
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
117290
- - \`jdbc:mysql://...\` / \`jdbc:mariadb://...\` \u2192 MySQL \u65B9\u8A00
117664
+ - \`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
117665
+ - \`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
117291
117666
  - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()\`
117292
117667
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
117293
- - \u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A LIMIT \u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044`
117668
+ - \`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
117669
+ - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'\`
117670
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'xxx'\`
117671
+ - \`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
117672
+ - \u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_NAME FROM USER_TABLES\`
117673
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = UPPER('xxx')\`
117674
+
117675
+ \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:
117676
+ \`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
117677
+
117678
+ ### \u884C\u6570\u5236\u9650\u306E\u4E92\u63DB\u6027\uFF08server-logic \u30B9\u30AD\u30FC\u30DE\u63A8\u8AD6\uFF09
117679
+
117680
+ \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`
117294
117681
  },
117295
117682
  tools: tools67,
117296
117683
  async checkConnection(params, _config) {
@@ -117306,6 +117693,12 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117306
117693
  error: e7 instanceof Error ? e7.message : String(e7)
117307
117694
  };
117308
117695
  }
117696
+ if (parsed.driver === "sqlserver") {
117697
+ return checkMssqlConnection(parsed.originalUrl, { username, password });
117698
+ }
117699
+ if (parsed.driver === "oracle") {
117700
+ return checkOracleConnection(parsed.originalUrl, { username, password });
117701
+ }
117309
117702
  const tunnel = await maybeOpenSshTunnel(
117310
117703
  params,
117311
117704
  parsed.nativeUrl,
@@ -117315,7 +117708,7 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117315
117708
  const { Pool } = await import("pg");
117316
117709
  const pool2 = new Pool({
117317
117710
  connectionString: tunnel.connectionUrl,
117318
- ssl: { rejectUnauthorized: false },
117711
+ ssl: parsed.forceSsl ? { rejectUnauthorized: false } : { rejectUnauthorized: false },
117319
117712
  connectionTimeoutMillis: 1e4
117320
117713
  });
117321
117714
  try {
@@ -117354,6 +117747,35 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117354
117747
  const username = params[parameters67.username.slug];
117355
117748
  const password = params[parameters67.password.slug];
117356
117749
  const parsed = parseJdbcUrl(jdbcUrl, { username, password });
117750
+ if (parsed.driver === "sqlserver") {
117751
+ const mssqlParsed = parseSqlServerJdbcUrl(parsed.originalUrl, {
117752
+ username,
117753
+ password
117754
+ });
117755
+ const wrapper = sql.match(SAMPLE_WRAPPER_RE);
117756
+ if (wrapper) {
117757
+ const inner = wrapper[1].trim();
117758
+ const limit = Number.parseInt(wrapper[2], 10);
117759
+ const result = await runMssqlQuery(mssqlParsed, inner);
117760
+ return { rows: result.rows.slice(0, limit) };
117761
+ }
117762
+ return runMssqlQuery(mssqlParsed, sql);
117763
+ }
117764
+ if (parsed.driver === "oracle") {
117765
+ const oracleParsed = parseOracleJdbcUrl(parsed.originalUrl, {
117766
+ username,
117767
+ password
117768
+ });
117769
+ const wrapper = sql.match(SAMPLE_WRAPPER_RE);
117770
+ if (wrapper) {
117771
+ const inner = wrapper[1].trim().replace(/;\s*$/, "");
117772
+ const limit = Number.parseInt(wrapper[2], 10);
117773
+ const result = await runOracleQuery(oracleParsed, inner);
117774
+ return { rows: result.rows.slice(0, limit) };
117775
+ }
117776
+ const cleanSql = sql.replace(/;\s*$/, "");
117777
+ return runOracleQuery(oracleParsed, cleanSql);
117778
+ }
117357
117779
  const tunnel = await maybeOpenSshTunnel(
117358
117780
  params,
117359
117781
  parsed.nativeUrl,
@@ -117364,7 +117786,7 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
117364
117786
  const cleanSql = sql.replace(/;\s*$/, "");
117365
117787
  const pool2 = new Pool({
117366
117788
  connectionString: tunnel.connectionUrl,
117367
- ssl: { rejectUnauthorized: false },
117789
+ ssl: parsed.forceSsl ? { rejectUnauthorized: false } : { rejectUnauthorized: false },
117368
117790
  connectionTimeoutMillis: 1e4,
117369
117791
  statement_timeout: 6e4
117370
117792
  });
@@ -118090,7 +118512,7 @@ var googleSearchConsoleOauthConnector = new ConnectorPlugin({
118090
118512
  description: "Connect to Google Search Console for search performance, indexing, and sitemap data using OAuth.",
118091
118513
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/3rPusKosno7i1emOCmskTp/9ed092a4dc95efb74e34e83098ef3905/google-search-console-icon.webp",
118092
118514
  parameters: parameters69,
118093
- releaseFlag: { dev1: true, dev2: false, prod: false },
118515
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118094
118516
  categories: ["marketing"],
118095
118517
  onboarding: googleSearchConsoleOauthOnboarding,
118096
118518
  proxyPolicy: {
@@ -118153,7 +118575,7 @@ The business logic type for this connector is "typescript". Write handler code u
118153
118575
  SDK surface (client created via \`connection(connectionId)\`):
118154
118576
  - \`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).
118155
118577
  - \`client.listSites()\` \u2014 list sites accessible by the OAuth user.
118156
- - \`client.querySearchAnalytics(request, siteUrl?)\` \u2014 query Search Analytics performance data.
118578
+ - \`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.
118157
118579
  - \`client.listSitemaps(siteUrl?)\` \u2014 list sitemaps submitted for a site.
118158
118580
 
118159
118581
  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.
@@ -118169,7 +118591,7 @@ const gsc = connection("<connectionId>");
118169
118591
  const sites = await gsc.listSites();
118170
118592
  console.log(sites.map(s => \`\${s.siteUrl} (\${s.permissionLevel})\`));
118171
118593
 
118172
- // Top queries for the last 28 days
118594
+ // Top queries for the last 28 days \u2014 flat shape (recommended)
118173
118595
  const { rows } = await gsc.querySearchAnalytics({
118174
118596
  startDate: "2024-01-01",
118175
118597
  endDate: "2024-01-28",
@@ -118178,6 +118600,12 @@ const { rows } = await gsc.querySearchAnalytics({
118178
118600
  });
118179
118601
  rows?.forEach(r => console.log(r.keys?.[0], r.clicks, r.impressions));
118180
118602
 
118603
+ // Override the configured site (also accepts requestBody envelope)
118604
+ await gsc.querySearchAnalytics({
118605
+ siteUrl: "sc-domain:example.com",
118606
+ requestBody: { startDate: "2024-01-01", endDate: "2024-01-28", dimensions: ["page"] },
118607
+ });
118608
+
118181
118609
  // List sitemaps
118182
118610
  const sitemaps = await gsc.listSitemaps();
118183
118611
  sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
@@ -118233,7 +118661,7 @@ sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
118233
118661
  SDK\uFF08\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\uFF09:
118234
118662
  - \`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
118235
118663
  - \`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
118236
- - \`client.querySearchAnalytics(request, siteUrl?)\` \u2014 \u691C\u7D22\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3002
118664
+ - \`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
118237
118665
  - \`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
118238
118666
 
118239
118667
  \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
@@ -118249,7 +118677,7 @@ const gsc = connection("<connectionId>");
118249
118677
  const sites = await gsc.listSites();
118250
118678
  console.log(sites.map(s => \`\${s.siteUrl} (\${s.permissionLevel})\`));
118251
118679
 
118252
- // Top queries for the last 28 days
118680
+ // Top queries for the last 28 days \u2014 \u30D5\u30E9\u30C3\u30C8\u5F62\u5F0F\uFF08\u63A8\u5968\uFF09
118253
118681
  const { rows } = await gsc.querySearchAnalytics({
118254
118682
  startDate: "2024-01-01",
118255
118683
  endDate: "2024-01-28",
@@ -118258,6 +118686,12 @@ const { rows } = await gsc.querySearchAnalytics({
118258
118686
  });
118259
118687
  rows?.forEach(r => console.log(r.keys?.[0], r.clicks, r.impressions));
118260
118688
 
118689
+ // siteUrl \u3092\u4E0A\u66F8\u304D\u3059\u308B\u5834\u5408\uFF08requestBody \u30A8\u30F3\u30D9\u30ED\u30FC\u30D7\u3082\u53EF\uFF09
118690
+ await gsc.querySearchAnalytics({
118691
+ siteUrl: "sc-domain:example.com",
118692
+ requestBody: { startDate: "2024-01-01", endDate: "2024-01-28", dimensions: ["page"] },
118693
+ });
118694
+
118261
118695
  // List sitemaps
118262
118696
  const sitemaps = await gsc.listSitemaps();
118263
118697
  sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
@@ -118401,7 +118835,7 @@ var supabaseConnector = new ConnectorPlugin({
118401
118835
  description: "Connect to a Supabase project's Postgres database to query application tables and Supabase-managed schemas (auth, storage).",
118402
118836
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/14k0U6F9PVovVjYjWyNzKb/2c4ff53adbe9334a63fee0a13d9f050a/supabase-icon.webp",
118403
118837
  parameters: parameters70,
118404
- releaseFlag: { dev1: true, dev2: false, prod: false },
118838
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118405
118839
  categories: ["database"],
118406
118840
  onboarding: supabaseOnboarding,
118407
118841
  systemPrompt: {
@@ -118628,7 +119062,7 @@ var clickupConnector = new ConnectorPlugin({
118628
119062
  description: "Connect to ClickUp for project management, task tracking, time tracking, and team collaboration data via Personal API Token.",
118629
119063
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5bzXkRjOeFJ7KoWdN55RAK/8b9270e4b09a9760912edae36d805fe4/clickup-icon.webp",
118630
119064
  parameters: parameters71,
118631
- releaseFlag: { dev1: true, dev2: false, prod: false },
119065
+ releaseFlag: { dev1: true, dev2: true, prod: true },
118632
119066
  categories: ["productivity"],
118633
119067
  onboarding: clickupOnboarding,
118634
119068
  systemPrompt: {
@@ -118808,117 +119242,6 @@ export default async function handler(c: Context) {
118808
119242
  tools: tools71
118809
119243
  });
118810
119244
 
118811
- // ../connectors/src/connectors/sqlserver/utils.ts
118812
- var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
118813
- var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
118814
- var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
118815
- function parseBoolean(value) {
118816
- if (value == null) return void 0;
118817
- const lower = value.toLowerCase();
118818
- if (TRUE_VALUES.has(lower)) return true;
118819
- if (FALSE_VALUES.has(lower)) return false;
118820
- return void 0;
118821
- }
118822
- function parseSqlServerJdbcUrl(jdbcUrl, options = {}) {
118823
- const trimmed = jdbcUrl.trim();
118824
- if (!SQLSERVER_PREFIX_RE.test(trimmed)) {
118825
- throw new Error(
118826
- `Unsupported SQL Server URL "${redactSqlServerUrl(trimmed)}". Expected prefix: jdbc:sqlserver:// or sqlserver://.`
118827
- );
118828
- }
118829
- const withoutPrefix = trimmed.replace(SQLSERVER_PREFIX_RE, "");
118830
- const [hostAndPath, ...propertySegments] = withoutPrefix.split(";");
118831
- const props = {};
118832
- for (const segment of propertySegments) {
118833
- if (!segment) continue;
118834
- const eqIdx = segment.indexOf("=");
118835
- if (eqIdx === -1) continue;
118836
- const key = segment.slice(0, eqIdx).trim().toLowerCase();
118837
- const value = segment.slice(eqIdx + 1).trim();
118838
- if (key) props[key] = value;
118839
- }
118840
- const url = new URL(`mssql://${hostAndPath}`);
118841
- for (const [key, value] of url.searchParams.entries()) {
118842
- if (!(key.toLowerCase() in props)) {
118843
- props[key.toLowerCase()] = value;
118844
- }
118845
- }
118846
- const server = url.hostname;
118847
- const port = url.port ? Number(url.port) : 1433;
118848
- const pathname = url.pathname.replace(/^\//, "");
118849
- const database = pathname || props["database"] || props["databasename"];
118850
- const user = props["user"] || props["username"] || props["userid"] || options.username;
118851
- const password = props["password"] || options.password;
118852
- return {
118853
- server,
118854
- port,
118855
- database,
118856
- user,
118857
- password,
118858
- options: props
118859
- };
118860
- }
118861
- function toMssqlConfig(parsed, defaults = {}) {
118862
- const encrypt = parseBoolean(parsed.options["encrypt"]) ?? defaults.encrypt ?? false;
118863
- const trustServerCertificate = parseBoolean(parsed.options["trustservercertificate"]) ?? !encrypt;
118864
- return {
118865
- server: parsed.server,
118866
- port: parsed.port,
118867
- database: parsed.database,
118868
- user: parsed.user,
118869
- password: parsed.password,
118870
- connectionTimeout: 1e4,
118871
- requestTimeout: 6e4,
118872
- options: {
118873
- encrypt,
118874
- trustServerCertificate
118875
- }
118876
- };
118877
- }
118878
- function redactSqlServerUrl(jdbcUrl) {
118879
- return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
118880
- }
118881
-
118882
- // ../connectors/src/lib/mssql-runner.ts
118883
- async function importMssql() {
118884
- const mod = await import("mssql");
118885
- return mod.default ?? mod;
118886
- }
118887
- async function runMssqlQuery(parsed, sql, options = {}) {
118888
- const sqlMod = await importMssql();
118889
- const config = toMssqlConfig(parsed, {
118890
- encrypt: options.forceEncrypt
118891
- });
118892
- const pool = new sqlMod.ConnectionPool(config);
118893
- await pool.connect();
118894
- try {
118895
- const result = await pool.request().query(sql);
118896
- const recordset = result.recordset ?? [];
118897
- return { rows: recordset };
118898
- } finally {
118899
- await pool.close();
118900
- }
118901
- }
118902
- async function checkMssqlConnection(url, credentials, options = {}) {
118903
- let parsed;
118904
- try {
118905
- parsed = parseSqlServerJdbcUrl(url, credentials);
118906
- } catch (err) {
118907
- return {
118908
- success: false,
118909
- error: err instanceof Error ? err.message : String(err)
118910
- };
118911
- }
118912
- try {
118913
- await runMssqlQuery(parsed, "SELECT 1 AS one", options);
118914
- return { success: true };
118915
- } catch (err) {
118916
- let msg = err instanceof Error ? err.message : String(err);
118917
- msg = msg.replaceAll(url, redactSqlServerUrl(url));
118918
- return { success: false, error: msg };
118919
- }
118920
- }
118921
-
118922
119245
  // ../connectors/src/connectors/sqlserver/setup.ts
118923
119246
  var sqlserverOnboarding = new ConnectorOnboarding({
118924
119247
  dataOverviewInstructions: {
@@ -119064,7 +119387,8 @@ The business logic type for this connector is "sql".
119064
119387
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119065
119388
  - Use \`TOP n\` instead of \`LIMIT n\` (e.g. \`SELECT TOP 100 * FROM ...\`).
119066
119389
  - Identifiers can be quoted with square brackets, e.g. \`[Order Details]\`.
119067
- - Always bound results with \`TOP\` in queries.`,
119390
+ - Always bound results with \`TOP\` in queries.
119391
+ - 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.`,
119068
119392
  ja: `### \u30C4\u30FC\u30EB
119069
119393
 
119070
119394
  - \`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
@@ -119080,7 +119404,8 @@ The business logic type for this connector is "sql".
119080
119404
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119081
119405
  - \`LIMIT n\` \u3067\u306F\u306A\u304F \`TOP n\` \u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08\u4F8B: \`SELECT TOP 100 * FROM ...\`\uFF09\u3002
119082
119406
  - \u8B58\u5225\u5B50\u306F\u89D2\u62EC\u5F27\u3067\u56F2\u3081\u307E\u3059\uFF08\u4F8B: \`[Order Details]\`\uFF09\u3002
119083
- - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
119407
+ - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002
119408
+ - \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`
119084
119409
  },
119085
119410
  tools: tools72,
119086
119411
  async checkConnection(params, _config) {
@@ -119097,6 +119422,15 @@ The business logic type for this connector is "sql".
119097
119422
  username: params[parameters72.username.slug],
119098
119423
  password: params[parameters72.password.slug]
119099
119424
  });
119425
+ const wrapper = sql.match(
119426
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119427
+ );
119428
+ if (wrapper) {
119429
+ const inner = wrapper[1].trim();
119430
+ const limit = Number.parseInt(wrapper[2], 10);
119431
+ const result = await runMssqlQuery(parsed, inner);
119432
+ return { rows: result.rows.slice(0, limit) };
119433
+ }
119100
119434
  return runMssqlQuery(parsed, sql);
119101
119435
  }
119102
119436
  });
@@ -119246,7 +119580,8 @@ The business logic type for this connector is "sql".
119246
119580
  - 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')\`
119247
119581
  - List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119248
119582
  - Cross-database queries are not supported on Azure SQL Database (single-DB scope per connection); always reference objects within the connected database.
119249
- - Always bound results with \`TOP\` in queries.`,
119583
+ - Always bound results with \`TOP\` in queries.
119584
+ - 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.`,
119250
119585
  ja: `### \u30C4\u30FC\u30EB
119251
119586
 
119252
119587
  - \`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
@@ -119262,7 +119597,8 @@ The business logic type for this connector is "sql".
119262
119597
  - \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')\`
119263
119598
  - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
119264
119599
  - 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
119265
- - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
119600
+ - \u7D50\u679C\u4EF6\u6570\u306F\u5FC5\u305A \`TOP\` \u3067\u5236\u9650\u3057\u3066\u304F\u3060\u3055\u3044\u3002
119601
+ - \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`
119266
119602
  },
119267
119603
  tools: tools73,
119268
119604
  async checkConnection(params, _config) {
@@ -119280,122 +119616,18 @@ The business logic type for this connector is "sql".
119280
119616
  username: params[parameters73.username.slug],
119281
119617
  password: params[parameters73.password.slug]
119282
119618
  });
119283
- return runMssqlQuery(parsed, sql, { forceEncrypt: true });
119284
- }
119285
- });
119286
-
119287
- // ../connectors/src/connectors/oracle/utils.ts
119288
- var JDBC_THIN_PREFIX_RE = /^jdbc:oracle:thin:/i;
119289
- var JDBC_OCI_PREFIX_RE = /^jdbc:oracle:oci/i;
119290
- var URL_PREFIX_RE = /^oracle:\/\//i;
119291
- function parseOracleJdbcUrl(jdbcUrl, options = {}) {
119292
- const trimmed = jdbcUrl.trim();
119293
- if (JDBC_OCI_PREFIX_RE.test(trimmed)) {
119294
- throw new Error(
119295
- "Oracle OCI driver URLs are not supported. Use the thin driver form: jdbc:oracle:thin:@host:port/service"
119296
- );
119297
- }
119298
- if (URL_PREFIX_RE.test(trimmed)) {
119299
- const url = new URL(trimmed);
119300
- const path5 = url.pathname.replace(/^\//, "");
119301
- if (!url.hostname || !path5) {
119302
- throw new Error(
119303
- `Invalid Oracle URL "${redactOracleUrl(trimmed)}". Expected oracle://[user:password@]host:port/service`
119304
- );
119305
- }
119306
- const port = url.port || "1521";
119307
- return {
119308
- connectString: `${url.hostname}:${port}/${path5}`,
119309
- user: url.username ? decodeURIComponent(url.username) : options.username,
119310
- password: url.password ? decodeURIComponent(url.password) : options.password
119311
- };
119312
- }
119313
- if (!JDBC_THIN_PREFIX_RE.test(trimmed)) {
119314
- throw new Error(
119315
- `Unsupported Oracle URL "${redactOracleUrl(trimmed)}". Expected prefix: jdbc:oracle:thin:@ or oracle://`
119619
+ const wrapper = sql.match(
119620
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119316
119621
  );
119317
- }
119318
- const afterPrefix = trimmed.replace(JDBC_THIN_PREFIX_RE, "");
119319
- const atIdx = afterPrefix.indexOf("@");
119320
- if (atIdx === -1) {
119321
- throw new Error(
119322
- `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Expected '@' separator before host.`
119323
- );
119324
- }
119325
- const credentialsPart = afterPrefix.slice(0, atIdx);
119326
- const target = afterPrefix.slice(atIdx + 1).replace(/^\/\//, "");
119327
- let user = options.username;
119328
- let password = options.password;
119329
- if (credentialsPart) {
119330
- const slashIdx = credentialsPart.indexOf("/");
119331
- if (slashIdx === -1) {
119332
- user = credentialsPart || user;
119333
- } else {
119334
- user = credentialsPart.slice(0, slashIdx) || user;
119335
- password = credentialsPart.slice(slashIdx + 1) || password;
119336
- }
119337
- }
119338
- if (!target) {
119339
- throw new Error(
119340
- `Invalid Oracle JDBC URL "${redactOracleUrl(trimmed)}". Missing host portion after '@'.`
119341
- );
119342
- }
119343
- return {
119344
- connectString: target,
119345
- user,
119346
- password
119347
- };
119348
- }
119349
- function redactOracleUrl(jdbcUrl) {
119350
- return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(thin:)([^@]+)@/i, "$1***@");
119351
- }
119352
-
119353
- // ../connectors/src/lib/oracle-runner.ts
119354
- async function importOracleDb() {
119355
- const mod = await import("oracledb");
119356
- return mod.default ?? mod;
119357
- }
119358
- async function runOracleQuery(parsed, sql) {
119359
- const oracledb = await importOracleDb();
119360
- const connection2 = await oracledb.getConnection({
119361
- user: parsed.user,
119362
- password: parsed.password,
119363
- connectString: parsed.connectString
119364
- });
119365
- try {
119366
- const result = await connection2.execute(sql, [], {
119367
- outFormat: oracledb.OUT_FORMAT_OBJECT,
119368
- // Bound by the connector's own row cap, but keep the driver from
119369
- // streaming arbitrarily large result sets.
119370
- maxRows: 5e3
119371
- });
119372
- return { rows: result.rows ?? [] };
119373
- } finally {
119374
- try {
119375
- await connection2.close();
119376
- } catch {
119622
+ if (wrapper) {
119623
+ const inner = wrapper[1].trim();
119624
+ const limit = Number.parseInt(wrapper[2], 10);
119625
+ const result = await runMssqlQuery(parsed, inner, { forceEncrypt: true });
119626
+ return { rows: result.rows.slice(0, limit) };
119377
119627
  }
119628
+ return runMssqlQuery(parsed, sql, { forceEncrypt: true });
119378
119629
  }
119379
- }
119380
- async function checkOracleConnection(url, credentials) {
119381
- let parsed;
119382
- try {
119383
- parsed = parseOracleJdbcUrl(url, credentials);
119384
- } catch (err) {
119385
- return {
119386
- success: false,
119387
- error: err instanceof Error ? err.message : String(err)
119388
- };
119389
- }
119390
- try {
119391
- await runOracleQuery(parsed, "SELECT 1 FROM DUAL");
119392
- return { success: true };
119393
- } catch (err) {
119394
- let msg = err instanceof Error ? err.message : String(err);
119395
- msg = msg.replaceAll(url, redactOracleUrl(url));
119396
- return { success: false, error: msg };
119397
- }
119398
- }
119630
+ });
119399
119631
 
119400
119632
  // ../connectors/src/connectors/oracle/setup.ts
119401
119633
  var oracleOnboarding = new ConnectorOnboarding({
@@ -119548,7 +119780,8 @@ The business logic type for this connector is "sql".
119548
119780
  - 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.
119549
119781
  - 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.
119550
119782
  - Single-row table: use \`SELECT 1 FROM DUAL\` for connection probes \u2014 Oracle requires a \`FROM\` clause on every query.
119551
- - Do not terminate statements with a semicolon; the thin driver rejects trailing terminators.`,
119783
+ - Do not terminate statements with a semicolon; the thin driver rejects trailing terminators.
119784
+ - 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.`,
119552
119785
  ja: `### \u30C4\u30FC\u30EB
119553
119786
 
119554
119787
  - \`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
@@ -119566,7 +119799,8 @@ The business logic type for this connector is "sql".
119566
119799
  - \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
119567
119800
  - \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
119568
119801
  - \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
119569
- - \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`
119802
+ - \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
119803
+ - \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`
119570
119804
  },
119571
119805
  tools: tools74,
119572
119806
  async checkConnection(params, _config) {
@@ -119580,6 +119814,15 @@ The business logic type for this connector is "sql".
119580
119814
  username: params[parameters74.username.slug],
119581
119815
  password: params[parameters74.password.slug]
119582
119816
  });
119817
+ const wrapper = sql.match(
119818
+ /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+_sq\s+LIMIT\s+(\d+)\s*;?\s*$/i
119819
+ );
119820
+ if (wrapper) {
119821
+ const inner = wrapper[1].trim().replace(/;\s*$/, "");
119822
+ const limit = Number.parseInt(wrapper[2], 10);
119823
+ const result = await runOracleQuery(parsed, inner);
119824
+ return { rows: result.rows.slice(0, limit) };
119825
+ }
119583
119826
  const cleanSql = sql.replace(/;\s*$/, "");
119584
119827
  return runOracleQuery(parsed, cleanSql);
119585
119828
  }
@@ -119754,7 +119997,7 @@ var freshserviceConnector = new ConnectorPlugin({
119754
119997
  description: "Connect to Freshservice (ITSM) for ticket, agent, asset, and ITIL workflow data via API key.",
119755
119998
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/6Tj64HZOoIrGgQYDayBosY/3f45b29d3479726b5d245ac38d5a7036/freshservice-icon.svg",
119756
119999
  parameters: parameters75,
119757
- releaseFlag: { dev1: true, dev2: false, prod: false },
120000
+ releaseFlag: { dev1: true, dev2: true, prod: true },
119758
120001
  categories: ["productivity"],
119759
120002
  onboarding: freshserviceOnboarding,
119760
120003
  systemPrompt: {
@@ -120083,8 +120326,8 @@ var freshdeskConnector = new ConnectorPlugin({
120083
120326
  description: "Connect to Freshdesk for customer support ticket, contact, and company data via API key.",
120084
120327
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1PSjIfQJgTYmiWriNTx4uE/26905f4120713bda0afd0b23d02a154e/freshdesk-icon.png",
120085
120328
  parameters: parameters76,
120086
- releaseFlag: { dev1: true, dev2: false, prod: false },
120087
- categories: ["productivity"],
120329
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120330
+ categories: ["crm"],
120088
120331
  onboarding: freshdeskOnboarding,
120089
120332
  systemPrompt: {
120090
120333
  en: `### Tools
@@ -120249,15 +120492,15 @@ export default async function handler(c: Context) {
120249
120492
  var freshsalesOnboarding = new ConnectorOnboarding({
120250
120493
  dataOverviewInstructions: {
120251
120494
  en: `1. Call freshsales_request with GET /selector/owners to confirm credentials and discover sales team members.
120252
- 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).
120253
- 3. Repeat the same pattern for accounts (GET /sales_accounts/view) and deals (GET /deals/view).
120495
+ 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).
120496
+ 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}).
120254
120497
  4. To inspect deal pipeline metadata, call GET /selector/deal_pipelines and GET /selector/deal_stages.
120255
- 5. Use the search endpoints (POST /lookup or POST /search) to find specific records by attribute (e.g., look up a contact by email).`,
120498
+ 5. Use GET /lookup to find specific records by attribute (e.g., look up a contact by email).`,
120256
120499
  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
120257
- 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
120258
- 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
120500
+ 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
120501
+ 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
120259
120502
  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
120260
- 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`
120503
+ 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`
120261
120504
  }
120262
120505
  });
120263
120506
 
@@ -120298,10 +120541,10 @@ var inputSchema93 = z93.object({
120298
120541
  ),
120299
120542
  connectionId: z93.string().describe("ID of the Freshsales connection to use"),
120300
120543
  method: z93.enum(["GET", "POST", "PUT", "DELETE"]).describe(
120301
- "HTTP method. GET for reading resources, POST for creating or running search/lookup, PUT for updating, DELETE for removing."
120544
+ "HTTP method. GET for reading resources (including /lookup), POST for creating, PUT for updating, DELETE for removing."
120302
120545
  ),
120303
120546
  path: z93.string().describe(
120304
- "API path (e.g., '/contacts', '/contacts/view', '/contacts/view/{view_id}', '/deals/{id}', '/lookup'). Append query parameters such as '?page=1&per_page=100'."
120547
+ "API path (e.g., '/contacts', '/contacts/filters', '/contacts/view/{view_id}', '/deals/{id}', '/lookup'). Append query parameters such as '?page=1&per_page=100'."
120305
120548
  ),
120306
120549
  body: z93.record(z93.string(), z93.unknown()).optional().describe(
120307
120550
  'Request body (JSON). For creating a contact: { "contact": { "first_name": "...", "last_name": "...", "email": "..." } }. For lookup: { "q": "john@example.com", "f": "email", "entities": "contact" }.'
@@ -120328,20 +120571,20 @@ Authentication uses the \`Authorization: Token token=<API_KEY>\` header (handled
120328
120571
  Provide the API path relative to the base URL (https://<bundle>.myfreshworks.com/crm/sales/api).
120329
120572
 
120330
120573
  Common endpoints:
120331
- - GET /contacts/view \u2014 List contact views (saved filters)
120574
+ - GET /contacts/filters \u2014 List contact views (saved filters)
120332
120575
  - GET /contacts/view/{view_id} \u2014 List contacts in a view (paginated)
120333
120576
  - GET /contacts/{id} \u2014 Get a contact (use ?include=owner,creator,deals for related data)
120334
120577
  - POST /contacts \u2014 Create a contact (body: { "contact": { ... } })
120335
120578
  - PUT /contacts/{id} \u2014 Update a contact
120336
- - GET /sales_accounts/view \u2014 List account views
120579
+ - GET /sales_accounts/filters \u2014 List account views
120337
120580
  - GET /sales_accounts/view/{view_id} \u2014 Accounts in a view
120338
- - GET /deals/view \u2014 Deal views
120581
+ - GET /deals/filters \u2014 Deal views
120339
120582
  - GET /deals/view/{view_id} \u2014 Deals in a view
120340
120583
  - GET /deals/{id} \u2014 Get a deal
120341
120584
  - POST /deals \u2014 Create a deal
120342
- - GET /leads/view \u2014 Lead views (legacy / Sales Cloud only)
120585
+ - GET /leads/filters \u2014 Lead views (legacy / Sales Cloud only)
120343
120586
  - GET /sales_activities \u2014 List sales activities
120344
- - POST /lookup?q=...&f=email&entities=contact \u2014 Look up a record by attribute
120587
+ - GET /lookup?q=...&f=email&entities=contact \u2014 Look up a record by attribute
120345
120588
  - GET /selector/owners \u2014 Available owners (sales reps)
120346
120589
  - GET /selector/deal_pipelines \u2014 Deal pipelines
120347
120590
  - GET /selector/deal_stages \u2014 Deal stages
@@ -120412,8 +120655,8 @@ var freshsalesConnector = new ConnectorPlugin({
120412
120655
  description: "Connect to Freshsales / Freshworks CRM for contact, account, and deal data via API key.",
120413
120656
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4UDOrFPM6wOFekbMVljjgl/4acc6060c3a1ff703980e6f4e76a3cd4/629b6c6f7c5cd817694c321f.png",
120414
120657
  parameters: parameters77,
120415
- releaseFlag: { dev1: true, dev2: false, prod: false },
120416
- categories: ["productivity"],
120658
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120659
+ categories: ["crm"],
120417
120660
  onboarding: freshsalesOnboarding,
120418
120661
  systemPrompt: {
120419
120662
  en: `### Tools
@@ -120460,26 +120703,26 @@ export default async function handler(c: Context) {
120460
120703
  #### Resource Endpoints
120461
120704
 
120462
120705
  **Contacts**
120463
- - GET \`/contacts/view\` \u2014 List saved views
120706
+ - GET \`/contacts/filters\` \u2014 List saved views (a.k.a. filters)
120464
120707
  - GET \`/contacts/view/{view_id}\` \u2014 Contacts in a view (paginated)
120465
120708
  - GET \`/contacts/{id}\` \u2014 Get a contact (use \`?include=owner,creator,deals,sales_accounts\`)
120466
120709
  - POST \`/contacts\` \u2014 Create a contact (body: \`{ "contact": { ... } }\`)
120467
120710
  - PUT \`/contacts/{id}\` \u2014 Update a contact
120468
120711
 
120469
120712
  **Sales accounts (companies)**
120470
- - GET \`/sales_accounts/view\` \u2014 List saved views
120713
+ - GET \`/sales_accounts/filters\` \u2014 List saved views
120471
120714
  - GET \`/sales_accounts/view/{view_id}\` \u2014 Accounts in a view
120472
120715
  - GET \`/sales_accounts/{id}\` \u2014 Get an account
120473
120716
  - POST \`/sales_accounts\` / PUT \`/sales_accounts/{id}\` \u2014 Write
120474
120717
 
120475
120718
  **Deals**
120476
- - GET \`/deals/view\` \u2014 List saved views
120719
+ - GET \`/deals/filters\` \u2014 List saved views
120477
120720
  - GET \`/deals/view/{view_id}\` \u2014 Deals in a view
120478
120721
  - GET \`/deals/{id}\` \u2014 Get a deal (use \`?include=owner,deal_stage,sales_account,contacts\`)
120479
120722
  - POST \`/deals\` / PUT \`/deals/{id}\` \u2014 Write
120480
120723
 
120481
120724
  **Leads (Sales Cloud only)**
120482
- - GET \`/leads/view\` \u2014 Saved views
120725
+ - GET \`/leads/filters\` \u2014 Saved views
120483
120726
  - GET \`/leads/view/{view_id}\` \u2014 Leads in a view
120484
120727
  - GET \`/leads/{id}\` \u2014 Get a lead
120485
120728
 
@@ -120490,7 +120733,7 @@ export default async function handler(c: Context) {
120490
120733
  - POST \`/notes\` \u2014 Create a note (body references a target contact/account/deal)
120491
120734
 
120492
120735
  **Search & lookup**
120493
- - 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\`).
120736
+ - 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\`).
120494
120737
 
120495
120738
  **Selector metadata**
120496
120739
  - GET \`/selector/owners\` \u2014 Sales reps available as owners
@@ -120543,26 +120786,26 @@ export default async function handler(c: Context) {
120543
120786
  #### \u30EA\u30BD\u30FC\u30B9\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
120544
120787
 
120545
120788
  **\u9023\u7D61\u5148\uFF08Contacts\uFF09**
120546
- - GET \`/contacts/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120789
+ - GET \`/contacts/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7\uFF08filters\uFF09
120547
120790
  - GET \`/contacts/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u9023\u7D61\u5148\u4E00\u89A7\uFF08\u30DA\u30FC\u30B8\u30F3\u30B0\uFF09
120548
120791
  - GET \`/contacts/{id}\` \u2014 \u9023\u7D61\u5148\u306E\u53D6\u5F97\uFF08\`?include=owner,creator,deals,sales_accounts\` \u3067\u95A2\u9023\u5C55\u958B\uFF09
120549
120792
  - POST \`/contacts\` \u2014 \u9023\u7D61\u5148\u306E\u4F5C\u6210\uFF08body: \`{ "contact": { ... } }\`\uFF09
120550
120793
  - PUT \`/contacts/{id}\` \u2014 \u9023\u7D61\u5148\u306E\u66F4\u65B0
120551
120794
 
120552
120795
  **\u53D6\u5F15\u5148\uFF08Sales accounts / \u4F1A\u793E\uFF09**
120553
- - GET \`/sales_accounts/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120796
+ - GET \`/sales_accounts/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120554
120797
  - GET \`/sales_accounts/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u53D6\u5F15\u5148
120555
120798
  - GET \`/sales_accounts/{id}\` \u2014 \u53D6\u5F15\u5148\u306E\u53D6\u5F97
120556
120799
  - POST \`/sales_accounts\` / PUT \`/sales_accounts/{id}\` \u2014 \u4F5C\u6210\u30FB\u66F4\u65B0
120557
120800
 
120558
120801
  **\u5546\u8AC7\uFF08Deals\uFF09**
120559
- - GET \`/deals/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120802
+ - GET \`/deals/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120560
120803
  - GET \`/deals/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u5546\u8AC7
120561
120804
  - GET \`/deals/{id}\` \u2014 \u5546\u8AC7\u306E\u53D6\u5F97\uFF08\`?include=owner,deal_stage,sales_account,contacts\` \u3067\u95A2\u9023\u5C55\u958B\uFF09
120562
120805
  - POST \`/deals\` / PUT \`/deals/{id}\` \u2014 \u4F5C\u6210\u30FB\u66F4\u65B0
120563
120806
 
120564
120807
  **\u30EA\u30FC\u30C9\uFF08Leads \u2014 Sales Cloud \u306E\u307F\uFF09**
120565
- - GET \`/leads/view\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120808
+ - GET \`/leads/filters\` \u2014 \u4FDD\u5B58\u30D3\u30E5\u30FC\u4E00\u89A7
120566
120809
  - GET \`/leads/view/{view_id}\` \u2014 \u30D3\u30E5\u30FC\u5185\u306E\u30EA\u30FC\u30C9
120567
120810
  - GET \`/leads/{id}\` \u2014 \u30EA\u30FC\u30C9\u306E\u53D6\u5F97
120568
120811
 
@@ -120573,7 +120816,7 @@ export default async function handler(c: Context) {
120573
120816
  - POST \`/notes\` \u2014 \u30CE\u30FC\u30C8\u306E\u4F5C\u6210\uFF08body \u3067\u9023\u7D61\u5148/\u53D6\u5F15\u5148/\u5546\u8AC7\u3092\u53C2\u7167\uFF09
120574
120817
 
120575
120818
  **\u691C\u7D22 & \u30EB\u30C3\u30AF\u30A2\u30C3\u30D7**
120576
- - 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
120819
+ - 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
120577
120820
 
120578
120821
  **\u30BB\u30EC\u30AF\u30BF\u30FC\u30E1\u30BF\u60C5\u5831**
120579
120822
  - GET \`/selector/owners\` \u2014 \u30AA\u30FC\u30CA\u30FC\uFF08\u55B6\u696D\u62C5\u5F53\uFF09\u4E00\u89A7
@@ -120768,7 +121011,7 @@ var githubConnector = new ConnectorPlugin({
120768
121011
  description: "Connect to GitHub for repository, issue, pull request, commit, and search data via Personal Access Token (Classic or fine-grained).",
120769
121012
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2flOAufkhDrLKuOQqEVS3/1f9dcf145680ef77aef149709263e2d4/github-icon.svg",
120770
121013
  parameters: parameters78,
120771
- releaseFlag: { dev1: true, dev2: false, prod: false },
121014
+ releaseFlag: { dev1: true, dev2: true, prod: true },
120772
121015
  categories: ["productivity"],
120773
121016
  onboarding: githubOnboarding,
120774
121017
  systemPrompt: {