neural-loom 0.2.48 → 0.2.50

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 (127) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/cache/.previewinfo +1 -1
  5. package/.next/cache/.rscinfo +1 -1
  6. package/.next/cache/.tsbuildinfo +1 -1
  7. package/.next/diagnostics/route-bundle-stats.json +2 -2
  8. package/.next/fallback-build-manifest.json +3 -3
  9. package/.next/prerender-manifest.json +3 -3
  10. package/.next/routes-manifest.json +24 -0
  11. package/.next/server/app/_global-error.html +1 -1
  12. package/.next/server/app/_global-error.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  23. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  24. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  25. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  26. package/.next/server/app/api/context/aider/route.js.nft.json +1 -1
  27. package/.next/server/app/api/context/claude/route.js.nft.json +1 -1
  28. package/.next/server/app/api/context/route.js.nft.json +1 -1
  29. package/.next/server/app/api/context/ssh/route.js.nft.json +1 -1
  30. package/.next/server/app/api/recents/route.js.nft.json +1 -1
  31. package/.next/server/app/api/sessions/inject/route.js.nft.json +1 -1
  32. package/.next/server/app/api/sessions/input/route.js.nft.json +1 -1
  33. package/.next/server/app/api/sessions/launch/route.js.nft.json +1 -1
  34. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  35. package/.next/server/app/api/sessions/scope/route.js.nft.json +1 -1
  36. package/.next/server/app/api/sessions/start/route.js.nft.json +1 -1
  37. package/.next/server/app/api/sessions/stats/route.js.nft.json +1 -1
  38. package/.next/server/app/api/sessions/stop/route.js.nft.json +1 -1
  39. package/.next/server/app/api/sql/connections/route/app-paths-manifest.json +3 -0
  40. package/.next/server/app/api/sql/connections/route/build-manifest.json +9 -0
  41. package/.next/server/app/api/sql/connections/route/server-reference-manifest.json +4 -0
  42. package/.next/server/app/api/sql/connections/route.js +6 -0
  43. package/.next/server/app/api/sql/connections/route.js.map +5 -0
  44. package/.next/server/app/api/sql/connections/route.js.nft.json +1 -0
  45. package/.next/server/app/api/sql/connections/route_client-reference-manifest.js +3 -0
  46. package/.next/server/app/api/sql/mcp/route/app-paths-manifest.json +3 -0
  47. package/.next/server/app/api/sql/mcp/route/build-manifest.json +9 -0
  48. package/.next/server/app/api/sql/mcp/route/server-reference-manifest.json +4 -0
  49. package/.next/server/app/api/sql/mcp/route.js +6 -0
  50. package/.next/server/app/api/sql/mcp/route.js.map +5 -0
  51. package/.next/server/app/api/sql/mcp/route.js.nft.json +1 -0
  52. package/.next/server/app/api/sql/mcp/route_client-reference-manifest.js +3 -0
  53. package/.next/server/app/api/sql/query/route/app-paths-manifest.json +3 -0
  54. package/.next/server/app/api/sql/query/route/build-manifest.json +9 -0
  55. package/.next/server/app/api/sql/query/route/server-reference-manifest.json +4 -0
  56. package/.next/server/app/api/sql/query/route.js +6 -0
  57. package/.next/server/app/api/sql/query/route.js.map +5 -0
  58. package/.next/server/app/api/sql/query/route.js.nft.json +1 -0
  59. package/.next/server/app/api/sql/query/route_client-reference-manifest.js +3 -0
  60. package/.next/server/app/api/sql/schema/route/app-paths-manifest.json +3 -0
  61. package/.next/server/app/api/sql/schema/route/build-manifest.json +9 -0
  62. package/.next/server/app/api/sql/schema/route/server-reference-manifest.json +4 -0
  63. package/.next/server/app/api/sql/schema/route.js +6 -0
  64. package/.next/server/app/api/sql/schema/route.js.map +5 -0
  65. package/.next/server/app/api/sql/schema/route.js.nft.json +1 -0
  66. package/.next/server/app/api/sql/schema/route_client-reference-manifest.js +3 -0
  67. package/.next/server/app/index.html +1 -1
  68. package/.next/server/app/index.rsc +2 -2
  69. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  70. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  71. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  72. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  73. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  74. package/.next/server/app/page/react-loadable-manifest.json +1 -1
  75. package/.next/server/app/page_client-reference-manifest.js +1 -1
  76. package/.next/server/app-paths-manifest.json +4 -0
  77. package/.next/server/chunks/[root-of-the-server]__0.ptwor._.js +86 -0
  78. package/.next/server/chunks/[root-of-the-server]__0.ptwor._.js.map +1 -0
  79. package/.next/server/chunks/[root-of-the-server]__00l5btc._.js +74 -0
  80. package/.next/server/chunks/[root-of-the-server]__00l5btc._.js.map +1 -0
  81. package/.next/server/chunks/[root-of-the-server]__06men8g._.js +74 -0
  82. package/.next/server/chunks/[root-of-the-server]__06men8g._.js.map +1 -0
  83. package/.next/server/chunks/[root-of-the-server]__0_o7_jj._.js +1 -1
  84. package/.next/server/chunks/[root-of-the-server]__0_o7_jj._.js.map +1 -1
  85. package/.next/server/chunks/[root-of-the-server]__0co.g5k._.js +74 -0
  86. package/.next/server/chunks/[root-of-the-server]__0co.g5k._.js.map +1 -0
  87. package/.next/server/chunks/_next-internal_server_app_api_sql_connections_route_actions_11cib8~.js +3 -0
  88. package/.next/server/chunks/_next-internal_server_app_api_sql_connections_route_actions_11cib8~.js.map +1 -0
  89. package/.next/server/chunks/_next-internal_server_app_api_sql_mcp_route_actions_0wihfps.js +3 -0
  90. package/.next/server/chunks/_next-internal_server_app_api_sql_mcp_route_actions_0wihfps.js.map +1 -0
  91. package/.next/server/chunks/_next-internal_server_app_api_sql_query_route_actions_11x3q3c.js +3 -0
  92. package/.next/server/chunks/_next-internal_server_app_api_sql_query_route_actions_11x3q3c.js.map +1 -0
  93. package/.next/server/chunks/_next-internal_server_app_api_sql_schema_route_actions_015okwb.js +3 -0
  94. package/.next/server/chunks/_next-internal_server_app_api_sql_schema_route_actions_015okwb.js.map +1 -0
  95. package/.next/server/chunks/ssr/_0t7oqy6._.js +6 -1
  96. package/.next/server/chunks/ssr/_0t7oqy6._.js.map +1 -1
  97. package/.next/server/middleware-build-manifest.js +3 -3
  98. package/.next/server/pages/404.html +1 -1
  99. package/.next/server/pages/500.html +1 -1
  100. package/.next/server/server-reference-manifest.js +1 -1
  101. package/.next/server/server-reference-manifest.json +1 -1
  102. package/.next/static/chunks/01mol-lwap~v1.js +6 -0
  103. package/.next/static/chunks/0p28yw2f2duy-.js +1 -0
  104. package/.next/trace +1 -1
  105. package/.next/trace-build +1 -1
  106. package/.next/types/routes.d.ts +5 -1
  107. package/.next/types/validator.ts +36 -0
  108. package/bin/cli.js +76 -0
  109. package/package.json +2 -2
  110. package/src/app/api/sql/connections/route.ts +60 -0
  111. package/src/app/api/sql/mcp/route.ts +27 -0
  112. package/src/app/api/sql/query/route.ts +56 -0
  113. package/src/app/api/sql/schema/route.ts +42 -0
  114. package/src/app/components/DbExplorer.tsx +1279 -0
  115. package/src/app/components/IdeLayout.tsx +27 -1
  116. package/src/app/page.tsx +9 -0
  117. package/src/lib/sql/ConnectionManager.ts +207 -0
  118. package/src/lib/sql/DbAdapter.ts +62 -0
  119. package/src/lib/sql/McpServer.ts +278 -0
  120. package/src/lib/sql/adapters/MysqlAdapter.ts +120 -0
  121. package/src/lib/sql/adapters/PostgresAdapter.ts +139 -0
  122. package/src/lib/sql/adapters/SqliteAdapter.ts +111 -0
  123. package/.next/static/chunks/0bclk7hf35ac4.js +0 -1
  124. package/.next/static/chunks/15zf~gqr_i8s1.js +0 -1
  125. /package/.next/static/{V3HKuGO63wx4G9xwdUktP → df_RTMKU1wNmlZ4ehP9yW}/_buildManifest.js +0 -0
  126. /package/.next/static/{V3HKuGO63wx4G9xwdUktP → df_RTMKU1wNmlZ4ehP9yW}/_clientMiddlewareManifest.js +0 -0
  127. /package/.next/static/{V3HKuGO63wx4G9xwdUktP → df_RTMKU1wNmlZ4ehP9yW}/_ssgManifest.js +0 -0
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-turbopack","duration":2400498,"timestamp":41957255227,"id":14,"parentId":1,"tags":{},"startTime":1781521341455,"traceId":"ed5f6425c49aa8c3"},{"name":"turbopack-build-events","duration":60,"timestamp":41957547531,"id":15,"parentId":1,"tags":{},"startTime":1781521341747,"traceId":"ed5f6425c49aa8c3"},{"name":"run-typescript","duration":3994132,"timestamp":41959664799,"id":16,"parentId":1,"tags":{},"startTime":1781521343864,"traceId":"ed5f6425c49aa8c3"},{"name":"static-check","duration":727416,"timestamp":41963780366,"id":19,"parentId":1,"tags":{},"startTime":1781521347980,"traceId":"ed5f6425c49aa8c3"},{"name":"static-generation","duration":663703,"timestamp":41964514721,"id":59,"parentId":1,"tags":{},"startTime":1781521348714,"traceId":"ed5f6425c49aa8c3"},{"name":"telemetry-flush","duration":166644,"timestamp":41965213339,"id":68,"parentId":1,"tags":{},"startTime":1781521349413,"traceId":"ed5f6425c49aa8c3"},{"name":"next-build","duration":8232285,"timestamp":41957147721,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1781521341347,"traceId":"ed5f6425c49aa8c3"}]
1
+ [{"name":"run-turbopack","duration":2269054,"timestamp":102194000080,"id":14,"parentId":1,"tags":{},"startTime":1781581576793,"traceId":"4e174a7fcc75ba7c"},{"name":"turbopack-build-events","duration":60,"timestamp":102194283727,"id":15,"parentId":1,"tags":{},"startTime":1781581577077,"traceId":"4e174a7fcc75ba7c"},{"name":"run-typescript","duration":3887948,"timestamp":102196278261,"id":16,"parentId":1,"tags":{},"startTime":1781581579071,"traceId":"4e174a7fcc75ba7c"},{"name":"static-check","duration":764929,"timestamp":102200303106,"id":19,"parentId":1,"tags":{},"startTime":1781581583096,"traceId":"4e174a7fcc75ba7c"},{"name":"static-generation","duration":653484,"timestamp":102201074093,"id":67,"parentId":1,"tags":{},"startTime":1781581583867,"traceId":"4e174a7fcc75ba7c"},{"name":"telemetry-flush","duration":166012,"timestamp":102201761242,"id":76,"parentId":1,"tags":{},"startTime":1781581584554,"traceId":"4e174a7fcc75ba7c"},{"name":"next-build","duration":8031411,"timestamp":102193895871,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1781581576689,"traceId":"4e174a7fcc75ba7c"}]
@@ -2,7 +2,7 @@
2
2
  // Do not edit this file manually
