@kiyeonjeon21/datacontext 0.3.1 → 0.3.3
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/.cursorrules +22 -0
- package/dist/adapters/sqlite.d.ts.map +1 -1
- package/dist/adapters/sqlite.js +13 -0
- package/dist/adapters/sqlite.js.map +1 -1
- package/dist/cli/index.js +58 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +10 -1
- package/dist/knowledge/store.js.map +1 -1
- package/docs/KNOWLEDGE_TYPES.md +261 -0
- package/package.json +1 -1
- package/scripts/create-sqlite-testdb.sh +75 -0
- package/scripts/test-databases.sh +324 -0
- package/sqlite:./test-sqlite.db +0 -0
- package/src/adapters/sqlite.ts +16 -0
- package/src/cli/index.ts +57 -16
- package/src/knowledge/store.ts +13 -1
- package/test-sqlite.db +0 -0
- package/cursor-mcp-config.json.example +0 -29
package/src/cli/index.ts
CHANGED
|
@@ -34,9 +34,14 @@ function createAdapter(connectionString: string): DatabaseAdapter {
|
|
|
34
34
|
return createPostgresAdapter(connectionString);
|
|
35
35
|
} else if (url.startsWith('mysql://') || url.startsWith('mariadb://')) {
|
|
36
36
|
return createMySQLAdapter(connectionString);
|
|
37
|
-
} else if (url.startsWith('sqlite://') || url.endsWith('.sqlite') || url.endsWith('.sqlite3') || url.endsWith('.db') || url === ':memory:') {
|
|
38
|
-
// SQLite: sqlite://path
|
|
39
|
-
|
|
37
|
+
} else if (url.startsWith('sqlite://') || url.startsWith('sqlite:') || url.endsWith('.sqlite') || url.endsWith('.sqlite3') || url.endsWith('.db') || url === ':memory:') {
|
|
38
|
+
// SQLite: sqlite://path or sqlite:path or ./mydb.sqlite or :memory:
|
|
39
|
+
let filePath = connectionString;
|
|
40
|
+
if (url.startsWith('sqlite://')) {
|
|
41
|
+
filePath = connectionString.replace(/^sqlite:\/\//i, '');
|
|
42
|
+
} else if (url.startsWith('sqlite:')) {
|
|
43
|
+
filePath = connectionString.replace(/^sqlite:/i, '');
|
|
44
|
+
}
|
|
40
45
|
return createSQLiteAdapter(filePath);
|
|
41
46
|
} else {
|
|
42
47
|
throw new Error(
|
|
@@ -65,20 +70,37 @@ program
|
|
|
65
70
|
.option('--allowed-tables <tables...>', 'Only allow access to these tables')
|
|
66
71
|
.action(async (connectionString: string, options) => {
|
|
67
72
|
try {
|
|
68
|
-
// Parse connection string
|
|
69
|
-
const config = parseConnectionString(connectionString);
|
|
70
|
-
|
|
71
73
|
// Create adapter (auto-detect database type)
|
|
72
74
|
const adapter = createAdapter(connectionString);
|
|
73
75
|
await adapter.connect();
|
|
74
76
|
|
|
77
|
+
// Determine database ID for knowledge store
|
|
78
|
+
let databaseId: string;
|
|
79
|
+
const url = connectionString.toLowerCase();
|
|
80
|
+
|
|
81
|
+
if (url.startsWith('sqlite://') || url.startsWith('sqlite:') || url.endsWith('.sqlite') || url.endsWith('.sqlite3') || url.endsWith('.db') || url === ':memory:') {
|
|
82
|
+
// SQLite: use filename as database ID
|
|
83
|
+
let filePath = connectionString;
|
|
84
|
+
if (url.startsWith('sqlite://')) {
|
|
85
|
+
filePath = connectionString.replace(/^sqlite:\/\//i, '');
|
|
86
|
+
} else if (url.startsWith('sqlite:')) {
|
|
87
|
+
filePath = connectionString.replace(/^sqlite:/i, '');
|
|
88
|
+
}
|
|
89
|
+
const fileName = filePath.split('/').pop() || 'sqlite';
|
|
90
|
+
databaseId = `sqlite_${fileName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
91
|
+
} else {
|
|
92
|
+
// URL-based databases (postgres, mysql)
|
|
93
|
+
const config = parseConnectionString(connectionString);
|
|
94
|
+
databaseId = `${config.host}_${config.database}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
75
97
|
// Create knowledge store
|
|
76
|
-
const databaseId = `${config.host}_${config.database}`;
|
|
77
98
|
const knowledge = createKnowledgeStore(databaseId);
|
|
78
99
|
await knowledge.load();
|
|
79
100
|
|
|
80
|
-
// Update schema hash
|
|
81
|
-
const
|
|
101
|
+
// Update schema hash (SQLite uses 'main' schema)
|
|
102
|
+
const schemaName = url.startsWith('sqlite') || url.endsWith('.db') ? 'main' : options.schema;
|
|
103
|
+
const schema = await adapter.getSchema(schemaName);
|
|
82
104
|
knowledge.updateSchemaHash(schema.schemaHash);
|
|
83
105
|
await knowledge.save();
|
|
84
106
|
|
|
@@ -836,21 +858,40 @@ program
|
|
|
836
858
|
try {
|
|
837
859
|
console.log('[datacontext] Starting REST API server...');
|
|
838
860
|
|
|
839
|
-
// Parse connection string
|
|
840
|
-
const config = parseConnectionString(connectionString);
|
|
841
|
-
|
|
842
861
|
// Create adapter (auto-detect database type)
|
|
843
862
|
const adapter = createAdapter(connectionString);
|
|
844
863
|
await adapter.connect();
|
|
845
|
-
|
|
864
|
+
|
|
865
|
+
// Determine database ID for knowledge store
|
|
866
|
+
let databaseId: string;
|
|
867
|
+
const url = connectionString.toLowerCase();
|
|
868
|
+
|
|
869
|
+
if (url.startsWith('sqlite://') || url.startsWith('sqlite:') || url.endsWith('.sqlite') || url.endsWith('.sqlite3') || url.endsWith('.db') || url === ':memory:') {
|
|
870
|
+
// SQLite: use filename as database ID
|
|
871
|
+
let filePath = connectionString;
|
|
872
|
+
if (url.startsWith('sqlite://')) {
|
|
873
|
+
filePath = connectionString.replace(/^sqlite:\/\//i, '');
|
|
874
|
+
} else if (url.startsWith('sqlite:')) {
|
|
875
|
+
filePath = connectionString.replace(/^sqlite:/i, '');
|
|
876
|
+
}
|
|
877
|
+
const fileName = filePath.split('/').pop() || 'sqlite';
|
|
878
|
+
databaseId = `sqlite_${fileName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
879
|
+
console.log(`[datacontext] Connected to SQLite: ${filePath}`);
|
|
880
|
+
} else {
|
|
881
|
+
// URL-based databases (postgres, mysql)
|
|
882
|
+
const config = parseConnectionString(connectionString);
|
|
883
|
+
databaseId = `${config.host}_${config.database}`;
|
|
884
|
+
console.log(`[datacontext] Connected to ${config.database}`);
|
|
885
|
+
}
|
|
846
886
|
|
|
847
887
|
// Create knowledge store
|
|
848
|
-
const databaseId = `${config.host}_${config.database}`;
|
|
849
888
|
const knowledge = createKnowledgeStore(databaseId);
|
|
850
889
|
await knowledge.load();
|
|
851
890
|
|
|
852
|
-
// Update schema hash
|
|
853
|
-
const
|
|
891
|
+
// Update schema hash (SQLite uses 'main' schema)
|
|
892
|
+
const isSqlite = url.startsWith('sqlite') || url.endsWith('.db') || url.endsWith('.sqlite') || url.endsWith('.sqlite3');
|
|
893
|
+
const schemaName = isSqlite ? 'main' : options.schema;
|
|
894
|
+
const schema = await adapter.getSchema(schemaName);
|
|
854
895
|
knowledge.updateSchemaHash(schema.schemaHash);
|
|
855
896
|
await knowledge.save();
|
|
856
897
|
|
package/src/knowledge/store.ts
CHANGED
|
@@ -48,7 +48,14 @@ export class KnowledgeStore {
|
|
|
48
48
|
if (existsSync(this.dataPath)) {
|
|
49
49
|
try {
|
|
50
50
|
const content = await readFile(this.dataPath, 'utf-8');
|
|
51
|
-
|
|
51
|
+
const parsed = JSON.parse(content) as KnowledgeData;
|
|
52
|
+
|
|
53
|
+
// Migration: ensure businessTerms array exists (for old data files)
|
|
54
|
+
if (!parsed.businessTerms) {
|
|
55
|
+
parsed.businessTerms = [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.data = parsed;
|
|
52
59
|
} catch (error) {
|
|
53
60
|
console.error(`Failed to load knowledge store: ${error}`);
|
|
54
61
|
this.data = this.createEmptyData();
|
|
@@ -387,6 +394,11 @@ export class KnowledgeStore {
|
|
|
387
394
|
throw new Error('Knowledge store not loaded');
|
|
388
395
|
}
|
|
389
396
|
|
|
397
|
+
// Initialize businessTerms if not exists (migration for old data)
|
|
398
|
+
if (!this.data.businessTerms) {
|
|
399
|
+
this.data.businessTerms = [];
|
|
400
|
+
}
|
|
401
|
+
|
|
390
402
|
// Check for duplicates
|
|
391
403
|
const existing = this.data.businessTerms.find(
|
|
392
404
|
t => t.term.toLowerCase() === term.toLowerCase()
|
package/test-sqlite.db
ADDED
|
Binary file
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mcpServers": {
|
|
3
|
-
"datacontext": {
|
|
4
|
-
"command": "node",
|
|
5
|
-
"args": [
|
|
6
|
-
"/Users/kiyeonjeon/Projects/business/DataContext-HQ/datacontext-cli/dist/cli/index.js",
|
|
7
|
-
"connect",
|
|
8
|
-
"sqlite:///Users/kiyeonjeon/Projects/business/DataContext-HQ/datacontext-cli/test-mcp.db"
|
|
9
|
-
],
|
|
10
|
-
"env": {
|
|
11
|
-
"ANTHROPIC_API_KEY": "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",
|
|
12
|
-
"NODE_PATH": "/Users/kiyeonjeon/Projects/business/DataContext-HQ/datacontext-cli/node_modules"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"datacontext": {
|
|
20
|
-
"command": "node",
|
|
21
|
-
"args": [
|
|
22
|
-
"/Users/kiyeonjeon/Projects/business/DataContext-HQ/datacontext-cli/dist/cli/index.js",
|
|
23
|
-
"connect",
|
|
24
|
-
"postgres://postgres:postgres@localhost:5432/datacontext_test"
|
|
25
|
-
],
|
|
26
|
-
"env": {
|
|
27
|
-
"NODE_PATH": "/Users/kiyeonjeon/Projects/business/DataContext-HQ/datacontext-cli/node_modules"
|
|
28
|
-
}
|
|
29
|
-
}
|