SPB Git forge

spb/spb-cloud

Public
10commits 1branches 0releases
3.2 MBsize
maindefault branch
4 h agolast push
JavaScript 56.7% TypeScript 42.6%
4.2 KB · 188 lines typescript
Raw Blame History
1import { NextRequest, NextResponse } from "next/server";2import { getIronSession } from "iron-session";3import { SessionData, sessionOptions } from "@/lib/session";4import { prisma } from "@/lib/prisma";56interface GraphNode {7  id: string;8  label: string;9  type: "root" | "folder" | "file" | "shared-space" | "user" | "tag";10  size?: number;11  mimeType?: string;12  count?: number;13  color?: string;14}1516interface GraphEdge {17  source: string;18  target: string;19  type: "contains" | "member" | "tagged";20}2122export async function GET(request: NextRequest) {23  const response = NextResponse.json({});24  const session = await getIronSession<SessionData>(request, response, sessionOptions);2526  if (!session.isLoggedIn || !session.userId) {27    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });28  }2930  const nodes: GraphNode[] = [];31  const edges: GraphEdge[] = [];3233  // Root node34  nodes.push({35    id: "root",36    label: "SPB Cloud",37    type: "root",38  });3940  // Folders41  const folders = await prisma.folder.findMany({42    include: {43      _count: { select: { files: true, children: true } },44    },45  });4647  for (const folder of folders) {48    nodes.push({49      id: `folder-${folder.id}`,50      label: folder.name,51      type: "folder",52      count: folder._count.files + folder._count.children,53    });5455    if (folder.parentId) {56      edges.push({57        source: `folder-${folder.parentId}`,58        target: `folder-${folder.id}`,59        type: "contains",60      });61    } else if (folder.sharedSpaceId) {62      edges.push({63        source: `space-${folder.sharedSpaceId}`,64        target: `folder-${folder.id}`,65        type: "contains",66      });67    } else {68      edges.push({69        source: "root",70        target: `folder-${folder.id}`,71        type: "contains",72      });73    }74  }7576  // Files (500 most recent, non-deleted)77  const files = await prisma.file.findMany({78    where: { deletedAt: null },79    orderBy: { createdAt: "desc" },80    take: 500,81    select: {82      id: true,83      name: true,84      size: true,85      mimeType: true,86      folderId: true,87      createdAt: true,88    },89  });9091  for (const file of files) {92    nodes.push({93      id: `file-${file.id}`,94      label: file.name,95      type: "file",96      size: Number(file.size),97      mimeType: file.mimeType,98    });99100    if (file.folderId) {101      edges.push({102        source: `folder-${file.folderId}`,103        target: `file-${file.id}`,104        type: "contains",105      });106    } else {107      edges.push({108        source: "root",109        target: `file-${file.id}`,110        type: "contains",111      });112    }113  }114115  // Shared Spaces116  const sharedSpaces = await prisma.sharedSpace.findMany({117    include: {118      _count: { select: { members: true, folders: true } },119    },120  });121122  for (const space of sharedSpaces) {123    nodes.push({124      id: `space-${space.id}`,125      label: space.name,126      type: "shared-space",127      count: space._count.members,128    });129    edges.push({130      source: "root",131      target: `space-${space.id}`,132      type: "contains",133    });134  }135136  // Users137  const users = await prisma.user.findMany({138    select: { id: true, name: true, username: true },139  });140141  for (const user of users) {142    nodes.push({143      id: `user-${user.id}`,144      label: user.name || user.username || "Utilisateur",145      type: "user",146    });147  }148149  // Shared space memberships150  const memberships = await prisma.sharedSpaceMember.findMany();151  for (const m of memberships) {152    edges.push({153      source: `user-${m.userId}`,154      target: `space-${m.sharedSpaceId}`,155      type: "member",156    });157  }158159  // Tags160  const tags = await prisma.tag.findMany({161    include: { files: { select: { fileId: true } } },162  });163164  const fileNodeIds = new Set(nodes.filter((n) => n.type === "file").map((n) => n.id));165166  for (const tag of tags) {167    nodes.push({168      id: `tag-${tag.id}`,169      label: tag.name,170      type: "tag",171      color: tag.color,172      count: tag.files.length,173    });174175    for (const ft of tag.files) {176      if (fileNodeIds.has(`file-${ft.fileId}`)) {177        edges.push({178          source: `tag-${tag.id}`,179          target: `file-${ft.fileId}`,180          type: "tagged",181        });182      }183    }184  }185186  return NextResponse.json({ nodes, edges });187}188