3
3
 
4
4
  type AppRoutes = "/"
5
- type AppRouteHandlerRoutes = "/api/context" | "/api/context/aider" | "/api/context/claude" | "/api/context/ssh" | "/api/files" | "/api/git" | "/api/recents" | "/api/sessions" | "/api/sessions/inject" | "/api/sessions/input" | "/api/sessions/launch" | "/api/sessions/scope" | "/api/sessions/start" | "/api/sessions/stats" | "/api/sessions/stop"
5
+ type AppRouteHandlerRoutes = "/api/context" | "/api/context/aider" | "/api/context/claude" | "/api/context/ssh" | "/api/files" | "/api/git" | "/api/recents" | "/api/sessions" | "/api/sessions/inject" | "/api/sessions/input" | "/api/sessions/launch" | "/api/sessions/scope" | "/api/sessions/start" | "/api/sessions/stats" | "/api/sessions/stop" | "/api/sql/connections" | "/api/sql/mcp" | "/api/sql/query" | "/api/sql/schema"
6
6
  type PageRoutes = never
7
7
  type LayoutRoutes = "/"
8
8
  type RedirectRoutes = never
@@ -27,6 +27,10 @@ interface ParamMap {
27
27
  "/api/sessions/start": {}
28
28
  "/api/sessions/stats": {}
29
29
  "/api/sessions/stop": {}
30
+ "/api/sql/connections": {}
31
+ "/api/sql/mcp": {}
32
+ "/api/sql/query": {}
33
+ "/api/sql/schema": {}
30
34
  }
