scaffoldlisted
Install: claude install-skill SONGYEONGSIN/vibe-flow
`$ARGUMENTS` 도메인의 보일러플레이트를 생성한다.
## 생성 파일
모든 파일은 `src/` 하위에 생성한다.
### 1. 스키마 — `features/$ARGUMENTS/schemas.ts`
```typescript
import { z } from "zod";
export const create${Domain}Schema = z.object({
// 필드 정의
});
export type Create${Domain}Input = z.infer<typeof create${Domain}Schema>;
```
### 2. 타입 — `features/$ARGUMENTS/types.ts`
```typescript
export interface ${Domain} {
id: string;
created_at: string;
// 필드 정의
}
export interface ${Domain}ActionState {
error?: string;
success?: boolean;
}
```
### 3. 액션 — `features/$ARGUMENTS/actions.ts`
```typescript
"use server";
import { revalidatePath } from "next/cache";
import { createClient } from "@/lib/supabase/server";
import { create${Domain}Schema } from "./schemas";
import type { ${Domain}ActionState } from "./types";
export async function create${Domain}(
prevState: ${Domain}ActionState,
formData: FormData,
): Promise<${Domain}ActionState> {
const parsed = create${Domain}Schema.safeParse(
Object.fromEntries(formData),
);
if (!parsed.success) {
return { error: parsed.error.issues[0].message };
}
const supabase = await createClient();
const { error } = await supabase.from("$ARGUMENTS").insert(parsed.data);
if (error) {
return { error: error.message };
}
revalidatePath("/$ARGUMENTS");
return { success: true };
}
```
### 4. 테스트 — `features/$ARGUMENTS/actions.test.ts`
```typescript
import { describe, it, expect, vi } from "vitest";
vi.mock("@/lib/supabase/server", ()