datapeek 0.1.6 → 0.1.8

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.
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+
3
+
4
+ // src/server/db/mssql.ts
5
+ import sql from "mssql";
6
+ var pool = null;
7
+ function parseConnectionString(connectionString) {
8
+ const config = {
9
+ server: "",
10
+ database: "",
11
+ options: {
12
+ encrypt: true,
13
+ trustServerCertificate: false,
14
+ enableArithAbort: true
15
+ }
16
+ };
17
+ const parts = connectionString.split(";");
18
+ for (const part of parts) {
19
+ const [key, ...valueParts] = part.split("=");
20
+ const value = valueParts.join("=").trim();
21
+ const keyLower = key.trim().toLowerCase();
22
+ switch (keyLower) {
23
+ case "server":
24
+ case "data source":
25
+ let serverValue = value;
26
+ if (serverValue.startsWith("tcp:")) {
27
+ serverValue = serverValue.substring(4);
28
+ }
29
+ const [serverHost, serverPort] = serverValue.split(",");
30
+ config.server = serverHost.trim();
31
+ if (serverPort) {
32
+ config.port = parseInt(serverPort.trim(), 10);
33
+ }
34
+ break;
35
+ case "database":
36
+ case "initial catalog":
37
+ config.database = value;
38
+ break;
39
+ case "user id":
40
+ case "userid":
41
+ case "uid":
42
+ config.user = value;
43
+ break;
44
+ case "password":
45
+ case "pwd":
46
+ config.password = value;
47
+ break;
48
+ case "port":
49
+ config.port = parseInt(value, 10);
50
+ break;
51
+ case "encrypt":
52
+ config.options.encrypt = value.toLowerCase() === "true";
53
+ break;
54
+ case "trustservercertificate":
55
+ case "trust server certificate":
56
+ config.options.trustServerCertificate = value.toLowerCase() === "true";
57
+ break;
58
+ }
59
+ }
60
+ return config;
61
+ }
62
+ async function testConnection(config) {
63
+ const testPool = typeof config === "string" ? new sql.ConnectionPool(parseConnectionString(config)) : new sql.ConnectionPool(config);
64
+ try {
65
+ await testPool.connect();
66
+ await testPool.close();
67
+ } catch (error) {
68
+ throw error;
69
+ }
70
+ }
71
+ async function connect(config) {
72
+ await disconnect();
73
+ const connectionConfig = typeof config === "string" ? parseConnectionString(config) : config;
74
+ pool = new sql.ConnectionPool(connectionConfig);
75
+ try {
76
+ await pool.connect();
77
+ } catch (error) {
78
+ pool = null;
79
+ throw error;
80
+ }
81
+ }
82
+ async function disconnect() {
83
+ if (pool) {
84
+ try {
85
+ await pool.close();
86
+ } catch (error) {
87
+ }
88
+ pool = null;
89
+ }
90
+ }
91
+ function getConnection() {
92
+ return pool;
93
+ }
94
+ async function executeQuery(query, parameters) {
95
+ if (!pool || !pool.connected) {
96
+ throw new Error("Not connected to database");
97
+ }
98
+ const request = pool.request();
99
+ if (parameters) {
100
+ for (const param of parameters) {
101
+ if (param.type) {
102
+ request.input(param.name, param.type, param.value);
103
+ } else {
104
+ request.input(param.name, param.value);
105
+ }
106
+ }
107
+ }
108
+ const result = await request.query(query);
109
+ return result.recordset || [];
110
+ }
111
+ async function executeQueryMultiple(query, parameters) {
112
+ if (!pool || !pool.connected) {
113
+ throw new Error("Not connected to database");
114
+ }
115
+ const request = pool.request();
116
+ if (parameters) {
117
+ for (const param of parameters) {
118
+ if (param.type) {
119
+ request.input(param.name, param.type, param.value);
120
+ } else {
121
+ request.input(param.name, param.value);
122
+ }
123
+ }
124
+ }
125
+ const result = await request.query(query);
126
+ return result.recordsets || [];
127
+ }
128
+
129
+ export {
130
+ parseConnectionString,
131
+ testConnection,
132
+ connect,
133
+ disconnect,
134
+ getConnection,
135
+ executeQuery,
136
+ executeQueryMultiple
137
+ };
package/dist/cli/dev.js CHANGED
@@ -4,9 +4,10 @@ import {
4
4
  connect,
5
5
  disconnect,
6
6
  executeQuery,
7
+ executeQueryMultiple,
7
8
  getConnection,
8
9
  testConnection
9
- } from "./chunk-PTI2CUG6.js";
10
+ } from "./chunk-5X2YZYYM.js";
10
11
 
