File size: 3,421 Bytes
743dad3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a51c5c9
743dad3
ef7bca1
 
 
 
 
 
 
 
 
 
 
 
 
743dad3
 
 
 
 
 
 
 
 
48357fd
743dad3
 
c89a5a0
48357fd
743dad3
 
 
48357fd
 
 
743dad3
 
 
48357fd
 
a51c5c9
 
 
 
 
 
 
 
 
 
 
 
 
743dad3
 
 
 
 
 
a51c5c9
743dad3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a51c5c9
c89a5a0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { NextRequest, NextResponse } from "next/server";
import { RepoDesignation, createRepo, listCommits, spaceInfo, uploadFiles } from "@huggingface/hub";

import { isAuthenticated } from "@/lib/auth";
import { Commit, Page } from "@/types";
import { COLORS } from "@/lib/utils";

export async function POST(
  req: NextRequest,
) {
  const user = await isAuthenticated();
  if (user instanceof NextResponse || !user) {
    return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
  }

  const { title: titleFromRequest, pages, prompt, initialFiles } = await req.json();

  const title = titleFromRequest ?? "OmniDev Project";

  let formattedTitle = title
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .split("-")
    .filter(Boolean)
    .join("-")
    .slice(0, 96);

  if (!formattedTitle || formattedTitle.trim().length === 0) {
    formattedTitle = `project-${Math.random().toString(36).slice(2, 8)}`;
  }

  const repo: RepoDesignation = {
    type: "space",
    name: `${user.name}/${formattedTitle}`,
  };
  const colorFrom = COLORS[Math.floor(Math.random() * COLORS.length)];
  const colorTo = COLORS[Math.floor(Math.random() * COLORS.length)];
  const README = `---
title: ${title}
emoji: 🚀
colorFrom: ${colorFrom}
colorTo: ${colorTo}
sdk: docker
app_port: 7860
pinned: false
---

# ${title}

This Space was scaffolded by OmniDev (Full‑Stack ready).
`;

  const files: File[] = [];
  files.push(new File([README], "README.md", { type: "text/markdown" }));

  if (Array.isArray(pages)) {
    pages.forEach((page: Page) => {
      const file = new File([page.html], page.path, { type: "text/html" });
      files.push(file);
    });
  }
  if (Array.isArray(initialFiles)) {
    initialFiles.forEach((f: { path: string; content: string; type?: string }) => {
      const path = (f.path || '').replace(/^\/+/, '');
      const type = f.type || (path.endsWith('.html') ? 'text/html' : path.endsWith('.json') ? 'application/json' : 'text/plain');
      files.push(new File([f.content || ''], path, { type }));
    });
  }

  try {
    const { repoUrl} = await createRepo({
      repo,
      accessToken: user.token as string,
    });
    const commitTitle = (!prompt || prompt.trim() === "") ? (Array.isArray(initialFiles) ? "OmniDev: Initialize project" : "Redesign my website") : prompt;
    await uploadFiles({
      repo,
      files,
      accessToken: user.token as string,
      commitTitle
    });

    const path = repoUrl.split("/").slice(-2).join("/");

    const commits: Commit[] = [];
    for await (const commit of listCommits({ repo, accessToken: user.token as string })) {
      if (commit.title.includes("initial commit") || commit.title.includes("image(s)") || commit.title.includes("Promote version")) {
        continue;
      }
      commits.push({
        title: commit.title,
        oid: commit.oid,
        date: commit.date,
      });
    }

    const space = await spaceInfo({
      name: repo.name,
      accessToken: user.token as string,
    });

    let newProject = {
      files,
      pages,
      commits,
      project: {
        id: space.id,
        space_id: space.name,
        _updatedAt: space.updatedAt,
      }
    }
    
    return NextResponse.json({ space: newProject, path, ok: true }, { status: 201 });
  } catch (err: any) {
    return NextResponse.json(
      { error: err.message, ok: false },
      { status: 500 }
    );
  }
}