planche 0.5.2 → 0.5.3
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/index.js +79 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -526,6 +526,7 @@ var MySqlDriver = class {
|
|
|
526
526
|
var mysqlDriverFactory = {
|
|
527
527
|
async open(config) {
|
|
528
528
|
const connection = await mysql.createConnection(toConnectionOptions(config));
|
|
529
|
+
connection.on("error", (err) => console.error("[mysql] Connection error:", err.message));
|
|
529
530
|
return new MySqlDriver(connection, config);
|
|
530
531
|
},
|
|
531
532
|
async test(config) {
|
|
@@ -719,6 +720,7 @@ var postgresDriverFactory = {
|
|
|
719
720
|
async open(config) {
|
|
720
721
|
const client = new pg.Client(toClientConfig(config));
|
|
721
722
|
await client.connect();
|
|
723
|
+
client.on("error", (err) => console.error("[postgres] Connection error:", err.message));
|
|
722
724
|
const driver = new PostgresDriver(client, config);
|
|
723
725
|
await driver.loadTypeNames();
|
|
724
726
|
return driver;
|
|
@@ -1520,6 +1522,69 @@ function testDirect(config) {
|
|
|
1520
1522
|
}
|
|
1521
1523
|
}
|
|
1522
1524
|
|
|
1525
|
+
// src/drivers/connection-lost.ts
|
|
1526
|
+
var ConnectionLostError = class extends Error {
|
|
1527
|
+
status = 404;
|
|
1528
|
+
constructor(message) {
|
|
1529
|
+
super(message);
|
|
1530
|
+
this.name = "ConnectionLostError";
|
|
1531
|
+
}
|
|
1532
|
+
};
|
|
1533
|
+
var LOST_CODES = /* @__PURE__ */ new Set([
|
|
1534
|
+
// mysql2
|
|
1535
|
+
"PROTOCOL_CONNECTION_LOST",
|
|
1536
|
+
"PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR",
|
|
1537
|
+
"PROTOCOL_ENQUEUE_AFTER_QUIT",
|
|
1538
|
+
"PROTOCOL_ENQUEUE_AFTER_DESTROY",
|
|
1539
|
+
// node sockets (pg, mssql/tedious surface these directly)
|
|
1540
|
+
"ECONNRESET",
|
|
1541
|
+
"EPIPE",
|
|
1542
|
+
"ETIMEDOUT",
|
|
1543
|
+
"ECONNABORTED",
|
|
1544
|
+
"ENETUNREACH",
|
|
1545
|
+
"EHOSTUNREACH",
|
|
1546
|
+
"ENETDOWN",
|
|
1547
|
+
// mssql
|
|
1548
|
+
"ESOCKET",
|
|
1549
|
+
"ECLOSE",
|
|
1550
|
+
"ENOTOPEN",
|
|
1551
|
+
// pg: admin_shutdown / crash_shutdown / cannot_connect_now
|
|
1552
|
+
"57P01",
|
|
1553
|
+
"57P02",
|
|
1554
|
+
"57P03"
|
|
1555
|
+
]);
|
|
1556
|
+
var LOST_MESSAGES = [
|
|
1557
|
+
/connection is in closed state/i,
|
|
1558
|
+
// mysql2 "Can't add new command when connection is in closed state"
|
|
1559
|
+
/connection lost/i,
|
|
1560
|
+
/connection terminated/i,
|
|
1561
|
+
// pg
|
|
1562
|
+
/client has encountered a connection error/i,
|
|
1563
|
+
// pg
|
|
1564
|
+
/client was closed and is not queryable/i,
|
|
1565
|
+
// pg
|
|
1566
|
+
/connection is closed/i,
|
|
1567
|
+
// mssql
|
|
1568
|
+
/socket hang up/i,
|
|
1569
|
+
/ORA-0311[34]\b/,
|
|
1570
|
+
/ORA-01012\b/,
|
|
1571
|
+
/ORA-12541\b/,
|
|
1572
|
+
/ORA-03135\b/,
|
|
1573
|
+
/NJS-500\b/,
|
|
1574
|
+
/NJS-521\b/
|
|
1575
|
+
// oracle
|
|
1576
|
+
];
|
|
1577
|
+
function isConnectionLost(err) {
|
|
1578
|
+
if (!err || typeof err !== "object") return false;
|
|
1579
|
+
const e = err;
|
|
1580
|
+
if (typeof e.code === "string" && LOST_CODES.has(e.code)) return true;
|
|
1581
|
+
if (e.fatal === true) return true;
|
|
1582
|
+
if (typeof e.errorNum === "number" && [3113, 3114, 1012, 12541, 3135].includes(e.errorNum)) return true;
|
|
1583
|
+
const message = typeof e.message === "string" ? e.message : "";
|
|
1584
|
+
if (LOST_MESSAGES.some((re) => re.test(message))) return true;
|
|
1585
|
+
return e.originalError !== void 0 && e.originalError !== err && isConnectionLost(e.originalError);
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1523
1588
|
// src/tunneling.ts
|
|
1524
1589
|
var IDLE_TIMEOUT_MS = Number(process.env.PLANCHE_IDLE_TIMEOUT_MS) || 30 * 60 * 1e3;
|
|
1525
1590
|
var MAX_CONNECTIONS = Number(process.env.PLANCHE_MAX_CONNECTIONS) || 64;
|
|
@@ -1567,7 +1632,16 @@ var ConnectionManager = class {
|
|
|
1567
1632
|
throw new Error(`Connection not found: ${connectionId}`);
|
|
1568
1633
|
}
|
|
1569
1634
|
this.lastUsed.set(connectionId, Date.now());
|
|
1570
|
-
|
|
1635
|
+
try {
|
|
1636
|
+
return await driver.query(sql2, database);
|
|
1637
|
+
} catch (err) {
|
|
1638
|
+
if (!isConnectionLost(err)) throw err;
|
|
1639
|
+
console.log(`[ConnectionManager] Connection lost, evicting: ${connectionId}`);
|
|
1640
|
+
this.connections.delete(connectionId);
|
|
1641
|
+
this.lastUsed.delete(connectionId);
|
|
1642
|
+
await driver.close().catch(() => void 0);
|
|
1643
|
+
throw new ConnectionLostError(`Connection lost: ${err instanceof Error ? err.message : String(err)}`);
|
|
1644
|
+
}
|
|
1571
1645
|
}
|
|
1572
1646
|
/**
|
|
1573
1647
|
* Close and remove a connection.
|
|
@@ -1818,6 +1892,10 @@ function createAgent(options) {
|
|
|
1818
1892
|
} catch (err) {
|
|
1819
1893
|
const message = errorMessage(err);
|
|
1820
1894
|
console.error("[query] Error:", message);
|
|
1895
|
+
if (err instanceof ConnectionLostError) {
|
|
1896
|
+
fail(res, 404, message);
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1821
1899
|
fail(res, 422, message);
|
|
1822
1900
|
}
|
|
1823
1901
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planche",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Local agent for Planche — lets the browser-based Planche SQL client reach MySQL/MariaDB/PostgreSQL/SQLite/SQL Server/Oracle/Neon/Supabase/Cloudflare D1 databases from your machine.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://planche.dev",
|