mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
### What does this PR do? Fixes #20729 ### How did you verify your code works? There is a test --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
13
packages/bun-types/sql.d.ts
vendored
13
packages/bun-types/sql.d.ts
vendored
@@ -272,14 +272,11 @@ declare module "bun" {
|
||||
*/
|
||||
ssl?: TLSOptions | boolean | undefined;
|
||||
|
||||
// `.path` is currently unsupported in Bun, the implementation is
|
||||
// incomplete.
|
||||
//
|
||||
// /**
|
||||
// * Unix domain socket path for connection
|
||||
// * @default ""
|
||||
// */
|
||||
// path?: string | undefined;
|
||||
/**
|
||||
* Unix domain socket path for connection
|
||||
* @default undefined
|
||||
*/
|
||||
path?: string | undefined;
|
||||
|
||||
/**
|
||||
* Callback executed when a connection attempt completes
|
||||
|
||||
@@ -305,7 +305,7 @@ function parseOptions(
|
||||
onclose: ((client: Bun.SQL) => void) | undefined,
|
||||
max: number | null | undefined,
|
||||
bigint: boolean | undefined,
|
||||
path: string | string[],
|
||||
path: string,
|
||||
adapter: Bun.SQL.__internal.Adapter;
|
||||
|
||||
let prepare = true;
|
||||
@@ -421,9 +421,19 @@ function parseOptions(
|
||||
port ||= Number(options.port || env.PGPORT || (adapter === "mysql" ? 3306 : 5432));
|
||||
|
||||
path ||= (options as { path?: string }).path || "";
|
||||
// add /.s.PGSQL.${port} if it doesn't exist
|
||||
if (path && path?.indexOf("/.s.PGSQL.") === -1 && adapter === "postgres") {
|
||||
path = `${path}/.s.PGSQL.${port}`;
|
||||
|
||||
if (adapter === "postgres") {
|
||||
// add /.s.PGSQL.${port} if the unix domain socket is listening on that path
|
||||
if (path && Number.isSafeInteger(port) && path?.indexOf("/.s.PGSQL.") === -1) {
|
||||
const pathWithSocket = `${path}/.s.PGSQL.${port}`;
|
||||
|
||||
// Only add the path if it actually exists. It would be better to just
|
||||
// always respect whatever the user passes in, but that would technically
|
||||
// be a breakpoint change at this point.
|
||||
if (require("node:fs").existsSync(pathWithSocket)) {
|
||||
path = pathWithSocket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
username ||=
|
||||
@@ -579,6 +589,12 @@ function parseOptions(
|
||||
ret.onclose = onclose;
|
||||
}
|
||||
|
||||
if (path) {
|
||||
if (require("node:fs").existsSync(path)) {
|
||||
ret.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,9 +147,88 @@ if (isDockerEnabled()) {
|
||||
// --- Expected pg_hba.conf ---
|
||||
process.env.DATABASE_URL = `postgres://bun_sql_test@localhost:${container.port}/bun_sql_test`;
|
||||
|
||||
const net = require("node:net");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const os = require("node:os");
|
||||
|
||||
// Create a temporary unix domain socket path
|
||||
const socketPath = path.join(os.tmpdir(), `postgres_echo_${Date.now()}.sock`);
|
||||
|
||||
// Clean up any existing socket file
|
||||
try {
|
||||
fs.unlinkSync(socketPath);
|
||||
} catch {}
|
||||
|
||||
// Create a unix domain socket server that proxies to the PostgreSQL container
|
||||
const socketServer = net.createServer(clientSocket => {
|
||||
console.log("PostgreSQL connection received on unix socket");
|
||||
|
||||
// Create connection to the actual PostgreSQL container
|
||||
const containerSocket = net.createConnection({
|
||||
host: login.host,
|
||||
port: login.port,
|
||||
});
|
||||
|
||||
// Handle container connection
|
||||
containerSocket.on("connect", () => {
|
||||
console.log("Connected to PostgreSQL container");
|
||||
});
|
||||
|
||||
containerSocket.on("error", err => {
|
||||
console.error("Container connection error:", err);
|
||||
clientSocket.destroy();
|
||||
});
|
||||
|
||||
containerSocket.on("close", () => {
|
||||
console.log("Container connection closed");
|
||||
clientSocket.end();
|
||||
});
|
||||
|
||||
// Handle client socket
|
||||
clientSocket.on("data", data => {
|
||||
// Forward client data to container
|
||||
containerSocket.write(data);
|
||||
});
|
||||
|
||||
clientSocket.on("error", err => {
|
||||
console.error("Client socket error:", err);
|
||||
containerSocket.destroy();
|
||||
});
|
||||
|
||||
clientSocket.on("close", () => {
|
||||
console.log("Client connection closed");
|
||||
containerSocket.end();
|
||||
});
|
||||
|
||||
// Forward container responses back to client
|
||||
containerSocket.on("data", data => {
|
||||
clientSocket.write(data);
|
||||
});
|
||||
});
|
||||
|
||||
socketServer.listen(socketPath, () => {
|
||||
console.log(`Unix domain socket server listening on ${socketPath}`);
|
||||
});
|
||||
|
||||
// Clean up the socket on exit
|
||||
afterAll(() => {
|
||||
socketServer.close();
|
||||
try {
|
||||
fs.unlinkSync(socketPath);
|
||||
} catch {}
|
||||
});
|
||||
|
||||
const login: Bun.SQL.PostgresOrMySQLOptions = {
|
||||
username: "bun_sql_test",
|
||||
port: container.port,
|
||||
path: socketPath,
|
||||
};
|
||||
|
||||
const login_domain_socket: Bun.SQL.PostgresOrMySQLOptions = {
|
||||
username: "bun_sql_test",
|
||||
port: container.port,
|
||||
path: socketPath,
|
||||
};
|
||||
|
||||
const login_md5: Bun.SQL.PostgresOrMySQLOptions = {
|
||||
@@ -1036,6 +1115,11 @@ if (isDockerEnabled()) {
|
||||
expect((await sql`select true as x`)[0].x).toBe(true);
|
||||
});
|
||||
|
||||
test("unix domain socket can send query", async () => {
|
||||
await using sql = postgres({ ...options, ...login_domain_socket });
|
||||
expect((await sql`select true as x`)[0].x).toBe(true);
|
||||
});
|
||||
|
||||
test("Login using MD5", async () => {
|
||||
await using sql = postgres({ ...options, ...login_md5 });
|
||||
expect(await sql`select true as x`).toEqual([{ x: true }]);
|
||||
|
||||
Reference in New Issue
Block a user