aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-10-11 01:59:09 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-10-13 18:08:24 -0700
commit9bc76f6628239f427c7b057a23a73e366fc0d509 (patch)
treec63a1c2a0d6ae31ef6706e7a305508be25e09a8f
parent0a6ef179f89b71492458134aae4af9cd32b1e70d (diff)
downloadbun-9bc76f6628239f427c7b057a23a73e366fc0d509.tar.gz
bun-9bc76f6628239f427c7b057a23a73e366fc0d509.tar.zst
bun-9bc76f6628239f427c7b057a23a73e366fc0d509.zip
wip
-rw-r--r--src/bun.js/bindings/bindings.cpp34
-rw-r--r--src/bun.js/bindings/bindings.zig10
-rw-r--r--src/bun.js/bindings/generated_classes_list.zig2
-rw-r--r--src/bun.js/rare_data.zig2
-rw-r--r--src/js/bun/sql.ts21
-rw-r--r--src/js/out/InternalModuleRegistryConstants.h6
-rw-r--r--src/jsc.zig1
-rw-r--r--src/sql/postgres.zig280
8 files changed, 308 insertions, 48 deletions
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index d06e8259e..a61a0221a 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -4689,6 +4689,40 @@ extern "C" EncodedJSValue JSC__JSValue__dateInstanceFromNullTerminatedString(JSC
return JSValue::encode(date);
}
+// this is largely copied from dateProtoFuncToISOString
+extern "C" int JSC__JSValue__toISOString(JSC::JSGlobalObject* globalObject, EncodedJSValue dateValue, char buffer[28])
+{
+ JSC::DateInstance* thisDateObj = JSC::jsDynamicCast<JSC::DateInstance*>(JSC::JSValue::decode(dateValue));
+ if (!thisDateObj)
+ return -1;
+
+ if (!std::isfinite(thisDateObj->internalNumber()))
+ return -1;
+
+ auto& vm = globalObject->vm();
+
+ const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache);
+ if (!gregorianDateTime)
+ return -1;
+
+ // If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1).
+ int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond));
+ if (ms < 0)
+ ms += msPerSecond;
+
+ int charactersWritten;
+ if (gregorianDateTime->year() > 9999 || gregorianDateTime->year() < 0)
+ charactersWritten = snprintf(buffer, sizeof(buffer), "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
+ else
+ charactersWritten = snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms);
+
+ ASSERT(charactersWritten > 0 && static_cast<unsigned>(charactersWritten) < sizeof(buffer));
+ if (static_cast<unsigned>(charactersWritten) >= sizeof(buffer))
+ return -1;
+
+ return charactersWritten;
+}
+
#pragma mark - WebCore::DOMFormData
CPP_DECL void WebCore__DOMFormData__append(WebCore__DOMFormData* arg0, ZigString* arg1, ZigString* arg2)
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index e6b218486..278ccd20e 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -3557,6 +3557,16 @@ pub const JSValue = enum(JSValueReprInt) {
cppFn("push", .{ value, globalObject, out });
}
+ extern fn JSC__JSValue__toISOString(*JSC.JSGlobalObject, JSC.JSValue, *[28]u8) c_int;
+ pub fn toISOString(this: JSValue, globalObject: *JSC.JSGlobalObject, buf: *[28]u8) []const u8 {
+ const count = JSC__JSValue__toISOString(globalObject, this, buf);
+ if (count < 0) {
+ return "";
+ }
+
+ return buf[0..@as(usize, @intCast(count))];
+ }
+
pub fn as(value: JSValue, comptime ZigType: type) ?*ZigType {
if (value.isEmptyOrUndefinedOrNull())
return null;
diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig
index 3b45f33b8..60b0b08c1 100644
--- a/src/bun.js/bindings/generated_classes_list.zig
+++ b/src/bun.js/bindings/generated_classes_list.zig
@@ -55,4 +55,6 @@ pub const Classes = struct {
pub const DebugHTTPSServer = JSC.API.DebugHTTPSServer;
pub const Crypto = JSC.WebCore.Crypto;
pub const FFI = JSC.FFI;
+ pub const PostgresSQLConnection = JSC.Postgres.PostgresSQLConnection;
+ pub const PostgresSQLQuery = JSC.Postgres.PostgresSQLQuery;
};
diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig
index c9d742d96..c9890d2dd 100644
--- a/src/bun.js/rare_data.zig
+++ b/src/bun.js/rare_data.zig
@@ -20,6 +20,8 @@ stderr_store: ?*Blob.Store = null,
stdin_store: ?*Blob.Store = null,
stdout_store: ?*Blob.Store = null,
+postgresql_context: JSC.Postgres.PostgresSQLContext = .{},
+
entropy_cache: ?*EntropyCache = null,
hot_map: ?HotMap = null,
diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts
index ff2d1b44e..9deed2ecb 100644
--- a/src/js/bun/sql.ts
+++ b/src/js/bun/sql.ts
@@ -145,15 +145,28 @@ function loadOptions(o) {
var hostname, port, username, password, database, tls, url, query, adapter;
const env = Bun.env;
- if (typeof o === "undefined" || (typeof o === "string" && o?.length === 0)) {
+ if (typeof o === "undefined" || (typeof o === "string" && o.length === 0)) {
const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;
if (urlString) {
- o = urlString;
+ url = new URL(urlString);
+ o = {};
}
+ } else if (o && typeof o === "object") {
+ if (o instanceof URL) {
+ url = o;
+ } else if (o?.url) {
+ const _url = o.url;
+ if (typeof _url === "string") {
+ url = new URL(_url);
+ } else if (_url && typeof _url === "object" && _url instanceof URL) {
+ url = _url;
+ }
+ }
+ } else if (typeof o === "string") {
+ url = new URL(o);
}
- if (typeof o === "string") {
- url = new URL(o);
+ if (url) {
({ hostname, port, username, password, protocol: adapter } = o = url);
if (adapter[adapter.length - 1] === ":") {
adapter = adapter.slice(0, -1);
diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h
index 73b5b1f49..0814ad631 100644
--- a/src/js/out/InternalModuleRegistryConstants.h
+++ b/src/js/out/InternalModuleRegistryConstants.h
@@ -10,7 +10,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j
//
//
-static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o\?.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n o = urlString;\n }\n if (typeof o === \"string\") {\n if (url = new URL(o), { hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
+static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
//
//
@@ -263,7 +263,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j
//
//
-static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o\?.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n o = urlString;\n }\n if (typeof o === \"string\") {\n if (url = new URL(o), { hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
+static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
//
//
@@ -517,7 +517,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j
//
//
-static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o\?.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n o = urlString;\n }\n if (typeof o === \"string\") {\n if (url = new URL(o), { hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
+static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query }, onConnected, onClose) {\n return new PostgresSQLConnection(hostname, port, username, password, tls, query, onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(connection.query(normalizeStrings(strings), values), closedConnectionHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(new PostgresSQLQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { PostgresSQLConnection, PostgresSQLQuery, PostgresSQLStatement, init } = @lazy(\"bun:sql\");\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_resolve](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.then(...arguments);\n }\n catch() {\n return this[_run](), super.catch(...arguments);\n }\n finally() {\n return this[_run](), super.finally(...arguments);\n }\n}\nObject.defineProperty(Query.prototype, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query.prototype, Symbol.toStringTag, { value: \"Query\" });\ninit(Query.prototype.resolve, Query.prototype.reject);\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"_s;
//
//
diff --git a/src/jsc.zig b/src/jsc.zig
index 5cdf739b3..82d4df1ce 100644
--- a/src/jsc.zig
+++ b/src/jsc.zig
@@ -46,6 +46,7 @@ pub const API = struct {
pub const TLSSocket = @import("./bun.js/api/bun/socket.zig").TLSSocket;
pub const Listener = @import("./bun.js/api/bun/socket.zig").Listener;
};
+pub const Postgres = @import("./sql/postgres.zig");
pub const DNS = @import("./bun.js/api/bun/dns_resolver.zig");
pub const FFI = @import("./bun.js/api/ffi.zig").FFI;
pub const Node = struct {
diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig
index 37bc47b21..abc9b4e51 100644
--- a/src/sql/postgres.zig
+++ b/src/sql/postgres.zig
@@ -42,21 +42,58 @@ const Data = union(enum) {
};
pub const protocol = struct {
- pub fn NewWriterWrap(comptime Context: type, comptime writeFunction_: (fn (ctx: Context, bytes: []const u8) anyerror!void)) type {
+ pub const ArrayList = struct {
+ array: *std.ArrayList(u8),
+
+ pub fn offset(this: @This()) usize {
+ return this.array.items.len;
+ }
+
+ pub fn write(this: @This(), bytes: []const u8) anyerror!void {
+ try this.array.appendSlice(bytes);
+ }
+
+ pub fn pwrite(this: @This(), bytes: []const u8, i: usize) anyerror!void {
+ @memcpy(this.array.items[i..][0..bytes.len], bytes);
+ }
+
+ pub const Writer = NewWriter(@This());
+ };
+
+ pub fn NewWriterWrap(
+ comptime Context: type,
+ comptime offsetFn_: (fn (ctx: Context) usize),
+ comptime writeFunction_: (fn (ctx: Context, bytes: []const u8) anyerror!void),
+ comptime pwriteFunction_: (fn (ctx: Context, bytes: []const u8, offset: usize) anyerror!void),
+ ) type {
return struct {
wrapped: Context,
const writeFn = writeFunction_;
+ const pwriteFn = pwriteFunction_;
+ const offsetFn = offsetFn_;
pub const Ctx = Context;
pub inline fn write(this: @This(), data: []const u8) anyerror!void {
try writeFn(this.wrapped, data);
}
+ pub inline fn offset(this: @This()) usize {
+ return offsetFn(this.wrapped);
+ }
+
+ pub inline fn pwrite(this: @This(), data: []const u8, i: usize) anyerror!void {
+ try pwriteFn(this.wrapped, data, i);
+ }
+
pub fn @"i32"(this: @This(), value: i32) !void {
try this.write(std.mem.asBytes(&@byteSwap(value)));
}
+ pub fn @"f64"(this: @This(), value: f64) !void {
+ try this.write(std.mem.asBytes(&@byteSwap(value)));
+ }
+
pub fn @"i16"(this: @This(), value: i16) !void {
try this.write(std.mem.asBytes(&@byteSwap(value)));
}
@@ -73,7 +110,20 @@ pub const protocol = struct {
try this.write(&[_]u8{0});
}
+ pub fn boolean(this: @This(), value: bool) !void {
+ try this.write(if (value) "t" else "f");
+ }
+
+ pub fn @"null"(this: @This()) !void {
+ try this.i32(0xFFFFFFFF);
+ }
+
pub fn String(this: @This(), value: bun.String) !void {
+ if (value.isEmpty()) {
+ try this.write(&[_]u8{0});
+ return;
+ }
+
var sliced = value.toUTF8(bun.default_allocator);
defer sliced.deinit();
var slice = sliced.slice();
@@ -276,7 +326,7 @@ pub const protocol = struct {
}
pub fn NewWriter(comptime Context: type) type {
- return NewWriterWrap(Context, Context.writeData);
+ return NewWriterWrap(Context, Context.offset, Context.write, Context.pwrite);
}
comptime {
@@ -1306,10 +1356,176 @@ const PreparedStatementsMap = std.HashMapUnmanaged(u64, *PostgresSQLStatement, b
pub const PostgresSQLContext = struct {
tcp: ?*uws.SocketContext = null,
- ssl: ?*uws.SocketContext = null,
- onQueryCompleteFn: JSC.Strong = .{},
- onStatementCompleteFn: JSC.Strong = .{},
+ onQueryResolveFn: JSC.Strong = .{},
+ onQueryRejectFn: JSC.Strong = .{},
+};
+
+pub const PostgresSQLQuery = struct {
+ statement: ?*PostgresSQLStatement = null,
+ query: bun.String = bun.String.empty,
+ cursor_name: bun.String = bun.String.empty,
+
+ pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*PostgresSQLQuery {
+ _ = callframe;
+ _ = globalThis;
+ }
+
+ pub fn doRun(this: *PostgresSQLQuery, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ var arguments_ = callframe.arguments(3);
+ const arguments = arguments_.slice();
+ var connection = arguments[0].as(PostgresSQLConnection) orelse {
+ globalObject.throwTypeError("connection must be a PostgresSQLConnection");
+ return .zero;
+ };
+ _ = connection;
+
+ var values_array = arguments[1];
+
+ var query = arguments[1];
+
+ if (!values_array.jsType().isArray()) {
+ globalObject.throwInvalidArgumentType("run", "values", "Array");
+ return .zero;
+ }
+ if (!query.isString()) {
+ globalObject.throwInvalidArgumentType("run", "query", "string");
+ return .zero;
+ }
+
+ var statement = this.statement orelse {};
+ _ = statement;
+
+ return .undefined;
+ }
+
+ pub fn doCancel(this: *PostgresSQLQuery, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
+ _ = callframe;
+ _ = globalObject;
+ _ = this;
+
+ return .undefined;
+ }
+};
+
+pub const PostgresRequest = struct {
+ pub fn writeBind(
+ statement: *PostgresSQLStatement,
+ cursor_name: bun.String,
+ globalObject: *JSC.JSGlobalObject,
+ values_array: JSC.JSValue,
+ comptime Context: type,
+ writer: protocol.NewWriter(Context),
+ ) !void {
+ try writer.bytes("B");
+ const length_offset = writer.offset();
+ try writer.i32(0);
+
+ try writer.string(statement.name);
+ try writer.String(cursor_name);
+
+ var iter = JSC.JSArrayIterator.init(values_array, globalObject);
+
+ try writer.i16(@truncate(iter.len));
+
+ while (iter.next()) |value| {
+ if (value.isUndefinedOrNull()) {
+ try writer.i16(0);
+ continue;
+ }
+
+ const tag = types.Tag.fromJS(globalObject, value);
+ switch (tag) {
+ .bytea, .number => {
+ try writer.i16(0);
+ },
+ else => {
+ try writer.i16(1);
+ },
+ }
+ }
+
+ try writer.i16(@truncate(iter.len));
+
+ iter = JSC.JSArrayIterator.init(values_array, globalObject);
+
+ while (iter.next()) |value| {
+ if (value.isUndefinedOrNull()) {
+ try writer.i32(4);
+ try writer.null();
+ continue;
+ }
+
+ const tag = types.Tag.fromJS(globalObject, value);
+ switch (tag) {
+ .number => {
+ if (value.isInt32()) {
+ try writer.i32(4);
+ try writer.i32(value.to(i32));
+ } else {
+ try writer.i32(8);
+ try writer.f64(value.coerceToDouble(globalObject));
+ }
+ },
+ .json => {
+ var str = bun.String.empty;
+ value.jsonStringify(globalObject, 0, &str);
+ try writer.String(str);
+ },
+ .boolean => {
+ try writer.boolean(value.toBoolean());
+ try writer.write(&[_]u8{0});
+ },
+ .time, .datetime, .date => {
+ var buf = std.mem.zeroes([28]u8);
+ const str = value.toISOString(globalObject, &buf);
+ try writer.string(str);
+ },
+ .bytea => {
+ var bytes: []const u8 = "";
+ if (value.asArrayBuffer(globalObject)) |buf| {
+ bytes = buf.byteSlice();
+ }
+ try writer.i32(@truncate(bytes.len));
+ try writer.bytes(bytes);
+ },
+ else => {
+ // TODO: check if this leaks
+ var str = value.toBunString(globalObject);
+ try writer.str(str);
+ },
+ }
+ }
+
+ try writer.pwrite(&@byteSwap(std.mem.toBytes(@as(i32, @intCast(writer.offset())))), length_offset);
+ }
+
+ pub fn writeQuery(
+ query: bun.String,
+ statement: *PostgresSQLStatement,
+ comptime Context: type,
+ writer: protocol.NewWriter(Context),
+ ) !void {
+ {
+ var query_str = query.toUTF8(bun.default_allocator);
+ defer query_str.deinit();
+ var q = protocol.Query{
+ .message = Data{
+ .temporary = query_str.slice(),
+ },
+ };
+ try q.writeInternal(Context, writer);
+ }
+
+ {
+ var d = protocol.Describe{
+ .p = .{
+ .prepared_statement = statement.name,
+ },
+ };
+ try d.writeInternal(Context, writer);
+ }
+ }
};
pub const PostgresSQLConnection = struct {
@@ -1318,6 +1534,7 @@ pub const PostgresSQLConnection = struct {
ref_count: u32 = 0,
write_buffer: bun.ByteList = .{},
+ requests: PostgresRequest.Queue,
poll_ref: bun.JSC.PollRef = .{},
globalObject: *JSC.JSGlobalObject,
@@ -1326,6 +1543,8 @@ pub const PostgresSQLConnection = struct {
has_pending_activity: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false),
js_value: JSC.JSValue = JSC.JSValue.undefined,
+ pub usingnamespace JSC.Codegen.JSPostgresSQLConnection;
+
pub fn hasPendingActivity(this: *PostgresSQLConnection) callconv(.C) bool {
@fence(.Acquire);
return this.has_pending_activity.load(.Acquire);
@@ -1389,29 +1608,17 @@ pub const PostgresSQLConnection = struct {
};
pub const PostgresSQLStatement = struct {
- connection: ?*PostgresSQLConnection = null,
+ structure: JSC.Strong = .{},
name: []const u8 = "",
ref_count: u32 = 0,
- poll_ref: JSC.PollRef = .{},
- has_pending_activity: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(false),
-
- pub fn hasPendingActivity(this: *PostgresSQLStatement) callconv(.C) bool {
- return this.has_pending_activity.load(.Monotonic);
- }
+ fields: []const protocol.FieldDescription = &[_]protocol.FieldDescription{},
- pub fn deinit(this: *PostgresSQLStatement) void {
- if (this.connection) |conn| conn.deref();
- this.poll_ref.deactivate(JSC.VirtualMachine.get().event_loop_handle.?);
-
- bun.default_allocator.free(this.name);
- bun.default_allocator.destroy(this);
- }
-
- pub fn finalize(this: *PostgresSQLStatement) callconv(.C) void {
- this.unref();
+ pub fn ref(this: *@This()) void {
+ std.debug.assert(this.ref_count > 0);
+ this.ref_count += 1;
}
- pub fn unref(this: *PostgresSQLStatement) void {
+ pub fn deref(this: *@This()) void {
const ref_count = this.ref_count;
this.ref_count -= 1;
@@ -1420,28 +1627,19 @@ pub const PostgresSQLStatement = struct {
}
}
- pub fn doRef(this: *PostgresSQLStatement, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) void {
- _ = callframe;
- this.poll_ref.ref(globalObject.bunVM());
- }
+ pub fn deinit(this: *PostgresSQLStatement) void {
+ std.debug.assert(this.ref_count == 0);
- pub fn doUnref(this: *PostgresSQLStatement, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) void {
- _ = callframe;
- this.poll_ref.unref(globalObject.bunVM());
+ for (this.fields) |*field| {
+ field.deinit();
+ }
+ bun.default_allocator.free(this.fields);
+ this.structure.deinit();
+ bun.default_allocator.free(this.name);
+ bun.default_allocator.destroy(this);
}
};
-pub const Host = struct {
- hostname: []const u8,
- port: u16,
-
- database: []const u8,
- user: []const u8,
- password: []const u8 = "",
-
- ssl: bool = false,
-};
-
pub const Status = enum {
disconnected,
connecting,