@squadbase/vite-server 0.1.9-dev.f236b23 → 0.1.10-dev.5aa0720

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.
@@ -20254,6 +20254,150 @@ var ParameterDefinition = class {
20254
20254
  }
20255
20255
  };
20256
20256
 
20257
+ // ../connectors/src/lib/ssh-tunnel.ts
20258
+ var sshTunnelParameters = {
20259
+ sshHost: new ParameterDefinition({
20260
+ slug: "ssh-host",
20261
+ name: "SSH Tunnel Host",
20262
+ description: "Optional. Hostname of the SSH bastion to tunnel through. Leave empty to connect directly.",
20263
+ envVarBaseKey: "SSH_TUNNEL_HOST",
20264
+ type: "text",
20265
+ secret: false,
20266
+ required: false
20267
+ }),
20268
+ sshPort: new ParameterDefinition({
20269
+ slug: "ssh-port",
20270
+ name: "SSH Tunnel Port",
20271
+ description: "Optional. SSH port of the bastion host (default: 22).",
20272
+ envVarBaseKey: "SSH_TUNNEL_PORT",
20273
+ type: "text",
20274
+ secret: false,
20275
+ required: false
20276
+ }),
20277
+ sshUsername: new ParameterDefinition({
20278
+ slug: "ssh-username",
20279
+ name: "SSH Tunnel Username",
20280
+ description: "Optional. Username for SSH authentication. Required when SSH Tunnel Host is set.",
20281
+ envVarBaseKey: "SSH_TUNNEL_USERNAME",
20282
+ type: "text",
20283
+ secret: false,
20284
+ required: false
20285
+ }),
20286
+ sshPrivateKeyBase64: new ParameterDefinition({
20287
+ slug: "ssh-private-key-base64",
20288
+ name: "SSH Private Key",
20289
+ description: "Optional. Private key (PEM, base64-encoded) used for SSH authentication. Required when SSH Tunnel Host is set.",
20290
+ envVarBaseKey: "SSH_TUNNEL_PRIVATE_KEY_BASE64",
20291
+ type: "base64EncodedText",
20292
+ secret: true,
20293
+ required: false
20294
+ }),
20295
+ sshPassphrase: new ParameterDefinition({
20296
+ slug: "ssh-passphrase",
20297
+ name: "SSH Private Key Passphrase",
20298
+ description: "Optional. Passphrase for the SSH private key, if it is encrypted.",
20299
+ envVarBaseKey: "SSH_TUNNEL_PASSPHRASE",
20300
+ type: "text",
20301
+ secret: true,
20302
+ required: false
20303
+ })
20304
+ };
20305
+ var NOOP_TUNNEL = (connectionUrl) => ({
20306
+ connectionUrl,
20307
+ close: async () => {
20308
+ }
20309
+ });
20310
+ var NOOP_TUNNEL_HOSTPORT = (host, port) => ({
20311
+ host,
20312
+ port,
20313
+ close: async () => {
20314
+ }
20315
+ });
20316
+ function connectionParamsToRecord(connection2) {
20317
+ const out = {};
20318
+ for (const p of connection2.parameters) {
20319
+ if (p.value != null) out[p.parameterSlug] = p.value;
20320
+ }
20321
+ return out;
20322
+ }
20323
+ async function maybeOpenSshTunnelHostPort(params, dbHost, dbPort) {
20324
+ const sshHost = params[sshTunnelParameters.sshHost.slug];
20325
+ if (!sshHost) return NOOP_TUNNEL_HOSTPORT(dbHost, dbPort);
20326
+ const sshUsername = params[sshTunnelParameters.sshUsername.slug];
20327
+ const sshPrivateKeyBase64 = params[sshTunnelParameters.sshPrivateKeyBase64.slug];
20328
+ if (!sshUsername || !sshPrivateKeyBase64) {
20329
+ throw new Error(
20330
+ "SSH tunnel requires `ssh-username` and `ssh-private-key-base64` when `ssh-host` is set."
20331
+ );
20332
+ }
20333
+ const sshPort = Number(params[sshTunnelParameters.sshPort.slug] || "22") || 22;
20334
+ const sshPassphrase = params[sshTunnelParameters.sshPassphrase.slug];
20335
+ const [{ Client }, net] = await Promise.all([
20336
+ Promise.resolve().then(() => __toESM(require_lib3(), 1)),
20337
+ import("net")
20338
+ ]);
20339
+ const sshClient = new Client();
20340
+ await new Promise((resolve, reject) => {
20341
+ sshClient.once("ready", () => resolve());
20342
+ sshClient.once("error", reject);
20343
+ sshClient.connect({
20344
+ host: sshHost,
20345
+ port: sshPort,
20346
+ username: sshUsername,
20347
+ privateKey: Buffer.from(sshPrivateKeyBase64, "base64"),
20348
+ passphrase: sshPassphrase || void 0,
20349
+ readyTimeout: 1e4
20350
+ });
20351
+ });
20352
+ const server = net.createServer((socket) => {
20353
+ sshClient.forwardOut(
20354
+ socket.remoteAddress ?? "127.0.0.1",
20355
+ socket.remotePort ?? 0,
20356
+ dbHost,
20357
+ dbPort,
20358
+ (err, stream) => {
20359
+ if (err) {
20360
+ socket.destroy(err);
20361
+ return;
20362
+ }
20363
+ socket.pipe(stream).pipe(socket);
20364
+ }
20365
+ );
20366
+ });
20367
+ await new Promise((resolve, reject) => {
20368
+ server.once("error", reject);
20369
+ server.listen(0, "127.0.0.1", () => resolve());
20370
+ });
20371
+ const address = server.address();
20372
+ if (!address || typeof address === "string") {
20373
+ server.close();
20374
+ sshClient.end();
20375
+ throw new Error("Failed to allocate local port for SSH tunnel.");
20376
+ }
20377
+ return {
20378
+ host: "127.0.0.1",
20379
+ port: address.port,
20380
+ close: async () => {
20381
+ await new Promise((resolve) => server.close(() => resolve()));
20382
+ sshClient.end();
20383
+ }
20384
+ };
20385
+ }
20386
+ async function maybeOpenSshTunnel(params, connectionUrl, defaultDbPort) {
20387
+ const sshHost = params[sshTunnelParameters.sshHost.slug];
20388
+ if (!sshHost) return NOOP_TUNNEL(connectionUrl);
20389
+ const url = new URL(connectionUrl);
20390
+ const dbHost = url.hostname;
20391
+ const dbPort = url.port ? Number(url.port) : defaultDbPort;
20392
+ const tunnel = await maybeOpenSshTunnelHostPort(params, dbHost, dbPort);
20393
+ url.hostname = tunnel.host;
20394
+ url.port = String(tunnel.port);
20395
+ return {
20396
+ connectionUrl: url.toString(),
20397
+ close: tunnel.close
20398
+ };
20399
+ }
20400
+
20257
20401
  // ../connectors/src/connectors/sqlserver/utils.ts
