s3db.js 12.0.1 → 12.2.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.
Files changed (45) hide show
  1. package/README.md +212 -196
  2. package/dist/s3db.cjs.js +1431 -4001
  3. package/dist/s3db.cjs.js.map +1 -1
  4. package/dist/s3db.es.js +1426 -3997
  5. package/dist/s3db.es.js.map +1 -1
  6. package/mcp/entrypoint.js +91 -57
  7. package/package.json +7 -1
  8. package/src/cli/index.js +954 -43
  9. package/src/cli/migration-manager.js +270 -0
  10. package/src/concerns/calculator.js +0 -4
  11. package/src/concerns/metadata-encoding.js +1 -21
  12. package/src/concerns/plugin-storage.js +17 -4
  13. package/src/concerns/typescript-generator.d.ts +171 -0
  14. package/src/concerns/typescript-generator.js +275 -0
  15. package/src/database.class.js +171 -28
  16. package/src/index.js +15 -9
  17. package/src/plugins/api/index.js +0 -1
  18. package/src/plugins/api/routes/resource-routes.js +86 -1
  19. package/src/plugins/api/server.js +79 -3
  20. package/src/plugins/api/utils/openapi-generator.js +195 -5
  21. package/src/plugins/backup/multi-backup-driver.class.js +0 -1
  22. package/src/plugins/backup.plugin.js +7 -14
  23. package/src/plugins/concerns/plugin-dependencies.js +73 -19
  24. package/src/plugins/eventual-consistency/analytics.js +0 -2
  25. package/src/plugins/eventual-consistency/consolidation.js +2 -13
  26. package/src/plugins/eventual-consistency/index.js +0 -1
  27. package/src/plugins/eventual-consistency/install.js +1 -1
  28. package/src/plugins/geo.plugin.js +5 -6
  29. package/src/plugins/importer/index.js +1 -1
  30. package/src/plugins/plugin.class.js +5 -0
  31. package/src/plugins/relation.plugin.js +193 -57
  32. package/src/plugins/replicator.plugin.js +12 -21
  33. package/src/plugins/s3-queue.plugin.js +4 -4
  34. package/src/plugins/scheduler.plugin.js +10 -12
  35. package/src/plugins/state-machine.plugin.js +8 -12
  36. package/src/plugins/tfstate/README.md +1 -1
  37. package/src/plugins/tfstate/errors.js +3 -3
  38. package/src/plugins/tfstate/index.js +41 -67
  39. package/src/plugins/ttl.plugin.js +479 -304
  40. package/src/resource.class.js +263 -61
  41. package/src/schema.class.js +0 -2
  42. package/src/testing/factory.class.js +286 -0
  43. package/src/testing/index.js +15 -0
  44. package/src/testing/seeder.class.js +183 -0
  45. package/dist/s3db-cli.js +0 -55543
package/mcp/entrypoint.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
5
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
6
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
7
7
  import { S3db, CachePlugin, CostsPlugin } from '../dist/s3db.es.js';
8
8
  import { FilesystemCache } from '../src/plugins/cache/filesystem-cache.class.js';
@@ -10,6 +10,7 @@ import { config } from 'dotenv';
10
10
  import { fileURLToPath } from 'url';
11
11
  import { dirname, join } from 'path';
12
12
  import { readFileSync } from 'fs';
13
+ import express from 'express';
13
14
 
14
15
  // Load environment variables
15
16
  config();
@@ -1109,70 +1110,103 @@ class S3dbMCPServer {
1109
1110
  }
1110
1111
 
