@eamonboyle/mssql-mcp 1.2.0 → 1.3.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.
Files changed (124) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +43 -7
  3. package/dist/config.d.ts +8 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +40 -0
  6. package/dist/config.js.map +1 -1
  7. package/dist/db.d.ts +1 -0
  8. package/dist/db.d.ts.map +1 -1
  9. package/dist/db.js +1 -1
  10. package/dist/db.js.map +1 -1
  11. package/dist/index.js +356 -44
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcpResults.d.ts +49 -0
  14. package/dist/mcpResults.d.ts.map +1 -0
  15. package/dist/mcpResults.js +246 -0
  16. package/dist/mcpResults.js.map +1 -0
  17. package/dist/promptRegistry.d.ts.map +1 -1
  18. package/dist/promptRegistry.js +6 -1
  19. package/dist/promptRegistry.js.map +1 -1
  20. package/dist/resourceRegistry.d.ts +2 -0
  21. package/dist/resourceRegistry.d.ts.map +1 -1
  22. package/dist/resourceRegistry.js +149 -10
  23. package/dist/resourceRegistry.js.map +1 -1
  24. package/dist/schema.d.ts +16 -0
  25. package/dist/schema.d.ts.map +1 -1
  26. package/dist/schema.js +180 -1
  27. package/dist/schema.js.map +1 -1
  28. package/dist/serverState.d.ts +28 -0
  29. package/dist/serverState.d.ts.map +1 -0
  30. package/dist/serverState.js +99 -0
  31. package/dist/serverState.js.map +1 -0
  32. package/dist/sql.js +0 -0
  33. package/dist/toolRegistry.d.ts +4 -0
  34. package/dist/toolRegistry.d.ts.map +1 -1
  35. package/dist/toolRegistry.js +210 -64
  36. package/dist/toolRegistry.js.map +1 -1
  37. package/dist/tools/AnalyzeTableTool.d.ts +37 -0
  38. package/dist/tools/AnalyzeTableTool.d.ts.map +1 -0
  39. package/dist/tools/AnalyzeTableTool.js +81 -0
  40. package/dist/tools/AnalyzeTableTool.js.map +1 -0
  41. package/dist/tools/DeleteDataTool.d.ts.map +1 -1
  42. package/dist/tools/DeleteDataTool.js +4 -1
  43. package/dist/tools/DeleteDataTool.js.map +1 -1
  44. package/dist/tools/DescribeRelationshipsTool.d.ts +20 -0
  45. package/dist/tools/DescribeRelationshipsTool.d.ts.map +1 -0
  46. package/dist/tools/DescribeRelationshipsTool.js +24 -0
  47. package/dist/tools/DescribeRelationshipsTool.js.map +1 -0
  48. package/dist/tools/ListDatabasesTool.d.ts +16 -0
  49. package/dist/tools/ListDatabasesTool.d.ts.map +1 -0
  50. package/dist/tools/ListDatabasesTool.js +26 -0
  51. package/dist/tools/ListDatabasesTool.js.map +1 -0
  52. package/dist/tools/ListForeignKeysTool.d.ts +19 -0
  53. package/dist/tools/ListForeignKeysTool.d.ts.map +1 -0
  54. package/dist/tools/ListForeignKeysTool.js +24 -0
  55. package/dist/tools/ListForeignKeysTool.js.map +1 -0
  56. package/dist/tools/PreviewDeleteTool.d.ts +28 -0
  57. package/dist/tools/PreviewDeleteTool.d.ts.map +1 -0
  58. package/dist/tools/PreviewDeleteTool.js +31 -0
  59. package/dist/tools/PreviewDeleteTool.js.map +1 -0
  60. package/dist/tools/PreviewUpdateTool.d.ts +30 -0
  61. package/dist/tools/PreviewUpdateTool.d.ts.map +1 -0
  62. package/dist/tools/PreviewUpdateTool.js +34 -0
  63. package/dist/tools/PreviewUpdateTool.js.map +1 -0
  64. package/dist/tools/ReadDataTool.js +2 -2
  65. package/dist/tools/ReadDataTool.js.map +1 -1
  66. package/dist/tools/UpdateDataTool.d.ts +1 -0
  67. package/dist/tools/UpdateDataTool.d.ts.map +1 -1
  68. package/dist/tools/UpdateDataTool.js +6 -3
  69. package/dist/tools/UpdateDataTool.js.map +1 -1
  70. package/dist/validation.js +0 -0
  71. package/dist/writePreview.d.ts +20 -0
  72. package/dist/writePreview.d.ts.map +1 -0
  73. package/dist/writePreview.js +27 -0
  74. package/dist/writePreview.js.map +1 -0
  75. package/dist/writePreviewGrant.d.ts +18 -0
  76. package/dist/writePreviewGrant.d.ts.map +1 -0
  77. package/dist/writePreviewGrant.js +71 -0
  78. package/dist/writePreviewGrant.js.map +1 -0
  79. package/dist/writePreviewGrantStore.d.ts +10 -0
  80. package/dist/writePreviewGrantStore.d.ts.map +1 -0
  81. package/dist/writePreviewGrantStore.js +47 -0
  82. package/dist/writePreviewGrantStore.js.map +1 -0
  83. package/dist/writeSafety.js +0 -0
  84. package/package.json +6 -2
  85. package/dist/__tests__/ExplainQueryTool.test.d.ts +0 -2
  86. package/dist/__tests__/ExplainQueryTool.test.d.ts.map +0 -1
  87. package/dist/__tests__/ExplainQueryTool.test.js +0 -96
  88. package/dist/__tests__/ExplainQueryTool.test.js.map +0 -1
  89. package/dist/__tests__/config.test.d.ts +0 -2
  90. package/dist/__tests__/config.test.d.ts.map +0 -1
  91. package/dist/__tests__/config.test.js +0 -29
  92. package/dist/__tests__/config.test.js.map +0 -1
  93. package/dist/__tests__/db.test.d.ts +0 -2
  94. package/dist/__tests__/db.test.d.ts.map +0 -1
  95. package/dist/__tests__/db.test.js +0 -204
  96. package/dist/__tests__/db.test.js.map +0 -1
  97. package/dist/__tests__/promptRegistry.test.d.ts +0 -2
  98. package/dist/__tests__/promptRegistry.test.d.ts.map +0 -1
  99. package/dist/__tests__/promptRegistry.test.js +0 -40
  100. package/dist/__tests__/promptRegistry.test.js.map +0 -1
  101. package/dist/__tests__/resourceRegistry.test.d.ts +0 -2
  102. package/dist/__tests__/resourceRegistry.test.d.ts.map +0 -1
  103. package/dist/__tests__/resourceRegistry.test.js +0 -40
  104. package/dist/__tests__/resourceRegistry.test.js.map +0 -1
  105. package/dist/__tests__/schema.test.d.ts +0 -2
  106. package/dist/__tests__/schema.test.d.ts.map +0 -1
  107. package/dist/__tests__/schema.test.js +0 -130
  108. package/dist/__tests__/schema.test.js.map +0 -1
  109. package/dist/__tests__/sql.test.d.ts +0 -2
  110. package/dist/__tests__/sql.test.d.ts.map +0 -1
  111. package/dist/__tests__/sql.test.js +0 -35
  112. package/dist/__tests__/sql.test.js.map +0 -1
  113. package/dist/__tests__/toolRegistry.test.d.ts +0 -2
  114. package/dist/__tests__/toolRegistry.test.d.ts.map +0 -1
  115. package/dist/__tests__/toolRegistry.test.js +0 -47
  116. package/dist/__tests__/toolRegistry.test.js.map +0 -1
  117. package/dist/__tests__/validation.test.d.ts +0 -2
  118. package/dist/__tests__/validation.test.d.ts.map +0 -1
  119. package/dist/__tests__/validation.test.js +0 -111
  120. package/dist/__tests__/validation.test.js.map +0 -1
  121. package/dist/__tests__/writeTools.test.d.ts +0 -2
  122. package/dist/__tests__/writeTools.test.d.ts.map +0 -1
  123. package/dist/__tests__/writeTools.test.js +0 -115
  124. package/dist/__tests__/writeTools.test.js.map +0 -1