31
35
 
32
36
 
@@ -191,6 +191,42 @@ type RouteHandlerConfig<Route extends AppRouteHandlerRoutes = AppRouteHandlerRou
191
191
  type __Unused = __Check
192
192
  }
193
193
 
194
+ // Validate ../../src/app/api/sql/connections/route.ts
195
+ {
196
+ type __IsExpected<Specific extends RouteHandlerConfig<"/api/sql/connections">> = Specific
197
+ const handler = {} as typeof import("../../src/app/api/sql/connections/route.js")
198
+ type __Check = __IsExpected<typeof handler>
199
+ // @ts-ignore
200
+ type __Unused = __Check
201
+ }
202
+
203
+ // Validate ../../src/app/api/sql/mcp/route.ts
204
+ {
205
+ type __IsExpected<Specific extends RouteHandlerConfig<"/api/sql/mcp">> = Specific
206
+ const handler = {} as typeof import("../../src/app/api/sql/mcp/route.js")
207
+ type __Check = __IsExpected<typeof handler>
208
+ // @ts-ignore
209
+ type __Unused = __Check
210
+ }
211
+
212
+ // Validate ../../src/app/api/sql/query/route.ts
213
+ {
214
+ type __IsExpected<Specific extends RouteHandlerConfig<"/api/sql/query">> = Specific
215
+ const handler = {} as typeof import("../../src/app/api/sql/query/route.js")
216
+ type __Check = __IsExpected<typeof handler>
217
+ // @ts-ignore
218
+ type __Unused = __Check
219
+ }
220
+
221
+ // Validate ../../src/app/api/sql/schema/route.ts
222
+ {
223
+ type __IsExpected<Specific extends RouteHandlerConfig<"/api/sql/schema">> = Specific
224
+ const handler = {} as typeof import("../../src/app/api/sql/schema/route.js")
225
+ type __Check = __IsExpected<typeof handler>
226
+ // @ts-ignore
227
+ type __Unused = __Check
228
+ }
229
+
194
230
 
