db-mcp 3.0.2 → 5.0.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 +112 -75
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/database-adapter.d.ts +11 -1
- package/dist/adapters/database-adapter.d.ts.map +1 -1
- package/dist/adapters/registration/resources.d.ts.map +1 -1
- package/dist/adapters/registration/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -1
- package/dist/adapters/sqlite/query-executor.d.ts.map +1 -1
- package/dist/adapters/sqlite/read-write-lock.d.ts +49 -0
- package/dist/adapters/sqlite/read-write-lock.d.ts.map +1 -0
- package/dist/adapters/sqlite/resources.d.ts +1 -1
- package/dist/adapters/sqlite/resources.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/admin.d.ts +33 -19
- package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/core.d.ts +96 -0
- package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/fts.d.ts +4 -0
- package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/introspection.d.ts +25 -15
- package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/migration.d.ts +2 -2
- package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/spatialite.d.ts +1 -0
- package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/text.d.ts +36 -0
- package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -1
- package/dist/adapters/sqlite/sqlite-adapter.d.ts +6 -0
- package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts +0 -4
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/versioning.d.ts +19 -0
- package/dist/adapters/sqlite/tools/core/versioning.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/helpers.d.ts +9 -0
- package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/search.d.ts +4 -0
- package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -1
- package/dist/adapters/sqlite/types.d.ts +5 -1
- package/dist/adapters/sqlite/types.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/index.d.ts +1 -1
- package/dist/adapters/sqlite-native/index.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts +52 -0
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts +159 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -1
- package/dist/audit/interceptor.d.ts.map +1 -1
- package/dist/audit/logger.d.ts +26 -25
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/auth/authorization-server-discovery.d.ts.map +1 -1
- package/dist/auth/scopes/mapping.d.ts.map +1 -1
- package/dist/auth/token-validator.d.ts.map +1 -1
- package/dist/{chunk-W5WQVNVX.js → chunk-27C5EE6U.js} +23 -17
- package/dist/chunk-2TYICG7B.js +1183 -0
- package/dist/{chunk-37G4DLL6.js → chunk-LLIAIJPO.js} +1146 -539
- package/dist/{chunk-NV34JSQM.js → chunk-UE7GVOBV.js} +1757 -1331
- package/dist/{chunk-L552U3QS.js → chunk-XLIYO3YA.js} +401 -77
- package/dist/cli.js +116 -11
- package/dist/codemode/api-constants.d.ts.map +1 -1
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/sandbox-factory.d.ts.map +1 -1
- package/dist/codemode/sandbox.d.ts +0 -3
- package/dist/codemode/sandbox.d.ts.map +1 -1
- package/dist/codemode/security.d.ts.map +1 -1
- package/dist/codemode/types.d.ts +2 -0
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/constants/server-instructions.d.ts +1 -1
- package/dist/constants/server-instructions.d.ts.map +1 -1
- package/dist/filtering/tool-constants.d.ts +11 -11
- package/dist/filtering/tool-constants.d.ts.map +1 -1
- package/dist/{http-HWTUVFIA.js → http-ZDMK46QU.js} +195 -32
- package/dist/index.js +4 -4
- package/dist/observability/metrics.d.ts +36 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/system-db.d.ts +13 -0
- package/dist/observability/system-db.d.ts.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/registration/admin-tools.d.ts +6 -0
- package/dist/server/registration/admin-tools.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/backup.d.ts +8 -0
- package/dist/server/registration/audit-tools/backup.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/helpers.d.ts +11 -0
- package/dist/server/registration/audit-tools/helpers.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/index.d.ts +4 -0
- package/dist/server/registration/audit-tools/index.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/resource.d.ts +8 -0
- package/dist/server/registration/audit-tools/resource.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/search.d.ts +7 -0
- package/dist/server/registration/audit-tools/search.d.ts.map +1 -0
- package/dist/server/registration/help-resources.d.ts.map +1 -1
- package/dist/server/registration/index.d.ts +3 -1
- package/dist/server/registration/index.d.ts.map +1 -1
- package/dist/server/registration/observability-resources.d.ts +11 -0
- package/dist/server/registration/observability-resources.d.ts.map +1 -0
- package/dist/server/subscription-manager.d.ts +35 -0
- package/dist/server/subscription-manager.d.ts.map +1 -0
- package/dist/{sqlite-TB56Z7G3.js → sqlite-XWZPEZJO.js} +195 -19
- package/dist/{sqlite-native-IF75BB3O.js → sqlite-native-5GQ3WKCZ.js} +311 -147
- package/dist/transports/http/middleware.d.ts.map +1 -1
- package/dist/transports/http/oauth.d.ts.map +1 -1
- package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -1
- package/dist/transports/http/sessions/stateful.d.ts +5 -1
- package/dist/transports/http/sessions/stateful.d.ts.map +1 -1
- package/dist/transports/http/transport.d.ts +2 -0
- package/dist/transports/http/transport.d.ts.map +1 -1
- package/dist/transports/http/types.d.ts +11 -0
- package/dist/transports/http/types.d.ts.map +1 -1
- package/dist/types/auth.d.ts +4 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/server.d.ts +5 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/utils/annotations.d.ts +8 -0
- package/dist/utils/annotations.d.ts.map +1 -1
- package/dist/utils/errors/categories.d.ts +16 -11
- package/dist/utils/errors/categories.d.ts.map +1 -1
- package/dist/utils/errors/classes.d.ts +37 -0
- package/dist/utils/errors/classes.d.ts.map +1 -1
- package/dist/utils/errors/format.d.ts +2 -2
- package/dist/utils/errors/format.d.ts.map +1 -1
- package/dist/utils/errors/index.d.ts +1 -1
- package/dist/utils/errors/index.d.ts.map +1 -1
- package/dist/utils/errors/suggestions.d.ts +1 -0
- package/dist/utils/errors/suggestions.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/logger/types.d.ts +1 -1
- package/dist/utils/logger/types.d.ts.map +1 -1
- package/dist/utils/security-utils.d.ts +29 -0
- package/dist/utils/security-utils.d.ts.map +1 -0
- package/dist/utils/stream-utils.d.ts +14 -0
- package/dist/utils/stream-utils.d.ts.map +1 -0
- package/dist/utils/tokens.d.ts +15 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/where-clause.d.ts +0 -13
- package/dist/utils/where-clause.d.ts.map +1 -1
- package/package.json +43 -44
- package/dist/adapters/sqlite-native/tools/window.d.ts +0 -7
- package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
- package/dist/chunk-E5IESRTK.js +0 -489
- package/dist/server/registration/audit-tools.d.ts +0 -13
- package/dist/server/registration/audit-tools.d.ts.map +0 -1
- package/dist/utils/insights-manager.d.ts +0 -39
- package/dist/utils/insights-manager.d.ts.map +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./built-in-tools.js";
|
|
2
2
|
export * from "./help-resources.js";
|
|
3
|
-
export
|
|
3
|
+
export { registerAuditResource, registerAuditBackupTools, registerAuditSearchTool, } from "./audit-tools/index.js";
|
|
4
|
+
export * from "./observability-resources.js";
|
|
5
|
+
export * from "./admin-tools.js";
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/registration/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/registration/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* db-mcp — Observability Resources
|
|
3
|
+
*
|
|
4
|
+
* Registers the sqlite://metrics resource.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register the metrics resource
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerObservabilityResources(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=observability-resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-resources.d.ts","sourceRoot":"","sources":["../../../src/server/registration/observability-resources.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsBtE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Manages MCP resource subscriptions for the server.
|
|
4
|
+
* Tracks which transport sessions are subscribed to which resource URIs.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SubscriptionManager {
|
|
7
|
+
private readonly server;
|
|
8
|
+
private subscriptions;
|
|
9
|
+
constructor(server: McpServer);
|
|
10
|
+
/**
|
|
11
|
+
* Subscribe a session to a resource URI.
|
|
12
|
+
*/
|
|
13
|
+
subscribe(uri: string, sessionId?: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Unsubscribe a session from a resource URI.
|
|
16
|
+
*/
|
|
17
|
+
unsubscribe(uri: string, sessionId?: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* Unsubscribe a session from all resources (useful on transport disconnect).
|
|
20
|
+
*/
|
|
21
|
+
unsubscribeSession(sessionId: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Notifies all subscribed clients that a resource has changed.
|
|
24
|
+
*/
|
|
25
|
+
notifyResourceUpdated(uri: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Notifies subscribers of schema-related resources (schema, tables, and specific tables).
|
|
28
|
+
*/
|
|
29
|
+
notifySchemaSubscribers(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Check if there are any active subscribers for a specific URI.
|
|
32
|
+
*/
|
|
33
|
+
hasSubscribers(uri: string): boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=subscription-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-manager.d.ts","sourceRoot":"","sources":["../../src/server/subscription-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IAGnC,OAAO,CAAC,aAAa,CAAkC;gBAE3C,MAAM,EAAE,SAAS;IAI7B;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAsBvD;;OAEG;IACI,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAkBzD;;OAEG;IACI,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmBlD;;OAEG;IACU,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9D;;OAEG;IACU,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBrD;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAI5C"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getCoreTools, getJsonHelperTools, getJsonOperationTools, getTextTools, getStatsTools, getVirtualTools, getVectorTools, getGeoTools, getAdminTools, getIntrospectionTools, getMigrationTools, getCodeModeTools, executeRead, executeWrite, isDDL, executeGeneral, getResourceDefinitions, getPromptDefinitions, applyCommonPragmas, autoEnableWal, detectAndSetJsonbSupport, SchemaManager } from './chunk-
|
|
2
|
-
export { getCoreTools } from './chunk-
|
|
3
|
-
import { DatabaseAdapter } from './chunk-
|
|
4
|
-
import { getToolGroupIcon, VERSION } from './chunk-
|
|
5
|
-
import { createModuleLogger, ConnectionError, ConfigurationError, ERROR_CODES, DbMcpError } from './chunk-
|
|
1
|
+
import { getCoreTools, getJsonHelperTools, getJsonOperationTools, getTextTools, getStatsTools, getVirtualTools, getVectorTools, getGeoTools, getAdminTools, getIntrospectionTools, getMigrationTools, getCodeModeTools, executeRead, executeWrite, isDDL, executeGeneral, getResourceDefinitions, getPromptDefinitions, applyCommonPragmas, autoEnableWal, detectAndSetJsonbSupport, SchemaManager } from './chunk-UE7GVOBV.js';
|
|
2
|
+
export { getCoreTools } from './chunk-UE7GVOBV.js';
|
|
3
|
+
import { DatabaseAdapter } from './chunk-27C5EE6U.js';
|
|
4
|
+
import { getToolGroupIcon, VERSION } from './chunk-2TYICG7B.js';
|
|
5
|
+
import { createModuleLogger, ConnectionError, ConfigurationError, ERROR_CODES, DbMcpError, ErrorCategory } from './chunk-XLIYO3YA.js';
|
|
6
6
|
import initSqlJs from 'sql.js';
|
|
7
7
|
|
|
8
8
|
// src/adapters/sqlite/tools/index.ts
|
|
@@ -34,6 +34,142 @@ function getAllToolDefinitions(adapter) {
|
|
|
34
34
|
function getToolsByGroup(adapter, group) {
|
|
35
35
|
return getAllToolDefinitions(adapter).filter((tool) => tool.group === group);
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
// src/adapters/sqlite/read-write-lock.ts
|
|
39
|
+
var ReadWriteLock = class {
|
|
40
|
+
activeReaders = 0;
|
|
41
|
+
isWriting = false;
|
|
42
|
+
readWaiters = [];
|
|
43
|
+
readHead = 0;
|
|
44
|
+
writeWaiters = [];
|
|
45
|
+
writeHead = 0;
|
|
46
|
+
maxConcurrentReaders;
|
|
47
|
+
consecutiveWriters = 0;
|
|
48
|
+
MAX_CONSECUTIVE_WRITERS = 5;
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.maxConcurrentReaders = options?.maxConcurrentReaders ?? 10;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Acquire a read lock.
|
|
54
|
+
* Multiple readers can acquire the lock simultaneously up to maxConcurrentReaders.
|
|
55
|
+
* If a writer is currently active OR there are writers waiting (fairness),
|
|
56
|
+
* the read request is queued.
|
|
57
|
+
*/
|
|
58
|
+
async acquireRead() {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const grantRead = () => {
|
|
61
|
+
this.activeReaders++;
|
|
62
|
+
let released = false;
|
|
63
|
+
resolve(() => {
|
|
64
|
+
if (released) return;
|
|
65
|
+
released = true;
|
|
66
|
+
this.releaseRead();
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
const writersWaiting = this.writeWaiters.length - this.writeHead > 0;
|
|
70
|
+
if (this.isWriting || writersWaiting && this.consecutiveWriters < this.MAX_CONSECUTIVE_WRITERS || this.activeReaders >= this.maxConcurrentReaders) {
|
|
71
|
+
this.readWaiters.push({ resolve: grantRead, reject });
|
|
72
|
+
} else {
|
|
73
|
+
grantRead();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Acquire a write lock.
|
|
79
|
+
* Writers have exclusive access.
|
|
80
|
+
* If there are active readers or an active writer, the write request is queued.
|
|
81
|
+
*/
|
|
82
|
+
async acquireWrite() {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const grantWrite = () => {
|
|
85
|
+
this.isWriting = true;
|
|
86
|
+
this.consecutiveWriters++;
|
|
87
|
+
let released = false;
|
|
88
|
+
resolve(() => {
|
|
89
|
+
if (released) return;
|
|
90
|
+
released = true;
|
|
91
|
+
this.releaseWrite();
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
if (this.isWriting || this.activeReaders > 0) {
|
|
95
|
+
this.writeWaiters.push({ resolve: grantWrite, reject });
|
|
96
|
+
} else {
|
|
97
|
+
grantWrite();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
releaseRead() {
|
|
102
|
+
this.activeReaders--;
|
|
103
|
+
this.processQueues();
|
|
104
|
+
}
|
|
105
|
+
releaseWrite() {
|
|
106
|
+
this.isWriting = false;
|
|
107
|
+
this.processQueues();
|
|
108
|
+
}
|
|
109
|
+
popReader() {
|
|
110
|
+
if (this.readHead >= this.readWaiters.length) return void 0;
|
|
111
|
+
const req = this.readWaiters[this.readHead++];
|
|
112
|
+
if (this.readHead > 100) {
|
|
113
|
+
this.readWaiters = this.readWaiters.slice(this.readHead);
|
|
114
|
+
this.readHead = 0;
|
|
115
|
+
}
|
|
116
|
+
return req;
|
|
117
|
+
}
|
|
118
|
+
popWriter() {
|
|
119
|
+
if (this.writeHead >= this.writeWaiters.length) return void 0;
|
|
120
|
+
const req = this.writeWaiters[this.writeHead++];
|
|
121
|
+
if (this.writeHead > 100) {
|
|
122
|
+
this.writeWaiters = this.writeWaiters.slice(this.writeHead);
|
|
123
|
+
this.writeHead = 0;
|
|
124
|
+
}
|
|
125
|
+
return req;
|
|
126
|
+
}
|
|
127
|
+
processQueues() {
|
|
128
|
+
const writersWaiting = this.writeWaiters.length - this.writeHead > 0;
|
|
129
|
+
const readersWaiting = this.readWaiters.length - this.readHead > 0;
|
|
130
|
+
if (!writersWaiting || readersWaiting && this.consecutiveWriters >= this.MAX_CONSECUTIVE_WRITERS) {
|
|
131
|
+
this.consecutiveWriters = 0;
|
|
132
|
+
}
|
|
133
|
+
if (writersWaiting && this.activeReaders === 0 && !this.isWriting && this.consecutiveWriters < this.MAX_CONSECUTIVE_WRITERS) {
|
|
134
|
+
const nextWriter = this.popWriter();
|
|
135
|
+
nextWriter?.resolve(() => void 0);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (!this.isWriting && (!writersWaiting || this.consecutiveWriters >= this.MAX_CONSECUTIVE_WRITERS)) {
|
|
139
|
+
while (this.readWaiters.length - this.readHead > 0 && this.activeReaders < this.maxConcurrentReaders) {
|
|
140
|
+
const nextReader = this.popReader();
|
|
141
|
+
nextReader?.resolve(() => void 0);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get current lock statistics
|
|
147
|
+
*/
|
|
148
|
+
getStats() {
|
|
149
|
+
return {
|
|
150
|
+
activeReaders: this.activeReaders,
|
|
151
|
+
isWriting: this.isWriting,
|
|
152
|
+
waitingReaders: this.readWaiters.length - this.readHead,
|
|
153
|
+
waitingWriters: this.writeWaiters.length - this.writeHead
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Force release all waiting locks (useful for shutdown)
|
|
158
|
+
*/
|
|
159
|
+
dispose() {
|
|
160
|
+
const cancelError = new ConnectionError("Database connection shutting down", "CONNECTION_CLOSED");
|
|
161
|
+
for (let i = this.readHead; i < this.readWaiters.length; i++) {
|
|
162
|
+
this.readWaiters[i]?.reject(cancelError);
|
|
163
|
+
}
|
|
164
|
+
for (let i = this.writeHead; i < this.writeWaiters.length; i++) {
|
|
165
|
+
this.writeWaiters[i]?.reject(cancelError);
|
|
166
|
+
}
|
|
167
|
+
this.readWaiters = [];
|
|
168
|
+
this.readHead = 0;
|
|
169
|
+
this.writeWaiters = [];
|
|
170
|
+
this.writeHead = 0;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
37
173
|
var log = createModuleLogger("SQLITE");
|
|
38
174
|
var _sqlJsPromise = null;
|
|
39
175
|
function getSqlJs() {
|
|
@@ -168,7 +304,7 @@ async function fallBackDescribeTable(adapter, tableName) {
|
|
|
168
304
|
throw new DbMcpError(
|
|
169
305
|
"Invalid table name",
|
|
170
306
|
"SQLITE_INVALID_TABLE",
|
|
171
|
-
|
|
307
|
+
ErrorCategory.VALIDATION
|
|
172
308
|
);
|
|
173
309
|
}
|
|
174
310
|
const result = await adapter.executeReadQuery(
|
|
@@ -248,6 +384,7 @@ async function fallBackGetIndexes(adapter, table) {
|
|
|
248
384
|
}
|
|
249
385
|
|
|
250
386
|
// src/adapters/sqlite/sqlite-adapter.ts
|
|
387
|
+
var DDL_NAME_REGEX = /(?:table|view|index)\s+([a-zA-Z0-9_]+)/i;
|
|
251
388
|
var SqliteAdapter = class extends DatabaseAdapter {
|
|
252
389
|
type = "sqlite";
|
|
253
390
|
name = "SQLite Adapter";
|
|
@@ -267,6 +404,7 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
267
404
|
return this.config?.filePath ?? this.config?.connectionString ?? ":memory:";
|
|
268
405
|
}
|
|
269
406
|
db = null;
|
|
407
|
+
rwLock = new ReadWriteLock();
|
|
270
408
|
config = null;
|
|
271
409
|
schemaManager = null;
|
|
272
410
|
cachedToolDefinitions = null;
|
|
@@ -284,6 +422,7 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
284
422
|
* Disconnect from the database
|
|
285
423
|
*/
|
|
286
424
|
async disconnect() {
|
|
425
|
+
this.rwLock.dispose();
|
|
287
426
|
if (this.db) {
|
|
288
427
|
await disconnectSqliteDatabase(this.db, this.config);
|
|
289
428
|
this.db = null;
|
|
@@ -321,10 +460,15 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
321
460
|
/**
|
|
322
461
|
* Execute a read-only query
|
|
323
462
|
*/
|
|
324
|
-
executeReadQuery(sql, params) {
|
|
463
|
+
async executeReadQuery(sql, params) {
|
|
325
464
|
this.ensureConnected();
|
|
326
465
|
this.validateQuery(sql, true);
|
|
327
|
-
|
|
466
|
+
const release = await this.rwLock.acquireRead();
|
|
467
|
+
try {
|
|
468
|
+
return await executeRead(this.ensureDb(), sql, params);
|
|
469
|
+
} finally {
|
|
470
|
+
release();
|
|
471
|
+
}
|
|
328
472
|
}
|
|
329
473
|
/**
|
|
330
474
|
* Execute a write query
|
|
@@ -332,14 +476,21 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
332
476
|
async executeWriteQuery(sql, params) {
|
|
333
477
|
this.ensureConnected();
|
|
334
478
|
this.validateQuery(sql, false);
|
|
335
|
-
const
|
|
479
|
+
const release = await this.rwLock.acquireWrite();
|
|
480
|
+
let result;
|
|
481
|
+
try {
|
|
482
|
+
result = await executeWrite(this.ensureDb(), sql, params);
|
|
483
|
+
} finally {
|
|
484
|
+
release();
|
|
485
|
+
}
|
|
336
486
|
if (isDDL(sql)) {
|
|
337
|
-
const match =
|
|
487
|
+
const match = DDL_NAME_REGEX.exec(sql);
|
|
338
488
|
if (match?.[1] && this.schemaManager) {
|
|
339
489
|
this.schemaManager.clearTableCache(match[1]);
|
|
340
490
|
} else {
|
|
341
491
|
this.clearSchemaCache();
|
|
342
492
|
}
|
|
493
|
+
this.emit("schemaChanged");
|
|
343
494
|
}
|
|
344
495
|
return result;
|
|
345
496
|
}
|
|
@@ -349,25 +500,37 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
349
500
|
async executeQuery(sql, params) {
|
|
350
501
|
this.ensureConnected();
|
|
351
502
|
this.validateQuery(sql, false);
|
|
352
|
-
const
|
|
503
|
+
const release = await this.rwLock.acquireWrite();
|
|
504
|
+
let result;
|
|
505
|
+
try {
|
|
506
|
+
result = await executeGeneral(this.ensureDb(), sql, params);
|
|
507
|
+
} finally {
|
|
508
|
+
release();
|
|
509
|
+
}
|
|
353
510
|
if (isDDL(sql)) {
|
|
354
|
-
const match =
|
|
511
|
+
const match = DDL_NAME_REGEX.exec(sql);
|
|
355
512
|
if (match?.[1] && this.schemaManager) {
|
|
356
513
|
this.schemaManager.clearTableCache(match[1]);
|
|
357
514
|
} else {
|
|
358
515
|
this.clearSchemaCache();
|
|
359
516
|
}
|
|
517
|
+
this.emit("schemaChanged");
|
|
360
518
|
}
|
|
361
519
|
return result;
|
|
362
520
|
}
|
|
363
521
|
/**
|
|
364
522
|
* Execute a SQL script containing multiple statements
|
|
365
523
|
*/
|
|
366
|
-
executeScript(sql) {
|
|
524
|
+
async executeScript(sql) {
|
|
367
525
|
this.ensureConnected();
|
|
368
|
-
this.
|
|
526
|
+
const release = await this.rwLock.acquireWrite();
|
|
527
|
+
try {
|
|
528
|
+
this.ensureDb().run(sql);
|
|
529
|
+
} finally {
|
|
530
|
+
release();
|
|
531
|
+
}
|
|
369
532
|
this.clearSchemaCache();
|
|
370
|
-
|
|
533
|
+
this.emit("schemaChanged");
|
|
371
534
|
}
|
|
372
535
|
/**
|
|
373
536
|
* Get full database schema (cached via SchemaManager)
|
|
@@ -448,8 +611,8 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
448
611
|
// SpatiaLite not bundled
|
|
449
612
|
transactions: true,
|
|
450
613
|
preparedStatements: true,
|
|
451
|
-
connectionPooling:
|
|
452
|
-
//
|
|
614
|
+
connectionPooling: true
|
|
615
|
+
// Managed by ReadWriteLock for WASM
|
|
453
616
|
};
|
|
454
617
|
}
|
|
455
618
|
/**
|
|
@@ -547,6 +710,12 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
547
710
|
}
|
|
548
711
|
return db;
|
|
549
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* Get pool statistics
|
|
715
|
+
*/
|
|
716
|
+
getPoolStats() {
|
|
717
|
+
return this.rwLock.getStats();
|
|
718
|
+
}
|
|
550
719
|
/**
|
|
551
720
|
* Get the raw database instance (for tools)
|
|
552
721
|
*/
|
|
@@ -556,8 +725,15 @@ var SqliteAdapter = class extends DatabaseAdapter {
|
|
|
556
725
|
/**
|
|
557
726
|
* Execute raw SQL and return results (for tools)
|
|
558
727
|
*/
|
|
559
|
-
rawQuery(sql, params) {
|
|
560
|
-
|
|
728
|
+
async rawQuery(sql, params) {
|
|
729
|
+
const trimmed = sql.trim().toUpperCase();
|
|
730
|
+
const isRead = trimmed.startsWith("SELECT") || trimmed.startsWith("EXPLAIN") || trimmed.startsWith("PRAGMA") && !sql.includes("=");
|
|
731
|
+
const release = isRead ? await this.rwLock.acquireRead() : await this.rwLock.acquireWrite();
|
|
732
|
+
try {
|
|
733
|
+
return await executeGeneral(this.ensureDb(), sql, params);
|
|
734
|
+
} finally {
|
|
735
|
+
release();
|
|
736
|
+
}
|
|
561
737
|
}
|
|
562
738
|
};
|
|
563
739
|
function createSqliteAdapter() {
|