20258
20402
  var SQLSERVER_PREFIX_RE = /^(?:jdbc:)?sqlserver:\/\//i;
20259
20403
  var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes"]);
@@ -20332,17 +20476,27 @@ async function importMssql() {
20332
20476
  }
20333
20477
  async function runMssqlQuery(parsed, sql, options = {}) {
20334
20478
  const sqlMod = await importMssql();
20335
- const config = toMssqlConfig(parsed, {
20336
- encrypt: options.forceEncrypt
20337
- });
20338
- const pool = new sqlMod.ConnectionPool(config);
20339
- await pool.connect();
20479
+ const tunnel = options.tunnelParams ? await maybeOpenSshTunnelHostPort(
20480
+ options.tunnelParams,
20481
+ parsed.server,
20482
+ parsed.port
20483
+ ) : null;
20340
20484
  try {
20341
- const result = await pool.request().query(sql);
20342
- const recordset = result.recordset ?? [];
20343
- return { rows: recordset };
20485
+ const tunneled = tunnel ? { ...parsed, server: tunnel.host, port: tunnel.port } : parsed;
20486
+ const config = toMssqlConfig(tunneled, {
20487
+ encrypt: options.forceEncrypt
20488
+ });
20489
+ const pool = new sqlMod.ConnectionPool(config);
20490
+ await pool.connect();
20491
+ try {
20492
+ const result = await pool.request().query(sql);
20493
+ const recordset = result.recordset ?? [];
20494
+ return { rows: recordset };
20495
+ } finally {
20496
+ await pool.close();
20497
+ }
20344
20498
  } finally {
20345
- await pool.close();
20499
+ await tunnel?.close();
20346
20500
  }
20347
20501
  }
