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