11
12
  // src/server/index.ts
12
13
  import express from "express";
@@ -87,15 +88,20 @@ connectionRoutes.delete("/", async (req, res) => {
87
88
  });
88
89
  connectionRoutes.get("/status", async (req, res) => {
89
90
  try {
90
- const { getConnection: getConnection2, executeQuery: executeQuery2 } = await import("./mssql-5VFXLOGV.js");
91
+ const { getConnection: getConnection2, executeQuery: executeQuery3 } = await import("./mssql-D7NDIUG7.js");
91
92
  const pool = getConnection2();
92
93
  if (pool && pool.connected) {
93
94
  try {
94
- const result = await executeQuery2("SELECT DB_NAME() as databaseName");
95
+ const result = await executeQuery3("SELECT DB_NAME() as databaseName");
95
96
  const databaseName = result[0]?.databaseName || null;
96
97
  res.json({ connected: true, databaseName });
97
- } catch {
98
- res.json({ connected: true, databaseName: null });
98
+ } catch (error) {
99
+ const errorMessage = error.message || "";
100
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
101
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
102
+ await disconnect2();
103
+ }
104
+ res.json({ connected: false });
99
105
  }
100
106
  } else {
101
107
  res.json({ connected: false });
@@ -126,6 +132,11 @@ tableRoutes.get("/", async (req, res) => {
126
132
  const result = await executeQuery(query);
127
133
  res.json(result);
128
134
  } catch (error) {
135
+ const errorMessage = error.message || "";
136
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
137
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
138
+ await disconnect2();
139
+ }
129
140
  res.status(500).json({ error: error.message || "Failed to fetch tables" });
130
141
  }
131
142
  });
@@ -164,6 +175,11 @@ tableRoutes.get("/:schema/:table", async (req, res) => {
164
175
  ]);
165
176
  res.json(result);
166
177
  } catch (error) {
178
+ const errorMessage = error.message || "";
179
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
180
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
181
+ await disconnect2();
182
+ }
167
183
  res.status(500).json({ error: error.message || "Failed to fetch table structure" });
168
184
  }
169
185
  });
