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