Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
ziteh committed Sep 15, 2024
2 parents bb38ed8 + 03da598 commit ba75384
Show file tree
Hide file tree
Showing 35 changed files with 853 additions and 414 deletions.
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.pnpm
.next
.git
**/*.db
prisma/migrations/

!.next/static
!.next/standalone
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ next-env.d.ts
/prisma/migrations/
*.db
*.db-journal

# Docker
.docker_temp_*
*.tar
65 changes: 65 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
FROM node:20-alpine AS base

# Install dependencies
FROM base AS deps

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json pnpm-lock.yaml* ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile


# Build stage
FROM base AS builder

WORKDIR /app

ENV DATABASE_URL=file:/app/db/hie_sqlite.db

COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN \
corepack enable pnpm && \
pnpm run prisma:update && \
pnpm run build

# Remove dev dependencies
# RUN pnpm prune --prod


# Production stage
FROM base as runner

WORKDIR /app

ENV NODE_ENV=production
ENV DATABASE_URL=file:/app/db/hie_sqlite.db

COPY --from=builder /app/public ./public

# TODO permissions related lines
# RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
# RUN mkdir .next && chown nextjs:nodejs .next

# TODO permissions related lines
# COPY --from=builder --chown=nextjs:nodejs /app/db/hie_sqlite.db /app/db/hie_sqlite.db
# COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
# COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

COPY --from=builder /app/db/hie_sqlite.db /app/db/hie_sqlite.db
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

# TODO permissions related lines
# USER nextjs

EXPOSE 3000
ENV PORT=3000

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
74 changes: 74 additions & 0 deletions app/api/folders/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { NextResponse } from "next/server";
import { prisma } from "@/app/lib/db/prisma";
import { StatusCodes } from "http-status-codes";

// Delete a folder
export async function DELETE(
_request: Request,
{ params }: { params: { id: string } }
) {
try {
const deleted = await prisma.folder.delete({
where: { id: Number(params.id) },
});

return NextResponse.json(deleted);
} catch (error) {
console.error("Error deleting folder:", error);
return NextResponse.json(
{ error: "Error deleting folder" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}

// Update a folder
export async function PATCH(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const { name, path } = await request.json();

// Normalization
let fmtPath = path.replace(/\\/g, "/").trim(); // Replace backslashes with forward
if (!fmtPath.endsWith("/")) {
fmtPath += "/"; // Always add trailing slash
}

const updated = await prisma.folder.update({
where: { id: Number(params.id) },
data: { name, path: fmtPath },
});

return NextResponse.json(updated);
} catch (error) {
console.error("Error update folder:", error);
return NextResponse.json(
{ error: "Error deleting folder" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}

// Get a folder
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const url = new URL(request.url);
const includeItems = url.searchParams.get("include") === "items";

try {
const list = await prisma.folder.findMany({
where: { id: Number(params.id) },
include: { items: includeItems },
});
return NextResponse.json(list);
} catch (error) {
return NextResponse.json(
{ error: "Error fetching folders" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}
54 changes: 3 additions & 51 deletions app/api/folders/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { NextResponse } from "next/server";
import { prisma } from "@/app/lib/db/prisma";
import { StatusCodes } from "http-status-codes";

// Create a folder
export async function POST(request: Request) {
try {
const { name, path } = await request.json();
console.debug("Received data:", { name, path });

// Normalization
let fmtPath = path.replace(/\\/g, "/"); // Replace backslashes with forward
let fmtPath = path.replace(/\\/g, "/").trim(); // Replace backslashes with forward
if (!fmtPath.endsWith("/")) {
fmtPath += "/"; // Always add trailing slash
}
Expand All @@ -27,56 +28,7 @@ export async function POST(request: Request) {
}
}

export async function DELETE(request: Request) {
try {
const { id } = await request.json();

if (!id) {
return NextResponse.json(
{ error: "ID is required" },
{ status: StatusCodes.BAD_REQUEST }
);
}

const deleted = await prisma.folder.delete({
where: { id },
});

return NextResponse.json(deleted);
} catch (error) {
console.error("Error deleting folder:", error);
return NextResponse.json(
{ error: "Error deleting folder" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}

export async function PATCH(request: Request) {
try {
const { id, name, path } = await request.json();

// Normalization
let fmtPath = path.replace(/\\/g, "/"); // Replace backslashes with forward
if (!fmtPath.endsWith("/")) {
fmtPath += "/"; // Always add trailing slash
}

const updated = await prisma.folder.update({
where: { id },
data: { name, path: fmtPath },
});

return NextResponse.json(updated);
} catch (error) {
console.error("Error update folder:", error);
return NextResponse.json(
{ error: "Error deleting folder" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}

// Get all folders
export async function GET(request: Request) {
const url = new URL(request.url);
const includeItems = url.searchParams.get("include") === "items";
Expand Down
22 changes: 22 additions & 0 deletions app/api/fs/[dir]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NextResponse } from "next/server";
import { StatusCodes } from "http-status-codes";
import path from "path";
import fs from "fs/promises";

export async function GET(
_request: Request,
{ params }: { params: { dir: string } }
) {
const dirPath = path.resolve(params.dir);

try {
const files = await fs.readdir(dirPath);
return NextResponse.json(files);
} catch (err) {
console.error("Error reading directory:", err);
return NextResponse.json(
{ error: "Error reading directory" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}
2 changes: 1 addition & 1 deletion app/api/image/[path]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export async function GET(
return new NextResponse(imageBuffer, {
headers: {
"Content-Type": "image/webp",
"Content-Disposition": `attachment; filename=${fileName}.webp`,
"Content-Disposition": `attachment; filename=${encodeURIComponent(fileName)}.webp`,
},
});
} catch (error) {
Expand Down
30 changes: 30 additions & 0 deletions app/api/items/[id]/path/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { NextResponse } from "next/server";
import { prisma } from "@/app/lib/db/prisma";
import { StatusCodes } from "http-status-codes";

export async function GET(
_request: Request,
{ params }: { params: { id: string } }
) {
try {
const item = await prisma.item.findUnique({
where: { id: Number(params.id) },
include: { folder: true },
});

if (!item) {
return NextResponse.json(
{ error: "Item not found" },
{ status: StatusCodes.NOT_FOUND }
);
}

const fullPath = `${item.folder.path}${item.path}`;
return NextResponse.json({ fullPath });
} catch (error) {
return NextResponse.json(
{ error: "Error fetching item" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
}
42 changes: 42 additions & 0 deletions app/api/items/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { NextResponse } from "next/server";
import { prisma } from "@/app/lib/db/prisma";
import { StatusCodes } from "http-status-codes";

// Get an item
export async function GET(
request: Request,
{ params }: { params: { id: string } }
Expand All @@ -23,3 +25,43 @@ export async function GET(
return NextResponse.json({ error: "Error fetching item" }, { status: 500 });
}
}

// Delete an item
export async function DELETE(
_request: Request,
{ params }: { params: { id: string } }
) {
try {
const deleted = await prisma.item.delete({
where: { id: Number(params.id) },
});

return NextResponse.json(deleted);
} catch (error) {
console.error("Error deleting item:", error);
return NextResponse.json({ error: "Error deleting item" }, { status: 500 });
}
}

// Update an item
export async function PATCH(
request: Request,
{ params }: { params: { id: string } }
) {
try {
const { folderId, path, name, starred } = await request.json();

// Normalization
const fmtPath = path.replace(/\\/g, "/"); // Replace backslashes with forward

const item = await prisma.item.update({
where: { id: Number(params.id) },
data: { path: fmtPath, folderId, name, starred },
});

return NextResponse.json(item);
} catch (error) {
console.error("Error update item:", error);
return NextResponse.json({ error: "Error deleting item" }, { status: 500 });
}
}
Loading

0 comments on commit ba75384

Please sign in to comment.