1111
1112
  setupTransport() {
1112
- const transport = process.argv.includes('--transport=sse') || process.env.MCP_TRANSPORT === 'sse'
1113
- ? new SSEServerTransport('/sse', process.env.MCP_SERVER_HOST || '0.0.0.0', parseInt(process.env.MCP_SERVER_PORT || '17500'))
1114
- : new StdioServerTransport();
1115
-
1116
- this.server.connect(transport);
1117
-
1118
- // SSE specific setup
1119
- if (transport instanceof SSEServerTransport) {
1120
- const host = process.env.MCP_SERVER_HOST || '0.0.0.0';
1121
- const port = process.env.MCP_SERVER_PORT || '17500';
1122
-
1123
- console.log(`S3DB MCP Server running on http://${host}:${port}/sse`);
1124
-
1125
- // Add health check endpoint for SSE transport
1126
- this.setupHealthCheck(host, port);
1113
+ const useHttp = process.argv.includes('--transport=http') || process.env.MCP_TRANSPORT === 'http';
1114
+
1115
+ if (useHttp) {
1116
+ // Setup Express server for Streamable HTTP transport
1117
+ this.setupHttpTransport();
1118
+ } else {
1119
+ // Use stdio transport (default)
1120
+ const transport = new StdioServerTransport();
1121
+ this.server.connect(transport);
1127
1122
  }
1128
1123
  }
1129
1124
 
1130
- setupHealthCheck(host, port) {
1131
- import('http').then(({ createServer }) => {
1132
- const healthServer = createServer((req, res) => {
1133
- if (req.url === '/health') {
1134
- const healthStatus = {
1135
- status: 'healthy',
1136
- timestamp: new Date().toISOString(),
1137
- uptime: process.uptime(),
1138
- version: SERVER_VERSION,
1139
- database: {
1140
- connected: database ? database.isConnected() : false,
1141
- bucket: database?.bucket || null,
1142
- keyPrefix: database?.keyPrefix || null,
1143
- resourceCount: database ? Object.keys(database.resources || {}).length : 0
1144
- },
1145
- memory: process.memoryUsage(),
1146
- environment: {
1147
- nodeVersion: process.version,
1148
- platform: process.platform,
1149
- transport: 'sse'
1150
- }
1151
- };
1125
+ setupHttpTransport() {
1126
+ const host = process.env.MCP_SERVER_HOST || '0.0.0.0';
1127
+ const port = parseInt(process.env.MCP_SERVER_PORT || '17500');
1128
+
1129
+ const app = express();
1130
+ app.use(express.json());
1131
+
1132
+ // Enable CORS for browser-based clients
1133
+ app.use((req, res, next) => {
1134
+ res.header('Access-Control-Allow-Origin', '*');
1135
+ res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
1136
+ res.header('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');
1137
+ res.header('Access-Control-Expose-Headers', 'Mcp-Session-Id');
1138
+
1139
+ if (req.method === 'OPTIONS') {
1140
+ return res.sendStatus(200);
1141
+ }
1142
+ next();
1143
+ });
1144
+
1145
+ // Streamable HTTP endpoint (stateless mode - recommended)
1146
+ app.post('/mcp', async (req, res) => {
1147
+ try {
1148
+ // Create a new transport for each request to prevent request ID collisions
1149
+ const transport = new StreamableHTTPServerTransport({
1150
+ sessionIdGenerator: undefined,
1151
+ enableJsonResponse: true
1152
+ });
1153
+
1154
+ res.on('close', () => {
1155
+ transport.close();
1156
+ });
1152
1157
 
1153
- res.writeHead(200, {
1154
- 'Content-Type': 'application/json',
1155
- 'Access-Control-Allow-Origin': '*',
1156
- 'Access-Control-Allow-Methods': 'GET',
1157
- 'Access-Control-Allow-Headers': 'Content-Type'
1158
+ await this.server.connect(transport);
1159
+ await transport.handleRequest(req, res, req.body);
1160
+ } catch (error) {
1161
+ console.error('Error handling MCP request:', error);
1162
+ if (!res.headersSent) {
1163
+ res.status(500).json({
1164
+ jsonrpc: '2.0',
1165
+ error: {
1166
+ code: -32603,
1167
+ message: 'Internal server error'
1168
+ },
1169
+ id: null
1158
1170
  });
1159
- res.end(JSON.stringify(healthStatus, null, 2));
1160
- } else {
1161
- res.writeHead(404, { 'Content-Type': 'text/plain' });
1162
- res.end('Not Found');
1163
1171
  }
1164
- });
1172
+ }
1173
+ });
1165
1174
 
1166
- // Listen on a different port for health checks to avoid conflicts
1167
- const healthPort = parseInt(port) + 1;
1168
- healthServer.listen(healthPort, host, () => {
1169
- console.log(`Health check endpoint: http://${host}:${healthPort}/health`);
1170
- });
1171
- }).catch(err => {
1172
- console.warn('Could not setup health check endpoint:', err.message);
1175
+ // Health check endpoint
1176
+ app.get('/health', (req, res) => {
1177
+ const healthStatus = {
1178
+ status: 'healthy',
1179
+ timestamp: new Date().toISOString(),
1180
+ uptime: process.uptime(),
1181
+ version: SERVER_VERSION,
1182
+ database: {
1183
+ connected: database ? database.isConnected() : false,
1184
+ bucket: database?.bucket || null,
1185
+ keyPrefix: database?.keyPrefix || null,
1186
+ resourceCount: database ? Object.keys(database.resources || {}).length : 0
1187
+ },
1188
+ memory: process.memoryUsage(),
1189
+ environment: {
1190
+ nodeVersion: process.version,
1191
+ platform: process.platform,
1192
+ transport: 'streamable-http'
1193
+ }
1194
+ };
1195
+
1196
+ res.json(healthStatus);
1197
+ });
1198
+
1199
+ // Start Express server
1200
+ app.listen(port, host, () => {
1201
+ console.log(`S3DB MCP Server running on http://${host}:${port}/mcp`);
1202
+ console.log(`Health check endpoint: http://${host}:${port}/health`);
1203
+ }).on('error', error => {
1204
+ console.error('Server error:', error);
1205
+ process.exit(1);
1173
1206
  });
1174
1207
  }
1175
1208
 
1209
+
1176
1210
  // 📖 DOCUMENTATION TOOLS HANDLERS
1177
1211
 
1178
1212
  async handleS3dbQueryDocs(args) {
@@ -2718,8 +2752,8 @@ async function main() {
2718
2752
 
2719
2753
  console.log(`S3DB MCP Server v${SERVER_VERSION} started`);
2720
2754
  console.log(`Transport: ${args.transport}`);
2721
- if (args.transport === 'sse') {
2722
- console.log(`URL: http://${args.host}:${args.port}/sse`);
2755
+ if (args.transport === 'http') {
2756
+ console.log(`URL: http://${args.host}:${args.port}/mcp`);
2723
2757
  }
2724
2758
  }
2725
2759
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3db.js",
3
- "version": "12.0.1",
3
+ "version": "12.2.0",
4
4
  "description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
5
5
  "main": "dist/s3db.cjs.js",
6
6
  "module": "dist/s3db.es.js",
@@ -52,6 +52,11 @@
52
52
  "types": "./dist/s3db.d.ts",
53
53
  "import": "./dist/s3db.es.js",
54
54
  "require": "./dist/s3db.cjs.js"
55
+ },
56
+ "./typescript-generator": {
57
+ "types": "./src/concerns/typescript-generator.d.ts",
58
+ "import": "./src/concerns/typescript-generator.js",
59
+ "require": "./src/concerns/typescript-generator.js"
55
60
  }
56
61
  },
57
62
  "files": [
@@ -70,6 +75,7 @@
70
75
  "@smithy/node-http-handler": "^4.4.2",
71
76
  "@supercharge/promise-pool": "^3.2.0",
72
77
  "dotenv": "^17.2.3",
78
+ "express": "^5.1.0",
73
79
  "fastest-validator": "^1.19.1",
74
80
  "flat": "^6.0.1",
75
81
  "glob": "^11.0.3",