sql-dashboard 1.0.0 → 1.0.1

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,76 @@
1
+ import {
2
+ __require
3
+ } from "./chunk-OCL5Y3AH.mjs";
4
+
5
+ // src/export/csv.ts
6
+ function toCSV(result, options = {}) {
7
+ const {
8
+ delimiter = ",",
9
+ includeHeader = true,
10
+ quoteAll = true,
11
+ nullValue = "NULL"
12
+ } = options;
13
+ const lines = [];
14
+ if (includeHeader && result.columns.length > 0) {
15
+ lines.push(result.columns.map((col) => formatCSVField(col, delimiter, quoteAll)).join(delimiter));
16
+ }
17
+ for (const row of result.rows) {
18
+ const line = result.columns.map((col) => {
19
+ const value = row[col];
20
+ if (value === null || value === void 0) return nullValue;
21
+ return formatCSVField(String(value), delimiter, quoteAll);
22
+ });
23
+ lines.push(line.join(delimiter));
24
+ }
25
+ return lines.join("\r\n");
26
+ }
27
+ function formatCSVField(value, delimiter, quoteAll) {
28
+ const needsQuoting = quoteAll || value.includes(delimiter) || value.includes('"') || value.includes("\n") || value.includes("\r");
29
+ if (needsQuoting) {
30
+ return `"${value.replace(/"/g, '""')}"`;
31
+ }
32
+ return value;
33
+ }
34
+ function toCSVStream(result, options = {}) {
35
+ const { Readable } = __require("stream");
36
+ const csv = toCSV(result, options);
37
+ const stream = new Readable();
38
+ stream.push(csv);
39
+ stream.push(null);
40
+ return stream;
41
+ }
42
+
43
+ // src/export/json.ts
44
+ function toJSON(result, options = {}) {
45
+ const {
46
+ pretty = true,
47
+ indent = 2,
48
+ includeMeta = false
49
+ } = options;
50
+ if (includeMeta) {
51
+ return JSON.stringify({
52
+ meta: {
53
+ rowCount: result.rowCount,
54
+ columns: result.columns,
55
+ duration: result.duration,
56
+ status: result.status
57
+ },
58
+ data: result.rows
59
+ }, null, pretty ? indent : void 0);
60
+ }
61
+ return JSON.stringify(result.rows, null, pretty ? indent : void 0);
62
+ }
63
+ function toJSONLines(result) {
64
+ return result.rows.map((row) => JSON.stringify(row)).join("\n");
65
+ }
66
+ function toJSONArray(result) {
67
+ return JSON.stringify(result.rows);
68
+ }
69
+
70
+ export {
71
+ toCSV,
72
+ toCSVStream,
73
+ toJSON,
74
+ toJSONLines,
75
+ toJSONArray
76
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MTCZXLV5.mjs";
4
4
  import {
5
5
  MySQLDriver
6
- } from "./chunk-7YLO3OSN.mjs";
6
+ } from "./chunk-62XBCHG5.mjs";
7
7
  import {
8
8
  PostgresDriver
9
9
  } from "./chunk-YGKUVVJT.mjs";
@@ -308,6 +308,12 @@ var SchemaBrowser = class {
308
308
  };
309
309
 
310
310
  // src/utils/pagination.ts