195
231
 
196
232
 
package/bin/cli.js CHANGED
@@ -4,6 +4,82 @@
4
4
  const { spawn } = require('child_process');
5
5
  const path = require('path');
6
6
 
7
+ if (process.argv[2] === 'mcp') {
8
+ const readline = require('readline');
9
+ const http = require('http');
10
+
11
+ let wsRoot = process.argv[3] || process.env.ORIGINAL_CWD || process.cwd();
12
+ wsRoot = path.resolve(wsRoot).replace(/\\/g, '/');
13
+
14
+ console.error(`[NeuralLoom MCP Bridge] Workspace context: ${wsRoot}`);
15
+ console.error(`[NeuralLoom MCP Bridge] Connecting to Next.js server on http://localhost:3000...`);
16
+
17
+ const rl = readline.createInterface({
18
+ input: process.stdin,
19
+ output: process.stdout,
20
+ terminal: false
21
+ });
22
+
23
+ rl.on('line', (line) => {
24
+ if (!line.trim()) return;
25
+
26
+ let requestObj;
27
+ try {
28
+ requestObj = JSON.parse(line);
29
+ } catch (e) {
30
+ const errResponse = {
31
+ jsonrpc: "2.0",
32
+ id: null,
33
+ error: { code: -32700, message: "Parse error" }
34
+ };
35
+ process.stdout.write(JSON.stringify(errResponse) + "\n");
36
+ return;
37
+ }
38
+
39
+ const payload = JSON.stringify(requestObj);
40
+ const options = {
41
+ hostname: 'localhost',
42
+ port: 3000,
43
+ path: '/api/sql/mcp',
44
+ method: 'POST',
45
+ headers: {
46
+ 'Content-Type': 'application/json',
47
+ 'Content-Length': Buffer.byteLength(payload),
48
+ 'x-workspace-root': wsRoot
49
+ }
50
+ };
51
+
52
+ const req = http.request(options, (res) => {
53
+ let data = '';
54
+ res.on('data', (chunk) => { data += chunk; });
55
+ res.on('end', () => {
56
+ if (res.statusCode === 204) {
57
+ return;
58
+ }
59
+ process.stdout.write(data + "\n");
60
+ });
61
+ });
62
+
63
+ req.on('error', (err) => {
64
+ console.error(`[NeuralLoom MCP Bridge ERROR] Failed to connect to local server: ${err.message}`);
65
+ const errResponse = {
66
+ jsonrpc: "2.0",
67
+ id: requestObj.id || null,
68
+ error: {
69
+ code: -32603,
70
+ message: "NeuralLoom backend server is offline. Please launch the dashboard first using 'npm run dev' or 'neural-loom'."
71
+ }
72
+ };
73
+ process.stdout.write(JSON.stringify(errResponse) + "\n");
74
+ });
75
+
76
+ req.write(payload);
77
+ req.end();
78
+ });
79
+
80
+ return;
81
+ }
82
+
7
83
  const originalCwd = process.cwd();
