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