Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .github/workflows/lint-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Generate Prisma Client
run: npx prisma generate

- name: Lint (src only)
run: npx eslint "src/**/*.{ts,tsx,js,jsx}" --max-warnings=0

- name: Prettier Check (src only)
run: npm run format

- name: TypeScript Type Check
run: npm run typecheck
40 changes: 28 additions & 12 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
hostname: "gravatar.com",
},
],
},
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
config.resolve.alias.canvas = false;
config.resolve.alias.encoding = false;
return config;
},
images: {
remotePatterns: [
{
hostname: 'gravatar.com',
},
{
hostname: 'img.clerk.com',
},
],
},
async rewrites() {
return [
{
source: '/ingest/static/:path*',
destination: 'https://us-assets.i.posthog.com/static/:path*',
},
{
source: '/ingest/:path*',
destination: 'https://us.i.posthog.com/:path*',
},
{
source: '/ingest/flags',
destination: 'https://us.i.posthog.com/flags',
},
];
},
// This is required to support PostHog trailing slash API requests
skipTrailingSlashRedirect: true,
};

module.exports = nextConfig;
84 changes: 84 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
"dev": "next dev",
"build": " npx prisma generate && next build",
"start": "next start",
"lint": "npx eslint \"src/**/*.{ts,tsx,js,jsx}\" --max-warnings=0",
"lint:fix": "npx eslint \"src/**/*.{ts,tsx,js,jsx}\" --fix",
"format": "npx prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
"check": "npx eslint \"src/**/*.{ts,tsx,js,jsx}\" --max-warnings=0 && npx prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
"lint": "npx eslint \"src/**/*.{ts,tsx}\" --max-warnings=0",
"lint:fix": "npx eslint \"src/**/*.{ts,tsx}\" --fix",
"format": "npx prettier --check \"src/**/*.{ts,tsx,json,md}\"",
"check": "npx eslint \"src/**/*.{ts,tsx}\" --max-warnings=0 && npx prettier --check \"src/**/*.{ts,tsx,json,md}\"",
"format:fix": "npx prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
"postinstall": "prisma generate"
"postinstall": "prisma generate",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
"@ai-sdk/mistral": "^2.0.1",
Expand Down Expand Up @@ -52,13 +53,16 @@
"lucide-react": "^0.279.0",
"next": "^14.2.14",
"next-themes": "^0.4.3",
"pdf-parse": "^1.1.1",
"postcss": "^8.4.47",
"posthog-js": "^1.259.0",
"posthog-node": "^5.6.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.46.2",
"react-intersection-observer": "^9.16.0",
"react-markdown": "^8.0.7",
"react-pdf": "^9.1.1",
"pdf-parse": "^1.1.1",
"react-resize-detector": "^9.1.0",
"simplebar-react": "^3.2.4",
"sonner": "^1.7.0",
Expand Down
13 changes: 6 additions & 7 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ model User {

File File[]
Message Message[]

}

enum UploadStatus {
Expand All @@ -41,8 +40,8 @@ model File {

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
User User? @relation(fields: [userId], references: [id])
userId String?
User User @relation(fields: [userId], references: [id])
userId String
}

model Message {
Expand All @@ -53,8 +52,8 @@ model Message {

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
User User? @relation(fields: [userId], references: [id])
userId String?
File File? @relation(fields: [fileId], references: [id], onDelete: Cascade)
fileId String?
User User @relation(fields: [userId], references: [id])
userId String
File File @relation(fields: [fileId], references: [id], onDelete: Cascade)
fileId String
}
78 changes: 78 additions & 0 deletions src/actions/messages.action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use server';

import { auth } from '@clerk/nextjs/server';
import type { Prisma } from '@prisma/client';

import { db } from '@/db';

export type MessageDTO = {
id: string;
text: string;
isUserMessage: boolean;
createdAt: string; // ISO string for client serialization
updatedAt: string; // ISO string for client serialization
userId: string | null;
fileId: string;
};

export type MessagesPage = {
items: MessageDTO[];
nextCursor?: string; // pass as `cursor` to load the next (older) page
};
export type MessagesChunk = {
items: MessageDTO[];
hasMore: boolean;
nextCursor?: string; // createdAt ISO of the oldest item returned
total?: number; // total count for simple pagination
};

export async function getMessages({
fileId,
before, // ISO string; fetch messages with createdAt < before
take = 4,
}: {
fileId: string;
before?: string;
take?: number;
}): Promise<MessagesChunk> {
const { userId } = await auth();
if (!userId) throw new Error('Unauthorized');
if (!fileId) throw new Error('File ID is required');
if (!take || take < 1) throw new Error('take must be positive');

const file = await db.file.findFirst({ where: { id: fileId, userId } });
if (!file) throw new Error('File not found or unauthorized');

const where: Prisma.MessageWhereInput = { fileId };
if (before) {
const d = new Date(before);
if (!isNaN(d.getTime())) where.createdAt = { lt: d };
}

const results = await db.message.findMany({
where,
orderBy: { createdAt: 'desc' },
take: take + 1, // fetch one extra to determine hasMore
});

const hasMore = results.length > take;
const slice = hasMore ? results.slice(0, take) : results;

const itemsDesc = slice;
const itemsAsc = itemsDesc
.slice()
.reverse()
.map((m) => ({
id: m.id,
text: m.text,
isUserMessage: m.isUserMessage,
createdAt: m.createdAt.toISOString(),
updatedAt: m.updatedAt.toISOString(),
userId: m.userId ?? null,
fileId: m.fileId,
}));

const nextCursor = itemsAsc[0]?.createdAt; // oldest in this batch

return { items: itemsAsc, hasMore, nextCursor };
}
5 changes: 5 additions & 0 deletions src/app/(root)/dashboard/[fileid]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { auth } from '@clerk/nextjs/server';
import Link from 'next/link';
import { redirect } from 'next/navigation';

import PdfRenderer from '@/components/PdfRenderer';
import ChatComponent from '@/components/chat/ChatComponent';
Expand All @@ -16,6 +17,10 @@ const Page = async ({ params }: PageProps) => {

const user = await auth();

if (!user.userId) {
redirect('/sign-in');
}

const file = await db.file.findFirst({
where: {
id: fileid,
Expand Down
Loading