8
84
  const fs = require('fs');
9
85
  const os = require('os');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neural-loom",
3
- "version": "0.2.48",
3
+ "version": "0.2.50",
4
4
  "bin": {
5
5
  "neural-loom": "./bin/cli.js"
6
6
  },
@@ -37,4 +37,4 @@
37
37
  "eslint-config-next": "16.2.6",
38
38
  "typescript": "^5"
39
39
  }
40
- }
40
+ }
@@ -0,0 +1,60 @@
1
+ import { NextResponse } from "next/server";
2
+ import { ConnectionManager } from "@/lib/sql/ConnectionManager";
3
+
4
+ export async function GET(request: Request) {
5
+ try {
6
+ const { searchParams } = new URL(request.url);
7
+ const root = searchParams.get("root") || undefined;
8
+ const data = await ConnectionManager.getProfiles(root);
9
+ return NextResponse.json({ success: true, ...data });
10
+ } catch (error: any) {
11
+ return NextResponse.json({ error: error.message || String(error) }, { status: 500 });
12
+ }
13
+ }
14
+
15
+ export async function POST(request: Request) {
16
+ try {
17
+ const body = await request.json();
18
+ const { action, profile, isGlobal, root, profileId } = body;
19
+
20
+ if (action === "save") {
21
+ if (!profile || !profile.id || !profile.name || !profile.type) {
22
+ return NextResponse.json({ error: "Missing required profile parameters" }, { status: 400 });
23
+ }
24
+ await ConnectionManager.saveProfile(profile, !!isGlobal, root);
25
+ return NextResponse.json({ success: true, message: "Profile saved successfully" });
26
+ }
27
+
28
+ if (action === "delete") {
29
+ if (!profileId) {
30
+ return NextResponse.json({ error: "Missing required parameter 'profileId'" }, { status: 400 });
31
+ }
32
+ await ConnectionManager.deleteProfile(profileId, !!isGlobal, root);
33
+ return NextResponse.json({ success: true, message: "Profile deleted successfully" });
34
+ }
35
+
36
+ if (action === "set_active") {
37
+ await ConnectionManager.setActiveProfile(profileId || null, !!isGlobal, root);
38
+ return NextResponse.json({ success: true, message: "Active profile updated successfully" });
39
+ }
40
+
41
+ if (action === "test") {
42
+ if (!profile) {
43
+ return NextResponse.json({ error: "Missing required parameter 'profile'" }, { status: 400 });
44
+ }
45
+ const adapter = ConnectionManager.createAdapter(profile, root);
46
+ try {
47
+ await adapter.connect();
48
+ await adapter.listTables(); // Quick verify
49
+ await adapter.disconnect();
50
+ return NextResponse.json({ success: true, message: "Connection test successful!" });
51
+ } catch (err: any) {
52
+ return NextResponse.json({ success: false, error: err.message || String(err) });
53
+ }
54
+ }
55
+
56
+ return NextResponse.json({ error: "Invalid action" }, { status: 400 });
57
+ } catch (error: any) {
58
+ return NextResponse.json({ error: error.message || String(error) }, { status: 500 });
59
+ }
60
+ }
@@ -0,0 +1,27 @@
1
+ import { NextResponse } from "next/server";
2
+ import { McpServer } from "@/lib/sql/McpServer";
3
+
4
+ export async function POST(request: Request) {
5
+ try {
6
+ const workspaceRoot = request.headers.get("x-workspace-root") || undefined;
7
+ const body = await request.json();
8
+
9
+ const mcpServer = new McpServer(workspaceRoot);
10
+ const response = await mcpServer.handleMessage(body);
11
+
12
+ if (response === null) {
13
+ return new Response("", { status: 204 });
14
+ }
15
+
16
+ return NextResponse.json(response);
17
+ } catch (error: any) {
18
+ return NextResponse.json({
19
+ jsonrpc: "2.0",
20
+ id: null,
21
+ error: {
22
+ code: -32603,
23
+ message: "Internal server error: " + (error.message || String(error))
24
+ }
25
+ }, { status: 500 });
26
+ }
27
+ }
@@ -0,0 +1,56 @@
1
+ import { NextResponse } from "next/server";
2
+ import { ConnectionManager } from "@/lib/sql/ConnectionManager";
3
+
4
+ const isMutation = (sql: string): boolean => {
5
+ const clean = sql.trim().toLowerCase();
6
+ return (
7
+ clean.startsWith("insert") ||
8
+ clean.startsWith("update") ||
9
+ clean.startsWith("delete") ||
10
+ clean.startsWith("drop") ||
11
+ clean.startsWith("alter") ||
12
+ clean.startsWith("create") ||
13
+ clean.startsWith("truncate") ||
14
+ clean.startsWith("replace")
15
+ );
16
+ };
17
+
18
+ export async function POST(request: Request) {
19
+ try {
20
+ const body = await request.json();
21
+ const { sql, root } = body;
22
+
23
+ if (!sql || !sql.trim()) {
24
+ return NextResponse.json({ error: "Missing parameter 'sql'" }, { status: 400 });
25
+ }
26
+
27
+ const active = await ConnectionManager.getActiveAdapter(root);
28
+ if (!active) {
29
+ return NextResponse.json({
30
+ error: "No active database connection configured. Please set up and select an active profile in the database panel."
31
+ }, { status: 400 });
32
+ }
33
+
34
+ const { adapter, profile } = active;
35
+
36
+ if (profile.readOnly && isMutation(sql)) {
37
+ return NextResponse.json({
38
+ error: "This connection profile is configured as Read-Only. Modifications are disabled."
39
+ }, { status: 403 });
40
+ }
41
+
42
+ const startTime = Date.now();
43
+ const result = await adapter.query(sql);
44
+ const durationMs = Date.now() - startTime;
45
+
46
+ return NextResponse.json({
47
+ success: true,
48
+ rows: result.rows,
49
+ fields: result.fields,
50
+ affectedRows: result.affectedRows,
51
+ durationMs
52
+ });
53
+ } catch (error: any) {
54
+ return NextResponse.json({ error: error.message || String(error) }, { status: 500 });
55
+ }
56
+ }
@@ -0,0 +1,42 @@
1
+ import { NextResponse } from "next/server";
2
+ import { ConnectionManager } from "@/lib/sql/ConnectionManager";
3
+
4
+ export async function GET(request: Request) {
5
+ try {
6
+ const { searchParams } = new URL(request.url);
7
+ const root = searchParams.get("root") || undefined;
8
+ const action = searchParams.get("action");
9
+
10
+ const active = await ConnectionManager.getActiveAdapter(root);
11
+ if (!active) {
12
+ return NextResponse.json({
13
+ error: "No active database connection configured."
14
+ }, { status: 400 });
15
+ }
16
+
17
+ const { adapter } = active;
18
+
19
+ if (action === "list_tables") {
20
+ const tables = await adapter.listTables();
21
+ return NextResponse.json({ success: true, tables });
22
+ }
23
+
24
+ if (action === "describe_table") {
25
+ const table = searchParams.get("table");
26
+ if (!table) {
27
+ return NextResponse.json({ error: "Missing required parameter 'table'" }, { status: 400 });
28
+ }
29
+ const columns = await adapter.describeTable(table);
30
+ return NextResponse.json({ success: true, columns });
31
+ }
32
+
33
+ if (action === "summary") {
34
+ const summary = await adapter.getSchemaSummary();
35
+ return NextResponse.json({ success: true, summary });
36
+ }
37
+
38
+ return NextResponse.json({ error: "Invalid action. Must be 'list_tables', 'describe_table', or 'summary'" }, { status: 400 });
39
+ } catch (error: any) {
40
+ return NextResponse.json({ error: error.message || String(error) }, { status: 500 });
41
+ }
42
+ }