@eamonboyle/mssql-mcp 1.1.0 → 1.3.0
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/README.md +169 -22
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +74 -0
- package/dist/config.js.map +1 -0
- package/dist/db.d.ts +29 -24
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +144 -112
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +382 -122
- package/dist/index.js.map +1 -1
- package/dist/mcpResults.d.ts +49 -0
- package/dist/mcpResults.d.ts.map +1 -0
- package/dist/mcpResults.js +246 -0
- package/dist/mcpResults.js.map +1 -0
- package/dist/promptRegistry.d.ts +16 -0
- package/dist/promptRegistry.d.ts.map +1 -0
- package/dist/promptRegistry.js +112 -0
- package/dist/promptRegistry.js.map +1 -0
- package/dist/resourceRegistry.d.ts +14 -0
- package/dist/resourceRegistry.d.ts.map +1 -0
- package/dist/resourceRegistry.js +311 -0
- package/dist/resourceRegistry.js.map +1 -0
- package/dist/schema.d.ts +57 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +390 -0
- package/dist/schema.js.map +1 -0
- package/dist/serverState.d.ts +28 -0
- package/dist/serverState.d.ts.map +1 -0
- package/dist/serverState.js +99 -0
- package/dist/serverState.js.map +1 -0
- package/dist/sql.d.ts +7 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +73 -0
- package/dist/sql.js.map +1 -0
- package/dist/toolRegistry.d.ts +20 -0
- package/dist/toolRegistry.d.ts.map +1 -0
- package/dist/toolRegistry.js +547 -0
- package/dist/toolRegistry.js.map +1 -0
- package/dist/tools/AnalyzeTableTool.d.ts +37 -0
- package/dist/tools/AnalyzeTableTool.d.ts.map +1 -0
- package/dist/tools/AnalyzeTableTool.js +81 -0
- package/dist/tools/AnalyzeTableTool.js.map +1 -0
- package/dist/tools/CreateIndexTool.d.ts +30 -23
- package/dist/tools/CreateIndexTool.d.ts.map +1 -1
- package/dist/tools/CreateIndexTool.js +47 -77
- package/dist/tools/CreateIndexTool.js.map +1 -1
- package/dist/tools/CreateTableTool.d.ts +18 -11
- package/dist/tools/CreateTableTool.d.ts.map +1 -1
- package/dist/tools/CreateTableTool.js +37 -61
- package/dist/tools/CreateTableTool.js.map +1 -1
- package/dist/tools/DeleteDataTool.d.ts +22 -0
- package/dist/tools/DeleteDataTool.d.ts.map +1 -0
- package/dist/tools/DeleteDataTool.js +38 -0
- package/dist/tools/DeleteDataTool.js.map +1 -0
- package/dist/tools/DescribeObjectTool.d.ts +21 -0
- package/dist/tools/DescribeObjectTool.d.ts.map +1 -0
- package/dist/tools/DescribeObjectTool.js +31 -0
- package/dist/tools/DescribeObjectTool.js.map +1 -0
- package/dist/tools/DescribeRelationshipsTool.d.ts +20 -0
- package/dist/tools/DescribeRelationshipsTool.d.ts.map +1 -0
- package/dist/tools/DescribeRelationshipsTool.js +24 -0
- package/dist/tools/DescribeRelationshipsTool.js.map +1 -0
- package/dist/tools/DescribeTableTool.d.ts +19 -20
- package/dist/tools/DescribeTableTool.d.ts.map +1 -1
- package/dist/tools/DescribeTableTool.js +23 -44
- package/dist/tools/DescribeTableTool.js.map +1 -1
- package/dist/tools/DropTableTool.d.ts +13 -11
- package/dist/tools/DropTableTool.d.ts.map +1 -1
- package/dist/tools/DropTableTool.js +30 -44
- package/dist/tools/DropTableTool.js.map +1 -1
- package/dist/tools/ExplainQueryTool.d.ts +32 -0
- package/dist/tools/ExplainQueryTool.d.ts.map +1 -0
- package/dist/tools/ExplainQueryTool.js +102 -0
- package/dist/tools/ExplainQueryTool.js.map +1 -0
- package/dist/tools/InsertDataTool.d.ts +20 -16
- package/dist/tools/InsertDataTool.d.ts.map +1 -1
- package/dist/tools/InsertDataTool.js +91 -108
- package/dist/tools/InsertDataTool.js.map +1 -1
- package/dist/tools/ListDatabasesTool.d.ts +16 -0
- package/dist/tools/ListDatabasesTool.d.ts.map +1 -0
- package/dist/tools/ListDatabasesTool.js +26 -0
- package/dist/tools/ListDatabasesTool.js.map +1 -0
- package/dist/tools/ListForeignKeysTool.d.ts +19 -0
- package/dist/tools/ListForeignKeysTool.d.ts.map +1 -0
- package/dist/tools/ListForeignKeysTool.js +24 -0
- package/dist/tools/ListForeignKeysTool.js.map +1 -0
- package/dist/tools/ListObjectsTool.d.ts +20 -0
- package/dist/tools/ListObjectsTool.d.ts.map +1 -0
- package/dist/tools/ListObjectsTool.js +26 -0
- package/dist/tools/ListObjectsTool.js.map +1 -0
- package/dist/tools/ListTableTool.d.ts +20 -16
- package/dist/tools/ListTableTool.d.ts.map +1 -1
- package/dist/tools/ListTableTool.js +32 -51
- package/dist/tools/ListTableTool.js.map +1 -1
- package/dist/tools/PreviewDeleteTool.d.ts +28 -0
- package/dist/tools/PreviewDeleteTool.d.ts.map +1 -0
- package/dist/tools/PreviewDeleteTool.js +31 -0
- package/dist/tools/PreviewDeleteTool.js.map +1 -0
- package/dist/tools/PreviewUpdateTool.d.ts +30 -0
- package/dist/tools/PreviewUpdateTool.d.ts.map +1 -0
- package/dist/tools/PreviewUpdateTool.js +34 -0
- package/dist/tools/PreviewUpdateTool.js.map +1 -0
- package/dist/tools/ReadDataTool.d.ts +35 -33
- package/dist/tools/ReadDataTool.d.ts.map +1 -1
- package/dist/tools/ReadDataTool.js +92 -105
- package/dist/tools/ReadDataTool.js.map +1 -1
- package/dist/tools/SearchDataTool.d.ts +27 -0
- package/dist/tools/SearchDataTool.d.ts.map +1 -0
- package/dist/tools/SearchDataTool.js +61 -0
- package/dist/tools/SearchDataTool.js.map +1 -0
- package/dist/tools/UpdateDataTool.d.ts +22 -16
- package/dist/tools/UpdateDataTool.d.ts.map +1 -1
- package/dist/tools/UpdateDataTool.js +48 -65
- package/dist/tools/UpdateDataTool.js.map +1 -1
- package/dist/validation.d.ts +13 -13
- package/dist/validation.js +133 -133
- package/dist/validation.js.map +1 -1
- package/dist/writePreview.d.ts +20 -0
- package/dist/writePreview.d.ts.map +1 -0
- package/dist/writePreview.js +27 -0
- package/dist/writePreview.js.map +1 -0
- package/dist/writePreviewGrant.d.ts +18 -0
- package/dist/writePreviewGrant.d.ts.map +1 -0
- package/dist/writePreviewGrant.js +71 -0
- package/dist/writePreviewGrant.js.map +1 -0
- package/dist/writePreviewGrantStore.d.ts +10 -0
- package/dist/writePreviewGrantStore.d.ts.map +1 -0
- package/dist/writePreviewGrantStore.js +47 -0
- package/dist/writePreviewGrantStore.js.map +1 -0
- package/dist/writeSafety.d.ts +21 -0
- package/dist/writeSafety.d.ts.map +1 -0
- package/dist/writeSafety.js +169 -0
- package/dist/writeSafety.js.map +1 -0
- package/package.json +6 -5
- package/dist/__tests__/db.test.d.ts +0 -2
- package/dist/__tests__/db.test.d.ts.map +0 -1
- package/dist/__tests__/db.test.js +0 -204
- package/dist/__tests__/db.test.js.map +0 -1
- package/dist/__tests__/validation.test.d.ts +0 -2
- package/dist/__tests__/validation.test.d.ts.map +0 -1
- package/dist/__tests__/validation.test.js +0 -111
- package/dist/__tests__/validation.test.js.map +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { quoteIdentifier } from "./sql.js";
|
|
2
|
+
export const SQL_FILTER_OPERATORS = [
|
|
3
|
+
"=",
|
|
4
|
+
"!=",
|
|
5
|
+
">",
|
|
6
|
+
">=",
|
|
7
|
+
"<",
|
|
8
|
+
"<=",
|
|
9
|
+
"LIKE",
|
|
10
|
+
"IN",
|
|
11
|
+
"IS NULL",
|
|
12
|
+
"IS NOT NULL",
|
|
13
|
+
];
|
|
14
|
+
const FILTER_OPERATOR_SET = new Set(SQL_FILTER_OPERATORS);
|
|
15
|
+
const LENGTH_TYPES = new Set([
|
|
16
|
+
"binary",
|
|
17
|
+
"char",
|
|
18
|
+
"nchar",
|
|
19
|
+
"nvarchar",
|
|
20
|
+
"varbinary",
|
|
21
|
+
"varchar",
|
|
22
|
+
]);
|
|
23
|
+
const PRECISION_SCALE_TYPES = new Set(["decimal", "numeric"]);
|
|
24
|
+
const OPTIONAL_PRECISION_TYPES = new Set(["float"]);
|
|
25
|
+
const OPTIONAL_SCALE_TYPES = new Set(["datetime2", "datetimeoffset", "time"]);
|
|
26
|
+
const SIMPLE_TYPES = new Set([
|
|
27
|
+
"bigint",
|
|
28
|
+
"bit",
|
|
29
|
+
"date",
|
|
30
|
+
"datetime",
|
|
31
|
+
"image",
|
|
32
|
+
"int",
|
|
33
|
+
"money",
|
|
34
|
+
"ntext",
|
|
35
|
+
"real",
|
|
36
|
+
"smalldatetime",
|
|
37
|
+
"smallint",
|
|
38
|
+
"smallmoney",
|
|
39
|
+
"sql_variant",
|
|
40
|
+
"text",
|
|
41
|
+
"tinyint",
|
|
42
|
+
"uniqueidentifier",
|
|
43
|
+
"xml",
|
|
44
|
+
]);
|
|
45
|
+
function assertPositiveInteger(value, label) {
|
|
46
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
47
|
+
throw new Error(`Invalid ${label}.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function normalizeTypeParameterList(typeName, params) {
|
|
51
|
+
if (LENGTH_TYPES.has(typeName)) {
|
|
52
|
+
const normalized = params.trim().toUpperCase();
|
|
53
|
+
if (normalized === "MAX") {
|
|
54
|
+
return "(MAX)";
|
|
55
|
+
}
|
|
56
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
57
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
58
|
+
throw new Error(`Invalid length for SQL type '${typeName}'.`);
|
|
59
|
+
}
|
|
60
|
+
return `(${parsed})`;
|
|
61
|
+
}
|
|
62
|
+
if (PRECISION_SCALE_TYPES.has(typeName)) {
|
|
63
|
+
const match = params.match(/^\s*(\d+)\s*,\s*(\d+)\s*$/);
|
|
64
|
+
if (!match) {
|
|
65
|
+
throw new Error(`Invalid precision/scale for SQL type '${typeName}'.`);
|
|
66
|
+
}
|
|
67
|
+
return `(${Number.parseInt(match[1], 10)}, ${Number.parseInt(match[2], 10)})`;
|
|
68
|
+
}
|
|
69
|
+
if (OPTIONAL_PRECISION_TYPES.has(typeName)) {
|
|
70
|
+
const parsed = Number.parseInt(params.trim(), 10);
|
|
71
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
72
|
+
throw new Error(`Invalid precision for SQL type '${typeName}'.`);
|
|
73
|
+
}
|
|
74
|
+
return `(${parsed})`;
|
|
75
|
+
}
|
|
76
|
+
if (OPTIONAL_SCALE_TYPES.has(typeName)) {
|
|
77
|
+
const parsed = Number.parseInt(params.trim(), 10);
|
|
78
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
79
|
+
throw new Error(`Invalid scale for SQL type '${typeName}'.`);
|
|
80
|
+
}
|
|
81
|
+
return `(${parsed})`;
|
|
82
|
+
}
|
|
83
|
+
throw new Error(`SQL type '${typeName}' does not accept parameters.`);
|
|
84
|
+
}
|
|
85
|
+
export function normalizeSqlType(rawType) {
|
|
86
|
+
if (typeof rawType !== "string" || rawType.trim() === "") {
|
|
87
|
+
throw new Error("Column type is required.");
|
|
88
|
+
}
|
|
89
|
+
const trimmed = rawType.trim();
|
|
90
|
+
const match = trimmed.match(/^([A-Za-z][A-Za-z0-9_]*)(?:\(([^)]+)\))?$/);
|
|
91
|
+
if (!match) {
|
|
92
|
+
throw new Error(`Unsupported SQL type declaration '${rawType}'.`);
|
|
93
|
+
}
|
|
94
|
+
const typeName = match[1].toLowerCase();
|
|
95
|
+
const rawParams = match[2];
|
|
96
|
+
if (!LENGTH_TYPES.has(typeName) &&
|
|
97
|
+
!PRECISION_SCALE_TYPES.has(typeName) &&
|
|
98
|
+
!OPTIONAL_PRECISION_TYPES.has(typeName) &&
|
|
99
|
+
!OPTIONAL_SCALE_TYPES.has(typeName) &&
|
|
100
|
+
!SIMPLE_TYPES.has(typeName)) {
|
|
101
|
+
throw new Error(`Unsupported SQL type '${rawType}'.`);
|
|
102
|
+
}
|
|
103
|
+
if (!rawParams) {
|
|
104
|
+
return typeName.toUpperCase();
|
|
105
|
+
}
|
|
106
|
+
return `${typeName.toUpperCase()}${normalizeTypeParameterList(typeName, rawParams)}`;
|
|
107
|
+
}
|
|
108
|
+
export function buildCreateColumnDefinition(columnName, declaration) {
|
|
109
|
+
const fragments = [quoteIdentifier(columnName), normalizeSqlType(declaration.type)];
|
|
110
|
+
if (declaration.isIdentity) {
|
|
111
|
+
const seed = declaration.identitySeed ?? 1;
|
|
112
|
+
const increment = declaration.identityIncrement ?? 1;
|
|
113
|
+
assertPositiveInteger(seed, "identity seed");
|
|
114
|
+
assertPositiveInteger(increment, "identity increment");
|
|
115
|
+
fragments.push(`IDENTITY(${seed}, ${increment})`);
|
|
116
|
+
}
|
|
117
|
+
if (declaration.isPrimaryKey) {
|
|
118
|
+
fragments.push("PRIMARY KEY");
|
|
119
|
+
}
|
|
120
|
+
else if (declaration.isUnique) {
|
|
121
|
+
fragments.push("UNIQUE");
|
|
122
|
+
}
|
|
123
|
+
if (declaration.nullable === false || declaration.isPrimaryKey) {
|
|
124
|
+
fragments.push("NOT NULL");
|
|
125
|
+
}
|
|
126
|
+
else if (declaration.nullable === true) {
|
|
127
|
+
fragments.push("NULL");
|
|
128
|
+
}
|
|
129
|
+
return fragments.join(" ");
|
|
130
|
+
}
|
|
131
|
+
export function buildParameterizedWhereClause(filters, input, parameterPrefix = "filter") {
|
|
132
|
+
if (!Array.isArray(filters) || filters.length === 0) {
|
|
133
|
+
throw new Error("At least one filter is required.");
|
|
134
|
+
}
|
|
135
|
+
return filters
|
|
136
|
+
.map((filter, index) => {
|
|
137
|
+
const columnName = quoteIdentifier(filter.column);
|
|
138
|
+
const operator = filter.operator;
|
|
139
|
+
if (!FILTER_OPERATOR_SET.has(operator)) {
|
|
140
|
+
throw new Error(`Unsupported filter operator '${operator}'.`);
|
|
141
|
+
}
|
|
142
|
+
switch (operator) {
|
|
143
|
+
case "IS NULL":
|
|
144
|
+
case "IS NOT NULL":
|
|
145
|
+
return `${columnName} ${operator}`;
|
|
146
|
+
case "IN": {
|
|
147
|
+
if (!Array.isArray(filter.values) || filter.values.length === 0) {
|
|
148
|
+
throw new Error(`Filter '${filter.column}' requires a non-empty 'values' array.`);
|
|
149
|
+
}
|
|
150
|
+
const placeholders = filter.values.map((value, valueIndex) => {
|
|
151
|
+
const parameterName = `${parameterPrefix}_${index}_${valueIndex}`;
|
|
152
|
+
input(parameterName, value);
|
|
153
|
+
return `@${parameterName}`;
|
|
154
|
+
});
|
|
155
|
+
return `${columnName} IN (${placeholders.join(", ")})`;
|
|
156
|
+
}
|
|
157
|
+
default: {
|
|
158
|
+
if (!("value" in filter)) {
|
|
159
|
+
throw new Error(`Filter '${filter.column}' requires a 'value'.`);
|
|
160
|
+
}
|
|
161
|
+
const parameterName = `${parameterPrefix}_${index}`;
|
|
162
|
+
input(parameterName, filter.value);
|
|
163
|
+
return `${columnName} ${operator} @${parameterName}`;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
.join(" AND ");
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=writeSafety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeSafety.js","sourceRoot":"","sources":["../src/writeSafety.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eamonboyle/mssql-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MCP server for Microsoft SQL Server - query and manage your database with natural language in Cursor, Claude, and VS Code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"mssql-mcp": "dist/index.js"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "tsc && shx chmod +x dist/*.js",
|
|
29
|
+
"build": "shx rm -rf dist && tsc && shx chmod +x dist/*.js",
|
|
30
30
|
"prepare": "npm run build",
|
|
31
31
|
"watch": "tsc --watch",
|
|
32
32
|
"start": "node dist/index.js",
|
|
@@ -49,14 +49,15 @@
|
|
|
49
49
|
"eslint-config-prettier": "^10.1.8",
|
|
50
50
|
"prettier": "^3.8.1",
|
|
51
51
|
"shx": "^0.3.4",
|
|
52
|
-
"typescript": "^
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
53
|
"typescript-eslint": "^8.55.0",
|
|
54
54
|
"vitest": "^2.1.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
57
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
58
58
|
"dotenv": "^10.0.0",
|
|
59
|
-
"mssql": "^11.0.1"
|
|
59
|
+
"mssql": "^11.0.1",
|
|
60
|
+
"zod": "^4.3.6"
|
|
60
61
|
},
|
|
61
62
|
"type": "module"
|
|
62
63
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"db.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/db.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
-
const mssqlMockState = vi.hoisted(() => ({
|
|
3
|
-
poolConfigs: [],
|
|
4
|
-
requestObject: { kind: "mock-request" },
|
|
5
|
-
connectCalls: vi.fn(),
|
|
6
|
-
closeCalls: vi.fn(),
|
|
7
|
-
requestCalls: vi.fn(),
|
|
8
|
-
}));
|
|
9
|
-
// Mock mssql to avoid loading native deps and transitive issues in test env
|
|
10
|
-
vi.mock("mssql", () => {
|
|
11
|
-
class MockConnectionPool {
|
|
12
|
-
constructor(config) {
|
|
13
|
-
this.config = config;
|
|
14
|
-
this.connected = false;
|
|
15
|
-
mssqlMockState.poolConfigs.push(config);
|
|
16
|
-
}
|
|
17
|
-
async connect() {
|
|
18
|
-
this.connected = true;
|
|
19
|
-
mssqlMockState.connectCalls(this.config);
|
|
20
|
-
return this;
|
|
21
|
-
}
|
|
22
|
-
async close() {
|
|
23
|
-
this.connected = false;
|
|
24
|
-
mssqlMockState.closeCalls(this.config);
|
|
25
|
-
}
|
|
26
|
-
request() {
|
|
27
|
-
mssqlMockState.requestCalls(this.config);
|
|
28
|
-
return mssqlMockState.requestObject;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
default: {
|
|
33
|
-
ConnectionPool: MockConnectionPool,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
import { getAllowedDatabases, getSqlRequest, resolveDatabaseName } from "../db.js";
|
|
38
|
-
describe("getAllowedDatabases", () => {
|
|
39
|
-
const originalEnv = process.env;
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
process.env = { ...originalEnv };
|
|
42
|
-
mssqlMockState.poolConfigs.length = 0;
|
|
43
|
-
mssqlMockState.connectCalls.mockClear();
|
|
44
|
-
mssqlMockState.closeCalls.mockClear();
|
|
45
|
-
mssqlMockState.requestCalls.mockClear();
|
|
46
|
-
});
|
|
47
|
-
afterEach(() => {
|
|
48
|
-
process.env = originalEnv;
|
|
49
|
-
});
|
|
50
|
-
it("returns DATABASE_NAME when DATABASES is not set", () => {
|
|
51
|
-
delete process.env.DATABASES;
|
|
52
|
-
process.env.DATABASE_NAME = "MyDb";
|
|
53
|
-
expect(getAllowedDatabases()).toEqual(["MyDb"]);
|
|
54
|
-
});
|
|
55
|
-
it("returns empty array when neither DATABASES nor DATABASE_NAME is set", () => {
|
|
56
|
-
delete process.env.DATABASES;
|
|
57
|
-
delete process.env.DATABASE_NAME;
|
|
58
|
-
expect(getAllowedDatabases()).toEqual([]);
|
|
59
|
-
});
|
|
60
|
-
it("returns empty array when DATABASE_NAME is empty string", () => {
|
|
61
|
-
delete process.env.DATABASES;
|
|
62
|
-
process.env.DATABASE_NAME = "";
|
|
63
|
-
expect(getAllowedDatabases()).toEqual([]);
|
|
64
|
-
});
|
|
65
|
-
it("returns DATABASES split by comma when set", () => {
|
|
66
|
-
process.env.DATABASES = "ProdDB,StagingDB,AnalyticsDB";
|
|
67
|
-
expect(getAllowedDatabases()).toEqual([
|
|
68
|
-
"ProdDB",
|
|
69
|
-
"StagingDB",
|
|
70
|
-
"AnalyticsDB",
|
|
71
|
-
]);
|
|
72
|
-
});
|
|
73
|
-
it("trims whitespace from DATABASES entries", () => {
|
|
74
|
-
process.env.DATABASES = " ProdDB , StagingDB , AnalyticsDB ";
|
|
75
|
-
expect(getAllowedDatabases()).toEqual([
|
|
76
|
-
"ProdDB",
|
|
77
|
-
"StagingDB",
|
|
78
|
-
"AnalyticsDB",
|
|
79
|
-
]);
|
|
80
|
-
});
|
|
81
|
-
it("filters out empty entries from DATABASES", () => {
|
|
82
|
-
process.env.DATABASES = "ProdDB,,StagingDB,";
|
|
83
|
-
expect(getAllowedDatabases()).toEqual(["ProdDB", "StagingDB"]);
|
|
84
|
-
});
|
|
85
|
-
it("prefers DATABASES over DATABASE_NAME when both set", () => {
|
|
86
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
87
|
-
process.env.DATABASE_NAME = "OtherDb";
|
|
88
|
-
expect(getAllowedDatabases()).toEqual(["ProdDB", "StagingDB"]);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
describe("resolveDatabaseName", () => {
|
|
92
|
-
const originalEnv = process.env;
|
|
93
|
-
beforeEach(() => {
|
|
94
|
-
process.env = { ...originalEnv };
|
|
95
|
-
mssqlMockState.poolConfigs.length = 0;
|
|
96
|
-
mssqlMockState.connectCalls.mockClear();
|
|
97
|
-
mssqlMockState.closeCalls.mockClear();
|
|
98
|
-
mssqlMockState.requestCalls.mockClear();
|
|
99
|
-
});
|
|
100
|
-
afterEach(() => {
|
|
101
|
-
process.env = originalEnv;
|
|
102
|
-
});
|
|
103
|
-
it("returns param when valid and in allowed list", () => {
|
|
104
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
105
|
-
expect(resolveDatabaseName("ProdDB")).toBe("ProdDB");
|
|
106
|
-
expect(resolveDatabaseName("StagingDB")).toBe("StagingDB");
|
|
107
|
-
});
|
|
108
|
-
it("returns DATABASE_NAME when param omitted and DATABASES not set", () => {
|
|
109
|
-
process.env.DATABASE_NAME = "DefaultDb";
|
|
110
|
-
delete process.env.DATABASES;
|
|
111
|
-
expect(resolveDatabaseName()).toBe("DefaultDb");
|
|
112
|
-
});
|
|
113
|
-
it("returns DATABASE_NAME when it is in DATABASES", () => {
|
|
114
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
115
|
-
process.env.DATABASE_NAME = "StagingDB";
|
|
116
|
-
expect(resolveDatabaseName()).toBe("StagingDB");
|
|
117
|
-
});
|
|
118
|
-
it("returns the first DATABASES entry when DATABASE_NAME is omitted", () => {
|
|
119
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
120
|
-
delete process.env.DATABASE_NAME;
|
|
121
|
-
expect(resolveDatabaseName()).toBe("ProdDB");
|
|
122
|
-
});
|
|
123
|
-
it("returns param when param provided and in allowed list", () => {
|
|
124
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
125
|
-
process.env.DATABASE_NAME = "ProdDB";
|
|
126
|
-
expect(resolveDatabaseName("StagingDB")).toBe("StagingDB");
|
|
127
|
-
});
|
|
128
|
-
it("falls back to the first DATABASES entry when DATABASE_NAME is not included in DATABASES", () => {
|
|
129
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
130
|
-
process.env.DATABASE_NAME = "OtherDb";
|
|
131
|
-
expect(resolveDatabaseName()).toBe("ProdDB");
|
|
132
|
-
});
|
|
133
|
-
it("returns null when param not in allowed list", () => {
|
|
134
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
135
|
-
expect(resolveDatabaseName("OtherDb")).toBeNull();
|
|
136
|
-
});
|
|
137
|
-
it("returns null when param is empty and DATABASE_NAME not set", () => {
|
|
138
|
-
delete process.env.DATABASE_NAME;
|
|
139
|
-
delete process.env.DATABASES;
|
|
140
|
-
expect(resolveDatabaseName()).toBeNull();
|
|
141
|
-
expect(resolveDatabaseName("")).toBeNull();
|
|
142
|
-
});
|
|
143
|
-
it("returns resolved name when no DATABASES set (only DATABASE_NAME allowed)", () => {
|
|
144
|
-
delete process.env.DATABASES;
|
|
145
|
-
process.env.DATABASE_NAME = "MyDb";
|
|
146
|
-
expect(resolveDatabaseName()).toBe("MyDb");
|
|
147
|
-
expect(resolveDatabaseName("MyDb")).toBe("MyDb");
|
|
148
|
-
expect(resolveDatabaseName("AnyDb")).toBeNull();
|
|
149
|
-
});
|
|
150
|
-
it("trims whitespace from param", () => {
|
|
151
|
-
process.env.DATABASES = "ProdDB";
|
|
152
|
-
expect(resolveDatabaseName(" ProdDB ")).toBe("ProdDB");
|
|
153
|
-
});
|
|
154
|
-
it("returns null when neither DATABASE_NAME nor DATABASES is configured", () => {
|
|
155
|
-
delete process.env.DATABASE_NAME;
|
|
156
|
-
delete process.env.DATABASES;
|
|
157
|
-
expect(resolveDatabaseName()).toBeNull();
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
describe("getSqlRequest", () => {
|
|
161
|
-
const originalEnv = process.env;
|
|
162
|
-
beforeEach(() => {
|
|
163
|
-
process.env = { ...originalEnv };
|
|
164
|
-
mssqlMockState.poolConfigs.length = 0;
|
|
165
|
-
mssqlMockState.connectCalls.mockClear();
|
|
166
|
-
mssqlMockState.closeCalls.mockClear();
|
|
167
|
-
mssqlMockState.requestCalls.mockClear();
|
|
168
|
-
});
|
|
169
|
-
afterEach(() => {
|
|
170
|
-
process.env = originalEnv;
|
|
171
|
-
});
|
|
172
|
-
it("returns a helpful error when no database access is configured", async () => {
|
|
173
|
-
delete process.env.DATABASE_NAME;
|
|
174
|
-
delete process.env.DATABASES;
|
|
175
|
-
const result = await getSqlRequest();
|
|
176
|
-
expect(result.error).toBe("Invalid or disallowed database. Set DATABASE_NAME or DATABASES to configure database access. Use the databaseName parameter to target a specific configured database.");
|
|
177
|
-
});
|
|
178
|
-
it("returns allowed databases in the error when a disallowed database is requested", async () => {
|
|
179
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
180
|
-
const result = await getSqlRequest("OtherDb");
|
|
181
|
-
expect(result.error).toBe("Invalid or disallowed database. Allowed: ProdDB, StagingDB. Use the databaseName parameter to target a specific configured database.");
|
|
182
|
-
});
|
|
183
|
-
it("returns a request using the resolved default database", async () => {
|
|
184
|
-
process.env.DATABASES = "ProdDBDefault,StagingDB";
|
|
185
|
-
delete process.env.DATABASE_NAME;
|
|
186
|
-
const result = await getSqlRequest();
|
|
187
|
-
expect(result.error).toBeUndefined();
|
|
188
|
-
expect(result.request).toBe(mssqlMockState.requestObject);
|
|
189
|
-
expect(mssqlMockState.poolConfigs).toContainEqual(expect.objectContaining({ database: "ProdDBDefault" }));
|
|
190
|
-
expect(mssqlMockState.connectCalls).toHaveBeenCalledWith(expect.objectContaining({ database: "ProdDBDefault" }));
|
|
191
|
-
expect(mssqlMockState.requestCalls).toHaveBeenCalledWith(expect.objectContaining({ database: "ProdDBDefault" }));
|
|
192
|
-
});
|
|
193
|
-
it("falls back to the first allowed database when DATABASE_NAME is disallowed", async () => {
|
|
194
|
-
process.env.DATABASES = "ProdDB,StagingDB";
|
|
195
|
-
process.env.DATABASE_NAME = "OtherDb";
|
|
196
|
-
const result = await getSqlRequest();
|
|
197
|
-
expect(result.error).toBeUndefined();
|
|
198
|
-
expect(result.request).toBe(mssqlMockState.requestObject);
|
|
199
|
-
expect(mssqlMockState.poolConfigs).toContainEqual(expect.objectContaining({ database: "ProdDB" }));
|
|
200
|
-
expect(mssqlMockState.connectCalls).toHaveBeenCalledWith(expect.objectContaining({ database: "ProdDB" }));
|
|
201
|
-
expect(mssqlMockState.requestCalls).toHaveBeenCalledWith(expect.objectContaining({ database: "ProdDB" }));
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
//# sourceMappingURL=db.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"db.test.js","sourceRoot":"","sources":["../../src/__tests__/db.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { validateReadQuery } from "../validation.js";
|
|
3
|
-
describe("validateReadQuery", () => {
|
|
4
|
-
it("accepts simple SELECT query", () => {
|
|
5
|
-
expect(validateReadQuery("SELECT * FROM movies")).toEqual({
|
|
6
|
-
isValid: true,
|
|
7
|
-
});
|
|
8
|
-
expect(validateReadQuery("SELECT id, name FROM users WHERE id = 1")).toEqual({
|
|
9
|
-
isValid: true,
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
it("rejects empty or non-string input", () => {
|
|
13
|
-
expect(validateReadQuery("")).toEqual({
|
|
14
|
-
isValid: false,
|
|
15
|
-
error: "Query must be a non-empty string",
|
|
16
|
-
});
|
|
17
|
-
expect(validateReadQuery(" ")).toEqual({
|
|
18
|
-
isValid: false,
|
|
19
|
-
error: "Query cannot be empty after removing comments",
|
|
20
|
-
});
|
|
21
|
-
expect(validateReadQuery(null)).toEqual({
|
|
22
|
-
isValid: false,
|
|
23
|
-
error: "Query must be a non-empty string",
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
it("rejects query that does not start with SELECT", () => {
|
|
27
|
-
expect(validateReadQuery("DELETE FROM users")).toEqual({
|
|
28
|
-
isValid: false,
|
|
29
|
-
error: "Query must start with SELECT for security reasons",
|
|
30
|
-
});
|
|
31
|
-
expect(validateReadQuery(" UPDATE users SET x = 1")).toEqual({
|
|
32
|
-
isValid: false,
|
|
33
|
-
error: "Query must start with SELECT for security reasons",
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
it("rejects dangerous keywords", () => {
|
|
37
|
-
expect(validateReadQuery("SELECT * FROM users; DELETE FROM logs")).toEqual({
|
|
38
|
-
isValid: false,
|
|
39
|
-
error: expect.stringContaining("Dangerous keyword"),
|
|
40
|
-
});
|
|
41
|
-
expect(validateReadQuery("SELECT * INTO backup FROM users")).toEqual({
|
|
42
|
-
isValid: false,
|
|
43
|
-
error: expect.stringContaining("Dangerous keyword"),
|
|
44
|
-
});
|
|
45
|
-
expect(validateReadQuery("SELECT * FROM users; DROP TABLE users")).toEqual({
|
|
46
|
-
isValid: false,
|
|
47
|
-
error: expect.stringContaining("Dangerous keyword"),
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
it("rejects SELECT INTO pattern", () => {
|
|
51
|
-
const result = validateReadQuery("SELECT * INTO newtable FROM users");
|
|
52
|
-
expect(result.isValid).toBe(false);
|
|
53
|
-
expect(result.error).toBeDefined();
|
|
54
|
-
});
|
|
55
|
-
it("rejects multiple statements", () => {
|
|
56
|
-
const result = validateReadQuery("SELECT 1; SELECT 2");
|
|
57
|
-
expect(result.isValid).toBe(false);
|
|
58
|
-
expect(result.error).toBeDefined();
|
|
59
|
-
});
|
|
60
|
-
it("rejects character conversion functions", () => {
|
|
61
|
-
expect(validateReadQuery("SELECT CHAR(65) FROM users")).toEqual({
|
|
62
|
-
isValid: false,
|
|
63
|
-
error: "Character conversion functions are not allowed as they may be used for obfuscation.",
|
|
64
|
-
});
|
|
65
|
-
expect(validateReadQuery("SELECT NCHAR(65) FROM users")).toEqual({
|
|
66
|
-
isValid: false,
|
|
67
|
-
error: "Character conversion functions are not allowed as they may be used for obfuscation.",
|
|
68
|
-
});
|
|
69
|
-
expect(validateReadQuery("SELECT ASCII('A') FROM users")).toEqual({
|
|
70
|
-
isValid: false,
|
|
71
|
-
error: "Character conversion functions are not allowed as they may be used for obfuscation.",
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
it("rejects query exceeding length limit", () => {
|
|
75
|
-
const longQuery = "SELECT * FROM users WHERE " + "x = 1 AND ".repeat(2000);
|
|
76
|
-
expect(longQuery.length).toBeGreaterThan(10000);
|
|
77
|
-
expect(validateReadQuery(longQuery)).toEqual({
|
|
78
|
-
isValid: false,
|
|
79
|
-
error: "Query is too long. Maximum allowed length is 10,000 characters.",
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
it("rejects stored procedure patterns", () => {
|
|
83
|
-
expect(validateReadQuery("SELECT * FROM sp_help")).toEqual({
|
|
84
|
-
isValid: false,
|
|
85
|
-
error: "Potentially malicious SQL pattern detected. Only simple SELECT queries are allowed.",
|
|
86
|
-
});
|
|
87
|
-
expect(validateReadQuery("SELECT * FROM xp_cmdshell")).toEqual({
|
|
88
|
-
isValid: false,
|
|
89
|
-
error: "Potentially malicious SQL pattern detected. Only simple SELECT queries are allowed.",
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
it("rejects WAITFOR delay/time patterns", () => {
|
|
93
|
-
const result = validateReadQuery("SELECT 1; WAITFOR DELAY '0:0:5'");
|
|
94
|
-
expect(result.isValid).toBe(false);
|
|
95
|
-
expect(result.error).toBeDefined();
|
|
96
|
-
});
|
|
97
|
-
it("rejects query that is only comments", () => {
|
|
98
|
-
expect(validateReadQuery("-- comment only")).toEqual({
|
|
99
|
-
isValid: false,
|
|
100
|
-
error: "Query cannot be empty after removing comments",
|
|
101
|
-
});
|
|
102
|
-
expect(validateReadQuery("/* block comment */")).toEqual({
|
|
103
|
-
isValid: false,
|
|
104
|
-
error: "Query cannot be empty after removing comments",
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
it("accepts SELECT with WHERE and JOIN", () => {
|
|
108
|
-
expect(validateReadQuery("SELECT u.id, u.name FROM users u JOIN orders o ON u.id = o.user_id WHERE u.active = 1")).toEqual({ isValid: true });
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
//# sourceMappingURL=validation.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../../src/__tests__/validation.test.ts"],"names":[],"mappings":"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"}
|