Skip to content

Commit dbac237

Browse files
Add API routes for cloud design storage with CRUD operations
Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
1 parent a9667a5 commit dbac237

5 files changed

Lines changed: 286 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { serverStorage } from '@/lib/serverStorage';
3+
4+
/**
5+
* GET /api/designs/:id - Get a single design
6+
*/
7+
export async function GET(
8+
request: NextRequest,
9+
{ params }: { params: Promise<{ id: string }> }
10+
) {
11+
try {
12+
const { id } = await params;
13+
const design = serverStorage.getDesign(id);
14+
15+
if (!design) {
16+
return NextResponse.json(
17+
{ error: 'Design not found' },
18+
{ status: 404 }
19+
);
20+
}
21+
22+
return NextResponse.json(design);
23+
} catch (error) {
24+
console.error('Error fetching design:', error);
25+
return NextResponse.json(
26+
{ error: 'Failed to fetch design' },
27+
{ status: 500 }
28+
);
29+
}
30+
}
31+
32+
/**
33+
* PUT /api/designs/:id - Update a design
34+
*/
35+
export async function PUT(
36+
request: NextRequest,
37+
{ params }: { params: Promise<{ id: string }> }
38+
) {
39+
try {
40+
const { id } = await params;
41+
const body = await request.json();
42+
43+
const updatedDesign = serverStorage.updateDesign(id, body);
44+
45+
if (!updatedDesign) {
46+
return NextResponse.json(
47+
{ error: 'Design not found' },
48+
{ status: 404 }
49+
);
50+
}
51+
52+
return NextResponse.json(updatedDesign);
53+
} catch (error) {
54+
console.error('Error updating design:', error);
55+
return NextResponse.json(
56+
{ error: 'Failed to update design' },
57+
{ status: 500 }
58+
);
59+
}
60+
}
61+
62+
/**
63+
* DELETE /api/designs/:id - Delete a design
64+
*/
65+
export async function DELETE(
66+
request: NextRequest,
67+
{ params }: { params: Promise<{ id: string }> }
68+
) {
69+
try {
70+
const { id } = await params;
71+
const deleted = serverStorage.deleteDesign(id);
72+
73+
if (!deleted) {
74+
return NextResponse.json(
75+
{ error: 'Design not found' },
76+
{ status: 404 }
77+
);
78+
}
79+
80+
return NextResponse.json({ success: true });
81+
} catch (error) {
82+
console.error('Error deleting design:', error);
83+
return NextResponse.json(
84+
{ error: 'Failed to delete design' },
85+
{ status: 500 }
86+
);
87+
}
88+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { serverStorage } from '@/lib/serverStorage';
3+
4+
/**
5+
* POST /api/designs/:id/share - Generate share link for a design
6+
*/
7+
export async function POST(
8+
request: NextRequest,
9+
{ params }: { params: Promise<{ id: string }> }
10+
) {
11+
try {
12+
const { id } = await params;
13+
const design = serverStorage.getDesign(id);
14+
15+
if (!design) {
16+
return NextResponse.json(
17+
{ error: 'Design not found' },
18+
{ status: 404 }
19+
);
20+
}
21+
22+
// Generate a unique share ID
23+
const shareId = crypto.randomUUID().replace(/-/g, '').substring(0, 12);
24+
25+
// Store the shared design
26+
serverStorage.shareDesign(id, shareId);
27+
28+
// Generate the share URL
29+
const baseUrl = request.nextUrl.origin;
30+
const shareUrl = `${baseUrl}/studio/shared/${shareId}`;
31+
32+
return NextResponse.json({ shareUrl, shareId });
33+
} catch (error) {
34+
console.error('Error sharing design:', error);
35+
return NextResponse.json(
36+
{ error: 'Failed to share design' },
37+
{ status: 500 }
38+
);
39+
}
40+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import type { Design } from '@/lib/designStorage';
3+
import { serverStorage } from '@/lib/serverStorage';
4+
5+
/**
6+
* GET /api/designs - List all designs
7+
*/
8+
export async function GET() {
9+
try {
10+
const allDesigns = serverStorage.getAllDesigns();
11+
return NextResponse.json(allDesigns);
12+
} catch (error) {
13+
console.error('Error fetching designs:', error);
14+
return NextResponse.json(
15+
{ error: 'Failed to fetch designs' },
16+
{ status: 500 }
17+
);
18+
}
19+
}
20+
21+
/**
22+
* POST /api/designs - Create new design
23+
*/
24+
export async function POST(request: NextRequest) {
25+
try {
26+
const body = await request.json();
27+
const { name, description, schema, tags } = body;
28+
29+
if (!name || !schema) {
30+
return NextResponse.json(
31+
{ error: 'Name and schema are required' },
32+
{ status: 400 }
33+
);
34+
}
35+
36+
const id = `design_${crypto.randomUUID()}`;
37+
const now = new Date().toISOString();
38+
39+
const newDesign: Design = {
40+
id,
41+
name,
42+
description,
43+
schema,
44+
tags: tags || [],
45+
createdAt: now,
46+
updatedAt: now,
47+
};
48+
49+
serverStorage.createDesign(newDesign);
50+
51+
return NextResponse.json(newDesign, { status: 201 });
52+
} catch (error) {
53+
console.error('Error creating design:', error);
54+
return NextResponse.json(
55+
{ error: 'Failed to create design' },
56+
{ status: 500 }
57+
);
58+
}
59+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { serverStorage } from '@/lib/serverStorage';
3+
4+
/**
5+
* GET /api/designs/shared/:shareId - Get a shared design
6+
*/
7+
export async function GET(
8+
request: NextRequest,
9+
{ params }: { params: Promise<{ shareId: string }> }
10+
) {
11+
try {
12+
const { shareId } = await params;
13+
const design = serverStorage.getSharedDesign(shareId);
14+
15+
if (!design) {
16+
return NextResponse.json(
17+
{ error: 'Shared design not found' },
18+
{ status: 404 }
19+
);
20+
}
21+
22+
return NextResponse.json(design);
23+
} catch (error) {
24+
console.error('Error fetching shared design:', error);
25+
return NextResponse.json(
26+
{ error: 'Failed to fetch shared design' },
27+
{ status: 500 }
28+
);
29+
}
30+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Server-side Design Storage
3+
*
4+
* This module provides centralized storage for designs on the server.
5+
* Currently uses in-memory storage for simplicity.
6+
*
7+
* TODO: Replace with persistent storage (e.g., Vercel KV, database)
8+
*/
9+
10+
import type { Design } from './designStorage';
11+
12+
// In-memory storage maps (shared across all API routes)
13+
const designs = new Map<string, Design>();
14+
const sharedDesigns = new Map<string, Design>();
15+
16+
export const serverStorage = {
17+
// Design operations
18+
getAllDesigns(): Design[] {
19+
return Array.from(designs.values());
20+
},
21+
22+
getDesign(id: string): Design | null {
23+
return designs.get(id) || null;
24+
},
25+
26+
createDesign(design: Design): Design {
27+
designs.set(design.id, design);
28+
return design;
29+
},
30+
31+
updateDesign(id: string, updates: Partial<Design>): Design | null {
32+
const existing = designs.get(id);
33+
if (!existing) return null;
34+
35+
const updated = {
36+
...existing,
37+
...updates,
38+
id: existing.id, // Preserve ID
39+
createdAt: existing.createdAt, // Preserve creation date
40+
updatedAt: new Date().toISOString(),
41+
};
42+
43+
designs.set(id, updated);
44+
return updated;
45+
},
46+
47+
deleteDesign(id: string): boolean {
48+
return designs.delete(id);
49+
},
50+
51+
// Shared design operations
52+
shareDesign(id: string, shareId: string): boolean {
53+
const design = designs.get(id);
54+
if (!design) return false;
55+
56+
sharedDesigns.set(shareId, design);
57+
return true;
58+
},
59+
60+
getSharedDesign(shareId: string): Design | null {
61+
return sharedDesigns.get(shareId) || null;
62+
},
63+
64+
// Utility
65+
clearAll(): void {
66+
designs.clear();
67+
sharedDesigns.clear();
68+
},
69+
};

0 commit comments

Comments
 (0)