@squadbase/vite-server 0.1.12-dev.a9ac647 → 0.1.17-dev.24af54e
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 +12374 -883
- package/dist/connectors/airtable-oauth.js +257 -46
- package/dist/connectors/airtable.js +294 -51
- package/dist/connectors/amplitude.js +297 -47
- package/dist/connectors/anthropic.js +135 -47
- package/dist/connectors/asana.js +302 -49
- package/dist/connectors/attio.js +277 -49
- package/dist/connectors/aws-billing.js +262 -46
- package/dist/connectors/azure-sql.js +396 -102
- package/dist/connectors/backlog-api-key.js +292 -47
- package/dist/connectors/clickup.js +313 -49
- package/dist/connectors/cosmosdb.js +280 -50
- package/dist/connectors/customerio.js +294 -47
- package/dist/connectors/dbt.js +315 -47
- package/dist/connectors/freshdesk.js +317 -53
- package/dist/connectors/freshsales.js +308 -52
- package/dist/connectors/freshservice.js +336 -53
- package/dist/connectors/gamma.js +302 -52
- package/dist/connectors/gemini.js +134 -47
- package/dist/connectors/github.js +361 -49
- package/dist/connectors/gmail-oauth.js +179 -7
- package/dist/connectors/gmail.js +325 -47
- package/dist/connectors/google-ads.js +263 -46
- package/dist/connectors/google-analytics-oauth.js +285 -46
- package/dist/connectors/google-analytics.js +387 -49
- package/dist/connectors/google-audit-log.js +413 -47
- package/dist/connectors/google-calendar-oauth.js +234 -46
- package/dist/connectors/google-calendar.js +334 -47
- package/dist/connectors/google-docs.js +195 -6
- package/dist/connectors/google-drive.js +237 -5
- package/dist/connectors/google-search-console-oauth.js +231 -46
- package/dist/connectors/google-sheets.js +247 -47
- package/dist/connectors/google-slides.js +180 -6
- package/dist/connectors/grafana.js +307 -49
- package/dist/connectors/hubspot-oauth.js +183 -5
- package/dist/connectors/hubspot.js +281 -49
- package/dist/connectors/influxdb.js +391 -51
- package/dist/connectors/intercom-oauth.js +185 -5
- package/dist/connectors/intercom.js +277 -49
- package/dist/connectors/jdbc.js +737 -110
- package/dist/connectors/jira-api-key.js +301 -47
- package/dist/connectors/kintone-api-token.js +256 -47
- package/dist/connectors/kintone.js +303 -47
- package/dist/connectors/linear.js +305 -49
- package/dist/connectors/linkedin-ads.js +243 -50
- package/dist/connectors/mailchimp-oauth.js +243 -46
- package/dist/connectors/mailchimp.js +295 -49
- package/dist/connectors/meta-ads-oauth.js +248 -48
- package/dist/connectors/meta-ads.js +260 -50
- package/dist/connectors/mixpanel.js +313 -47
- package/dist/connectors/monday.js +335 -49
- package/dist/connectors/mongodb.js +294 -57
- package/dist/connectors/notion-oauth.js +206 -5
- package/dist/connectors/notion.js +298 -51
- package/dist/connectors/openai.js +134 -47
- package/dist/connectors/oracle.js +414 -103
- package/dist/connectors/outlook-oauth.js +179 -5
- package/dist/connectors/powerbi-oauth.js +226 -5
- package/dist/connectors/salesforce.js +359 -49
- package/dist/connectors/semrush.js +289 -49
- package/dist/connectors/sentry.js +264 -50
- package/dist/connectors/shopify-oauth.js +162 -5
- package/dist/connectors/shopify.js +332 -47
- package/dist/connectors/sqlserver.js +390 -102
- package/dist/connectors/stripe-api-key.js +244 -46
- package/dist/connectors/stripe-oauth.js +177 -5
- package/dist/connectors/supabase.js +278 -48
- package/dist/connectors/tableau.js +389 -184
- package/dist/connectors/tiktok-ads.js +254 -48
- package/dist/connectors/wix-store.js +295 -49
- package/dist/connectors/zendesk-oauth.js +214 -5
- package/dist/connectors/zendesk.js +333 -47
- package/dist/index.d.ts +149 -1
- package/dist/index.js +13677 -1969
- package/dist/main.js +13627 -1927
- package/dist/vite-plugin.js +12391 -890
- package/package.json +1 -1
package/dist/connectors/jdbc.js
CHANGED
|
@@ -1,105 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
description;
|
|
6
|
-
envVarBaseKey;
|
|
7
|
-
type;
|
|
8
|
-
secret;
|
|
9
|
-
required;
|
|
10
|
-
constructor(config) {
|
|
11
|
-
this.slug = config.slug;
|
|
12
|
-
this.name = config.name;
|
|
13
|
-
this.description = config.description;
|
|
14
|
-
this.envVarBaseKey = config.envVarBaseKey;
|
|
15
|
-
this.type = config.type;
|
|
16
|
-
this.secret = config.secret;
|
|
17
|
-
this.required = config.required;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Get the parameter value from a ConnectorConnectionObject.
|
|
21
|
-
*/
|
|
22
|
-
getValue(connection2) {
|
|
23
|
-
const param = connection2.parameters.find(
|
|
24
|
-
(p) => p.parameterSlug === this.slug
|
|
25
|
-
);
|
|
26
|
-
if (!param || param.value == null) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
return param.value;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
35
|
-
*/
|
|
36
|
-
tryGetValue(connection2) {
|
|
37
|
-
const param = connection2.parameters.find(
|
|
38
|
-
(p) => p.parameterSlug === this.slug
|
|
39
|
-
);
|
|
40
|
-
if (!param || param.value == null) return void 0;
|
|
41
|
-
return param.value;
|
|
42
|
-
}
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
43
5
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
sshHost: new ParameterDefinition({
|
|
48
|
-
slug: "ssh-host",
|
|
49
|
-
name: "SSH Tunnel Host",
|
|
50
|
-
description: "Optional. Hostname of the SSH bastion to tunnel through. Leave empty to connect directly.",
|
|
51
|
-
envVarBaseKey: "SSH_TUNNEL_HOST",
|
|
52
|
-
type: "text",
|
|
53
|
-
secret: false,
|
|
54
|
-
required: false
|
|
55
|
-
}),
|
|
56
|
-
sshPort: new ParameterDefinition({
|
|
57
|
-
slug: "ssh-port",
|
|
58
|
-
name: "SSH Tunnel Port",
|
|
59
|
-
description: "Optional. SSH port of the bastion host (default: 22).",
|
|
60
|
-
envVarBaseKey: "SSH_TUNNEL_PORT",
|
|
61
|
-
type: "text",
|
|
62
|
-
secret: false,
|
|
63
|
-
required: false
|
|
64
|
-
}),
|
|
65
|
-
sshUsername: new ParameterDefinition({
|
|
66
|
-
slug: "ssh-username",
|
|
67
|
-
name: "SSH Tunnel Username",
|
|
68
|
-
description: "Optional. Username for SSH authentication. Required when SSH Tunnel Host is set.",
|
|
69
|
-
envVarBaseKey: "SSH_TUNNEL_USERNAME",
|
|
70
|
-
type: "text",
|
|
71
|
-
secret: false,
|
|
72
|
-
required: false
|
|
73
|
-
}),
|
|
74
|
-
sshPrivateKeyBase64: new ParameterDefinition({
|
|
75
|
-
slug: "ssh-private-key-base64",
|
|
76
|
-
name: "SSH Private Key",
|
|
77
|
-
description: "Optional. Private key (PEM, base64-encoded) used for SSH authentication. Required when SSH Tunnel Host is set.",
|
|
78
|
-
envVarBaseKey: "SSH_TUNNEL_PRIVATE_KEY_BASE64",
|
|
79
|
-
type: "base64EncodedText",
|
|
80
|
-
secret: true,
|
|
81
|
-
required: false
|
|
82
|
-
}),
|
|
83
|
-
sshPassphrase: new ParameterDefinition({
|
|
84
|
-
slug: "ssh-passphrase",
|
|
85
|
-
name: "SSH Private Key Passphrase",
|
|
86
|
-
description: "Optional. Passphrase for the SSH private key, if it is encrypted.",
|
|
87
|
-
envVarBaseKey: "SSH_TUNNEL_PASSPHRASE",
|
|
88
|
-
type: "text",
|
|
89
|
-
secret: true,
|
|
90
|
-
required: false
|
|
91
|
-
})
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
92
9
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
10
|
+
|
|
11
|
+
// ../connectors/src/parameter-definition.ts
|
|
12
|
+
var ParameterDefinition;
|
|
13
|
+
var init_parameter_definition = __esm({
|
|
14
|
+
"../connectors/src/parameter-definition.ts"() {
|
|
15
|
+
"use strict";
|
|
16
|
+
ParameterDefinition = class {
|
|
17
|
+
slug;
|
|
18
|
+
name;
|
|
19
|
+
description;
|
|
20
|
+
envVarBaseKey;
|
|
21
|
+
type;
|
|
22
|
+
secret;
|
|
23
|
+
required;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.slug = config.slug;
|
|
26
|
+
this.name = config.name;
|
|
27
|
+
this.description = config.description;
|
|
28
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
29
|
+
this.type = config.type;
|
|
30
|
+
this.secret = config.secret;
|
|
31
|
+
this.required = config.required;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
35
|
+
*/
|
|
36
|
+
getValue(connection2) {
|
|
37
|
+
const param = connection2.parameters.find(
|
|
38
|
+
(p) => p.parameterSlug === this.slug
|
|
39
|
+
);
|
|
40
|
+
if (!param || param.value == null) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return param.value;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
49
|
+
*/
|
|
50
|
+
tryGetValue(connection2) {
|
|
51
|
+
const param = connection2.parameters.find(
|
|
52
|
+
(p) => p.parameterSlug === this.slug
|
|
53
|
+
);
|
|
54
|
+
if (!param || param.value == null) return void 0;
|
|
55
|
+
return param.value;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
96
58
|
}
|
|
97
59
|
});
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
60
|
+
|
|
61
|
+
// ../connectors/src/lib/ssh-tunnel.ts
|
|
62
|
+
var ssh_tunnel_exports = {};
|
|
63
|
+
__export(ssh_tunnel_exports, {
|
|
64
|
+
connectionParamsToRecord: () => connectionParamsToRecord,
|
|
65
|
+
maybeOpenSshTunnel: () => maybeOpenSshTunnel,
|
|
66
|
+
maybeOpenSshTunnelHostPort: () => maybeOpenSshTunnelHostPort,
|
|
67
|
+
sshTunnelParameters: () => sshTunnelParameters
|
|
103
68
|
});
|
|
104
69
|
function connectionParamsToRecord(connection2) {
|
|
105
70
|
const out = {};
|
|
@@ -185,11 +150,80 @@ async function maybeOpenSshTunnel(params, connectionUrl, defaultDbPort) {
|
|
|
185
150
|
close: tunnel.close
|
|
186
151
|
};
|
|
187
152
|
}
|
|
153
|
+
var sshTunnelParameters, NOOP_TUNNEL, NOOP_TUNNEL_HOSTPORT;
|
|
154
|
+
var init_ssh_tunnel = __esm({
|
|
155
|
+
"../connectors/src/lib/ssh-tunnel.ts"() {
|
|
156
|
+
"use strict";
|
|
157
|
+
init_parameter_definition();
|
|
158
|
+
sshTunnelParameters = {
|
|
159
|
+
sshHost: new ParameterDefinition({
|
|
160
|
+
slug: "ssh-host",
|
|
161
|
+
name: "SSH Tunnel Host",
|
|
162
|
+
description: "Optional. Hostname of the SSH bastion to tunnel through. Leave empty to connect directly.",
|
|
163
|
+
envVarBaseKey: "SSH_TUNNEL_HOST",
|
|
164
|
+
type: "text",
|
|
165
|
+
secret: false,
|
|
166
|
+
required: false
|
|
167
|
+
}),
|
|
168
|
+
sshPort: new ParameterDefinition({
|
|
169
|
+
slug: "ssh-port",
|
|
170
|
+
name: "SSH Tunnel Port",
|
|
171
|
+
description: "Optional. SSH port of the bastion host (default: 22).",
|
|
172
|
+
envVarBaseKey: "SSH_TUNNEL_PORT",
|
|
173
|
+
type: "text",
|
|
174
|
+
secret: false,
|
|
175
|
+
required: false
|
|
176
|
+
}),
|
|
177
|
+
sshUsername: new ParameterDefinition({
|
|
178
|
+
slug: "ssh-username",
|
|
179
|
+
name: "SSH Tunnel Username",
|
|
180
|
+
description: "Optional. Username for SSH authentication. Required when SSH Tunnel Host is set.",
|
|
181
|
+
envVarBaseKey: "SSH_TUNNEL_USERNAME",
|
|
182
|
+
type: "text",
|
|
183
|
+
secret: false,
|
|
184
|
+
required: false
|
|
185
|
+
}),
|
|
186
|
+
sshPrivateKeyBase64: new ParameterDefinition({
|
|
187
|
+
slug: "ssh-private-key-base64",
|
|
188
|
+
name: "SSH Private Key",
|
|
189
|
+
description: "Optional. Private key (PEM, base64-encoded) used for SSH authentication. Required when SSH Tunnel Host is set.",
|
|
190
|
+
envVarBaseKey: "SSH_TUNNEL_PRIVATE_KEY_BASE64",
|
|
191
|
+
type: "base64EncodedText",
|
|
192
|
+
secret: true,
|
|
193
|
+
required: false
|
|
194
|
+
}),
|
|
195
|
+
sshPassphrase: new ParameterDefinition({
|
|
196
|
+
slug: "ssh-passphrase",
|
|
197
|
+
name: "SSH Private Key Passphrase",
|
|
198
|
+
description: "Optional. Passphrase for the SSH private key, if it is encrypted.",
|
|
199
|
+
envVarBaseKey: "SSH_TUNNEL_PASSPHRASE",
|
|
200
|
+
type: "text",
|
|
201
|
+
secret: true,
|
|
202
|
+
required: false
|
|
203
|
+
})
|
|
204
|
+
};
|
|
205
|
+
NOOP_TUNNEL = (connectionUrl) => ({
|
|
206
|
+
connectionUrl,
|
|
207
|
+
close: async () => {
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
NOOP_TUNNEL_HOSTPORT = (host, port) => ({
|
|
211
|
+
host,
|
|
212
|
+
port,
|
|
213
|
+
close: async () => {
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
188
218
|
|
|
189
219
|
// ../connectors/src/connectors/sqlserver/utils.ts
|
|
190
|
-
var
|
|
191
|
-
|
|
192
|
-
|
|
220
|
+
var utils_exports = {};
|
|
221
|
+
__export(utils_exports, {
|
|
222
|
+
parseSqlServerJdbcUrl: () => parseSqlServerJdbcUrl,
|
|
223
|
+
redactSqlServerUrl: () => redactSqlServerUrl,
|
|
224
|
+
runSqlServerSetupQuery: () => runSqlServerSetupQuery,
|
|
225
|
+
toMssqlConfig: () => toMssqlConfig
|
|
226
|
+
});
|
|
193
227
|
function parseBoolean(value) {
|
|
194
228
|
if (value == null) return void 0;
|
|
195
229
|
const lower = value.toLowerCase();
|
|
@@ -256,8 +290,34 @@ function toMssqlConfig(parsed, defaults = {}) {
|
|
|
256
290
|
function redactSqlServerUrl(jdbcUrl) {
|
|
257
291
|
return jdbcUrl.replace(/(:\/\/)([^@/;]+)@/, "$1***@").replace(/(password\s*=\s*)([^;]+)/gi, "$1***");
|
|
258
292
|
}
|
|
293
|
+
async function runSqlServerSetupQuery(params, sql, forceEncrypt) {
|
|
294
|
+
const { runMssqlQuery: runMssqlQuery2 } = await Promise.resolve().then(() => (init_mssql_runner(), mssql_runner_exports));
|
|
295
|
+
const parsed = parseSqlServerJdbcUrl(params["jdbc-url"] ?? "", {
|
|
296
|
+
username: params["username"],
|
|
297
|
+
password: params["password"]
|
|
298
|
+
});
|
|
299
|
+
const result = await runMssqlQuery2(parsed, sql, {
|
|
300
|
+
forceEncrypt,
|
|
301
|
+
tunnelParams: params
|
|
302
|
+
});
|
|
303
|
+
return result.rows;
|
|
304
|
+
}
|
|
305
|
+
var SQLSERVER_PREFIX_RE, TRUE_VALUES, FALSE_VALUES;
|
|
306
|
+
var init_utils = __esm({
|
|
307
|
+
"../connectors/src/connectors/sqlserver/utils.ts"() {
|
|
308
|
+
"use strict";
|
|
309
|
+
SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
|
|
310
|
+
TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
|
|
311
|
+
FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no"]);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
259
314
|
|
|
260
315
|
// ../connectors/src/lib/mssql-runner.ts
|
|
316
|
+
var mssql_runner_exports = {};
|
|
317
|
+
__export(mssql_runner_exports, {
|
|
318
|
+
checkMssqlConnection: () => checkMssqlConnection,
|
|
319
|
+
runMssqlQuery: () => runMssqlQuery
|
|
320
|
+
});
|
|
261
321
|
async function importMssql() {
|
|
262
322
|
const mod = await import("mssql");
|
|
263
323
|
return mod.default ?? mod;
|
|
@@ -306,11 +366,23 @@ async function checkMssqlConnection(url, credentials, options = {}) {
|
|
|
306
366
|
return { success: false, error: msg };
|
|
307
367
|
}
|
|
308
368
|
}
|
|
369
|
+
var init_mssql_runner = __esm({
|
|
370
|
+
"../connectors/src/lib/mssql-runner.ts"() {
|
|
371
|
+
"use strict";
|
|
372
|
+
init_ssh_tunnel();
|
|
373
|
+
init_utils();
|
|
374
|
+
}
|
|
375
|
+
});
|
|
309
376
|
|
|
310
377
|
// ../connectors/src/connectors/oracle/utils.ts
|
|
311
|
-
var
|
|
312
|
-
|
|
313
|
-
|
|
378
|
+
var utils_exports2 = {};
|
|
379
|
+
__export(utils_exports2, {
|
|
380
|
+
parseOracleConnectStringHostPort: () => parseOracleConnectStringHostPort,
|
|
381
|
+
parseOracleJdbcUrl: () => parseOracleJdbcUrl,
|
|
382
|
+
redactOracleUrl: () => redactOracleUrl,
|
|
383
|
+
rewriteOracleConnectStringHostPort: () => rewriteOracleConnectStringHostPort,
|
|
384
|
+
runOracleSetupQuery: () => runOracleSetupQuery
|
|
385
|
+
});
|
|
314
386
|
function parseOracleJdbcUrl(jdbcUrl, options = {}) {
|
|
315
387
|
const trimmed = jdbcUrl.trim();
|
|
316
388
|
if (JDBC_OCI_PREFIX_RE.test(trimmed)) {
|
|
@@ -382,9 +454,34 @@ function rewriteOracleConnectStringHostPort(connectString, host, port) {
|
|
|
382
454
|
if (!parts) return connectString;
|
|
383
455
|
return `${host}:${port}${parts.trailing}`;
|
|
384
456
|
}
|
|
457
|
+
async function runOracleSetupQuery(params, sql) {
|
|
458
|
+
const { runOracleQuery: runOracleQuery2 } = await Promise.resolve().then(() => (init_oracle_runner(), oracle_runner_exports));
|
|
459
|
+
const parsed = parseOracleJdbcUrl(params["jdbc-url"] ?? "", {
|
|
460
|
+
username: params["username"],
|
|
461
|
+
password: params["password"]
|
|
462
|
+
});
|
|
463
|
+
const cleanSql = sql.replace(/;\s*$/, "");
|
|
464
|
+
const result = await runOracleQuery2(parsed, cleanSql, {
|
|
465
|
+
tunnelParams: params
|
|
466
|
+
});
|
|
467
|
+
return result.rows;
|
|
468
|
+
}
|
|
469
|
+
var JDBC_THIN_PREFIX_RE, JDBC_OCI_PREFIX_RE, URL_PREFIX_RE;
|
|
470
|
+
var init_utils2 = __esm({
|
|
471
|
+
"../connectors/src/connectors/oracle/utils.ts"() {
|
|
472
|
+
"use strict";
|
|
473
|
+
JDBC_THIN_PREFIX_RE = /^jdbc:oracle:thin:/i;
|
|
474
|
+
JDBC_OCI_PREFIX_RE = /^jdbc:oracle:oci/i;
|
|
475
|
+
URL_PREFIX_RE = /^oracle:\/\//i;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
385
478
|
|
|
386
479
|
// ../connectors/src/lib/oracle-runner.ts
|
|
387
|
-
var
|
|
480
|
+
var oracle_runner_exports = {};
|
|
481
|
+
__export(oracle_runner_exports, {
|
|
482
|
+
checkOracleConnection: () => checkOracleConnection,
|
|
483
|
+
runOracleQuery: () => runOracleQuery
|
|
484
|
+
});
|
|
388
485
|
async function importOracleDb() {
|
|
389
486
|
let mod;
|
|
390
487
|
try {
|
|
@@ -460,8 +557,22 @@ async function checkOracleConnection(url, credentials, options = {}) {
|
|
|
460
557
|
return { success: false, error: msg };
|
|
461
558
|
}
|
|
462
559
|
}
|
|
560
|
+
var GLOBAL_ORACLEDB_PATH;
|
|
561
|
+
var init_oracle_runner = __esm({
|
|
562
|
+
"../connectors/src/lib/oracle-runner.ts"() {
|
|
563
|
+
"use strict";
|
|
564
|
+
init_ssh_tunnel();
|
|
565
|
+
init_utils2();
|
|
566
|
+
GLOBAL_ORACLEDB_PATH = "/usr/lib/node_modules/oracledb/index.js";
|
|
567
|
+
}
|
|
568
|
+
});
|
|
463
569
|
|
|
464
570
|
// ../connectors/src/lib/pg-pool.ts
|
|
571
|
+
var pg_pool_exports = {};
|
|
572
|
+
__export(pg_pool_exports, {
|
|
573
|
+
attachStatementTimeout: () => attachStatementTimeout,
|
|
574
|
+
withStatementTimeout: () => withStatementTimeout
|
|
575
|
+
});
|
|
465
576
|
function attachStatementTimeout(pool, statementTimeoutMs) {
|
|
466
577
|
pool.on("connect", (client) => {
|
|
467
578
|
void client.query(`SET statement_timeout = ${statementTimeoutMs}`).catch(() => {
|
|
@@ -486,8 +597,23 @@ async function withStatementTimeout(promise, statementTimeoutMs) {
|
|
|
486
597
|
if (timer) clearTimeout(timer);
|
|
487
598
|
}
|
|
488
599
|
}
|
|
600
|
+
var init_pg_pool = __esm({
|
|
601
|
+
"../connectors/src/lib/pg-pool.ts"() {
|
|
602
|
+
"use strict";
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// ../connectors/src/connectors/jdbc/sdk/index.ts
|
|
607
|
+
init_mssql_runner();
|
|
608
|
+
init_oracle_runner();
|
|
609
|
+
init_pg_pool();
|
|
610
|
+
init_ssh_tunnel();
|
|
611
|
+
init_utils();
|
|
612
|
+
init_utils2();
|
|
489
613
|
|
|
490
614
|
// ../connectors/src/connectors/jdbc/parameters.ts
|
|
615
|
+
init_parameter_definition();
|
|
616
|
+
init_ssh_tunnel();
|
|
491
617
|
var parameters = {
|
|
492
618
|
jdbcUrl: new ParameterDefinition({
|
|
493
619
|
slug: "jdbc-url",
|
|
@@ -608,6 +734,91 @@ function parseJdbcUrl(jdbcUrl, options = {}) {
|
|
|
608
734
|
function redactJdbcUrl(jdbcUrl) {
|
|
609
735
|
return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(password\s*=\s*)([^;&]+)/gi, "$1***");
|
|
610
736
|
}
|
|
737
|
+
async function runJdbcSetupQuery(params, sql, values) {
|
|
738
|
+
const jdbcUrl = params["jdbc-url"] ?? "";
|
|
739
|
+
const username = params["username"] || void 0;
|
|
740
|
+
const password = params["password"] || void 0;
|
|
741
|
+
const parsed = parseJdbcUrl(jdbcUrl, { username, password });
|
|
742
|
+
if (parsed.driver === "sqlserver") {
|
|
743
|
+
const { parseSqlServerJdbcUrl: parseSqlServerJdbcUrl2 } = await Promise.resolve().then(() => (init_utils(), utils_exports));
|
|
744
|
+
const { runMssqlQuery: runMssqlQuery2 } = await Promise.resolve().then(() => (init_mssql_runner(), mssql_runner_exports));
|
|
745
|
+
const sqlParsed = parseSqlServerJdbcUrl2(parsed.originalUrl, {
|
|
746
|
+
username,
|
|
747
|
+
password
|
|
748
|
+
});
|
|
749
|
+
const result = await runMssqlQuery2(sqlParsed, sql, { tunnelParams: params });
|
|
750
|
+
return result.rows;
|
|
751
|
+
}
|
|
752
|
+
if (parsed.driver === "oracle") {
|
|
753
|
+
const { parseOracleJdbcUrl: parseOracleJdbcUrl2 } = await Promise.resolve().then(() => (init_utils2(), utils_exports2));
|
|
754
|
+
const { runOracleQuery: runOracleQuery2 } = await Promise.resolve().then(() => (init_oracle_runner(), oracle_runner_exports));
|
|
755
|
+
const oracleParsed = parseOracleJdbcUrl2(parsed.originalUrl, {
|
|
756
|
+
username,
|
|
757
|
+
password
|
|
758
|
+
});
|
|
759
|
+
const cleanSql = sql.replace(/;\s*$/, "");
|
|
760
|
+
const result = await runOracleQuery2(oracleParsed, cleanSql, {
|
|
761
|
+
tunnelParams: params
|
|
762
|
+
});
|
|
763
|
+
return result.rows;
|
|
764
|
+
}
|
|
765
|
+
const { maybeOpenSshTunnel: maybeOpenSshTunnel2 } = await Promise.resolve().then(() => (init_ssh_tunnel(), ssh_tunnel_exports));
|
|
766
|
+
const tunnel = await maybeOpenSshTunnel2(
|
|
767
|
+
params,
|
|
768
|
+
parsed.nativeUrl,
|
|
769
|
+
parsed.defaultPort
|
|
770
|
+
);
|
|
771
|
+
if (parsed.driver === "postgresql") {
|
|
772
|
+
const { Pool } = await import("pg");
|
|
773
|
+
const { attachStatementTimeout: attachStatementTimeout2, withStatementTimeout: withStatementTimeout2 } = await Promise.resolve().then(() => (init_pg_pool(), pg_pool_exports));
|
|
774
|
+
const pool2 = new Pool({
|
|
775
|
+
connectionString: tunnel.connectionUrl,
|
|
776
|
+
ssl: { rejectUnauthorized: false },
|
|
777
|
+
connectionTimeoutMillis: 1e4
|
|
778
|
+
});
|
|
779
|
+
attachStatementTimeout2(pool2, 3e4);
|
|
780
|
+
try {
|
|
781
|
+
const result = await withStatementTimeout2(
|
|
782
|
+
pool2.query(sql, values ?? []),
|
|
783
|
+
3e4
|
|
784
|
+
);
|
|
785
|
+
return result.rows;
|
|
786
|
+
} finally {
|
|
787
|
+
await pool2.end();
|
|
788
|
+
await tunnel.close();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
const mysql = await import("mysql2/promise");
|
|
792
|
+
const pool = mysql.createPool({
|
|
793
|
+
uri: tunnel.connectionUrl,
|
|
794
|
+
connectTimeout: 1e4
|
|
795
|
+
});
|
|
796
|
+
try {
|
|
797
|
+
const queryPromise = pool.query(sql, values ?? []);
|
|
798
|
+
const timeoutPromise = new Promise(
|
|
799
|
+
(_, reject) => setTimeout(
|
|
800
|
+
() => reject(new Error("Query timed out after 30 seconds")),
|
|
801
|
+
3e4
|
|
802
|
+
)
|
|
803
|
+
);
|
|
804
|
+
const [rows] = await Promise.race([queryPromise, timeoutPromise]);
|
|
805
|
+
return Array.isArray(rows) ? rows : [];
|
|
806
|
+
} finally {
|
|
807
|
+
await pool.end();
|
|
808
|
+
await tunnel.close();
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function getJdbcDialect(params) {
|
|
812
|
+
try {
|
|
813
|
+
const parsed = parseJdbcUrl(params["jdbc-url"] ?? "", {
|
|
814
|
+
username: params["username"] || void 0,
|
|
815
|
+
password: params["password"] || void 0
|
|
816
|
+
});
|
|
817
|
+
return parsed.driver;
|
|
818
|
+
} catch {
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
611
822
|
|
|
612
823
|
// ../connectors/src/connectors/jdbc/sdk/index.ts
|
|
613
824
|
function createClient(params) {
|
|
@@ -763,6 +974,28 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
763
974
|
tools;
|
|
764
975
|
query;
|
|
765
976
|
checkConnection;
|
|
977
|
+
/**
|
|
978
|
+
* SQPD-1212: Logic-based, rule-driven connection setup. Connectors that
|
|
979
|
+
* implement this expose a step-by-step exploration flow (database/schema/
|
|
980
|
+
* table/etc. discovery) that the dashboard backend drives via the
|
|
981
|
+
* `/connections/:connectionId/setup` endpoint. Implement by delegating to
|
|
982
|
+
* `runSetupFlow` from `setup-flow.ts`.
|
|
983
|
+
*/
|
|
984
|
+
setup;
|
|
985
|
+
/**
|
|
986
|
+
* Opt-out of the default "verify before save" behavior on connection
|
|
987
|
+
* creation. The backend invokes `checkConnection` synchronously while
|
|
988
|
+
* creating the connection and aborts (no row inserted) if it fails — this
|
|
989
|
+
* flag disables that for connectors where the check cannot succeed pre-save:
|
|
990
|
+
*
|
|
991
|
+
* - `squadbase-db` populates `connection-url` only after Neon provisioning
|
|
992
|
+
* - OAuth connectors require an OAuth-aware proxyFetch keyed by the
|
|
993
|
+
* connectionId, which doesn't exist until the row is saved
|
|
994
|
+
*
|
|
995
|
+
* Exceptions are the explicit position; new credential-input connectors get
|
|
996
|
+
* the default verify-on-create behavior without opt-in.
|
|
997
|
+
*/
|
|
998
|
+
skipConnectionCheckOnCreate;
|
|
766
999
|
constructor(config) {
|
|
767
1000
|
this.slug = config.slug;
|
|
768
1001
|
this.authType = config.authType;
|
|
@@ -779,6 +1012,8 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
779
1012
|
this.tools = config.tools;
|
|
780
1013
|
this.query = config.query;
|
|
781
1014
|
this.checkConnection = config.checkConnection;
|
|
1015
|
+
this.setup = config.setup;
|
|
1016
|
+
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
782
1017
|
}
|
|
783
1018
|
get connectorKey() {
|
|
784
1019
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -843,6 +1078,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
843
1078
|
}
|
|
844
1079
|
};
|
|
845
1080
|
|
|
1081
|
+
// ../connectors/src/setup-flow.ts
|
|
1082
|
+
async function runSetupFlow(flow, params, ctx, config) {
|
|
1083
|
+
const runtime = {
|
|
1084
|
+
params,
|
|
1085
|
+
language: ctx.language,
|
|
1086
|
+
config
|
|
1087
|
+
};
|
|
1088
|
+
let state = flow.initialState();
|
|
1089
|
+
let answerIdx = 0;
|
|
1090
|
+
for (const step of flow.steps) {
|
|
1091
|
+
const ans = ctx.answers[answerIdx];
|
|
1092
|
+
if (ans && ans.questionSlug === step.slug) {
|
|
1093
|
+
state = step.applyAnswer(state, ans.answer);
|
|
1094
|
+
answerIdx += 1;
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1097
|
+
if (step.type === "text") {
|
|
1098
|
+
return {
|
|
1099
|
+
type: "nextQuestion",
|
|
1100
|
+
questionSlug: step.slug,
|
|
1101
|
+
question: step.question[ctx.language],
|
|
1102
|
+
questionType: "text"
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
|
|
1106
|
+
if (options.length === 0) {
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
return {
|
|
1110
|
+
type: "nextQuestion",
|
|
1111
|
+
questionSlug: step.slug,
|
|
1112
|
+
question: step.question[ctx.language],
|
|
1113
|
+
questionType: step.type,
|
|
1114
|
+
options
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
const dataInvestigationResult = await flow.finalize(state, runtime);
|
|
1118
|
+
return { type: "fulfilled", dataInvestigationResult };
|
|
1119
|
+
}
|
|
1120
|
+
async function resolveSetupSelection(params) {
|
|
1121
|
+
const { selected, allSentinel, fetchAll, limit } = params;
|
|
1122
|
+
const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
|
|
1123
|
+
return resolved.slice(0, limit);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
846
1126
|
// ../connectors/src/auth-types.ts
|
|
847
1127
|
var AUTH_TYPES = {
|
|
848
1128
|
OAUTH: "oauth",
|
|
@@ -853,6 +1133,14 @@ var AUTH_TYPES = {
|
|
|
853
1133
|
USER_PASSWORD: "user-password"
|
|
854
1134
|
};
|
|
855
1135
|
|
|
1136
|
+
// ../connectors/src/connectors/jdbc/index.ts
|
|
1137
|
+
init_pg_pool();
|
|
1138
|
+
init_ssh_tunnel();
|
|
1139
|
+
init_mssql_runner();
|
|
1140
|
+
init_oracle_runner();
|
|
1141
|
+
init_utils();
|
|
1142
|
+
init_utils2();
|
|
1143
|
+
|
|
856
1144
|
// ../connectors/src/connectors/jdbc/setup.ts
|
|
857
1145
|
var jdbcOnboarding = new ConnectorOnboarding({
|
|
858
1146
|
dataOverviewInstructions: {
|
|
@@ -871,8 +1159,326 @@ var jdbcOnboarding = new ConnectorOnboarding({
|
|
|
871
1159
|
}
|
|
872
1160
|
});
|
|
873
1161
|
|
|
1162
|
+
// ../connectors/src/connectors/jdbc/setup-flow.ts
|
|
1163
|
+
var ALL_TABLES = "__ALL_TABLES__";
|
|
1164
|
+
var JDBC_SETUP_MAX_TABLES = 20;
|
|
1165
|
+
function quoteLiteral(value) {
|
|
1166
|
+
return "'" + value.replace(/'/g, "''") + "'";
|
|
1167
|
+
}
|
|
1168
|
+
var PG_INTERNAL_SCHEMAS = /* @__PURE__ */ new Set([
|
|
1169
|
+
"information_schema",
|
|
1170
|
+
"pg_catalog",
|
|
1171
|
+
"pg_toast"
|
|
1172
|
+
]);
|
|
1173
|
+
var MYSQL_INTERNAL_DATABASES = /* @__PURE__ */ new Set([
|
|
1174
|
+
"mysql",
|
|
1175
|
+
"information_schema",
|
|
1176
|
+
"performance_schema",
|
|
1177
|
+
"sys"
|
|
1178
|
+
]);
|
|
1179
|
+
var SQLSERVER_INTERNAL_SCHEMAS = /* @__PURE__ */ new Set([
|
|
1180
|
+
"sys",
|
|
1181
|
+
"information_schema",
|
|
1182
|
+
"guest",
|
|
1183
|
+
"db_owner",
|
|
1184
|
+
"db_accessadmin",
|
|
1185
|
+
"db_securityadmin",
|
|
1186
|
+
"db_ddladmin",
|
|
1187
|
+
"db_backupoperator",
|
|
1188
|
+
"db_datareader",
|
|
1189
|
+
"db_datawriter",
|
|
1190
|
+
"db_denydatareader",
|
|
1191
|
+
"db_denydatawriter"
|
|
1192
|
+
]);
|
|
1193
|
+
var ORACLE_INTERNAL_OWNERS = /* @__PURE__ */ new Set([
|
|
1194
|
+
"SYS",
|
|
1195
|
+
"SYSTEM",
|
|
1196
|
+
"XDB",
|
|
1197
|
+
"OUTLN",
|
|
1198
|
+
"ANONYMOUS",
|
|
1199
|
+
"APEX_PUBLIC_USER",
|
|
1200
|
+
"APPQOSSYS",
|
|
1201
|
+
"AUDSYS",
|
|
1202
|
+
"CTXSYS",
|
|
1203
|
+
"DBSFWUSER",
|
|
1204
|
+
"DBSNMP",
|
|
1205
|
+
"DIP",
|
|
1206
|
+
"DVF",
|
|
1207
|
+
"DVSYS",
|
|
1208
|
+
"GGSYS",
|
|
1209
|
+
"GSMADMIN_INTERNAL",
|
|
1210
|
+
"GSMCATUSER",
|
|
1211
|
+
"GSMUSER",
|
|
1212
|
+
"LBACSYS",
|
|
1213
|
+
"MDDATA",
|
|
1214
|
+
"MDSYS",
|
|
1215
|
+
"OJVMSYS",
|
|
1216
|
+
"OLAPSYS",
|
|
1217
|
+
"ORACLE_OCM",
|
|
1218
|
+
"ORDDATA",
|
|
1219
|
+
"ORDPLUGINS",
|
|
1220
|
+
"ORDSYS",
|
|
1221
|
+
"PDBADMIN",
|
|
1222
|
+
"REMOTE_SCHEDULER_AGENT",
|
|
1223
|
+
"SI_INFORMTN_SCHEMA",
|
|
1224
|
+
"SPATIAL_CSW_ADMIN_USR",
|
|
1225
|
+
"SPATIAL_WFS_ADMIN_USR",
|
|
1226
|
+
"SQLTXADMIN",
|
|
1227
|
+
"SQLTXPLAIN",
|
|
1228
|
+
"SYSBACKUP",
|
|
1229
|
+
"SYSDG",
|
|
1230
|
+
"SYSKM",
|
|
1231
|
+
"SYSRAC",
|
|
1232
|
+
"TSMSYS",
|
|
1233
|
+
"WMSYS",
|
|
1234
|
+
"XS$NULL"
|
|
1235
|
+
]);
|
|
1236
|
+
async function listNamespaces(params) {
|
|
1237
|
+
const dialect = getJdbcDialect(params);
|
|
1238
|
+
if (dialect === "postgresql") {
|
|
1239
|
+
const rows = await runJdbcSetupQuery(
|
|
1240
|
+
params,
|
|
1241
|
+
`SELECT schema_name FROM information_schema.schemata ORDER BY schema_name`
|
|
1242
|
+
);
|
|
1243
|
+
return rows.map((r) => String(r["schema_name"] ?? "")).filter(
|
|
1244
|
+
(name) => name && !PG_INTERNAL_SCHEMAS.has(name.toLowerCase()) && !name.toLowerCase().startsWith("pg_")
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
if (dialect === "mysql") {
|
|
1248
|
+
const rows = await runJdbcSetupQuery(params, "SHOW DATABASES");
|
|
1249
|
+
return rows.map(
|
|
1250
|
+
(r) => String(r["Database"] ?? r["database"] ?? r["SCHEMA_NAME"] ?? "")
|
|
1251
|
+
).filter(
|
|
1252
|
+
(name) => name && !MYSQL_INTERNAL_DATABASES.has(name.toLowerCase())
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
if (dialect === "sqlserver") {
|
|
1256
|
+
const rows = await runJdbcSetupQuery(
|
|
1257
|
+
params,
|
|
1258
|
+
`SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY SCHEMA_NAME`
|
|
1259
|
+
);
|
|
1260
|
+
return rows.map((r) => String(r["SCHEMA_NAME"] ?? "")).filter(
|
|
1261
|
+
(name) => name && !SQLSERVER_INTERNAL_SCHEMAS.has(name.toLowerCase())
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
if (dialect === "oracle") {
|
|
1265
|
+
const rows = await runJdbcSetupQuery(
|
|
1266
|
+
params,
|
|
1267
|
+
`SELECT USERNAME FROM ALL_USERS ORDER BY USERNAME`
|
|
1268
|
+
);
|
|
1269
|
+
return rows.map((r) => String(r["USERNAME"] ?? "")).filter((name) => {
|
|
1270
|
+
if (!name) return false;
|
|
1271
|
+
const upper = name.toUpperCase();
|
|
1272
|
+
return !ORACLE_INTERNAL_OWNERS.has(upper) && !upper.startsWith("APEX_");
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
return [];
|
|
1276
|
+
}
|
|
1277
|
+
async function listTables(params, namespace) {
|
|
1278
|
+
const dialect = getJdbcDialect(params);
|
|
1279
|
+
if (dialect === "postgresql") {
|
|
1280
|
+
const rows = await runJdbcSetupQuery(
|
|
1281
|
+
params,
|
|
1282
|
+
`SELECT table_name FROM information_schema.tables
|
|
1283
|
+
WHERE table_schema = $1 AND table_type IN ('BASE TABLE', 'VIEW')
|
|
1284
|
+
ORDER BY table_name`,
|
|
1285
|
+
[namespace]
|
|
1286
|
+
);
|
|
1287
|
+
return rows.map((r) => String(r["table_name"] ?? "")).filter((name) => name);
|
|
1288
|
+
}
|
|
1289
|
+
if (dialect === "mysql") {
|
|
1290
|
+
const rows = await runJdbcSetupQuery(
|
|
1291
|
+
params,
|
|
1292
|
+
`SELECT TABLE_NAME FROM information_schema.TABLES
|
|
1293
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_TYPE IN ('BASE TABLE', 'VIEW')
|
|
1294
|
+
ORDER BY TABLE_NAME`,
|
|
1295
|
+
[namespace]
|
|
1296
|
+
);
|
|
1297
|
+
return rows.map((r) => String(r["TABLE_NAME"] ?? r["table_name"] ?? "")).filter((name) => name);
|
|
1298
|
+
}
|
|
1299
|
+
if (dialect === "sqlserver") {
|
|
1300
|
+
const rows = await runJdbcSetupQuery(
|
|
1301
|
+
params,
|
|
1302
|
+
`SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
|
1303
|
+
WHERE TABLE_TYPE IN ('BASE TABLE', 'VIEW')
|
|
1304
|
+
AND TABLE_SCHEMA = ${quoteLiteral(namespace)}
|
|
1305
|
+
ORDER BY TABLE_NAME`
|
|
1306
|
+
);
|
|
1307
|
+
return rows.map((r) => String(r["TABLE_NAME"] ?? "")).filter((name) => name);
|
|
1308
|
+
}
|
|
1309
|
+
if (dialect === "oracle") {
|
|
1310
|
+
const rows = await runJdbcSetupQuery(
|
|
1311
|
+
params,
|
|
1312
|
+
`SELECT TABLE_NAME FROM ALL_TABLES
|
|
1313
|
+
WHERE OWNER = ${quoteLiteral(namespace)}
|
|
1314
|
+
ORDER BY TABLE_NAME`
|
|
1315
|
+
);
|
|
1316
|
+
return rows.map((r) => String(r["TABLE_NAME"] ?? "")).filter((name) => name);
|
|
1317
|
+
}
|
|
1318
|
+
return [];
|
|
1319
|
+
}
|
|
1320
|
+
async function describeTable(params, namespace, table) {
|
|
1321
|
+
const dialect = getJdbcDialect(params);
|
|
1322
|
+
if (dialect === "postgresql") {
|
|
1323
|
+
const rows = await runJdbcSetupQuery(
|
|
1324
|
+
params,
|
|
1325
|
+
`SELECT column_name, data_type, is_nullable, column_default
|
|
1326
|
+
FROM information_schema.columns
|
|
1327
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
1328
|
+
ORDER BY ordinal_position`,
|
|
1329
|
+
[namespace, table]
|
|
1330
|
+
);
|
|
1331
|
+
return rows.map((c) => ({
|
|
1332
|
+
name: String(c["column_name"] ?? ""),
|
|
1333
|
+
type: String(c["data_type"] ?? ""),
|
|
1334
|
+
nullable: String(c["is_nullable"] ?? ""),
|
|
1335
|
+
default: c["column_default"] == null ? "-" : String(c["column_default"])
|
|
1336
|
+
}));
|
|
1337
|
+
}
|
|
1338
|
+
if (dialect === "mysql") {
|
|
1339
|
+
const rows = await runJdbcSetupQuery(
|
|
1340
|
+
params,
|
|
1341
|
+
`SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
|
|
1342
|
+
FROM information_schema.COLUMNS
|
|
1343
|
+
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?
|
|
1344
|
+
ORDER BY ORDINAL_POSITION`,
|
|
1345
|
+
[namespace, table]
|
|
1346
|
+
);
|
|
1347
|
+
return rows.map((c) => ({
|
|
1348
|
+
name: String(c["COLUMN_NAME"] ?? c["column_name"] ?? ""),
|
|
1349
|
+
type: String(c["DATA_TYPE"] ?? c["data_type"] ?? ""),
|
|
1350
|
+
nullable: String(c["IS_NULLABLE"] ?? c["is_nullable"] ?? ""),
|
|
1351
|
+
default: (c["COLUMN_DEFAULT"] ?? c["column_default"]) == null ? "-" : String(c["COLUMN_DEFAULT"] ?? c["column_default"])
|
|
1352
|
+
}));
|
|
1353
|
+
}
|
|
1354
|
+
if (dialect === "sqlserver") {
|
|
1355
|
+
const rows = await runJdbcSetupQuery(
|
|
1356
|
+
params,
|
|
1357
|
+
`SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
|
|
1358
|
+
FROM INFORMATION_SCHEMA.COLUMNS
|
|
1359
|
+
WHERE TABLE_SCHEMA = ${quoteLiteral(namespace)}
|
|
1360
|
+
AND TABLE_NAME = ${quoteLiteral(table)}
|
|
1361
|
+
ORDER BY ORDINAL_POSITION`
|
|
1362
|
+
);
|
|
1363
|
+
return rows.map((c) => ({
|
|
1364
|
+
name: String(c["COLUMN_NAME"] ?? ""),
|
|
1365
|
+
type: String(c["DATA_TYPE"] ?? ""),
|
|
1366
|
+
nullable: String(c["IS_NULLABLE"] ?? ""),
|
|
1367
|
+
default: c["COLUMN_DEFAULT"] == null ? "-" : String(c["COLUMN_DEFAULT"])
|
|
1368
|
+
}));
|
|
1369
|
+
}
|
|
1370
|
+
if (dialect === "oracle") {
|
|
1371
|
+
const rows = await runJdbcSetupQuery(
|
|
1372
|
+
params,
|
|
1373
|
+
`SELECT COLUMN_NAME, DATA_TYPE, NULLABLE, DATA_DEFAULT
|
|
1374
|
+
FROM ALL_TAB_COLUMNS
|
|
1375
|
+
WHERE OWNER = ${quoteLiteral(namespace)}
|
|
1376
|
+
AND TABLE_NAME = ${quoteLiteral(table)}
|
|
1377
|
+
ORDER BY COLUMN_ID`
|
|
1378
|
+
);
|
|
1379
|
+
return rows.map((c) => {
|
|
1380
|
+
const defaultRaw = c["DATA_DEFAULT"];
|
|
1381
|
+
return {
|
|
1382
|
+
name: String(c["COLUMN_NAME"] ?? ""),
|
|
1383
|
+
type: String(c["DATA_TYPE"] ?? ""),
|
|
1384
|
+
nullable: String(c["NULLABLE"] ?? ""),
|
|
1385
|
+
default: defaultRaw == null ? "-" : String(defaultRaw).trim() || "-"
|
|
1386
|
+
};
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
return [];
|
|
1390
|
+
}
|
|
1391
|
+
function namespaceLabel(dialect, language) {
|
|
1392
|
+
if (dialect === "mysql") {
|
|
1393
|
+
return language === "ja" ? "\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9" : "Database";
|
|
1394
|
+
}
|
|
1395
|
+
if (dialect === "oracle") {
|
|
1396
|
+
return language === "ja" ? "\u30AA\u30FC\u30CA\u30FC\uFF08\u30B9\u30AD\u30FC\u30DE\uFF09" : "Schema (owner)";
|
|
1397
|
+
}
|
|
1398
|
+
return language === "ja" ? "\u30B9\u30AD\u30FC\u30DE" : "Schema";
|
|
1399
|
+
}
|
|
1400
|
+
var jdbcSetupFlow = {
|
|
1401
|
+
initialState: () => ({}),
|
|
1402
|
+
steps: [
|
|
1403
|
+
{
|
|
1404
|
+
slug: "namespace",
|
|
1405
|
+
type: "select",
|
|
1406
|
+
question: {
|
|
1407
|
+
ja: "\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306B\u4F7F\u3046\u30B9\u30AD\u30FC\u30DE\u307E\u305F\u306F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044",
|
|
1408
|
+
en: "Select the schema or database to use for setup"
|
|
1409
|
+
},
|
|
1410
|
+
async fetchOptions(_state, rt) {
|
|
1411
|
+
const names = await listNamespaces(rt.params);
|
|
1412
|
+
return names.map((value) => ({ value }));
|
|
1413
|
+
},
|
|
1414
|
+
applyAnswer: (state, answer) => ({ ...state, namespace: answer[0] })
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
slug: "tables",
|
|
1418
|
+
type: "multiSelect",
|
|
1419
|
+
question: {
|
|
1420
|
+
ja: "\u5BFE\u8C61\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
|
|
1421
|
+
en: "Select target tables (multi-select allowed)"
|
|
1422
|
+
},
|
|
1423
|
+
async fetchOptions(state, rt) {
|
|
1424
|
+
if (!state.namespace) return [];
|
|
1425
|
+
const names = await listTables(rt.params, state.namespace);
|
|
1426
|
+
const tableOptions = names.map((value) => ({ value }));
|
|
1427
|
+
return [
|
|
1428
|
+
{
|
|
1429
|
+
value: ALL_TABLES,
|
|
1430
|
+
label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C6\u30FC\u30D6\u30EB" : "All tables"
|
|
1431
|
+
},
|
|
1432
|
+
...tableOptions
|
|
1433
|
+
];
|
|
1434
|
+
},
|
|
1435
|
+
applyAnswer: (state, answer) => ({ ...state, tables: answer })
|
|
1436
|
+
}
|
|
1437
|
+
],
|
|
1438
|
+
async finalize(state, rt) {
|
|
1439
|
+
if (!state.namespace || !state.tables) {
|
|
1440
|
+
throw new Error("JDBC setup: incomplete state on finalize");
|
|
1441
|
+
}
|
|
1442
|
+
const namespace = state.namespace;
|
|
1443
|
+
const dialect = getJdbcDialect(rt.params);
|
|
1444
|
+
const targetTables = await resolveSetupSelection({
|
|
1445
|
+
selected: state.tables,
|
|
1446
|
+
allSentinel: ALL_TABLES,
|
|
1447
|
+
fetchAll: () => listTables(rt.params, namespace),
|
|
1448
|
+
limit: JDBC_SETUP_MAX_TABLES
|
|
1449
|
+
});
|
|
1450
|
+
const label = namespaceLabel(dialect, rt.language);
|
|
1451
|
+
const sections = [
|
|
1452
|
+
"## JDBC",
|
|
1453
|
+
"",
|
|
1454
|
+
`### Dialect: ${dialect ?? "unknown"}`,
|
|
1455
|
+
`### ${label}: ${namespace}`,
|
|
1456
|
+
""
|
|
1457
|
+
];
|
|
1458
|
+
for (const table of targetTables) {
|
|
1459
|
+
const cols = await describeTable(rt.params, namespace, table);
|
|
1460
|
+
sections.push(`#### Table: ${table}`, "");
|
|
1461
|
+
sections.push("| Column | Type | Nullable | Default |");
|
|
1462
|
+
sections.push("|--------|------|----------|---------|");
|
|
1463
|
+
for (const c of cols) {
|
|
1464
|
+
sections.push(
|
|
1465
|
+
`| ${c.name} | ${c.type} | ${c.nullable} | ${c.default} |`
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
sections.push("");
|
|
1469
|
+
}
|
|
1470
|
+
return sections.join("\n");
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
|
|
874
1474
|
// ../connectors/src/connectors/jdbc/tools/execute-query.ts
|
|
875
1475
|
import { z } from "zod";
|
|
1476
|
+
init_pg_pool();
|
|
1477
|
+
init_ssh_tunnel();
|
|
1478
|
+
init_mssql_runner();
|
|
1479
|
+
init_oracle_runner();
|
|
1480
|
+
init_utils();
|
|
1481
|
+
init_utils2();
|
|
876
1482
|
var MAX_ROWS = 500;
|
|
877
1483
|
var CONNECT_TIMEOUT_MS = 1e4;
|
|
878
1484
|
var STATEMENT_TIMEOUT_MS = 6e4;
|
|
@@ -1128,6 +1734,7 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
|
|
|
1128
1734
|
\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`
|
|
1129
1735
|
},
|
|
1130
1736
|
tools,
|
|
1737
|
+
setup: (params, ctx, config) => runSetupFlow(jdbcSetupFlow, params, ctx, config),
|
|
1131
1738
|
async checkConnection(params, _config) {
|
|
1132
1739
|
const jdbcUrl = params[parameters.jdbcUrl.slug];
|
|
1133
1740
|
const username = params[parameters.username.slug];
|
|
@@ -1307,6 +1914,7 @@ function resolveEnvVarOptional(entry, key) {
|
|
|
1307
1914
|
import { getContext } from "hono/context-storage";
|
|
1308
1915
|
import { getCookie } from "hono/cookie";
|
|
1309
1916
|
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
1917
|
+
var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
|
|
1310
1918
|
function normalizeHeaders(input) {
|
|
1311
1919
|
const out = {};
|
|
1312
1920
|
if (!input) return out;
|
|
@@ -1315,6 +1923,11 @@ function normalizeHeaders(input) {
|
|
|
1315
1923
|
});
|
|
1316
1924
|
return out;
|
|
1317
1925
|
}
|
|
1926
|
+
function extractInputUrl(input) {
|
|
1927
|
+
if (typeof input === "string") return input;
|
|
1928
|
+
if (input instanceof URL) return input.href;
|
|
1929
|
+
return input.url;
|
|
1930
|
+
}
|
|
1318
1931
|
function createSandboxProxyFetch(connectionId) {
|
|
1319
1932
|
return async (input, init) => {
|
|
1320
1933
|
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
@@ -1324,10 +1937,17 @@ function createSandboxProxyFetch(connectionId) {
|
|
|
1324
1937
|
"Connection proxy is not configured. Please check your deployment settings."
|
|
1325
1938
|
);
|
|
1326
1939
|
}
|
|
1327
|
-
const originalUrl =
|
|
1940
|
+
const originalUrl = extractInputUrl(input);
|
|
1941
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
1942
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1943
|
+
const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
1944
|
+
return fetch(sessionUrl, {
|
|
1945
|
+
method: "POST",
|
|
1946
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1328
1949
|
const originalMethod = init?.method ?? "GET";
|
|
1329
1950
|
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1330
|
-
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
1331
1951
|
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1332
1952
|
return fetch(proxyUrl, {
|
|
1333
1953
|
method: "POST",
|
|
@@ -1353,10 +1973,9 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
1353
1973
|
}
|
|
1354
1974
|
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
1355
1975
|
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1976
|
+
const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
|
|
1356
1977
|
return async (input, init) => {
|
|
1357
|
-
const originalUrl =
|
|
1358
|
-
const originalMethod = init?.method ?? "GET";
|
|
1359
|
-
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1978
|
+
const originalUrl = extractInputUrl(input);
|
|
1360
1979
|
const c = getContext();
|
|
1361
1980
|
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
1362
1981
|
if (!appSession) {
|
|
@@ -1364,6 +1983,14 @@ function createDeployedAppProxyFetch(connectionId) {
|
|
|
1364
1983
|
"No authentication method available for connection proxy."
|
|
1365
1984
|
);
|
|
1366
1985
|
}
|
|
1986
|
+
if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
|
|
1987
|
+
return fetch(sessionUrl, {
|
|
1988
|
+
method: "POST",
|
|
1989
|
+
headers: { Authorization: `Bearer ${appSession}` }
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
const originalMethod = init?.method ?? "GET";
|
|
1993
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
1367
1994
|
return fetch(proxyUrl, {
|
|
1368
1995
|
method: "POST",
|
|
1369
1996
|
headers: {
|