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