@@ -175,12 +191,63 @@ tableRoutes.get("/:schema/:table/data", async (req, res) => {
175
191
  const sortColumn = req.query.sortColumn;
176
192
  const sortDirection = req.query.sortDirection || "asc";
177
193
  const offset = (page - 1) * pageSize;
194
+ const filters = {};
195
+ Object.keys(req.query).forEach((key) => {
196
+ const match = key.match(/^filter\[(.+)\]$/);
197
+ if (match && req.query[key] && String(req.query[key]).trim()) {
198
+ filters[match[1]] = String(req.query[key]).trim();
199
+ }
200
+ });
201
+ console.log("Received filters from query:", filters);
202
+ console.log("All query params:", req.query);
178
203
  const pool = getConnection();
179
204
  if (!pool || !pool.connected) {
180
205
  return res.status(400).json({ error: "Not connected to database" });
181
206
  }
182
- const countQuery = `SELECT COUNT(*) as total FROM [${schema}].[${table}]`;
183
- const countResult = await executeQuery(countQuery);
207
+ const filterColumns = [];
208
+ if (Object.keys(filters).length > 0) {
209
+ try {
210
+ const columnNames = Object.keys(filters);
211
+ const placeholders = columnNames.map((_, i) => `@col${i}`).join(", ");
212
+ const validateQuery = `
213
+ SELECT COLUMN_NAME
214
+ FROM INFORMATION_SCHEMA.COLUMNS
215
+ WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND COLUMN_NAME IN (${placeholders})
216
+ `;
217
+ const validateParams = [
218
+ { name: "schema", value: schema, type: sql.NVarChar },
219
+ { name: "table", value: table, type: sql.NVarChar },
220
+ ...columnNames.map((col, i) => ({ name: `col${i}`, value: col, type: sql.NVarChar }))
221
+ ];
222
+ const validateResult = await executeQuery(validateQuery, validateParams);
223
+ filterColumns.push(...validateResult.map((r) => r.COLUMN_NAME));
224
+ console.log("Validated filter columns:", filterColumns, "from filters:", filters);
225
+ } catch (e) {
226
+ console.error("Error validating filter columns:", e);
227
+ console.error("Filters that failed validation:", filters);
228
+ }
229
+ }
230
+ let whereClause = "";
231
+ const filterParams = [];
232
+ if (filterColumns.length > 0) {
233
+ const validFilters = filterColumns.filter((col) => {
234
+ const filterValue = filters[col];
235
+ return filterValue && filterValue.trim() !== "";
236
+ });
237
+ if (validFilters.length > 0) {
238
+ const whereConditions = validFilters.map((col, index) => {
239
+ const filterValue = filters[col];
240
+ filterParams.push({ name: `filter${index}`, value: `%${filterValue.trim()}%`, type: sql.NVarChar });
241
+ return `[${col}] LIKE @filter${index}`;
242
+ });
243
+ whereClause = `WHERE ${whereConditions.join(" AND ")}`;
244
+ console.log("Applying WHERE clause:", whereClause);
245
+ console.log("Filter params:", filterParams);
246
+ console.log("Valid filters:", validFilters);
247
+ }
248
+ }
249
+ const countQuery = `SELECT COUNT(*) as total FROM [${schema}].[${table}]${whereClause ? " " + whereClause : ""}`;
250
+ const countResult = await executeQuery(countQuery, filterParams.length > 0 ? filterParams : []);
184
251
  const total = countResult[0]?.total || 0;
185
252
  let orderByColumn = sortColumn || "";
186
253
  let orderByDirection = sortDirection?.toUpperCase() === "DESC" ? "DESC" : "ASC";
@@ -224,24 +291,26 @@ tableRoutes.get("/:schema/:table/data", async (req, res) => {
224
291
  let data;
225
292
  let generatedQuery = "";
226
293
  if (orderByColumn) {
227
- generatedQuery = `SELECT * FROM [${schema}].[${table}]
294
+ generatedQuery = `SELECT * FROM [${schema}].[${table}]${whereClause ? "\n" + whereClause : ""}
228
295
  ORDER BY [${orderByColumn}] ${orderByDirection}
229
296
  OFFSET ${offset} ROWS
230
297
  FETCH NEXT ${pageSize} ROWS ONLY`;
231
298
  const dataQuery = `
232
299
  SELECT * FROM [${schema}].[${table}]
300
+ ${whereClause}
233
301
  ORDER BY [${orderByColumn}] ${orderByDirection}
234
302
  OFFSET @offset ROWS
235
303
  FETCH NEXT @pageSize ROWS ONLY
236
304
  `;
237
305
  data = await executeQuery(dataQuery, [
238
306
  { name: "offset", value: offset, type: sql.Int },
239
- { name: "pageSize", value: pageSize, type: sql.Int }
307
+ { name: "pageSize", value: pageSize, type: sql.Int },
308
+ ...filterParams
240
309
  ]);
241
310
  } else {
242
311
  generatedQuery = `SELECT * FROM (
243
312
  SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as rn
244
- FROM [${schema}].[${table}]
313
+ FROM [${schema}].[${table}]${whereClause ? "\n " + whereClause : ""}
245
314
  ) t
246
315
  WHERE rn > ${offset} AND rn <= ${offset + pageSize}
247
316
  ORDER BY rn`;
@@ -249,13 +318,15 @@ ORDER BY rn`;
249
318
  SELECT * FROM (
250
319
  SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as rn
251
320
  FROM [${schema}].[${table}]
321
+ ${whereClause}
252
322
  ) t
253
323
  WHERE rn > @offset AND rn <= @offset + @pageSize
254
324
  ORDER BY rn
255
325
  `;
256
326
  data = await executeQuery(dataQuery, [
257
327
  { name: "offset", value: offset, type: sql.Int },
258
- { name: "pageSize", value: pageSize, type: sql.Int }
328
+ { name: "pageSize", value: pageSize, type: sql.Int },
329
+ ...filterParams
259
330
  ]);
260
331
  data = data.map((row) => {
261
332
  const { rn, ...rest } = row;
@@ -274,7 +345,11 @@ ORDER BY rn`;
274
345
  });
275
346
  } catch (error) {
276
347
  console.error("Error fetching table data:", error);
277
- const errorMessage = error.message || "Failed to fetch table data";
348
+ const errorMessage = error.message || "";
349
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
350
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
351
+ await disconnect2();
352
+ }
278
353
  const errorDetails = error.originalError?.message || error.originalError?.info?.message || "";
279
354
  res.status(500).json({
280
355
  error: errorMessage,
@@ -299,17 +374,29 @@ queryRoutes.post("/", async (req, res) => {
299
374
  });
300
375
  }
301
376
  const dangerousKeywords = ["DROP", "DELETE", "INSERT", "UPDATE", "ALTER", "CREATE", "TRUNCATE", "EXEC", "EXECUTE"];
302
- const hasDangerousKeyword = dangerousKeywords.some(
303
- (keyword) => trimmedQuery.includes(keyword)
304
- );
377
+ const hasDangerousKeyword = dangerousKeywords.some((keyword) => {
378
+ const regex = new RegExp(`\\b${keyword}\\b`, "i");
379
+ return regex.test(sqlQuery);
380
+ });
305
381
  if (hasDangerousKeyword) {
306
382
  return res.status(400).json({
307
383
  error: "Query contains prohibited keywords. Only SELECT queries are allowed."
308
384
  });
309
385
  }
310
- const result = await executeQuery(sqlQuery);
311
- res.json({ data: result });
386
+ const startTime = Date.now();
387
+ const resultSets = await executeQueryMultiple(sqlQuery);
388
+ const executionTime = Date.now() - startTime;
389
+ res.json({
390
+ data: resultSets[0] || [],
391
+ resultSets: resultSets.length > 0 ? resultSets : [],
392
+ executionTime
393
+ });
312
394
  } catch (error) {
395
+ const errorMessage = error.message || "";
396
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
397
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
398
+ await disconnect2();
399
+ }
313
400
  res.status(500).json({
314
401
  error: error.message || "Query execution failed",
315
402
  details: error.originalError?.message
package/dist/cli/index.js CHANGED
@@ -4,9 +4,10 @@ import {
4
4
  connect,
5
5
  disconnect,
6
6
  executeQuery,
7
+ executeQueryMultiple,
7
8
  getConnection,
8
9
  testConnection
9
- } from "./chunk-PTI2CUG6.js";
10
+ } from "./chunk-5X2YZYYM.js";
10
11
 
11
12
  // src/cli/index.ts
12
13
  import { Command } from "commander";
@@ -90,15 +91,20 @@ connectionRoutes.delete("/", async (req, res) => {
90
91
  });
91
92
  connectionRoutes.get("/status", async (req, res) => {
92
93
  try {
93
- const { getConnection: getConnection2, executeQuery: executeQuery2 } = await import("./mssql-5VFXLOGV.js");
94
+ const { getConnection: getConnection2, executeQuery: executeQuery3 } = await import("./mssql-D7NDIUG7.js");
94
95
  const pool = getConnection2();
95
96
  if (pool && pool.connected) {
96
97
  try {
97
- const result = await executeQuery2("SELECT DB_NAME() as databaseName");
98
+ const result = await executeQuery3("SELECT DB_NAME() as databaseName");
98
99
  const databaseName = result[0]?.databaseName || null;
99
100
  res.json({ connected: true, databaseName });
100
- } catch {
101
- res.json({ connected: true, databaseName: null });
101
+ } catch (error) {
102
+ const errorMessage = error.message || "";
103
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
104
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
105
+ await disconnect2();
106
+ }
107
+ res.json({ connected: false });
102
108
  }
103
109
  } else {
104
110
  res.json({ connected: false });
@@ -129,6 +135,11 @@ tableRoutes.get("/", async (req, res) => {
129
135
  const result = await executeQuery(query);
130
136
  res.json(result);
131
137
  } catch (error) {
138
+ const errorMessage = error.message || "";
139
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
140
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
141
+ await disconnect2();
142
+ }
132
143
  res.status(500).json({ error: error.message || "Failed to fetch tables" });
133
144
  }
134
145
  });
@@ -167,6 +178,11 @@ tableRoutes.get("/:schema/:table", async (req, res) => {
167
178
  ]);
168
179
  res.json(result);
169
180
  } catch (error) {
181
+ const errorMessage = error.message || "";
182
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
183
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
184
+ await disconnect2();
185
+ }
170
186
  res.status(500).json({ error: error.message || "Failed to fetch table structure" });
171
187
  }
172
188
  });