20348
20502
  async function checkMssqlConnection(url, credentials, options = {}) {
@@ -20430,35 +20584,69 @@ function parseOracleJdbcUrl(jdbcUrl, options = {}) {
20430
20584
  function redactOracleUrl(jdbcUrl) {
20431
20585
  return jdbcUrl.replace(/(:\/\/)([^@/]+)@/, "$1***@").replace(/(thin:)([^@]+)@/i, "$1***@");
20432
20586
  }
20587
+ function parseOracleConnectStringHostPort(connectString) {
20588
+ const m = /^([^:/]+):(\d+)(.*)$/.exec(connectString);
20589
+ if (!m) return null;
20590
+ return { host: m[1], port: Number(m[2]), trailing: m[3] };
20591
+ }
20592
+ function rewriteOracleConnectStringHostPort(connectString, host, port) {
20593
+ const parts = parseOracleConnectStringHostPort(connectString);
20594
+ if (!parts) return connectString;
20595
+ return `${host}:${port}${parts.trailing}`;
20596
+ }
20433
20597
 
20434
20598
  // ../connectors/src/lib/oracle-runner.ts
20435
20599
  async function importOracleDb() {
20436
20600
  const mod = await import("oracledb");
20437
20601
  return mod.default ?? mod;
20438
20602
  }
20439
- async function runOracleQuery(parsed, sql) {
20603
+ async function runOracleQuery(parsed, sql, options = {}) {
20440
20604
  const oracledb = await importOracleDb();
20441
- const connection2 = await oracledb.getConnection({
20442
- user: parsed.user,
20443
- password: parsed.password,
20444
- connectString: parsed.connectString
20445
- });
20605
+ let tunnel = null;
20606
+ if (options.tunnelParams) {
20607
+ const hostPort = parseOracleConnectStringHostPort(parsed.connectString);
20608
+ if (hostPort) {
20609
+ tunnel = await maybeOpenSshTunnelHostPort(
20610
+ options.tunnelParams,
20611
+ hostPort.host,
20612
+ hostPort.port
20613
+ );
20614
+ }
20615
+ }
20446
20616
  try {
20447
- const result = await connection2.execute(sql, [], {
20448
- outFormat: oracledb.OUT_FORMAT_OBJECT,
20449
- // Bound by the connector's own row cap, but keep the driver from
20450
- // streaming arbitrarily large result sets.
20451
- maxRows: 5e3
20617
+ const connectString = tunnel ? rewriteOracleConnectStringHostPort(
20618
+ parsed.connectString,
20619
+ tunnel.host,
20620
+ tunnel.port
20621
+ ) : parsed.connectString;
20622
+ const connection2 = await oracledb.getConnection({
20623
+ user: parsed.user,
20624
+ password: parsed.password,
20625
+ connectString
20452
20626
  });
20453
- return { rows: result.rows ?? [] };
20454
- } finally {
20455
20627
  try {
20456
- await connection2.close();
20457
- } catch {
20628
+ const result = await connection2.execute(
20629
+ sql,
20630
+ [],
20631
+ {
20632
+ outFormat: oracledb.OUT_FORMAT_OBJECT,
20633
+ // Bound by the connector's own row cap, but keep the driver from
20634
+ // streaming arbitrarily large result sets.
20635
+ maxRows: 5e3
20636
+ }
20637
+ );
20638
+ return { rows: result.rows ?? [] };
20639
+ } finally {
20640
+ try {
20641
+ await connection2.close();
20642
+ } catch {
20643
+ }
20458
20644
  }
20645
+ } finally {
20646
+ await tunnel?.close();
20459
20647
  }
20460
20648
  }
20461
- async function checkOracleConnection(url, credentials) {
20649
+ async function checkOracleConnection(url, credentials, options = {}) {
20462
20650
  let parsed;
20463
20651
  try {
20464
20652
  parsed = parseOracleJdbcUrl(url, credentials);
@@ -20469,7 +20657,7 @@ async function checkOracleConnection(url, credentials) {
20469
20657
  };
20470
20658
  }
20471
20659
  try {
20472
- await runOracleQuery(parsed, "SELECT 1 FROM DUAL");
20660
+ await runOracleQuery(parsed, "SELECT 1 FROM DUAL", options);
20473
20661
  return { success: true };
20474
20662
  } catch (err) {
20475
20663
  let msg = err instanceof Error ? err.message : String(err);
@@ -20478,134 +20666,6 @@ async function checkOracleConnection(url, credentials) {
20478
20666
  }
20479
20667
  }
20480
20668
 
20481
- // ../connectors/src/lib/ssh-tunnel.ts
20482
- var sshTunnelParameters = {
20483
- sshHost: new ParameterDefinition({
20484
- slug: "ssh-host",
20485
- name: "SSH Tunnel Host",
20486
- description: "Optional. Hostname of the SSH bastion to tunnel through. Leave empty to connect directly.",
20487
- envVarBaseKey: "SSH_TUNNEL_HOST",
20488
- type: "text",
20489
- secret: false,
20490
- required: false
20491
- }),
20492
- sshPort: new ParameterDefinition({
20493
- slug: "ssh-port",
20494
- name: "SSH Tunnel Port",
20495
- description: "Optional. SSH port of the bastion host (default: 22).",
20496
- envVarBaseKey: "SSH_TUNNEL_PORT",
20497
- type: "text",
20498
- secret: false,
20499
- required: false
20500
- }),
20501
- sshUsername: new ParameterDefinition({
20502
- slug: "ssh-username",
20503
- name: "SSH Tunnel Username",
20504
- description: "Optional. Username for SSH authentication. Required when SSH Tunnel Host is set.",
20505
- envVarBaseKey: "SSH_TUNNEL_USERNAME",
20506
- type: "text",
20507
- secret: false,
20508
- required: false
20509
- }),
20510
- sshPrivateKeyBase64: new ParameterDefinition({
20511
- slug: "ssh-private-key-base64",
20512
- name: "SSH Private Key",
20513
- description: "Optional. Private key (PEM, base64-encoded) used for SSH authentication. Required when SSH Tunnel Host is set.",
20514
- envVarBaseKey: "SSH_TUNNEL_PRIVATE_KEY_BASE64",
20515
- type: "base64EncodedText",
20516
- secret: true,
20517
- required: false
20518
- }),
20519
- sshPassphrase: new ParameterDefinition({
20520
- slug: "ssh-passphrase",
20521
- name: "SSH Private Key Passphrase",
20522
- description: "Optional. Passphrase for the SSH private key, if it is encrypted.",
20523
- envVarBaseKey: "SSH_TUNNEL_PASSPHRASE",
20524
- type: "text",
20525
- secret: true,
20526
- required: false
20527
- })
20528
- };
20529
- var NOOP_TUNNEL = (connectionUrl) => ({
20530
- connectionUrl,
20531
- close: async () => {
20532
- }
20533
- });
20534
- function connectionParamsToRecord(connection2) {
20535
- const out = {};
20536
- for (const p of connection2.parameters) {
20537
- if (p.value != null) out[p.parameterSlug] = p.value;
20538
- }
20539
- return out;
20540
- }
20541
- async function maybeOpenSshTunnel(params, connectionUrl, defaultDbPort) {
20542
- const sshHost = params[sshTunnelParameters.sshHost.slug];
20543
- if (!sshHost) return NOOP_TUNNEL(connectionUrl);
20544
- const sshUsername = params[sshTunnelParameters.sshUsername.slug];
20545
- const sshPrivateKeyBase64 = params[sshTunnelParameters.sshPrivateKeyBase64.slug];
20546
- if (!sshUsername || !sshPrivateKeyBase64) {
20547
- throw new Error(
20548
- "SSH tunnel requires `ssh-username` and `ssh-private-key-base64` when `ssh-host` is set."
20549
- );
20550
- }
20551
- const sshPort = Number(params[sshTunnelParameters.sshPort.slug] || "22") || 22;
20552
- const sshPassphrase = params[sshTunnelParameters.sshPassphrase.slug];
20553
- const url = new URL(connectionUrl);
20554
- const dbHost = url.hostname;
20555
- const dbPort = url.port ? Number(url.port) : defaultDbPort;
20556
- const [{ Client }, net] = await Promise.all([
20557
- Promise.resolve().then(() => __toESM(require_lib3(), 1)),
20558
- import("net")
20559
- ]);
20560
- const sshClient = new Client();
20561
- await new Promise((resolve, reject) => {
20562
- sshClient.once("ready", () => resolve());
20563
- sshClient.once("error", reject);
20564
- sshClient.connect({
20565
- host: sshHost,
20566
- port: sshPort,
20567
- username: sshUsername,
20568
- privateKey: Buffer.from(sshPrivateKeyBase64, "base64"),
20569
- passphrase: sshPassphrase || void 0,
20570
- readyTimeout: 1e4
20571
- });
20572
- });
20573
- const server = net.createServer((socket) => {
20574
- sshClient.forwardOut(
20575
- socket.remoteAddress ?? "127.0.0.1",
20576
- socket.remotePort ?? 0,
20577
- dbHost,
20578
- dbPort,
20579
- (err, stream) => {
20580
- if (err) {
20581
- socket.destroy(err);
20582
- return;
20583
- }
20584
- socket.pipe(stream).pipe(socket);
20585
- }
20586
- );
20587
- });
20588
- await new Promise((resolve, reject) => {
20589
- server.once("error", reject);
20590
- server.listen(0, "127.0.0.1", () => resolve());
20591
- });
20592
- const address = server.address();
20593
- if (!address || typeof address === "string") {
20594
- server.close();
20595
- sshClient.end();
20596
- throw new Error("Failed to allocate local port for SSH tunnel.");
20597
- }
20598
- url.hostname = "127.0.0.1";
20599
- url.port = String(address.port);
20600
- return {
20601
- connectionUrl: url.toString(),
20602
- close: async () => {
20603
- await new Promise((resolve) => server.close(() => resolve()));
20604
- sshClient.end();
20605
- }
20606
- };
20607
- }
20608
-
20609
20669
  // ../connectors/src/connectors/jdbc/parameters.ts
20610
20670
  var parameters = {
20611
20671
  jdbcUrl: new ParameterDefinition({
@@ -20749,7 +20809,9 @@ function createClient(params) {
20749
20809
  username,
20750
20810
  password
20751
20811
  });
20752
- const result = await runMssqlQuery(mssqlParsed, sql);
20812
+ const result = await runMssqlQuery(mssqlParsed, sql, {
20813
+ tunnelParams: params
20814
+ });
20753
20815
  return result.rows;
20754
20816
  }
20755
20817
  if (parsed.driver === "oracle") {
@@ -20763,7 +20825,9 @@ function createClient(params) {
20763
20825
  password
20764
20826
  });
20765
20827
  const cleanSql = sql.replace(/;\s*$/, "");
20766
- const result = await runOracleQuery(oracleParsed, cleanSql);
20828
+ const result = await runOracleQuery(oracleParsed, cleanSql, {
20829
+ tunnelParams: params
20830
+ });
20767
20831
  return result.rows;
20768
20832
  }
20769
20833
  const tunnel = await maybeOpenSshTunnel(
@@ -21042,12 +21106,13 @@ Always bound results: LIMIT for PG/MySQL/Redshift, TOP for SQL Server, FETCH FIR
21042
21106
  };
21043
21107
  }
21044
21108
  try {
21109
+ const tunnelParams = connectionParamsToRecord(connection2);
21045
21110
  if (parsed.driver === "sqlserver") {
21046
21111
  const mssqlParsed = parseSqlServerJdbcUrl(parsed.originalUrl, {
21047
21112
  username,
21048
21113
  password
21049
21114
  });
21050
- const result = await runMssqlQuery(mssqlParsed, sql);
21115
+ const result = await runMssqlQuery(mssqlParsed, sql, { tunnelParams });
21051
21116
  const rows = result.rows;
21052
21117
  return {
21053
21118
  success: true,
@@ -21062,7 +21127,9 @@ Always bound results: LIMIT for PG/MySQL/Redshift, TOP for SQL Server, FETCH FIR
21062
21127
  password
21063
21128
  });
21064
21129
  const cleanSql = sql.replace(/;\s*$/, "");
21065
- const result = await runOracleQuery(oracleParsed, cleanSql);
21130
+ const result = await runOracleQuery(oracleParsed, cleanSql, {
21131
+ tunnelParams
21132
+ });
21066
21133
  const rows = result.rows;
21067
21134
  return {
21068
21135
  success: true,
@@ -21074,7 +21141,7 @@ Always bound results: LIMIT for PG/MySQL/Redshift, TOP for SQL Server, FETCH FIR
21074
21141
  let tunnel;
21075
21142
  try {
21076
21143
  tunnel = await maybeOpenSshTunnel(
21077
- connectionParamsToRecord(connection2),
21144
+ tunnelParams,
21078
21145
  parsed.nativeUrl,
21079
21146
  parsed.defaultPort
21080
21147
  );
@@ -21248,10 +21315,18 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
21248
21315
  };
21249
21316
  }
21250
21317
  if (parsed.driver === "sqlserver") {
21251
- return checkMssqlConnection(parsed.originalUrl, { username, password });
21318
+ return checkMssqlConnection(
21319
+ parsed.originalUrl,
21320
+ { username, password },
21321
+ { tunnelParams: params }
21322
+ );
21252
21323
  }
21253
21324
  if (parsed.driver === "oracle") {
21254
- return checkOracleConnection(parsed.originalUrl, { username, password });
21325
+ return checkOracleConnection(
21326
+ parsed.originalUrl,
21327
+ { username, password },
21328
+ { tunnelParams: params }
21329
+ );
21255
21330
  }
21256
21331
  const tunnel = await maybeOpenSshTunnel(
21257
21332
  params,
@@ -21308,10 +21383,12 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
21308
21383
  });
21309
21384
  const sample = unwrapSampleLimit(sql);
21310
21385
  if (sample) {
21311
- const result = await runMssqlQuery(mssqlParsed, sample.inner);
21386
+ const result = await runMssqlQuery(mssqlParsed, sample.inner, {
21387
+ tunnelParams: params
21388
+ });
21312
21389
  return { rows: result.rows.slice(0, sample.limit) };
21313
21390
  }
21314
- return runMssqlQuery(mssqlParsed, sql);
21391
+ return runMssqlQuery(mssqlParsed, sql, { tunnelParams: params });
21315
21392
  }
21316
21393
  if (parsed.driver === "oracle") {
21317
21394
  const oracleParsed = parseOracleJdbcUrl(parsed.originalUrl, {
@@ -21321,11 +21398,13 @@ JDBC URL \u306E\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306B\u3088\u308A\u65B
21321
21398
  const sample = unwrapSampleLimit(sql);
21322
21399
  if (sample) {
21323
21400
  const inner = sample.inner.replace(/;\s*$/, "");
21324
- const result = await runOracleQuery(oracleParsed, inner);
21401
+ const result = await runOracleQuery(oracleParsed, inner, {
21402
+ tunnelParams: params
21403
+ });
21325
21404
  return { rows: result.rows.slice(0, sample.limit) };
21326
21405
  }
21327
21406
  const cleanSql = sql.replace(/;\s*$/, "");
21328
- return runOracleQuery(oracleParsed, cleanSql);
21407
+ return runOracleQuery(oracleParsed, cleanSql, { tunnelParams: params });
21329
21408
  }
21330
21409
  const tunnel = await maybeOpenSshTunnel(
21331
21410
  params,