311
+ function calculatePagination(params) {
312
+ const page = Math.max(1, params.page ?? 1);
313
+ const pageSize = Math.min(Math.max(1, params.pageSize ?? 50), 1e3);
314
+ const offset = params.offset ?? (page - 1) * pageSize;
315
+ return { limit: pageSize, offset };
316
+ }
311
317
  function createPaginatedResult(data, total, params) {
312
318
  const page = Math.max(1, params.page ?? 1);
313
319
  const pageSize = Math.min(Math.max(1, params.pageSize ?? 50), 1e3);
@@ -657,7 +663,7 @@ function extractTableNames(sql) {
657
663
  }
658
664
  function validateQuery(sql, security) {
659
665
  const errors = [];
660
- const trimmedSql = sql.trim();
666
+ let trimmedSql = sql.trim();
661
667
  if (!trimmedSql) {
662
668
  errors.push({
663
669
  code: "EMPTY_QUERY",
@@ -667,7 +673,7 @@ function validateQuery(sql, security) {
667
673
  return { valid: false, errors, normalizedQuery: sql, statementType: "UNKNOWN", isReadOnly: true, tables: [] };
668
674
  }
669
675
  if (!trimmedSql.endsWith(";")) {
670
- trimmedSql + ";";
676
+ trimmedSql = trimmedSql + ";";
671
677
  }
672
678
  const statementType = detectStatementType(trimmedSql);
673
679
  const detectedTables = extractTableNames(trimmedSql);
@@ -761,6 +767,9 @@ function detectInjection(sql) {
761
767
  }
762
768
  return false;
763
769
  }
770
+ function sanitizeIdentifier(name) {
771
+ return name.replace(/[^a-zA-Z0-9_$]/g, "").replace(/^(\d)/, "_$1");
772
+ }
764
773
  function prepareBatchQueries(sql) {
765
774
  const sanitized = sanitizeComment(sql);
766
775
  const queries = sanitized.split(";").map((q) => q.trim()).filter((q) => q.length > 0).map((q) => q + ";");
@@ -768,6 +777,180 @@ function prepareBatchQueries(sql) {
768
777
  }
769
778
 
770
779
  // src/core/formatter.ts
780
+ function formatSQL(sql, options = {}) {
781
+ const {
782
+ uppercase = true,
783
+ indent = " "
784
+ } = options;
785
+ let formatted = sql.trim();
786
+ if (uppercase) {
787
+ formatted = uppercaseKeywords(formatted);
788
+ }
789
+ formatted = formatClauses(formatted, indent);
790
+ formatted = formatParentheses(formatted, indent);
791
+ formatted = formatCommas(formatted);
792
+ formatted = formatOperators(formatted);
793
+ return formatted;
794
+ }
795
+ var KEYWORDS = [
796
+ "SELECT",
797
+ "FROM",
798
+ "WHERE",
799
+ "AND",
800
+ "OR",
801
+ "NOT",
802
+ "IN",
803
+ "IS",
804
+ "NULL",
805
+ "LIKE",
806
+ "BETWEEN",
807
+ "EXISTS",
808
+ "HAVING",
809
+ "GROUP BY",
810
+ "ORDER BY",
811
+ "LIMIT",
812
+ "OFFSET",
813
+ "JOIN",
814
+ "LEFT JOIN",
815
+ "RIGHT JOIN",
816
+ "INNER JOIN",
817
+ "OUTER JOIN",
818
+ "FULL JOIN",
819
+ "CROSS JOIN",
820
+ "ON",
821
+ "AS",
822
+ "INSERT INTO",
823
+ "VALUES",
824
+ "UPDATE",
825
+ "SET",
826
+ "DELETE FROM",
827
+ "CREATE TABLE",
828
+ "ALTER TABLE",
829
+ "DROP TABLE",
830
+ "TRUNCATE TABLE",
831
+ "CREATE INDEX",
832
+ "DROP INDEX",
833
+ "CREATE VIEW",
834
+ "DROP VIEW",
835
+ "UNION",
836
+ "UNION ALL",
837
+ "INTERSECT",
838
+ "EXCEPT",
839
+ "CASE",
840
+ "WHEN",
841
+ "THEN",
842
+ "ELSE",
843
+ "END",
844
+ "ASC",
845
+ "DESC",
846
+ "DISTINCT",
847
+ "ALL",
848
+ "TOP",
849
+ "WITH",
850
+ "RECURSIVE",
851
+ "RETURNING",
852
+ "BEGIN",
853
+ "COMMIT",
854
+ "ROLLBACK",
855
+ "SAVEPOINT"
856
+ ];
857
+ function uppercaseKeywords(sql) {
858
+ const pattern = new RegExp(`\\b(${KEYWORDS.join("|")})\\b`, "gi");
859
+ return sql.replace(pattern, (match) => match.toUpperCase());
860
+ }
861
+ function formatClauses(sql, indent) {
862
+ const clausePatterns = [
863
+ "SELECT",
864
+ "FROM",
865
+ "WHERE",
866
+ "GROUP BY",
867
+ "HAVING",
868
+ "ORDER BY",
869
+ "LIMIT",
870
+ "OFFSET",
871
+ "INSERT INTO",
872
+ "VALUES",
873
+ "UPDATE",
874
+ "SET",
875
+ "DELETE FROM"
876
+ ];
877
+ for (const clause of clausePatterns) {
878
+ const regex = new RegExp(`\\b${clause}\\b`, "i");
879
+ sql = sql.replace(regex, `
880
+ ${clause}`);
881
+ }
882
+ const joinPatterns = [
883
+ "JOIN",
884
+ "LEFT JOIN",
885
+ "RIGHT JOIN",
886
+ "INNER JOIN",
887
+ "OUTER JOIN",
888
+ "FULL JOIN",
889
+ "CROSS JOIN",
890
+ "UNION",
891
+ "UNION ALL",
892
+ "INTERSECT",
893
+ "EXCEPT"
894
+ ];
895
+ for (const clause of joinPatterns) {
896
+ const regex = new RegExp(`\\n${clause}\\b`, "i");
897
+ if (regex.test(sql)) continue;
898
+ const inlineRegex = new RegExp(`\\b${clause}\\b`, "i");
899
+ sql = sql.replace(inlineRegex, `
900
+ ${clause}`);
901
+ }
902
+ const lines = sql.split("\n").map((line) => line.trim());
903
+ return lines.map((line, i) => {
904
+ if (i > 0 && !line.startsWith(indent)) {
905
+ const trimmed = line.trim();
906
+ if (trimmed.length > 0 && !KEYWORDS.some((kw) => trimmed.toUpperCase().startsWith(kw))) {
907
+ return indent + line;
908
+ }
909
+ }
910
+ return line || "";
911
+ }).join("\n").replace(/\n{3,}/g, "\n\n");
912
+ }
913
+ function formatParentheses(sql, indent) {
914
+ let depth = 0;
915
+ return sql.split("").map((char) => {
916
+ if (char === "(") {
917
+ depth++;
918
+ return `(
919
+ ${indent.repeat(depth)}`;
920
+ }
921
+ if (char === ")") {
922
+ depth--;
923
+ return `
924
+ ${indent.repeat(depth)})`;
925
+ }
926
+ return char;
927
+ }).join("");
928
+ }
929
+ function formatCommas(sql) {
930
+ return sql.replace(/,\s*/g, ", ");
931
+ }
932
+ function formatOperators(sql) {
933
+ return sql.replace(/\s*=\s*/g, " = ").replace(/\s*!=\s*/g, " != ").replace(/\s*<>\s*/g, " <> ").replace(/\s*>\s*/g, " > ").replace(/\s*<\s*/g, " < ").replace(/\s*>=\s*/g, " >= ").replace(/\s*<=\s*/g, " <= ").replace(/\s*\+\s*/g, " + ").replace(/\s*-\s*/g, " - ");
934
+ }
935
+ function formatResultRow(row, columns) {
936
+ const formatted = {};
937
+ const cols = columns || Object.keys(row);
938
+ for (const col of cols) {
939
+ const value = row[col];
940
+ if (value === null || value === void 0) {
941
+ formatted[col] = "NULL";
942
+ } else if (Buffer.isBuffer(value)) {
943
+ formatted[col] = `[Buffer ${value.length} bytes]`;
944
+ } else if (value instanceof Date) {
945
+ formatted[col] = value.toISOString();
946
+ } else if (typeof value === "object") {
947
+ formatted[col] = JSON.stringify(value);
948
+ } else {
949
+ formatted[col] = value;
950
+ }
951
+ }
952
+ return formatted;
953
+ }
771
954
  function truncateResult(rows, maxRows) {
772
955
  if (rows.length <= maxRows) {
773
956
  return { rows, truncated: false };
@@ -779,7 +962,7 @@ function truncateResult(rows, maxRows) {
779
962
  var SQLDashboard = class extends EventEmitter {
780
963
  constructor(options) {
781
964
  super();
782
- this.version = "1.0.0";
965
+ this.version = "1.0.1";
783
966
  this.connected = false;
784
967
  this.connectionPromise = null;
785
968
  this.config = {
@@ -1027,7 +1210,22 @@ var SQLDashboard = class extends EventEmitter {
1027
1210
  this.removeAllListeners();
1028
1211
  }
1029
1212
  };
1213
+ function createDashboard(options) {
1214
+ return new SQLDashboard(options);
1215
+ }
1030
1216
 
1031
1217
  export {
1032
- SQLDashboard
1218
+ calculatePagination,
1219
+ createPaginatedResult,
1220
+ ReadOnlyGuard,
1221
+ RateLimiter,
1222
+ Logger,
1223
+ detectStatementType,
1224
+ validateQuery,
1225
+ detectInjection,
1226
+ sanitizeIdentifier,
1227
+ formatSQL,
1228
+ formatResultRow,
1229
+ SQLDashboard,
1230
+ createDashboard
1033
1231
  };
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }