Skillsfigma-v3-migration-plugin-dev
figma-v3-migration-plugin-dev

figma-v3-migration-plugin-dev

Figma V3 Migration Plugin development specialist. Use when developing Figma V3 Migration Plugin. Focuses on Figma V3 Migration Plugin development.

figma-v3-migration-plugin-devdaangn
815 stars
16.3k downloads
Updated 6d ago

Readme

figma-v3-migration-plugin-dev follows the SKILL.md standard. Use the install command to add it to your agent stack.

---
name: figma-v3-migration-plugin-dev
description: Figma V3 Migration Plugin development specialist. Use when developing Figma V3 Migration Plugin. Focuses on Figma V3 Migration Plugin development.
allowed-tools: Read, Write, Edit, MultiEdit, Bash, Glob, Grep
---

## 개요

Figma V3 Migration 플러그인은 SEED Design System V2 컴포넌트를 V3로 마이그레이션하는 Figma 플러그인입니다.

### 디렉토리 구조

```
tools/figma-v3-migration/
├── src/main/
│   ├── mapping/                    # 매핑 정의 파일들
│   │   ├── types.ts                # 타입 정의
│   │   ├── index.ts                # 모든 매핑 export
│   │   ├── buttons.ts              # 버튼 컴포넌트 매핑
│   │   ├── action-sheet.ts         # Action Sheet 매핑
│   │   └── [component].ts          # 기타 컴포넌트별 매핑
│   ├── data/
│   │   └── __generated__/          # 자동 생성된 메타데이터
│   │       ├── v2-component-sets/  # V2 컴포넌트 메타데이터
│   │       └── v3-component-sets/  # V3 컴포넌트 메타데이터
│   └── services/                   # Figma API 서비스
├── figma-extractor.config.ts       # 추출 설정
└── package.json
```

## 환경 설정

### 1. 환경변수 설정

```bash
export FIGMA_PERSONAL_ACCESS_TOKEN="your-figma-token"
```

Figma Personal Access Token은 Figma Settings > Account > Personal access tokens에서 생성할 수 있습니다.

### 2. 의존성 설치

```bash
cd tools/figma-v3-migration
bun install
```

## 매핑 최신화 프로세스

### 1. 메타데이터 추출

```bash
cd tools/figma-v3-migration
bun extract
```

이 명령어는 Figma API에서 V3 컴포넌트 메타데이터를 추출하여 `src/main/data/__generated__/v3-component-sets/` 디렉토리에 `.d.ts` 파일로 저장합니다.

### 2. 변경된 파일 확인

```bash
git status
git diff src/main/data/__generated__/
```

### 3. 매핑 파일 업데이트 워크플로우

1. **변경된 Generated 파일 분석**: 새로 추가되거나 변경된 컴포넌트 확인
2. **관련 매핑 파일 수정**: `src/main/mapping/` 디렉토리의 해당 컴포넌트 매핑 업데이트
3. **index.ts 업데이트**: 새 매핑 추가 시 export 목록에 추가
4. **타입 체크**: `bun run typecheck:main`으로 매핑 파일 타입 에러 확인

## 매핑 파일 작성 가이드

### 기본 구조

매핑 파일은 `ComponentMapping<OldComponentName, NewComponentName>` 타입을 사용합니다.

```typescript
import type { ComponentMapping, NewComponentProperties } from "./types";

export const exampleMapping: ComponentMapping<"Old Component Name", "New Component Name"> = {
  oldComponent: "Old Component Name",    // V2 컴포넌트 이름 (Generated 파일의 name과 일치)
  newComponent: "New Component Name",    // V3 컴포넌트 이름
  variantMap: {
    // Variant 값 매핑
  },
  calculateProperties(oldProperties) {
    // 프로퍼티 변환 로직
    const newProperties: NewComponentProperties<"New Component Name"> = {};
    return newProperties;
  },
};
```

### 실제 예제: buttons.ts

```typescript
// tools/figma-v3-migration/src/main/mapping/buttons.ts

import type { ComponentMapping, NewComponentProperties } from "./types";

export const boxButtonMapping: ComponentMapping<"✅ Box Button v2", "🟢 Action Button"> = {
  oldComponent: "✅ Box Button v2",
  newComponent: "🟢 Action Button",

  // 1. variantMap: Variant 값 매핑
  variantMap: {
    // 형식: "VariantName:OldValue": "VariantName:NewValue"
    "Size:XSmall": "Size:Small",
    "Size:Small": "Size:Small",
    "Size:Medium": "Size:Medium",
    "Size:Large": "Size:Large",
    "Size:XLarge": "Size:Large",
    "State:Enabled": "State:Enabled",
    "State:Disabled": "State:Disabled",
    "State:Loading": "State:Loading",
    "State:Pressed": "State:Pressed",
    "Variant:Primary": "Variant:Neutral Solid",
    "Variant:Primary low": "Variant:Neutral Weak",
    "Variant:Secondary": "Variant:Neutral Weak",
    "Variant:Danger": "Variant:Critical Solid",
  },

  // 2. calculateProperties: 프로퍼티 변환 로직
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<"🟢 Action Button"> = {
      // TEXT 프로퍼티 매핑: "PropertyName#NodeId"
      "Label#5987:61": oldProperties["Label#28272:77"].value,
    };

    // BOOLEAN 프로퍼티 읽기
    const prefixIcon = oldProperties["Prefix icon#28272:78"].value;
    const suffixIcon = oldProperties["Suffix icon#28272:76"].value;

    // 조건부 로직으로 Layout 설정
    if (prefixIcon && suffixIcon) {
      newProperties.Layout = "Icon Last";
      newProperties["Prefix Icon#5987:305"] = oldProperties["↳Icons#28292:0"].value;
    } else if (prefixIcon) {
      newProperties.Layout = "Icon First";
      newProperties["Prefix Icon#5987:305"] = oldProperties["↳Icons#28292:0"].value;
    } else if (suffixIcon) {
      newProperties.Layout = "Icon Last";
    } else {
      newProperties.Layout = "Text Only";
    }

    return newProperties;
  },
};
```

### 중첩 컴포넌트 처리: action-sheet.ts

부모 컴포넌트 내부에 자식 컴포넌트가 있는 경우 `childrenMappings`를 사용합니다.

```typescript
// tools/figma-v3-migration/src/main/mapping/action-sheet.ts

import type { ComponentMapping, NewComponentProperties } from "./types";

// 자식 컴포넌트 매핑 정의
const itemMenuGroupMapping: ComponentMapping<"Action button group", ".Item / Menu Group"> = {
  oldComponent: "Action button group",
  newComponent: ".Item / Menu Group",
  variantMap: {},
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<".Item / Menu Group"> = {
      "Action Count":
        oldProperties["Action count"].value === "8 (Max)"
          ? "8"
          : oldProperties["Action count"].value,
    };
    return newProperties;
  },
};

const itemMenuItemMapping: ComponentMapping<"Action button", ".Item / Menu Item"> = {
  oldComponent: "Action button",
  newComponent: ".Item / Menu Item",
  variantMap: {
    "State:Default": "State:Enabled",
    "State:Pressed": "State:Pressed",
    "Type:Destructive": "Tone:Critical",
    "Type:Enabled": "Tone:Neutral",
    "Prefix icon:True": "Layout:Text with Icon",
    "Prefix icon:False": "Layout:\bText Only",
  },
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<".Item / Menu Item"> = {
      "Label#55905:8": oldProperties["🅃 Action label#55905:8"].value,
    };

    const hasPrefixIcon = oldProperties["Prefix icon"].value === "True";
    if (hasPrefixIcon) {
      newProperties["Show Prefix Icon#17043:5"] = true;
      newProperties["Prefix Icon#55948:0"] = oldProperties["Icon#55948:0"].value;
    }

    return newProperties;
  },
};

// 부모 컴포넌트 매핑 (childrenMappings 포함)
export const actionSheetMapping: ComponentMapping<"✅ Action Sheet v2", "🟢 Menu Sheet"> = {
  oldComponent: "✅ Action Sheet v2",
  newComponent: "🟢 Menu Sheet",
  variantMap: {},
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<"🟢 Menu Sheet"> = {
      Layout: "Text Only",
      "Show Safe Area#25531:15": true,
      "Menu Group Count": "1",
    };

    const hasTitle = oldProperties.Title.value === "True";
    if (hasTitle) {
      newProperties["Show Header#17043:12"] = true;
    }

    return newProperties;
  },
  // 자식 컴포넌트 매핑 배열
  childrenMappings: [itemMenuGroupMapping, itemMenuItemMapping],
};
```

### 새 매핑 추가 시 체크리스트

1. **Generated 파일 확인**
   - V2: `src/main/data/__generated__/v2-component-sets/[component].d.ts`
   - V3: `src/main/data/__generated__/v3-component-sets/[component].d.ts`

2. **매핑 파일 생성/수정**
   - `src/main/mapping/[component].ts` 파일 생성 또는 기존 파일에 추가

3. **index.ts 업데이트**
   ```typescript
   // src/main/mapping/index.ts
   import { newComponentMapping } from "./new-component";

   export default [
     // ... 기존 매핑들
     newComponentMapping,
   ] as const;
   ```

4. **타입 체크**
   ```bash
   cd tools/figma-v3-migration
   bun run typecheck:main  # 매핑 파일 타입 체크
   bun run typecheck       # 전체 타입 체크 (main + ui)
   ```

## 타입 시스템

### Generated 메타데이터 구조

```typescript
// src/main/data/__generated__/v3-component-sets/action-button.d.ts
export declare const metadata: {
  "name": "🟢 Action Button",
  "key": "450ede9d0bf42fc6ef14345c77e6e407d6d5ee89",
  "componentPropertyDefinitions": {
    "Label#5987:61": {
      "type": "TEXT",
      "defaultValue": "라벨"
    },
    "Size": {
      "type": "VARIANT",
      "defaultValue": "XSmall",
      "variantOptions": ["XSmall", "Small", "Medium", "Large"]
    },
    "Layout": {
      "type": "VARIANT",
      "defaultValue": "Text Only",
      "variantOptions": ["Text Only", "Icon First", "Icon Last", "Icon Only"]
    },
    "Prefix Icon#5987:305": {
      "type": "INSTANCE_SWAP",
      "defaultValue": "37665:153410",
      "preferredValues": []
    }
  }
};
```

### 프로퍼티 타입별 처리

| 타입 | 설명 | 값 형식 |
|------|------|---------|
| `VARIANT` | 선택 가능한 옵션들 | `variantOptions` 중 하나 |
| `TEXT` | 텍스트 입력 | `string` |
| `BOOLEAN` | 참/거짓 | `boolean` |
| `INSTANCE_SWAP` | 컴포넌트 교체 | 컴포넌트 key (`string`) |

### 타입 안전성

`ComponentMapping` 타입은 Generated 메타데이터를 기반으로 타입 검증을 수행합니다:

- **컴포넌트 이름**: V2/V3 Generated 파일의 `name`과 일치해야 함
- **프로퍼티 키**: `"PropertyName#NodeId"` 형식으로 정확히 일치해야 함
- **Variant 값**: `variantOptions`에 정의된 값만 사용 가능

잘못된 프로퍼티 이름이나 값을 사용하면 TypeScript 컴파일 에러가 발생합니다.

## 트러블슈팅

### 일반적인 에러

#### 1. "Property does not exist" 타입 에러

**원인**: 프로퍼티 이름이 Generated 파일과 일치하지 않음

**해결**: Generated `.d.ts` 파일에서 정확한 프로퍼티 이름 확인
```bash
cat src/main/data/__generated__/v3-component-sets/[component].d.ts
```

#### 2. "Type is not assignable" 에러

**원인**: Variant 값이 `variantOptions`에 없는 값

**해결**: Generated 파일의 `variantOptions` 확인 후 올바른 값 사용

#### 3. Extract 명령어 실패

**원인**: `FIGMA_PERSONAL_ACCESS_TOKEN` 미설정 또는 만료

**해결**:
```bash
export FIGMA_PERSONAL_ACCESS_TOKEN="new-token"
bun extract
```

### 디버깅 팁

1. **프로퍼티 이름 확인**
   ```bash
   # V2 컴포넌트 프로퍼티 확인
   cat src/main/data/__generated__/v2-component-sets/[component].d.ts

   # V3 컴포넌트 프로퍼티 확인
   cat src/main/data/__generated__/v3-component-sets/[component].d.ts
   ```

2. **기존 매핑 패턴 참고**
   ```bash
   # 비슷한 컴포넌트의 매핑 확인
   cat src/main/mapping/buttons.ts
   cat src/main/mapping/checkbox.ts
   ```

3. **타입 에러 확인**
   ```bash
   cd tools/figma-v3-migration
   bun run typecheck:main  # 매핑 파일만 체크
   bun run typecheck       # 전체 체크
   ```

Install

Requires askill CLI v1.0+

Metadata

LicenseUnknown
Version-
Updated6d ago
Publisherdaangn

Tags

apici-cd