@@ -178,12 +194,63 @@ tableRoutes.get("/:schema/:table/data", async (req, res) => {
178
194
  const sortColumn = req.query.sortColumn;
179
195
  const sortDirection = req.query.sortDirection || "asc";
180
196
  const offset = (page - 1) * pageSize;
197
+ const filters = {};
198
+ Object.keys(req.query).forEach((key) => {
199
+ const match = key.match(/^filter\[(.+)\]$/);
200
+ if (match && req.query[key] && String(req.query[key]).trim()) {
201
+ filters[match[1]] = String(req.query[key]).trim();
202
+ }
203
+ });
204
+ console.log("Received filters from query:", filters);
205
+ console.log("All query params:", req.query);
181
206
  const pool = getConnection();
182
207
  if (!pool || !pool.connected) {
183
208
  return res.status(400).json({ error: "Not connected to database" });
184
209
  }
185
- const countQuery = `SELECT COUNT(*) as total FROM [${schema}].[${table}]`;
186
- const countResult = await executeQuery(countQuery);
210
+ const filterColumns = [];
211
+ if (Object.keys(filters).length > 0) {
212
+ try {
213
+ const columnNames = Object.keys(filters);
214
+ const placeholders = columnNames.map((_, i) => `@col${i}`).join(", ");
215
+ const validateQuery = `
216
+ SELECT COLUMN_NAME
217
+ FROM INFORMATION_SCHEMA.COLUMNS
218
+ WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND COLUMN_NAME IN (${placeholders})
219
+ `;
220
+ const validateParams = [
221
+ { name: "schema", value: schema, type: sql.NVarChar },
222
+ { name: "table", value: table, type: sql.NVarChar },
223
+ ...columnNames.map((col, i) => ({ name: `col${i}`, value: col, type: sql.NVarChar }))
224
+ ];
225
+ const validateResult = await executeQuery(validateQuery, validateParams);
226
+ filterColumns.push(...validateResult.map((r) => r.COLUMN_NAME));
227
+ console.log("Validated filter columns:", filterColumns, "from filters:", filters);
228
+ } catch (e) {
229
+ console.error("Error validating filter columns:", e);
230
+ console.error("Filters that failed validation:", filters);
231
+ }
232
+ }
233
+ let whereClause = "";
234
+ const filterParams = [];
235
+ if (filterColumns.length > 0) {
236
+ const validFilters = filterColumns.filter((col) => {
237
+ const filterValue = filters[col];
238
+ return filterValue && filterValue.trim() !== "";
239
+ });
240
+ if (validFilters.length > 0) {
241
+ const whereConditions = validFilters.map((col, index) => {
242
+ const filterValue = filters[col];
243
+ filterParams.push({ name: `filter${index}`, value: `%${filterValue.trim()}%`, type: sql.NVarChar });
244
+ return `[${col}] LIKE @filter${index}`;
245
+ });
246
+ whereClause = `WHERE ${whereConditions.join(" AND ")}`;
247
+ console.log("Applying WHERE clause:", whereClause);
248
+ console.log("Filter params:", filterParams);
249
+ console.log("Valid filters:", validFilters);
250
+ }
251
+ }
252
+ const countQuery = `SELECT COUNT(*) as total FROM [${schema}].[${table}]${whereClause ? " " + whereClause : ""}`;
253
+ const countResult = await executeQuery(countQuery, filterParams.length > 0 ? filterParams : []);
187
254
  const total = countResult[0]?.total || 0;
188
255
  let orderByColumn = sortColumn || "";
189
256
  let orderByDirection = sortDirection?.toUpperCase() === "DESC" ? "DESC" : "ASC";
@@ -227,24 +294,26 @@ tableRoutes.get("/:schema/:table/data", async (req, res) => {
227
294
  let data;
228
295
  let generatedQuery = "";
229
296
  if (orderByColumn) {
230
- generatedQuery = `SELECT * FROM [${schema}].[${table}]
297
+ generatedQuery = `SELECT * FROM [${schema}].[${table}]${whereClause ? "\n" + whereClause : ""}
231
298
  ORDER BY [${orderByColumn}] ${orderByDirection}
232
299
  OFFSET ${offset} ROWS
233
300
  FETCH NEXT ${pageSize} ROWS ONLY`;
234
301
  const dataQuery = `
235
302
  SELECT * FROM [${schema}].[${table}]
303
+ ${whereClause}
236
304
  ORDER BY [${orderByColumn}] ${orderByDirection}
237
305
  OFFSET @offset ROWS
238
306
  FETCH NEXT @pageSize ROWS ONLY
239
307
  `;
240
308
  data = await executeQuery(dataQuery, [
241
309
  { name: "offset", value: offset, type: sql.Int },
242
- { name: "pageSize", value: pageSize, type: sql.Int }
310
+ { name: "pageSize", value: pageSize, type: sql.Int },
311
+ ...filterParams
243
312
  ]);
244
313
  } else {
245
314
  generatedQuery = `SELECT * FROM (
246
315
  SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as rn
247
- FROM [${schema}].[${table}]
316
+ FROM [${schema}].[${table}]${whereClause ? "\n " + whereClause : ""}
248
317
  ) t
249
318
  WHERE rn > ${offset} AND rn <= ${offset + pageSize}
250
319
  ORDER BY rn`;
@@ -252,13 +321,15 @@ ORDER BY rn`;
252
321
  SELECT * FROM (
253
322
  SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as rn
254
323
  FROM [${schema}].[${table}]
324
+ ${whereClause}
255
325
  ) t
256
326
  WHERE rn > @offset AND rn <= @offset + @pageSize
257
327
  ORDER BY rn
258
328
  `;
259
329
  data = await executeQuery(dataQuery, [
260
330
  { name: "offset", value: offset, type: sql.Int },
261
- { name: "pageSize", value: pageSize, type: sql.Int }
331
+ { name: "pageSize", value: pageSize, type: sql.Int },
332
+ ...filterParams
262
333
  ]);
263
334
  data = data.map((row) => {
264
335
  const { rn, ...rest } = row;
@@ -277,7 +348,11 @@ ORDER BY rn`;
277
348
  });
278
349
  } catch (error) {
279
350
  console.error("Error fetching table data:", error);
280
- const errorMessage = error.message || "Failed to fetch table data";
351
+ const errorMessage = error.message || "";
352
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
353
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
354
+ await disconnect2();
355
+ }
281
356
  const errorDetails = error.originalError?.message || error.originalError?.info?.message || "";
282
357
  res.status(500).json({
283
358
  error: errorMessage,
@@ -302,17 +377,29 @@ queryRoutes.post("/", async (req, res) => {
302
377
  });
303
378
  }
304
379
  const dangerousKeywords = ["DROP", "DELETE", "INSERT", "UPDATE", "ALTER", "CREATE", "TRUNCATE", "EXEC", "EXECUTE"];
305
- const hasDangerousKeyword = dangerousKeywords.some(
306
- (keyword) => trimmedQuery.includes(keyword)
307
- );
380
+ const hasDangerousKeyword = dangerousKeywords.some((keyword) => {
381
+ const regex = new RegExp(`\\b${keyword}\\b`, "i");
382
+ return regex.test(sqlQuery);
383
+ });
308
384
  if (hasDangerousKeyword) {
309
385
  return res.status(400).json({
310
386
  error: "Query contains prohibited keywords. Only SELECT queries are allowed."
311
387
  });
312
388
  }
313
- const result = await executeQuery(sqlQuery);
314
- res.json({ data: result });
389
+ const startTime = Date.now();
390
+ const resultSets = await executeQueryMultiple(sqlQuery);
391
+ const executionTime = Date.now() - startTime;
392
+ res.json({
393
+ data: resultSets[0] || [],
394
+ resultSets: resultSets.length > 0 ? resultSets : [],
395
+ executionTime
396
+ });
315
397
  } catch (error) {
398
+ const errorMessage = error.message || "";
399
+ if (errorMessage.includes("Login failed") || errorMessage.includes("authentication")) {
400
+ const { disconnect: disconnect2 } = await import("./mssql-D7NDIUG7.js");
401
+ await disconnect2();
402
+ }
316
403
  res.status(500).json({
317
404
  error: error.message || "Query execution failed",
318
405
  details: error.originalError?.message
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ connect,
5
+ disconnect,
6
+ executeQuery,
7
+ executeQueryMultiple,
8
+ getConnection,
9
+ parseConnectionString,
10
+ testConnection
11
+ } from "./chunk-5X2YZYYM.js";
12
+ export {
13
+ connect,
14
+ disconnect,
15
+ executeQuery,
16
+ executeQueryMultiple,
17
+ getConnection,
18
+ parseConnectionString,
19
+ testConnection
20
+ };