@@ -1,40 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- const resourceRegistryMockState = vi.hoisted(() => ({
3
- listDatabaseTables: vi.fn(async () => [
4
- { schemaName: "dbo", tableName: "Users" },
5
- ]),
6
- listDatabaseObjects: vi.fn(async () => []),
7
- }));
8
- vi.mock("../schema.js", () => ({
9
- describeDatabaseObject: vi.fn(),
10
- describeTableSchema: vi.fn(),
11
- listDatabaseObjects: resourceRegistryMockState.listDatabaseObjects,
12
- listDatabaseTables: resourceRegistryMockState.listDatabaseTables,
13
- }));
14
- import { registerResources } from "../resourceRegistry.js";
15
- describe("resourceRegistry", () => {
16
- it("caches database listing reads for a short TTL", async () => {
17
- const handlers = new Map();
18
- const server = {
19
- registerResource(name, _resource, _meta, handler) {
20
- handlers.set(name, handler);
21
- },
22
- };
23
- registerResources(server, {
24
- serverName: "mssql-mcp-server",
25
- serverVersion: "1.2.0",
26
- isReadOnly: false,
27
- allowedDatabases: ["AppDb"],
28
- toolNames: [],
29
- maxRows: 100,
30
- queryTimeoutMs: 30000,
31
- });
32
- const readTables = handlers.get("AppDb_tables");
33
- expect(readTables).toBeDefined();
34
- await readTables?.(new URL("mssql://database/AppDb/tables"));
35
- await readTables?.(new URL("mssql://database/AppDb/tables"));
36
- expect(resourceRegistryMockState.listDatabaseTables).toHaveBeenCalledTimes(1);
37
- expect(resourceRegistryMockState.listDatabaseObjects).not.toHaveBeenCalled();
38
- });
39
- });
40
- //# sourceMappingURL=resourceRegistry.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resourceRegistry.test.js","sourceRoot":"","sources":["../../src/__tests__/resourceRegistry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,yBAAyB,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,kBAAkB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QACpC,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE;KAC1C,CAAC;IACF,mBAAmB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;CAC3C,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7B,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC/B,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC5B,mBAAmB,EAAE,yBAAyB,CAAC,mBAAmB;IAClE,kBAAkB,EAAE,yBAAyB,CAAC,kBAAkB;CACjE,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0C,CAAC;QACnE,MAAM,MAAM,GAAG;YACb,gBAAgB,CACd,IAAY,EACZ,SAAkB,EAClB,KAAc,EACd,OAAuC;gBAEvC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9B,CAAC;SACF,CAAC;QAEF,iBAAiB,CAAC,MAAe,EAAE;YACjC,UAAU,EAAE,kBAAkB;YAC9B,aAAa,EAAE,OAAO;YACtB,UAAU,EAAE,KAAK;YACjB,gBAAgB,EAAE,CAAC,OAAO,CAAC;YAC3B,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,GAAG;YACZ,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAChD,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QAEjC,MAAM,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAC7D,MAAM,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAE7D,MAAM,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CACxE,CAAC,CACF,CAAC;QACF,MAAM,CACJ,yBAAyB,CAAC,mBAAmB,CAC9C,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=schema.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema.test.ts"],"names":[],"mappings":""}
@@ -1,130 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
- const schemaMockState = vi.hoisted(() => ({
3
- getSqlRequestCalls: 0,
4
- inputCalls: [],
5
- queryCalls: [],
6
- queryResults: [],
7
- }));
8
- vi.mock("mssql", () => ({
9
- default: {
10
- NVarChar: "NVarChar",
11
- Int: "Int",
12
- },
13
- }));
14
- vi.mock("../db.js", () => ({
15
- getSqlRequest: vi.fn(async () => {
16
- schemaMockState.getSqlRequestCalls += 1;
17
- return {
18
- request: {
19
- input(name, type, value) {
20
- schemaMockState.inputCalls.push({ name, type, value });
21
- },
22
- async query(query) {
23
- schemaMockState.queryCalls.push(query);
24
- return (schemaMockState.queryResults.shift() ?? {
25
- recordset: [],
26
- recordsets: [],
27
- });
28
- },
29
- },
30
- };
31
- }),
32
- }));
33
- import { describeDatabaseObject } from "../schema.js";
34
- describe("describeDatabaseObject", () => {
35
- beforeEach(() => {
36
- schemaMockState.getSqlRequestCalls = 0;
37
- schemaMockState.inputCalls.length = 0;
38
- schemaMockState.queryCalls.length = 0;
39
- schemaMockState.queryResults.length = 0;
40
- });
41
- it("throws an ambiguity error when multiple schema matches exist", async () => {
42
- schemaMockState.queryResults.push({
43
- recordset: [
44
- {
45
- objectId: 1,
46
- name: "Users",
47
- schemaName: "dbo",
48
- typeCode: "U",
49
- typeDescription: "USER_TABLE",
50
- createdAt: new Date(),
51
- modifiedAt: new Date(),
52
- definition: null,
53
- },
54
- {
55
- objectId: 2,
56
- name: "Users",
57
- schemaName: "audit",
58
- typeCode: "V",
59
- typeDescription: "VIEW",
60
- createdAt: new Date(),
61
- modifiedAt: new Date(),
62
- definition: null,
63
- },
64
- ],
65
- });
66
- await expect(describeDatabaseObject("Users", "AppDb")).rejects.toThrow("Specify schemaName or objectTypes to disambiguate");
67
- expect(schemaMockState.getSqlRequestCalls).toBe(1);
68
- });
69
- it("reuses a single request flow and batches detail queries", async () => {
70
- schemaMockState.queryResults.push({
71
- recordset: [
72
- {
73
- objectId: 7,
74
- name: "Users",
75
- schemaName: "dbo",
76
- typeCode: "U",
77
- typeDescription: "USER_TABLE",
78
- createdAt: new Date("2024-01-01"),
79
- modifiedAt: new Date("2024-01-02"),
80
- definition: null,
81
- },
82
- ],
83
- }, {
84
- recordsets: [
85
- [
86
- {
87
- name: "id",
88
- dataType: "int",
89
- maxLength: 4,
90
- precision: 10,
91
- scale: 0,
92
- isNullable: false,
93
- isIdentity: true,
94
- defaultValue: null,
95
- },
96
- ],
97
- [
98
- {
99
- name: "PK_Users",
100
- type: "CLUSTERED",
101
- isUnique: true,
102
- columnName: "id",
103
- keyOrdinal: 1,
104
- },
105
- ],
106
- ],
107
- });
108
- const result = await describeDatabaseObject("Users", "AppDb", "dbo");
109
- expect(result).toMatchObject({
110
- name: "Users",
111
- schemaName: "dbo",
112
- objectType: "table",
113
- columns: [
114
- {
115
- name: "id",
116
- dataType: "int",
117
- },
118
- ],
119
- indexes: [
120
- {
121
- name: "PK_Users",
122
- columns: ["id"],
123
- },
124
- ],
125
- });
126
- expect(schemaMockState.getSqlRequestCalls).toBe(1);
127
- expect(schemaMockState.queryCalls).toHaveLength(2);
128
- });
129
- });
130
- //# sourceMappingURL=schema.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../src/__tests__/schema.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9D,MAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,kBAAkB,EAAE,CAAC;IACrB,UAAU,EAAE,EAA4D;IACxE,UAAU,EAAE,EAAc;IAC1B,YAAY,EAAE,EAGZ;CACH,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IACtB,OAAO,EAAE;QACP,QAAQ,EAAE,UAAU;QACpB,GAAG,EAAE,KAAK;KACX;CACF,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IACzB,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;QAC9B,eAAe,CAAC,kBAAkB,IAAI,CAAC,CAAC;QACxC,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,CAAC,IAAY,EAAE,IAAa,EAAE,KAAc;oBAC/C,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACzD,CAAC;gBACD,KAAK,CAAC,KAAK,CAAC,KAAa;oBACvB,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACvC,OAAO,CACL,eAAe,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI;wBACtC,SAAS,EAAE,EAAE;wBACb,UAAU,EAAE,EAAE;qBACf,CACF,CAAC;gBACJ,CAAC;aACF;SACF,CAAC;IACJ,CAAC,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEtD,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,UAAU,CAAC,GAAG,EAAE;QACd,eAAe,CAAC,kBAAkB,GAAG,CAAC,CAAC;QACvC,eAAe,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QACtC,eAAe,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QACtC,eAAe,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC;YAChC,SAAS,EAAE;gBACT;oBACE,QAAQ,EAAE,CAAC;oBACX,IAAI,EAAE,OAAO;oBACb,UAAU,EAAE,KAAK;oBACjB,QAAQ,EAAE,GAAG;oBACb,eAAe,EAAE,YAAY;oBAC7B,SAAS,EAAE,IAAI,IAAI,EAAE;oBACrB,UAAU,EAAE,IAAI,IAAI,EAAE;oBACtB,UAAU,EAAE,IAAI;iBACjB;gBACD;oBACE,QAAQ,EAAE,CAAC;oBACX,IAAI,EAAE,OAAO;oBACb,UAAU,EAAE,OAAO;oBACnB,QAAQ,EAAE,GAAG;oBACb,eAAe,EAAE,MAAM;oBACvB,SAAS,EAAE,IAAI,IAAI,EAAE;oBACrB,UAAU,EAAE,IAAI,IAAI,EAAE;oBACtB,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACpE,mDAAmD,CACpD,CAAC;QACF,MAAM,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,eAAe,CAAC,YAAY,CAAC,IAAI,CAC/B;YACE,SAAS,EAAE;gBACT;oBACE,QAAQ,EAAE,CAAC;oBACX,IAAI,EAAE,OAAO;oBACb,UAAU,EAAE,KAAK;oBACjB,QAAQ,EAAE,GAAG;oBACb,eAAe,EAAE,YAAY;oBAC7B,SAAS,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC;oBACjC,UAAU,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC;oBAClC,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,EACD;YACE,UAAU,EAAE;gBACV;oBACE;wBACE,IAAI,EAAE,IAAI;wBACV,QAAQ,EAAE,KAAK;wBACf,SAAS,EAAE,CAAC;wBACZ,SAAS,EAAE,EAAE;wBACb,KAAK,EAAE,CAAC;wBACR,UAAU,EAAE,KAAK;wBACjB,UAAU,EAAE,IAAI;wBAChB,YAAY,EAAE,IAAI;qBACnB;iBACF;gBACD;oBACE;wBACE,IAAI,EAAE,UAAU;wBAChB,IAAI,EAAE,WAAW;wBACjB,QAAQ,EAAE,IAAI;wBACd,UAAU,EAAE,IAAI;wBAChB,UAAU,EAAE,CAAC;qBACd;iBACF;aACF;SACF,CACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QAErE,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC3B,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,OAAO;YACnB,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,IAAI;oBACV,QAAQ,EAAE,KAAK;iBAChB;aACF;YACD,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,UAAU;oBAChB,OAAO,EAAE,CAAC,IAAI,CAAC;iBAChB;aACF;SACF,CAAC,CAAC;QACH,MAAM,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sql.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sql.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sql.test.ts"],"names":[],"mappings":""}
@@ -1,35 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { buildQualifiedName, getFriendlyObjectType, getObjectTypeCodes, quoteIdentifier, } from "../sql.js";
3
- describe("sql helpers", () => {
4
- it("quotes safe identifiers", () => {
5
- expect(quoteIdentifier("Users")).toBe("[Users]");
6
- expect(buildQualifiedName("Users", "dbo")).toBe("[dbo].[Users]");
7
- expect(quoteIdentifier("Order Details")).toBe("[Order Details]");
8
- expect(quoteIdentifier("Users]Archive")).toBe("[Users]]Archive]");
9
- });
10
- it("rejects empty or control-character identifiers", () => {
11
- expect(() => quoteIdentifier("")).toThrow("Invalid identifier.");
12
- expect(() => buildQualifiedName("", "dbo")).toThrow("Invalid object name.");
13
- expect(() => buildQualifiedName("Users", "dbo\u0000")).toThrow("Invalid schema name.");
14
- expect(() => quoteIdentifier("Users\u0000Archive")).toThrow("Invalid identifier.");
15
- });
16
- it("maps friendly object types", () => {
17
- expect(getFriendlyObjectType("U")).toBe("table");
18
- expect(getFriendlyObjectType("V")).toBe("view");
19
- expect(getFriendlyObjectType("P")).toBe("procedure");
20
- expect(getFriendlyObjectType("FN")).toBe("function");
21
- expect(getFriendlyObjectType("TR")).toBe("trigger");
22
- });
23
- it("resolves object type filters", () => {
24
- expect(getObjectTypeCodes(["table", "view"])).toEqual(["U", "V"]);
25
- expect(getObjectTypeCodes(["function"])).toEqual([
26
- "FN",
27
- "IF",
28
- "TF",
29
- "FS",
30
- "FT",
31
- ]);
32
- expect(() => getObjectTypeCodes(["queue"])).toThrow("Unsupported object type 'queue'. Expected one of: table, view, procedure, function, trigger.");
33
- });
34
- });
35
- //# sourceMappingURL=sql.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sql.test.js","sourceRoot":"","sources":["../../src/__tests__/sql.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,GAChB,MAAM,WAAW,CAAC;AAEnB,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACjE,MAAM,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACjE,MAAM,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAC5E,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAC5D,sBAAsB,CACvB,CAAC;QACF,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CACzD,qBAAqB,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,kBAAkB,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/C,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;YACJ,IAAI;SACL,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CACjD,8FAA8F,CAC/F,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=toolRegistry.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolRegistry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/toolRegistry.test.ts"],"names":[],"mappings":""}
@@ -1,47 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { toolDefinitions } from "../toolRegistry.js";
3
- function getToolSchema(name) {
4
- const definition = toolDefinitions.find((tool) => tool.tool.name === name);
5
- if (!definition) {
6
- throw new Error(`Missing tool definition for ${name}`);
7
- }
8
- return definition.inputSchema;
9
- }
10
- describe("toolRegistry write schemas", () => {
11
- it("requires structured filters for update_data", () => {
12
- const schema = getToolSchema("update_data");
13
- expect(schema.safeParse({
14
- tableName: "Users",
15
- updates: { status: "active" },
16
- whereClause: "id = 1",
17
- }).success).toBe(false);
18
- expect(schema.safeParse({
19
- tableName: "Users",
20
- updates: { status: "active" },
21
- filters: [{ column: "id", operator: "=", value: 1 }],
22
- }).success).toBe(true);
23
- });
24
- it("rejects unknown keys for delete_data", () => {
25
- const schema = getToolSchema("delete_data");
26
- expect(schema.safeParse({
27
- tableName: "Users",
28
- filters: [{ column: "id", operator: "=", value: 1 }],
29
- extra: true,
30
- }).success).toBe(false);
31
- });
32
- it("rejects extra column properties for create_table", () => {
33
- const schema = getToolSchema("create_table");
34
- expect(schema.safeParse({
35
- tableName: "Users",
36
- columns: [
37
- {
38
- name: "id",
39
- type: "INT",
40
- nullable: false,
41
- unexpected: "value",
42
- },
43
- ],
44
- }).success).toBe(false);
45
- });
46
- });
47
- //# sourceMappingURL=toolRegistry.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"toolRegistry.test.js","sourceRoot":"","sources":["../../src/__tests__/toolRegistry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC3E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,UAAU,CAAC,WAAW,CAAC;AAChC,CAAC;AAED,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;QAE5C,MAAM,CACJ,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAC7B,WAAW,EAAE,QAAQ;SACtB,CAAC,CAAC,OAAO,CACX,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEd,MAAM,CACJ,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;SACrD,CAAC,CAAC,OAAO,CACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;QAE5C,MAAM,CACJ,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YACpD,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC,OAAO,CACX,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;QAE7C,MAAM,CACJ,MAAM,CAAC,SAAS,CAAC;YACf,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,KAAK;oBACf,UAAU,EAAE,OAAO;iBACpB;aACF;SACF,CAAC,CAAC,OAAO,CACX,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=validation.test.d.ts.map
@@ -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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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=writeTools.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeTools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/writeTools.test.ts"],"names":[],"mappings":""}
@@ -1,115 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
- const dbMockState = vi.hoisted(() => ({
3
- error: undefined,
4
- inputCalls: [],
5
- queryCalls: [],
6
- queryResults: [],
7
- }));
8
- vi.mock("../db.js", () => ({
9
- getSqlRequest: vi.fn(async () => {
10
- if (dbMockState.error) {
11
- return {
12
- request: null,
13
- error: dbMockState.error,
14
- };
15
- }
16
- return {
17
- request: {
18
- input(name, value) {
19
- dbMockState.inputCalls.push({ name, value });
20
- },
21
- async query(query) {
22
- dbMockState.queryCalls.push(query);
23
- return (dbMockState.queryResults.shift() ?? {
24
- rowsAffected: [1],
25
- recordset: [],
26
- });
27
- },
28
- },
29
- };
30
- }),
31
- }));
32
- import { CreateIndexTool } from "../tools/CreateIndexTool.js";
33
- import { CreateTableTool } from "../tools/CreateTableTool.js";
34
- import { DeleteDataTool } from "../tools/DeleteDataTool.js";
35
- import { InsertDataTool } from "../tools/InsertDataTool.js";
36
- import { UpdateDataTool } from "../tools/UpdateDataTool.js";
37
- describe("write tools", () => {
38
- beforeEach(() => {
39
- vi.spyOn(console, "error").mockImplementation(() => { });
40
- dbMockState.error = undefined;
41
- dbMockState.inputCalls.length = 0;
42
- dbMockState.queryCalls.length = 0;
43
- dbMockState.queryResults.length = 0;
44
- });
45
- afterEach(() => {
46
- vi.restoreAllMocks();
47
- });
48
- it("parameterizes delete filters instead of interpolating raw SQL", async () => {
49
- const tool = new DeleteDataTool();
50
- const result = await tool.run({
51
- tableName: "Order Details",
52
- schemaName: "sales-data",
53
- filters: [{ column: "Order ID", operator: "=", value: 42 }],
54
- });
55
- expect(result).toMatchObject({ success: true, rowsAffected: 1 });
56
- expect(dbMockState.queryCalls[0]).toBe("DELETE FROM [sales-data].[Order Details] WHERE [Order ID] = @delete_filter_0");
57
- expect(dbMockState.inputCalls).toEqual([
58
- { name: "delete_filter_0", value: 42 },
59
- ]);
60
- });
61
- it("parameterizes update filters and quotes updated columns", async () => {
62
- const tool = new UpdateDataTool();
63
- const result = await tool.run({
64
- tableName: "Users",
65
- updates: { "display name": "Ada" },
66
- filters: [{ column: "id", operator: "IN", values: [1, 2] }],
67
- });
68
- expect(result).toMatchObject({ success: true, rowsAffected: 1 });
69
- expect(dbMockState.queryCalls[0]).toBe("UPDATE [Users] SET [display name] = @update_0 WHERE [id] IN (@update_filter_0_0, @update_filter_0_1)");
70
- expect(dbMockState.inputCalls).toEqual([
71
- { name: "update_0", value: "Ada" },
72
- { name: "update_filter_0_0", value: 1 },
73
- { name: "update_filter_0_1", value: 2 },
74
- ]);
75
- });
76
- it("quotes identifiers for inserts", async () => {
77
- const tool = new InsertDataTool();
78
- const result = await tool.run({
79
- tableName: "Order Details",
80
- data: {
81
- "Customer Name": "Ada",
82
- "Order ID": 10,
83
- },
84
- });
85
- expect(result).toMatchObject({ success: true, recordsInserted: 1 });
86
- expect(dbMockState.queryCalls[0]).toBe("INSERT INTO [Order Details] ([Customer Name], [Order ID]) VALUES (@value0, @value1)");
87
- });
88
- it("quotes identifiers for created indexes", async () => {
89
- const tool = new CreateIndexTool();
90
- const result = await tool.run({
91
- schemaName: "sales-data",
92
- tableName: "Order Details",
93
- indexName: "IX Order Lookup",
94
- columns: ["Order ID", "Line Number"],
95
- });
96
- expect(result).toMatchObject({ success: true });
97
- expect(dbMockState.queryCalls[0]).toBe("CREATE NONCLUSTERED INDEX [IX Order Lookup] ON [sales-data].[Order Details] ([Order ID], [Line Number])");
98
- });
99
- it("rejects unsafe free-form column type fragments", async () => {
100
- const tool = new CreateTableTool();
101
- const result = await tool.run({
102
- tableName: "Users",
103
- columns: [
104
- {
105
- name: "id",
106
- type: "INT); DROP TABLE users; --",
107
- },
108
- ],
109
- });
110
- expect(result).toMatchObject({ success: false });
111
- expect(String(result.message)).toContain("Unsupported SQL type declaration");
112
- expect(dbMockState.queryCalls).toHaveLength(0);
113
- });
114
- });
115
- //# sourceMappingURL=writeTools.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeTools.test.js","sourceRoot":"","sources":["../../src/__tests__/writeTools.test.ts"],"names":[],"mappings":"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"}