s3db.js 11.3.1 → 12.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 +102 -8
- package/dist/s3db.cjs.js +36664 -15480
- package/dist/s3db.cjs.js.map +1 -1
- package/dist/s3db.d.ts +57 -0
- package/dist/s3db.es.js +36661 -15531
- package/dist/s3db.es.js.map +1 -1
- package/mcp/entrypoint.js +58 -0
- package/mcp/tools/documentation.js +434 -0
- package/mcp/tools/index.js +4 -0
- package/package.json +27 -6
- package/src/behaviors/user-managed.js +13 -6
- package/src/client.class.js +41 -46
- package/src/concerns/base62.js +85 -0
- package/src/concerns/dictionary-encoding.js +294 -0
- package/src/concerns/geo-encoding.js +256 -0
- package/src/concerns/high-performance-inserter.js +34 -30
- package/src/concerns/ip.js +325 -0
- package/src/concerns/metadata-encoding.js +345 -66
- package/src/concerns/money.js +193 -0
- package/src/concerns/partition-queue.js +7 -4
- package/src/concerns/plugin-storage.js +39 -19
- package/src/database.class.js +76 -74
- package/src/errors.js +0 -4
- package/src/plugins/api/auth/api-key-auth.js +88 -0
- package/src/plugins/api/auth/basic-auth.js +154 -0
- package/src/plugins/api/auth/index.js +112 -0
- package/src/plugins/api/auth/jwt-auth.js +169 -0
- package/src/plugins/api/index.js +539 -0
- package/src/plugins/api/middlewares/index.js +15 -0
- package/src/plugins/api/middlewares/validator.js +185 -0
- package/src/plugins/api/routes/auth-routes.js +241 -0
- package/src/plugins/api/routes/resource-routes.js +304 -0
- package/src/plugins/api/server.js +350 -0
- package/src/plugins/api/utils/error-handler.js +147 -0
- package/src/plugins/api/utils/openapi-generator.js +1240 -0
- package/src/plugins/api/utils/response-formatter.js +218 -0
- package/src/plugins/backup/streaming-exporter.js +132 -0
- package/src/plugins/backup.plugin.js +103 -50
- package/src/plugins/cache/s3-cache.class.js +95 -47
- package/src/plugins/cache.plugin.js +107 -9
- package/src/plugins/concerns/plugin-dependencies.js +313 -0
- package/src/plugins/concerns/prometheus-formatter.js +255 -0
- package/src/plugins/consumers/rabbitmq-consumer.js +4 -0
- package/src/plugins/consumers/sqs-consumer.js +4 -0
- package/src/plugins/costs.plugin.js +255 -39
- package/src/plugins/eventual-consistency/helpers.js +15 -1
- package/src/plugins/geo.plugin.js +873 -0
- package/src/plugins/importer/index.js +1020 -0
- package/src/plugins/index.js +11 -0
- package/src/plugins/metrics.plugin.js +163 -4
- package/src/plugins/queue-consumer.plugin.js +6 -27
- package/src/plugins/relation.errors.js +139 -0
- package/src/plugins/relation.plugin.js +1242 -0
- package/src/plugins/replicators/bigquery-replicator.class.js +180 -8
- package/src/plugins/replicators/dynamodb-replicator.class.js +383 -0
- package/src/plugins/replicators/index.js +28 -3
- package/src/plugins/replicators/mongodb-replicator.class.js +391 -0
- package/src/plugins/replicators/mysql-replicator.class.js +558 -0
- package/src/plugins/replicators/planetscale-replicator.class.js +409 -0
- package/src/plugins/replicators/postgres-replicator.class.js +182 -7
- package/src/plugins/replicators/s3db-replicator.class.js +1 -12
- package/src/plugins/replicators/schema-sync.helper.js +601 -0
- package/src/plugins/replicators/sqs-replicator.class.js +11 -9
- package/src/plugins/replicators/turso-replicator.class.js +416 -0
- package/src/plugins/replicators/webhook-replicator.class.js +612 -0
- package/src/plugins/state-machine.plugin.js +122 -68
- package/src/plugins/tfstate/README.md +745 -0
- package/src/plugins/tfstate/base-driver.js +80 -0
- package/src/plugins/tfstate/errors.js +112 -0
- package/src/plugins/tfstate/filesystem-driver.js +129 -0
- package/src/plugins/tfstate/index.js +2660 -0
- package/src/plugins/tfstate/s3-driver.js +192 -0
- package/src/plugins/ttl.plugin.js +536 -0
- package/src/resource.class.js +14 -10
- package/src/s3db.d.ts +57 -0
- package/src/schema.class.js +366 -32
- package/SECURITY.md +0 -76
- package/mcp/CLAUDE_CLI_SETUP.md +0 -302
- package/mcp/Dockerfile +0 -45
- package/mcp/Makefile +0 -162
- package/mcp/NPX_SETUP.md +0 -327
- package/mcp/PUBLISHING.md +0 -281
- package/mcp/README.md +0 -125
- package/mcp/docker-compose.yml +0 -120
- package/mcp/examples/test-filesystem-cache.js +0 -147
- package/mcp/examples/test-mcp.js +0 -433
- package/mcp/package.json +0 -66
- package/src/partition-drivers/base-partition-driver.js +0 -106
- package/src/partition-drivers/index.js +0 -66
- package/src/partition-drivers/memory-partition-driver.js +0 -289
- package/src/partition-drivers/sqs-partition-driver.js +0 -337
- package/src/partition-drivers/sync-partition-driver.js +0 -38
package/mcp/examples/test-mcp.js
DELETED
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* S3DB MCP Server Test Script
|
|
5
|
-
*
|
|
6
|
-
* This script demonstrates how to test the S3DB MCP server functionality
|
|
7
|
-
* by making direct tool calls and showing the expected responses.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { createRequire } from 'module';
|
|
11
|
-
const require = createRequire(import.meta.url);
|
|
12
|
-
|
|
13
|
-
// Mock MCP client for testing
|
|
14
|
-
class MockMCPClient {
|
|
15
|
-
constructor(serverUrl) {
|
|
16
|
-
this.serverUrl = serverUrl;
|
|
17
|
-
this.tools = [];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async initialize() {
|
|
21
|
-
console.log('🔌 Initializing MCP Client...');
|
|
22
|
-
console.log(`📡 Server URL: ${this.serverUrl}`);
|
|
23
|
-
|
|
24
|
-
// In a real implementation, this would connect to the MCP server
|
|
25
|
-
// and fetch the available tools
|
|
26
|
-
this.tools = [
|
|
27
|
-
'dbConnect', 'dbDisconnect', 'dbStatus', 'dbCreateResource', 'dbListResources', 'dbGetStats', 'dbClearCache',
|
|
28
|
-
'resourceInsert', 'resourceGet', 'resourceUpdate', 'resourceDelete', 'resourceList'
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
console.log(`✅ Found ${this.tools.length} available tools`);
|
|
32
|
-
return this.tools;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async callTool(name, args = {}) {
|
|
36
|
-
console.log(`\n🔧 Calling tool: ${name}`);
|
|
37
|
-
console.log(`📥 Arguments:`, JSON.stringify(args, null, 2));
|
|
38
|
-
|
|
39
|
-
// Mock successful responses for demonstration
|
|
40
|
-
const mockResponses = {
|
|
41
|
-
dbConnect: {
|
|
42
|
-
success: true,
|
|
43
|
-
message: 'Connected to S3DB database',
|
|
44
|
-
status: {
|
|
45
|
-
connected: true,
|
|
46
|
-
bucket: 'test-bucket',
|
|
47
|
-
keyPrefix: 'databases/test',
|
|
48
|
-
version: '7.2.1'
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
dbStatus: {
|
|
53
|
-
connected: true,
|
|
54
|
-
bucket: 'test-bucket',
|
|
55
|
-
keyPrefix: 'databases/test',
|
|
56
|
-
version: '7.2.1',
|
|
57
|
-
resourceCount: 2,
|
|
58
|
-
resources: ['users', 'posts']
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
dbCreateResource: {
|
|
62
|
-
success: true,
|
|
63
|
-
resource: {
|
|
64
|
-
name: args.name,
|
|
65
|
-
behavior: args.behavior || 'user-managed',
|
|
66
|
-
attributes: args.attributes,
|
|
67
|
-
partitions: args.partitions || {},
|
|
68
|
-
timestamps: args.timestamps || false
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
dbListResources: {
|
|
73
|
-
success: true,
|
|
74
|
-
resources: [
|
|
75
|
-
{ name: 'users' },
|
|
76
|
-
{ name: 'posts' }
|
|
77
|
-
],
|
|
78
|
-
count: 2
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
resourceInsert: {
|
|
82
|
-
success: true,
|
|
83
|
-
data: {
|
|
84
|
-
id: 'doc_' + Math.random().toString(36).substr(2, 9),
|
|
85
|
-
...args.data,
|
|
86
|
-
createdAt: new Date().toISOString(),
|
|
87
|
-
updatedAt: new Date().toISOString()
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
resourceGet: {
|
|
92
|
-
success: true,
|
|
93
|
-
data: {
|
|
94
|
-
id: args.id,
|
|
95
|
-
name: 'John Doe',
|
|
96
|
-
email: 'john@example.com',
|
|
97
|
-
createdAt: '2024-01-15T10:30:00Z',
|
|
98
|
-
updatedAt: '2024-01-15T10:30:00Z'
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
resourceList: {
|
|
103
|
-
success: true,
|
|
104
|
-
data: [
|
|
105
|
-
{
|
|
106
|
-
id: 'doc_123',
|
|
107
|
-
name: 'John Doe',
|
|
108
|
-
email: 'john@example.com',
|
|
109
|
-
createdAt: '2024-01-15T10:30:00Z'
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
id: 'doc_456',
|
|
113
|
-
name: 'Jane Smith',
|
|
114
|
-
email: 'jane@example.com',
|
|
115
|
-
createdAt: '2024-01-15T11:30:00Z'
|
|
116
|
-
}
|
|
117
|
-
],
|
|
118
|
-
count: 2,
|
|
119
|
-
pagination: {
|
|
120
|
-
limit: args.limit || 100,
|
|
121
|
-
offset: args.offset || 0,
|
|
122
|
-
hasMore: false
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
resourceCount: {
|
|
127
|
-
success: true,
|
|
128
|
-
count: 42,
|
|
129
|
-
resource: args.resourceName
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
dbGetStats: {
|
|
133
|
-
success: true,
|
|
134
|
-
stats: {
|
|
135
|
-
database: {
|
|
136
|
-
connected: true,
|
|
137
|
-
bucket: 'test-bucket',
|
|
138
|
-
keyPrefix: 'databases/test',
|
|
139
|
-
version: '7.2.1',
|
|
140
|
-
resourceCount: 2,
|
|
141
|
-
resources: ['users', 'posts']
|
|
142
|
-
},
|
|
143
|
-
costs: {
|
|
144
|
-
total: 0.000042,
|
|
145
|
-
totalRequests: 156,
|
|
146
|
-
requestsByType: { get: 89, put: 45, list: 12, delete: 10 },
|
|
147
|
-
eventsByType: { GetObjectCommand: 89, PutObjectCommand: 45 },
|
|
148
|
-
estimatedCostUSD: 0.000042
|
|
149
|
-
},
|
|
150
|
-
cache: {
|
|
151
|
-
enabled: true,
|
|
152
|
-
driver: 'FilesystemCache',
|
|
153
|
-
size: 23,
|
|
154
|
-
directory: './test-cache',
|
|
155
|
-
ttl: 300000,
|
|
156
|
-
keyCount: 23,
|
|
157
|
-
sampleKeys: ['resource=users/action=list.json.gz', 'resource=posts/action=count.json.gz']
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
|
|
162
|
-
dbClearCache: {
|
|
163
|
-
success: true,
|
|
164
|
-
message: args.resourceName
|
|
165
|
-
? `Cache cleared for resource: ${args.resourceName}`
|
|
166
|
-
: 'All cache cleared'
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
const response = mockResponses[name] || { success: false, error: 'Tool not found' };
|
|
171
|
-
|
|
172
|
-
console.log(`📤 Response:`, JSON.stringify(response, null, 2));
|
|
173
|
-
return response;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Test scenarios
|
|
178
|
-
async function runTests() {
|
|
179
|
-
console.log('🧪 S3DB MCP Server Test Suite');
|
|
180
|
-
console.log('================================\n');
|
|
181
|
-
|
|
182
|
-
const client = new MockMCPClient('http://localhost:8000/sse');
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
// Initialize client
|
|
186
|
-
await client.initialize();
|
|
187
|
-
|
|
188
|
-
// Test 1: Connect to database
|
|
189
|
-
console.log('\n📋 Test 1: Database Connection');
|
|
190
|
-
console.log('-------------------------------');
|
|
191
|
-
await client.callTool('dbConnect', {
|
|
192
|
-
connectionString: 's3://test-key:test-secret@test-bucket/databases/demo',
|
|
193
|
-
verbose: false,
|
|
194
|
-
parallelism: 10,
|
|
195
|
-
enableCache: true,
|
|
196
|
-
enableCosts: true,
|
|
197
|
-
cacheDriver: 'filesystem', // Test filesystem cache
|
|
198
|
-
cacheDirectory: './test-cache',
|
|
199
|
-
cachePrefix: 'test',
|
|
200
|
-
cacheTtl: 300000
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// Test 2: Check database status
|
|
204
|
-
console.log('\n📋 Test 2: Database Status');
|
|
205
|
-
console.log('---------------------------');
|
|
206
|
-
await client.callTool('dbStatus');
|
|
207
|
-
|
|
208
|
-
// Test 3: Create a resource
|
|
209
|
-
console.log('\n📋 Test 3: Create Resource');
|
|
210
|
-
console.log('---------------------------');
|
|
211
|
-
await client.callTool('dbCreateResource', {
|
|
212
|
-
name: 'users',
|
|
213
|
-
attributes: {
|
|
214
|
-
name: 'string|required',
|
|
215
|
-
email: 'email|required|unique',
|
|
216
|
-
age: 'number|positive',
|
|
217
|
-
profile: {
|
|
218
|
-
bio: 'string|optional',
|
|
219
|
-
avatar: 'url|optional'
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
behavior: 'user-managed',
|
|
223
|
-
timestamps: true,
|
|
224
|
-
partitions: {
|
|
225
|
-
byAge: {
|
|
226
|
-
fields: { ageGroup: 'string' }
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
// Test 4: List resources
|
|
232
|
-
console.log('\n📋 Test 4: List Resources');
|
|
233
|
-
console.log('--------------------------');
|
|
234
|
-
await client.callTool('dbListResources');
|
|
235
|
-
|
|
236
|
-
// Test 5: Insert data
|
|
237
|
-
console.log('\n📋 Test 5: Insert Document');
|
|
238
|
-
console.log('---------------------------');
|
|
239
|
-
await client.callTool('resourceInsert', {
|
|
240
|
-
resourceName: 'users',
|
|
241
|
-
data: {
|
|
242
|
-
name: 'John Doe',
|
|
243
|
-
email: 'john@example.com',
|
|
244
|
-
age: 30,
|
|
245
|
-
profile: {
|
|
246
|
-
bio: 'Software developer and AI enthusiast',
|
|
247
|
-
avatar: 'https://example.com/avatar.jpg'
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Test 6: Get document
|
|
253
|
-
console.log('\n📋 Test 6: Get Document');
|
|
254
|
-
console.log('------------------------');
|
|
255
|
-
await client.callTool('resourceGet', {
|
|
256
|
-
resourceName: 'users',
|
|
257
|
-
id: 'doc_123'
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// Test 7: List documents
|
|
261
|
-
console.log('\n📋 Test 7: List Documents');
|
|
262
|
-
console.log('--------------------------');
|
|
263
|
-
await client.callTool('resourceList', {
|
|
264
|
-
resourceName: 'users',
|
|
265
|
-
limit: 10,
|
|
266
|
-
offset: 0
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// Test 8: Count documents
|
|
270
|
-
console.log('\n📋 Test 8: Count Documents');
|
|
271
|
-
console.log('---------------------------');
|
|
272
|
-
await client.callTool('resourceCount', {
|
|
273
|
-
resourceName: 'users'
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
// Test 9: Get database statistics
|
|
277
|
-
console.log('\n📋 Test 9: Database Statistics');
|
|
278
|
-
console.log('-------------------------------');
|
|
279
|
-
await client.callTool('dbGetStats');
|
|
280
|
-
|
|
281
|
-
// Test 10: Clear cache
|
|
282
|
-
console.log('\n📋 Test 10: Clear Cache');
|
|
283
|
-
console.log('------------------------');
|
|
284
|
-
await client.callTool('dbClearCache', {
|
|
285
|
-
resourceName: 'users'
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
console.log('\n✅ All tests completed successfully!');
|
|
289
|
-
console.log('\n💡 To run against a real S3DB MCP server:');
|
|
290
|
-
console.log(' 1. Start the server: npm start');
|
|
291
|
-
console.log(' 2. Configure your .env file');
|
|
292
|
-
console.log(' 3. Use a real MCP client to connect');
|
|
293
|
-
|
|
294
|
-
} catch (error) {
|
|
295
|
-
console.error('\n❌ Test failed:', error.message);
|
|
296
|
-
process.exit(1);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Real MCP client example (commented out - requires actual MCP client library)
|
|
301
|
-
async function realMCPExample() {
|
|
302
|
-
console.log('\n🔗 Real MCP Client Example');
|
|
303
|
-
console.log('===========================');
|
|
304
|
-
|
|
305
|
-
console.log(`
|
|
306
|
-
This is how you would connect to a real S3DB MCP server:
|
|
307
|
-
|
|
308
|
-
import { MCPClient } from '@modelcontextprotocol/client';
|
|
309
|
-
|
|
310
|
-
const client = new MCPClient({
|
|
311
|
-
transport: 'sse',
|
|
312
|
-
url: 'http://localhost:8000/sse'
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
await client.connect();
|
|
316
|
-
|
|
317
|
-
// Connect to S3DB
|
|
318
|
-
const result = await client.callTool('dbConnect', {
|
|
319
|
-
connectionString: process.env.S3DB_CONNECTION_STRING
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// Create a resource
|
|
323
|
-
await client.callTool('dbCreateResource', {
|
|
324
|
-
name: 'products',
|
|
325
|
-
attributes: {
|
|
326
|
-
name: 'string|required',
|
|
327
|
-
price: 'number|positive|required',
|
|
328
|
-
category: 'string|required'
|
|
329
|
-
},
|
|
330
|
-
timestamps: true
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
// Insert data
|
|
334
|
-
await client.callTool('resourceInsert', {
|
|
335
|
-
resourceName: 'products',
|
|
336
|
-
data: {
|
|
337
|
-
name: 'Laptop Pro',
|
|
338
|
-
price: 1299.99,
|
|
339
|
-
category: 'electronics'
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
`);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Configuration examples
|
|
346
|
-
function showConfigurationExamples() {
|
|
347
|
-
console.log('\n⚙️ Configuration Examples');
|
|
348
|
-
console.log('===========================');
|
|
349
|
-
|
|
350
|
-
console.log(`
|
|
351
|
-
# AWS S3 Configuration
|
|
352
|
-
S3DB_CONNECTION_STRING=s3://ACCESS_KEY:SECRET_KEY@bucket/databases/myapp
|
|
353
|
-
|
|
354
|
-
# MinIO Configuration (local development)
|
|
355
|
-
S3DB_CONNECTION_STRING=s3://minioadmin:minioadmin@test-bucket/databases/dev?endpoint=http://localhost:9000&forcePathStyle=true
|
|
356
|
-
|
|
357
|
-
# DigitalOcean Spaces Configuration
|
|
358
|
-
S3DB_CONNECTION_STRING=s3://DO_KEY:DO_SECRET@space-name/databases/prod?endpoint=https://nyc3.digitaloceanspaces.com
|
|
359
|
-
|
|
360
|
-
# Claude Desktop Configuration (claude_desktop_config.json)
|
|
361
|
-
{
|
|
362
|
-
"mcpServers": {
|
|
363
|
-
"s3db": {
|
|
364
|
-
"transport": "sse",
|
|
365
|
-
"url": "http://localhost:8000/sse"
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
# Cursor IDE Configuration
|
|
371
|
-
{
|
|
372
|
-
"mcpServers": {
|
|
373
|
-
"s3db": {
|
|
374
|
-
"url": "http://localhost:8000/sse"
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
`);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// Main execution
|
|
382
|
-
async function main() {
|
|
383
|
-
const args = process.argv.slice(2);
|
|
384
|
-
|
|
385
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
386
|
-
console.log(`
|
|
387
|
-
S3DB MCP Server Test Script
|
|
388
|
-
|
|
389
|
-
Usage:
|
|
390
|
-
node test-mcp.js [options]
|
|
391
|
-
|
|
392
|
-
Options:
|
|
393
|
-
--help, -h Show this help message
|
|
394
|
-
--config Show configuration examples
|
|
395
|
-
--real Show real MCP client examples
|
|
396
|
-
|
|
397
|
-
Examples:
|
|
398
|
-
node test-mcp.js # Run mock tests
|
|
399
|
-
node test-mcp.js --config # Show configuration examples
|
|
400
|
-
node test-mcp.js --real # Show real client examples
|
|
401
|
-
`);
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (args.includes('--config')) {
|
|
406
|
-
showConfigurationExamples();
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if (args.includes('--real')) {
|
|
411
|
-
await realMCPExample();
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// Run the test suite
|
|
416
|
-
await runTests();
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Handle errors
|
|
420
|
-
process.on('unhandledRejection', (error) => {
|
|
421
|
-
console.error('❌ Unhandled rejection:', error);
|
|
422
|
-
process.exit(1);
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
process.on('uncaughtException', (error) => {
|
|
426
|
-
console.error('❌ Uncaught exception:', error);
|
|
427
|
-
process.exit(1);
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
// Run main function
|
|
431
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
432
|
-
main().catch(console.error);
|
|
433
|
-
}
|
package/mcp/package.json
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "s3db-mcp-server",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Model Context Protocol (MCP) server for S3DB - Transform AWS S3 into a powerful document database",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "s3db_mcp_server.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"s3db-mcp": "./s3db_mcp_server.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"start": "node s3db_mcp_server.js",
|
|
12
|
-
"start:sse": "node s3db_mcp_server.js --transport=sse",
|
|
13
|
-
"start:stdio": "node s3db_mcp_server.js --transport=stdio",
|
|
14
|
-
"dev": "node --watch s3db_mcp_server.js --transport=sse",
|
|
15
|
-
"docker:build": "docker build -t s3db-mcp-server .",
|
|
16
|
-
"docker:run": "docker run -p 8000:8000 --env-file .env s3db-mcp-server",
|
|
17
|
-
"docker:compose": "docker compose up",
|
|
18
|
-
"docker:compose:build": "docker compose up --build",
|
|
19
|
-
"test": "echo 'Tests coming soon!' && exit 0"
|
|
20
|
-
},
|
|
21
|
-
"keywords": [
|
|
22
|
-
"mcp",
|
|
23
|
-
"model-context-protocol",
|
|
24
|
-
"s3db",
|
|
25
|
-
"s3",
|
|
26
|
-
"aws",
|
|
27
|
-
"database",
|
|
28
|
-
"document-database",
|
|
29
|
-
"ai-agent",
|
|
30
|
-
"llm"
|
|
31
|
-
],
|
|
32
|
-
"author": "S3DB Community",
|
|
33
|
-
"license": "UNLICENSED",
|
|
34
|
-
"repository": {
|
|
35
|
-
"type": "git",
|
|
36
|
-
"url": "git+https://github.com/forattini-dev/s3db.js.git",
|
|
37
|
-
"directory": "mcp-server"
|
|
38
|
-
},
|
|
39
|
-
"bugs": {
|
|
40
|
-
"url": "https://github.com/forattini-dev/s3db.js/issues"
|
|
41
|
-
},
|
|
42
|
-
"homepage": "https://github.com/forattini-dev/s3db.js/tree/main/mcp-server#readme",
|
|
43
|
-
"engines": {
|
|
44
|
-
"node": ">=18.0.0"
|
|
45
|
-
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
48
|
-
"s3db.js": "^7.2.1",
|
|
49
|
-
"dotenv": "^16.4.5"
|
|
50
|
-
},
|
|
51
|
-
"devDependencies": {
|
|
52
|
-
"@types/node": "^20.11.0"
|
|
53
|
-
},
|
|
54
|
-
"files": [
|
|
55
|
-
"s3db_mcp_server.js",
|
|
56
|
-
"README.md",
|
|
57
|
-
"Dockerfile",
|
|
58
|
-
"docker-compose.yml",
|
|
59
|
-
".env.example",
|
|
60
|
-
"Makefile",
|
|
61
|
-
"examples/"
|
|
62
|
-
],
|
|
63
|
-
"publishConfig": {
|
|
64
|
-
"access": "public"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
import { PartitionDriverError } from '../errors.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Base class for all partition drivers
|
|
6
|
-
* Defines the interface that all drivers must implement
|
|
7
|
-
*/
|
|
8
|
-
export class BasePartitionDriver extends EventEmitter {
|
|
9
|
-
constructor(options = {}) {
|
|
10
|
-
super();
|
|
11
|
-
this.options = options;
|
|
12
|
-
this.stats = {
|
|
13
|
-
queued: 0,
|
|
14
|
-
processed: 0,
|
|
15
|
-
failed: 0,
|
|
16
|
-
processing: 0
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Initialize the driver
|
|
22
|
-
*/
|
|
23
|
-
async initialize() {
|
|
24
|
-
// Override in subclasses if needed
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Queue partition operations for processing
|
|
29
|
-
* @param {Object} operation - The partition operation to queue
|
|
30
|
-
* @param {string} operation.type - 'create', 'update', or 'delete'
|
|
31
|
-
* @param {Object} operation.resource - The resource instance
|
|
32
|
-
* @param {Object} operation.data - The data for the operation
|
|
33
|
-
*/
|
|
34
|
-
async queue(operation) {
|
|
35
|
-
throw new PartitionDriverError('queue() must be implemented by subclass', {
|
|
36
|
-
driver: this.name || 'BasePartitionDriver',
|
|
37
|
-
operation: 'queue',
|
|
38
|
-
suggestion: 'Extend BasePartitionDriver and implement the queue() method'
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Process a single partition operation
|
|
44
|
-
*/
|
|
45
|
-
async processOperation(operation) {
|
|
46
|
-
const { type, resource, data } = operation;
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
this.stats.processing++;
|
|
50
|
-
|
|
51
|
-
switch (type) {
|
|
52
|
-
case 'create':
|
|
53
|
-
await resource.createPartitionReferences(data.object);
|
|
54
|
-
break;
|
|
55
|
-
|
|
56
|
-
case 'update':
|
|
57
|
-
await resource.handlePartitionReferenceUpdates(data.original, data.updated);
|
|
58
|
-
break;
|
|
59
|
-
|
|
60
|
-
case 'delete':
|
|
61
|
-
await resource.deletePartitionReferences(data.object);
|
|
62
|
-
break;
|
|
63
|
-
|
|
64
|
-
default:
|
|
65
|
-
throw new PartitionDriverError(`Unknown partition operation type: ${type}`, {
|
|
66
|
-
driver: this.name || 'BasePartitionDriver',
|
|
67
|
-
operation: type,
|
|
68
|
-
availableOperations: ['create', 'update', 'delete'],
|
|
69
|
-
suggestion: 'Use one of the supported partition operations: create, update, or delete'
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
this.stats.processed++;
|
|
74
|
-
this.emit('processed', operation);
|
|
75
|
-
|
|
76
|
-
} catch (error) {
|
|
77
|
-
this.stats.failed++;
|
|
78
|
-
this.emit('error', { operation, error });
|
|
79
|
-
throw error;
|
|
80
|
-
} finally {
|
|
81
|
-
this.stats.processing--;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Flush any pending operations
|
|
87
|
-
*/
|
|
88
|
-
async flush() {
|
|
89
|
-
// Override in subclasses if needed
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get driver statistics
|
|
94
|
-
*/
|
|
95
|
-
getStats() {
|
|
96
|
-
return { ...this.stats };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Shutdown the driver
|
|
101
|
-
*/
|
|
102
|
-
async shutdown() {
|
|
103
|
-
await this.flush();
|
|
104
|
-
this.removeAllListeners();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { SyncPartitionDriver } from './sync-partition-driver.js';
|
|
2
|
-
import { MemoryPartitionDriver } from './memory-partition-driver.js';
|
|
3
|
-
import { SQSPartitionDriver } from './sqs-partition-driver.js';
|
|
4
|
-
import { PartitionDriverError } from '../errors.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Partition driver factory
|
|
8
|
-
*/
|
|
9
|
-
export class PartitionDriverFactory {
|
|
10
|
-
static drivers = {
|
|
11
|
-
sync: SyncPartitionDriver,
|
|
12
|
-
memory: MemoryPartitionDriver,
|
|
13
|
-
sqs: SQSPartitionDriver
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Create a partition driver instance
|
|
18
|
-
* @param {string|Object} config - Driver name or configuration object
|
|
19
|
-
* @returns {BasePartitionDriver} Driver instance
|
|
20
|
-
*/
|
|
21
|
-
static create(config) {
|
|
22
|
-
// Handle string shorthand
|
|
23
|
-
if (typeof config === 'string') {
|
|
24
|
-
config = { driver: config };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Default to memory driver
|
|
28
|
-
const driverName = config.driver || 'memory';
|
|
29
|
-
|
|
30
|
-
// Get driver class
|
|
31
|
-
const DriverClass = this.drivers[driverName];
|
|
32
|
-
if (!DriverClass) {
|
|
33
|
-
throw new PartitionDriverError(`Unknown partition driver: ${driverName}`, {
|
|
34
|
-
driver: driverName,
|
|
35
|
-
operation: 'create',
|
|
36
|
-
availableDrivers: Object.keys(this.drivers),
|
|
37
|
-
suggestion: `Use one of the available drivers: ${Object.keys(this.drivers).join(', ')}, or register a custom driver`
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Create and initialize driver
|
|
42
|
-
const driver = new DriverClass(config);
|
|
43
|
-
|
|
44
|
-
return driver;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Register a custom driver
|
|
49
|
-
*/
|
|
50
|
-
static register(name, DriverClass) {
|
|
51
|
-
this.drivers[name] = DriverClass;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get available driver names
|
|
56
|
-
*/
|
|
57
|
-
static getAvailableDrivers() {
|
|
58
|
-
return Object.keys(this.drivers);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Export individual drivers
|
|
63
|
-
export { BasePartitionDriver } from './base-partition-driver.js';
|
|
64
|
-
export { SyncPartitionDriver } from './sync-partition-driver.js';
|
|
65
|
-
export { MemoryPartitionDriver } from './memory-partition-driver.js';
|
|
66
|
-
export { SQSPartitionDriver } from './sqs-partition-driver.js';
|