Skip to content

Commit 150caa4

Browse files
committed
Refactor devlog services and schema for improved document handling and metadata management
1 parent 434eb8b commit 150caa4

File tree

9 files changed

+212
-132
lines changed

9 files changed

+212
-132
lines changed

apps/web/app/api/projects/[name]/devlogs/[devlogId]/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ export async function PUT(
107107
updatedEntry.closedAt = null;
108108
}
109109

110-
await devlogService.save(updatedEntry);
110+
const result = await devlogService.update(devlogId, updatedEntry);
111111

112112
// Transform and return updated entry
113-
return createSuccessResponse(updatedEntry, { sseEventType: RealtimeEventType.DEVLOG_UPDATED });
113+
return createSuccessResponse(result, { sseEventType: RealtimeEventType.DEVLOG_UPDATED });
114114
} catch (error) {
115115
console.error('Error updating devlog:', error);
116116
const message = error instanceof Error ? error.message : 'Failed to update devlog';

apps/web/app/api/projects/[name]/devlogs/route.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,30 +128,17 @@ export async function POST(request: NextRequest, { params }: { params: { name: s
128128
const devlogService = PrismaDevlogService.getInstance(project.id);
129129
await devlogService.ensureInitialized();
130130

131-
// Add required fields and get next ID
132-
const now = new Date().toISOString();
133-
const nextId = await devlogService.getNextId();
134-
131+
// Prepare entry for creation
135132
const entry = {
136133
...bodyValidation.data,
137-
id: nextId,
138-
createdAt: now,
139-
updatedAt: now,
140134
projectId: project.id, // Ensure project context
141135
};
142136

143-
// Save the entry
144-
await devlogService.save(entry);
145-
146-
// Retrieve the actual saved entry to ensure we have the correct ID
147-
const savedEntry = await devlogService.get(nextId);
148-
149-
if (!savedEntry) {
150-
throw new Error('Failed to retrieve saved devlog entry');
151-
}
137+
// Create the entry
138+
const result = await devlogService.create(entry);
152139

153-
// Transform and return the actual saved devlog
154-
return createSuccessResponse(savedEntry, {
140+
// Transform and return the created devlog
141+
return createSuccessResponse(result, {
155142
status: 201,
156143
sseEventType: RealtimeEventType.DEVLOG_CREATED,
157144
});

apps/web/app/api/projects/[name]/devlogs/search/route.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,27 +76,27 @@ export async function GET(request: NextRequest, { params }: { params: { name: st
7676
if (queryData.fromDate) filter.fromDate = queryData.fromDate;
7777
if (queryData.toDate) filter.toDate = queryData.toDate;
7878

79-
// Perform the enhanced search using PrismaDevlogService
80-
const result = await devlogService.searchWithRelevance(searchQuery, filter);
79+
// Perform the search using PrismaDevlogService
80+
const result = await devlogService.search(searchQuery, filter);
8181

8282
// Transform the response to match the expected interface
8383
const response: SearchResponse = {
84-
query: result.searchMeta.query,
84+
query: searchQuery,
8585
results: result.items.map((item) => ({
86-
entry: item.entry,
87-
relevance: item.relevance,
88-
matchedFields: item.matchedFields,
89-
highlights: item.highlights,
86+
entry: item,
87+
relevance: 1.0, // Default relevance since we don't have relevance scoring yet
88+
matchedFields: ['title', 'description'], // Default matched fields
89+
highlights: undefined,
9090
})),
9191
pagination: {
9292
...result.pagination,
9393
total: result.pagination.total ?? 0,
9494
totalPages: result.pagination.totalPages ?? 0,
9595
},
9696
searchMeta: {
97-
searchTime: result.searchMeta.searchTime,
98-
totalMatches: result.searchMeta.totalMatches,
99-
appliedFilters: result.searchMeta.appliedFilters,
97+
searchTime: 0, // Default search time since we don't track it yet
98+
totalMatches: result.pagination.total ?? 0,
99+
appliedFilters: filter,
100100
},
101101
};
102102

apps/web/app/api/projects/[name]/devlogs/stats/timeseries/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const GET = withErrorHandling(
5151

5252
// Get devlog service and time series stats
5353
const devlogService = await ServiceHelper.getPrismaDevlogService(project.id);
54-
const stats = await devlogService.getTimeSeriesStats(project.id, timeSeriesRequest);
54+
const stats = await devlogService.getTimeSeries(timeSeriesRequest);
5555

5656
return createSuccessResponse(stats);
5757
},

apps/web/lib/realtime/realtime-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class RealtimeService {
8585
*/
8686
async connect(): Promise<void> {
8787
if (!this.initialized) {
88-
await this.ensureInitialized();
88+
await this.initialize();
8989
} else if (this.provider) {
9090
await this.provider.connect();
9191
}

packages/core/src/services/prisma-devlog-service.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ export class PrismaDevlogService extends PrismaServiceBase {
283283
/**
284284
* List devlog entries with filtering and pagination
285285
*/
286-
async list(filter?: DevlogFilter, sort?: SortOptions, pagination?: { limit?: number; offset?: number }): Promise<PaginatedResult<DevlogEntry>> {
286+
async list(filter?: DevlogFilter, pagination?: { limit?: number; offset?: number }, sort?: SortOptions): Promise<PaginatedResult<DevlogEntry>> {
287287
await this.ensureInitialized();
288288

289289
try {
@@ -555,7 +555,19 @@ export class PrismaDevlogService extends PrismaServiceBase {
555555
*/
556556
private mapPrismaToDevlogEntry(prismaEntry: PrismaDevlogEntry & {
557557
notes?: Array<{ id: string; timestamp: Date; category: string; content: string }>;
558-
documents?: Array<{ id: string; title: string; content: string; contentType: string; createdAt: Date; updatedAt: Date }>;
558+
documents?: Array<{
559+
id: string;
560+
filename: string;
561+
originalName: string;
562+
mimeType: string;
563+
size: number;
564+
type: string;
565+
textContent: string | null;
566+
metadata: any;
567+
uploadedBy: string | null;
568+
createdAt: Date;
569+
updatedAt: Date;
570+
}>;
559571
}): DevlogEntry {
560572
return {
561573
id: prismaEntry.id,
@@ -583,13 +595,15 @@ export class PrismaDevlogService extends PrismaServiceBase {
583595
documents: prismaEntry.documents?.map((doc) => ({
584596
id: doc.id,
585597
devlogId: prismaEntry.id,
586-
filename: doc.title,
587-
originalName: doc.title,
588-
mimeType: doc.contentType,
589-
size: 0, // Will need to calculate this
590-
type: 'text' as any, // Will need to determine from contentType
591-
content: doc.content,
598+
filename: doc.filename,
599+
originalName: doc.originalName,
600+
mimeType: doc.mimeType,
601+
size: doc.size,
602+
type: doc.type as any,
603+
content: doc.textContent || undefined,
604+
metadata: doc.metadata || {},
592605
uploadedAt: doc.createdAt.toISOString(),
606+
uploadedBy: doc.uploadedBy || undefined,
593607
})) || [],
594608
};
595609
}

packages/core/src/services/prisma-document-service.ts

Lines changed: 35 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,24 @@ export class PrismaDocumentService extends PrismaServiceBase {
110110
const documentType = this.determineDocumentType(file.mimeType, file.originalName);
111111
const textContent = this.extractTextContent(file.content, documentType);
112112

113-
// Store both text content and metadata as JSON in the content field
114-
const documentContent = JSON.stringify({
115-
originalName: file.originalName,
116-
mimeType: file.mimeType,
117-
size: file.size,
118-
type: documentType,
119-
uploadedBy,
120-
metadata: metadata || {},
121-
textContent: textContent || '',
122-
binaryContent: Buffer.isBuffer(file.content)
123-
? file.content.toString('base64')
124-
: Buffer.from(file.content, 'utf-8').toString('base64')
125-
});
113+
// Prepare binary content
114+
const binaryContent = Buffer.isBuffer(file.content)
115+
? file.content
116+
: Buffer.from(file.content, 'utf-8');
126117

127118
const document = await this.prismaClient!.devlogDocument.create({
128119
data: {
129120
id: documentId,
130121
devlogId: Number(devlogId),
131-
title: file.originalName,
132-
content: documentContent,
133-
contentType: file.mimeType,
122+
filename: documentId,
123+
originalName: file.originalName,
124+
mimeType: file.mimeType,
125+
size: file.size,
126+
type: documentType,
127+
textContent: textContent || null,
128+
binaryContent: binaryContent,
129+
metadata: metadata || {},
130+
uploadedBy: uploadedBy || null,
134131
},
135132
});
136133

@@ -202,24 +199,10 @@ export class PrismaDocumentService extends PrismaServiceBase {
202199
try {
203200
const document = await this.prismaClient!.devlogDocument.findUnique({
204201
where: { id: documentId },
205-
select: { content: true },
202+
select: { binaryContent: true },
206203
});
207204

208-
if (!document?.content) {
209-
return null;
210-
}
211-
212-
try {
213-
const parsedContent = JSON.parse(document.content);
214-
if (parsedContent.binaryContent) {
215-
return Buffer.from(parsedContent.binaryContent, 'base64');
216-
}
217-
} catch {
218-
// If content is not JSON, treat as plain text
219-
return Buffer.from(document.content, 'utf-8');
220-
}
221-
222-
return null;
205+
return document?.binaryContent ? Buffer.from(document.binaryContent) : null;
223206
} catch (error) {
224207
console.error('[DocumentService] Failed to get document content:', error);
225208
throw new Error(`Failed to get document content: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -249,13 +232,14 @@ export class PrismaDocumentService extends PrismaServiceBase {
249232
try {
250233
const where: any = {
251234
OR: [
252-
{ title: { contains: query, mode: 'insensitive' } },
253-
{ content: { contains: query, mode: 'insensitive' } },
235+
{ originalName: { contains: query, mode: 'insensitive' } },
236+
{ textContent: { contains: query, mode: 'insensitive' } },
254237
],
255238
};
256239

257240
if (options?.devlogId) where.devlogId = Number(options.devlogId);
258-
if (options?.mimeType) where.contentType = { contains: options.mimeType };
241+
if (options?.type) where.type = options.type;
242+
if (options?.mimeType) where.mimeType = { contains: options.mimeType };
259243

260244
const [documents, total] = await Promise.all([
261245
this.prismaClient!.devlogDocument.findMany({
@@ -309,19 +293,13 @@ export class PrismaDocumentService extends PrismaServiceBase {
309293
throw new Error('Document not found');
310294
}
311295

312-
// Parse existing content and update metadata
313-
let parsedContent;
314-
try {
315-
parsedContent = JSON.parse(existingDoc.content);
316-
} catch {
317-
parsedContent = { metadata: {} };
318-
}
319-
320-
parsedContent.metadata = { ...parsedContent.metadata, ...metadata };
296+
// Merge with existing metadata
297+
const existingMetadata = existingDoc.metadata as Record<string, any> || {};
298+
const updatedMetadata = { ...existingMetadata, ...metadata };
321299

322300
const document = await this.prismaClient!.devlogDocument.update({
323301
where: { id: documentId },
324-
data: { content: JSON.stringify(parsedContent) },
302+
data: { metadata: updatedMetadata },
325303
});
326304

327305
return this.mapPrismaToDocument(document);
@@ -395,28 +373,17 @@ export class PrismaDocumentService extends PrismaServiceBase {
395373
try {
396374
const documents = await this.prismaClient!.devlogDocument.findMany({
397375
where: { devlogId: Number(devlogId) },
398-
select: { content: true, contentType: true },
376+
select: { size: true, type: true },
399377
});
400378

401379
const totalDocuments = documents.length;
402380
let totalSize = 0;
403381
const typeBreakdown: Record<string, number> = {};
404382

405383
documents.forEach(doc => {
406-
try {
407-
const parsedContent = JSON.parse(doc.content);
408-
if (parsedContent.size) {
409-
totalSize += parsedContent.size;
410-
}
411-
if (parsedContent.type) {
412-
typeBreakdown[parsedContent.type] = (typeBreakdown[parsedContent.type] || 0) + 1;
413-
}
414-
} catch {
415-
// If content is not JSON, estimate size and use contentType
416-
totalSize += doc.content.length;
417-
const documentType = this.determineDocumentType(doc.contentType, '');
418-
typeBreakdown[documentType] = (typeBreakdown[documentType] || 0) + 1;
419-
}
384+
totalSize += doc.size;
385+
const documentType = doc.type as DocumentType;
386+
typeBreakdown[documentType] = (typeBreakdown[documentType] || 0) + 1;
420387
});
421388

422389
return {
@@ -497,34 +464,18 @@ export class PrismaDocumentService extends PrismaServiceBase {
497464
* Map Prisma document entity to domain type
498465
*/
499466
private mapPrismaToDocument(prismaDoc: any): DevlogDocument {
500-
// Try to parse the content as JSON to extract structured data
501-
let parsedContent: any = {};
502-
try {
503-
parsedContent = JSON.parse(prismaDoc.content);
504-
} catch {
505-
// If content is not JSON, treat as plain text content
506-
parsedContent = {
507-
textContent: prismaDoc.content,
508-
originalName: prismaDoc.title,
509-
mimeType: prismaDoc.contentType,
510-
type: this.determineDocumentType(prismaDoc.contentType, prismaDoc.title),
511-
size: prismaDoc.content.length,
512-
metadata: {},
513-
};
514-
}
515-
516467
return {
517468
id: prismaDoc.id,
518469
devlogId: prismaDoc.devlogId,
519-
filename: prismaDoc.id, // Use ID as filename since we don't store it separately
520-
originalName: parsedContent.originalName || prismaDoc.title,
521-
mimeType: parsedContent.mimeType || prismaDoc.contentType,
522-
size: parsedContent.size || prismaDoc.content.length,
523-
type: parsedContent.type || this.determineDocumentType(prismaDoc.contentType, prismaDoc.title),
524-
content: parsedContent.textContent || undefined,
525-
metadata: parsedContent.metadata || {},
470+
filename: prismaDoc.filename,
471+
originalName: prismaDoc.originalName,
472+
mimeType: prismaDoc.mimeType,
473+
size: prismaDoc.size,
474+
type: prismaDoc.type as DocumentType,
475+
content: prismaDoc.textContent || undefined,
476+
metadata: prismaDoc.metadata as Record<string, any> || {},
526477
uploadedAt: prismaDoc.createdAt?.toISOString() || new Date().toISOString(),
527-
uploadedBy: parsedContent.uploadedBy || undefined,
478+
uploadedBy: prismaDoc.uploadedBy || undefined,
528479
};
529480
}
530481

0 commit comments

Comments
 (0)