Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions app/api/code-completion/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
CodeSnippet,
batchGenerateCompletions,
} from '@/lib/code-completion'
import { getCurrentUser } from '@/lib/auth'
import { getDb } from '@/lib/db'

const LANG_EXTENSIONS: Record<string, string[]> = {
Expand All @@ -24,18 +25,20 @@ const LANG_EXTENSIONS: Record<string, string[]> = {
shell: ['.sh', '.bash'],
}

async function fetchSnippetsFromDb(language: string): Promise<CodeSnippet[]> {
async function fetchSnippetsFromDb(language: string, userId: string): Promise<CodeSnippet[]> {
try {
const sql = getDb()
const extensions = LANG_EXTENSIONS[language.toLowerCase()] ?? []
if (extensions.length === 0) return []

const rows = await sql`
SELECT id, path, name, extension, ai_summary, reusability_score, exports, imports
FROM repo_files
WHERE extension = ANY(${extensions}::text[])
AND ai_summary IS NOT NULL
ORDER BY reusability_score DESC
SELECT rf.id, rf.path, rf.name, rf.extension, rf.ai_summary, rf.reusability_score, rf.exports, rf.imports
FROM repo_files rf
INNER JOIN repositories r ON r.id = rf.repository_id
WHERE r.user_id = ${userId}
AND rf.extension = ANY(${extensions}::text[])
AND rf.ai_summary IS NOT NULL
ORDER BY rf.reusability_score DESC
LIMIT 20
`

Expand Down Expand Up @@ -63,6 +66,9 @@ async function fetchSnippetsFromDb(language: string): Promise<CodeSnippet[]> {

export async function POST(request: NextRequest) {
try {
const user = await getCurrentUser()
if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

const body = await request.json()
const { incompleteCode, codebaseSnippets = [], language = 'python' } = body

Expand All @@ -75,7 +81,7 @@ export async function POST(request: NextRequest) {

const snippets: CodeSnippet[] = codebaseSnippets.length > 0
? codebaseSnippets
: await fetchSnippetsFromDb(language)
: await fetchSnippetsFromDb(language, user.id)

const result = await generateRelevanceGuidedCompletion(
incompleteCode,
Expand Down Expand Up @@ -120,6 +126,9 @@ export async function POST(request: NextRequest) {
*/
export async function PUT(request: NextRequest) {
try {
const user = await getCurrentUser()
if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

const body = await request.json()
const { codeSnippets = [], codebaseSnippets = [], language = 'python' } = body

Expand All @@ -132,7 +141,7 @@ export async function PUT(request: NextRequest) {

const snippets: CodeSnippet[] = codebaseSnippets.length > 0
? codebaseSnippets
: await fetchSnippetsFromDb(language)
: await fetchSnippetsFromDb(language, user.id)

const results = await batchGenerateCompletions(
codeSnippets,
Expand Down
9 changes: 5 additions & 4 deletions app/api/projects/[id]/milestones/[milestoneId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export async function PATCH(
const user = await getCurrentUser()
if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

const { milestoneId } = await params
const { id, milestoneId } = await params
try {
const { completed } = await request.json()
const milestone = await toggleMilestone(milestoneId, Boolean(completed))
const milestone = await toggleMilestone(milestoneId, id, user.id, Boolean(completed))
if (!milestone) return NextResponse.json({ error: 'Not found' }, { status: 404 })
return NextResponse.json({ milestone })
} catch (err) {
Expand All @@ -28,9 +28,10 @@ export async function DELETE(
const user = await getCurrentUser()
if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

const { milestoneId } = await params
const { id, milestoneId } = await params
try {
await deleteMilestone(milestoneId)
const deleted = await deleteMilestone(milestoneId, id, user.id)
if (!deleted) return NextResponse.json({ error: 'Not found' }, { status: 404 })
return NextResponse.json({ ok: true })
} catch (err) {
console.error('[milestones/id] DELETE error:', err)
Expand Down
44 changes: 35 additions & 9 deletions lib/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,27 +1044,53 @@ export async function createMilestone(data: {
return result[0] as ProjectMilestone
}

export async function toggleMilestone(id: string, completed: boolean): Promise<ProjectMilestone | null> {
export async function toggleMilestone(
id: string,
projectId: string,
userId: string,
completed: boolean,
): Promise<ProjectMilestone | null> {
const sql = getDb()
const result = completed
? await sql`
UPDATE project_milestones
UPDATE project_milestones AS m
SET completed = true, completed_at = NOW()
WHERE id = ${id}
RETURNING *
FROM projects AS p
WHERE m.id = ${id}
AND m.project_id = ${projectId}
AND p.id = m.project_id
AND p.user_id = ${userId}
RETURNING m.*
`
: await sql`
UPDATE project_milestones
UPDATE project_milestones AS m
SET completed = false, completed_at = NULL
WHERE id = ${id}
RETURNING *
FROM projects AS p
WHERE m.id = ${id}
AND m.project_id = ${projectId}
AND p.id = m.project_id
AND p.user_id = ${userId}
RETURNING m.*
`
return (result[0] as ProjectMilestone) || null
}

export async function deleteMilestone(id: string): Promise<void> {
export async function deleteMilestone(
id: string,
projectId: string,
userId: string,
): Promise<boolean> {
const sql = getDb()
await sql`DELETE FROM project_milestones WHERE id = ${id}`
const result = await sql`
DELETE FROM project_milestones AS m
USING projects AS p
WHERE m.id = ${id}
AND m.project_id = ${projectId}
AND p.id = m.project_id
AND p.user_id = ${userId}
RETURNING m.id
`
return result.length > 0
}

export async function seedDefaultMilestones(projectId: string): Promise<void> {
Expand Down
Loading