-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restyling #188
Restyling #188
Changes from 18 commits
5fb6d51
b652d8b
a80b174
ec11a2a
ecbef2a
e7c8d76
706b487
fbe93b2
3d0ad9e
98f3cb6
56ce407
d80b8f3
9920291
8f85cdd
1426b64
6c72394
96e29aa
e447054
938dec2
679b236
d1de315
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { NextRequest, NextResponse } from "next/server" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function POST(request: NextRequest, { params }: { params: { graph: string } }) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const graphName = params.graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const msg = request.nextUrl.searchParams.get('msg') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and type safety The route handler lacks proper input validation and type definitions. Consider implementing these improvements: +interface ChatRequest {
+ repo: string;
+ msg: string;
+}
+
+interface ChatResponse {
+ result: unknown;
+}
+
export async function POST(request: NextRequest, { params }: { params: { graph: string } }) {
const graphName = params.graph
const msg = request.nextUrl.searchParams.get('msg')
+
+ if (!msg?.trim()) {
+ return NextResponse.json(
+ { message: 'Message is required' },
+ { status: 400 }
+ )
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const result = await fetch(`http://127.0.0.1:5000/chat`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
method: 'POST', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
body: JSON.stringify({ repo: graphName, msg}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Content-Type": 'application/json' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!result.ok) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error(await result.text()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const json = await result.json() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance API call resilience The API call implementation lacks timeout handling and retry mechanism, which could lead to poor user experience during network issues or server delays. Consider implementing these improvements: +const TIMEOUT_MS = 10000
+const MAX_RETRIES = 3
+
try {
- const result = await fetch(`http://127.0.0.1:5000/chat`, {
+ const controller = new AbortController()
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS)
+
+ let lastError: Error | null = null
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
+ try {
+ const result = await fetch(`${env.CHAT_API_URL}/chat`, {
method: 'POST',
body: JSON.stringify({ repo: graphName, msg}),
headers: {
"Content-Type": 'application/json'
- }
+ },
+ signal: controller.signal
})
+ clearTimeout(timeoutId)
if (!result.ok) {
- throw new Error(await result.text())
+ const errorText = await result.text()
+ throw new Error(`Server error: ${result.status} - ${errorText}`)
}
const json = await result.json()
+ return NextResponse.json({ result: json }, { status: 200 })
+ } catch (err) {
+ lastError = err as Error
+ if (err.name === 'AbortError') {
+ throw new Error('Request timeout')
+ }
+ // Only retry on network errors
+ if (!err.message.startsWith('Server error:')) {
+ await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
+ continue
+ }
+ throw err
+ }
+ }
+ throw lastError || new Error('Max retries reached') 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ result: json }, { status: 200 }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ message: (err as Error).message }, { status: 400 }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+25
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve error handling and add logging The current error handling is too generic and lacks proper logging, making it difficult to debug issues in production. Consider implementing these improvements: - return NextResponse.json({ message: (err as Error).message }, { status: 400 })
+ console.error('[ChatAPI] Error:', err)
+
+ if (err.message === 'Request timeout') {
+ return NextResponse.json(
+ { error: 'Request timed out', code: 'TIMEOUT' },
+ { status: 408 }
+ )
+ }
+
+ if (err.message.startsWith('Server error:')) {
+ return NextResponse.json(
+ { error: 'Chat service error', code: 'SERVER_ERROR' },
+ { status: 502 }
+ )
+ }
+
+ return NextResponse.json(
+ { error: 'Internal server error', code: 'INTERNAL_ERROR' },
+ { status: 500 }
+ )
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add rate limiting to prevent abuse The chat endpoint is vulnerable to abuse as it lacks rate limiting. This could lead to excessive load on both your server and the chat service. Consider implementing rate limiting using a Redis-based solution or Next.js middleware: // app/api/chat/[graph]/middleware.ts
import { rateLimit } from '@/lib/rate-limit'
import { NextResponse } from 'next/server'
const limiter = rateLimit({
interval: 60 * 1000, // 1 minute
uniqueTokenPerInterval: 500,
limit: 10, // requests per interval
})
export async function middleware(request: Request) {
try {
await limiter.check(request)
return NextResponse.next()
} catch {
return new NextResponse('Too Many Requests', { status: 429 })
}
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,24 +1,51 @@ | ||||||||||||||||||||||||||||||||||||||||
import { FalkorDB, Graph } from "falkordb"; | ||||||||||||||||||||||||||||||||||||||||
import { NextRequest, NextResponse } from "next/server"; | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
export async function GET(request: NextRequest, { params }: { params: { graph: string, node: string } }) { | ||||||||||||||||||||||||||||||||||||||||
const nodeId = parseInt(params.node); | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const nodeId = parseInt(params.node); | ||||||||||||||||||||||||||||||||||||||||
const graphId = params.graph; | ||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Ensure consistent parsing of In the Apply this diff to make parsing consistent in the - const nodeId = params.node;
+ const nodeId = parseInt(params.node); Also applies to: 23-24 |
||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const result = await fetch(`http://127.0.0.1:5000/get_neighbors?repo=${graphId}&node_id=${nodeId}`, { | ||||||||||||||||||||||||||||||||||||||||
method: 'GET', | ||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const json = await result.json() | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ result: json }, { status: 200 }) | ||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ massage: (err as Error).message }, { status: 400 }) | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Check response status before processing in In the Apply this diff to add response status check: const result = await fetch(`http://127.0.0.1:5000/get_neighbors?repo=${graphId}&node_id=${nodeId}`, {
method: 'GET',
})
+ if (!result.ok) {
+ throw new Error(await result.text())
+ } This aligns error handling in the 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct typo in error response property name from 'massage' to 'message'. In both the Apply this diff to fix the typo: - return NextResponse.json({ massage: (err as Error).message }, { status: 400 })
+ return NextResponse.json({ message: (err as Error).message }, { status: 400 })
- return NextResponse.json({ massage: (err as Error).message }, { status: 200 })
+ return NextResponse.json({ message: (err as Error).message }, { status: 400 }) Note: Also updated the status code in the Also applies to: 49-49 |
||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
export async function POST(request: NextRequest, { params }: { params: { graph: string, node: string } }) { | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const nodeId = params.node; | ||||||||||||||||||||||||||||||||||||||||
const graphId = params.graph; | ||||||||||||||||||||||||||||||||||||||||
const targetId = request.nextUrl.searchParams.get('targetId') | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential null value of The Apply this diff to add a null check for const targetId = request.nextUrl.searchParams.get('targetId')
+ if (!targetId) {
+ return NextResponse.json({ message: 'targetId is required' }, { status: 400 })
+ } Also applies to: 37-37 |
||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const db = await FalkorDB.connect({url: process.env.FALKORDB_URL || 'falkor://localhost:6379',}); | ||||||||||||||||||||||||||||||||||||||||
const graph = db.selectGraph(graphId); | ||||||||||||||||||||||||||||||||||||||||
const result = await fetch(`http://127.0.0.1:5000/find_paths`, { | ||||||||||||||||||||||||||||||||||||||||
method: 'POST', | ||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||
'Content-Type': 'application/json' | ||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||
body: JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||
repo: graphId, | ||||||||||||||||||||||||||||||||||||||||
src: Number(nodeId), | ||||||||||||||||||||||||||||||||||||||||
dest: Number(targetId!) | ||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
// Get node's neighbors | ||||||||||||||||||||||||||||||||||||||||
const q_params = {nodeId: nodeId}; | ||||||||||||||||||||||||||||||||||||||||
const query = `MATCH (src)-[e]-(n) | ||||||||||||||||||||||||||||||||||||||||
WHERE ID(src) = $nodeId | ||||||||||||||||||||||||||||||||||||||||
RETURN collect(distinct { label:labels(n)[0], id:ID(n), name: n.name } ) as nodes, | ||||||||||||||||||||||||||||||||||||||||
collect( { src: ID(startNode(e)), id: ID(e), dest: ID(endNode(e)), type: type(e) } ) as edges`; | ||||||||||||||||||||||||||||||||||||||||
if (!result.ok) { | ||||||||||||||||||||||||||||||||||||||||
throw new Error(await result.text()) | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
let res: any = await graph.query(query, { params: q_params }); | ||||||||||||||||||||||||||||||||||||||||
let nodes = res.data[0]['nodes']; | ||||||||||||||||||||||||||||||||||||||||
let edges = res.data[0]['edges']; | ||||||||||||||||||||||||||||||||||||||||
const json = await result.json() | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ id: graphId, nodes: nodes, edges: edges }, { status: 200 }) | ||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ result: json }, { status: 200 }) | ||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||
return NextResponse.json({ massage: (err as Error).message }, { status: 200 }) | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
Comment on lines
+53
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Return appropriate error status code in In the Apply this diff to fix the status code: - return NextResponse.json({ message: (err as Error).message }, { status: 200 })
+ return NextResponse.json({ message: (err as Error).message }, { status: 400 }) 📝 Committable suggestion
Suggested change
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move hardcoded URL to environment variable
The server URL should not be hardcoded in the code. Consider using environment variables for better configuration management across different environments.
Add this to your
.env
file:+CHAT_API_URL=http://127.0.0.1:5000
Then modify the imports:
import { NextRequest, NextResponse } from "next/server" +import { env } from "@/env.mjs"