Repository: sipe-team/side
Pull request #130: feat(plugin-figma-codegen): add figma codegen plugin
Author: login: noahluftyang
Created: 2025-03-08T04:45:36Z | Merged: 2025-03-09T18:04:43Z

## Changes
- Add basic Side component codegen plugin for Figma.

## Visuals
![스크린샷 12](https://github.com/user-attachments/assets/99d13938-f416-49a1-99f7-8eaa8d27ab7c)

## Checklist
- [ ] Have you written the functional specifications?
- [ ] Have you written the test code?

## Additional Discussion Points
<!-- If there are any additional points to be aware of, please specify them. -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
	- 새로운 플러그인 메타데이터를 도입하여 플러그인 기능과 지원 언어를 명확하게 정의했습니다.
	- 디자인 요소를 기반으로 컴포넌트 코드 생성을 자동화하는 기능이 추가되었습니다.
- **Chores**
	- 개발과 배포를 원활하게 하는 구성 및 설정 파일들이 업데이트되었습니다.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/packages/plugin-figma-codegen/manifest.json b/packages/plugin-figma-codegen/manifest.json
new file mode 100644
index 00000000..203c56f9
--- /dev/null
+++ b/packages/plugin-figma-codegen/manifest.json
@@ -0,0 +1,9 @@
+{
+  "name": "@sipe-team/plugin-figma-codegen",
+  "api": "1.0.0",
+  "capabilities": ["codegen", "vscode"],
+  "codegenLanguages": [{ "label": "React", "value": "react" }],
+  "editorType": ["dev"],
+  "id": "1477931843428059075",
+  "main": "dist/index.js"
+}
diff --git a/packages/plugin-figma-codegen/package.json b/packages/plugin-figma-codegen/package.json
new file mode 100644
index 00000000..48c2a252
--- /dev/null
+++ b/packages/plugin-figma-codegen/package.json
@@ -0,0 +1,36 @@
+{
+  "name": "@sipe-team/plugin-figma-codegen",
+  "description": "Figma codegen plugin for Sipe Design System",
+  "version": "0.0.0",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sipe-team/side"
+  },
+  "type": "module",
+  "exports": "./src/index.ts",
+  "files": ["dist", "manifest.json"],
+  "scripts": {
+    "build": "tsup",
+    "dev": "pnpm build --watch",
+    "lint": "biome lint .",
+    "typecheck": "tsc",
+    "prepack": "pnpm run build"
+  },
+  "devDependencies": {
+    "@figma/plugin-typings": "^1.108.0",
+    "tsup": "catalog:",
+    "typescript": "catalog:"
+  },
+  "publishConfig": {
+    "access": "public",
+    "registry": "https://npm.pkg.github.com",
+    "exports": {
+      ".": {
+        "types": "./dist/index.d.ts",
+        "default": "./dist/index.js"
+      }
+    }
+  },
+  "sideEffects": false
+}
diff --git a/packages/plugin-figma-codegen/src/index.ts b/packages/plugin-figma-codegen/src/index.ts
new file mode 100644
index 00000000..b2f8cbaa
--- /dev/null
+++ b/packages/plugin-figma-codegen/src/index.ts
@@ -0,0 +1,22 @@
+if (figma.editorType !== 'dev' || figma.mode !== 'codegen') {
+  figma.closePlugin();
+}
+
+figma.codegen.on('generate', async ({ node }) => {
+  const ComponentName = node.name;
+
+  if (node.type === 'INSTANCE') {
+    const props = node.componentProperties;
+    const result = Object.entries(props).map(([name, { value }]) => `${name}="${value}"`);
+
+    return [
+      {
+        title: ComponentName,
+        language: 'TYPESCRIPT',
+        code: `<${ComponentName} ${result.join(' ')} />`,
+      },
+    ];
+  }
+
+  return [];
+});
diff --git a/packages/plugin-figma-codegen/tsconfig.json b/packages/plugin-figma-codegen/tsconfig.json
new file mode 100644
index 00000000..5ac6a43e
--- /dev/null
+++ b/packages/plugin-figma-codegen/tsconfig.json
@@ -0,0 +1,6 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "typeRoots": ["./node_modules/@types", "./node_modules/@figma"]
+  }
+}
diff --git a/packages/plugin-figma-codegen/tsup.config.ts b/packages/plugin-figma-codegen/tsup.config.ts
new file mode 100644
index 00000000..bb7f6d0c
--- /dev/null
+++ b/packages/plugin-figma-codegen/tsup.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'tsup';
+
+export default defineConfig({
+  entry: ['src/index.ts'],
+  clean: true,
+  dts: true,
+  format: 'esm',
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 716c8ad8..9f69ea5e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -888,6 +888,18 @@ importers:
         specifier: 'catalog:'
         version: 2.1.8(@types/node@22.10.1)(happy-dom@15.11.7)(terser@5.37.0)
 
+  packages/plugin-figma-codegen:
+    devDependencies:
+      '@figma/plugin-typings':
+        specifier: ^1.108.0
+        version: 1.108.0
+      tsup:
+        specifier: 'catalog:'
+        version: 8.3.5(jiti@2.4.1)(postcss@8.4.49)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.6.1)
+      typescript:
+        specifier: 'catalog:'
+        version: 5.6.3
+
   packages/radio-group:
     devDependencies:
       '@storybook/addon-essentials':
@@ -3196,6 +3208,9 @@ packages:
     resolution: {integrity: sha512-ulqQu4KMr1/sTFIYvqSdegHT8NIkt66tFAkugGnHA+1WAfEn6hMzNR+svjXGFRVLnapxvej67Z/LwchFrnLBUg==}
     engines: {node: '>=18.0.0', npm: '>=9.0.0'}
 
+  '@figma/plugin-typings@1.108.0':
+    resolution: {integrity: sha512-hZocQwkMUfQZSa/6H9qkSkIKMDC70OOcV8U7hBocAsD/bWEZh13uj+aP6IHHmStscoavo9Ir5pU7NWEUUcXLug==}
+
   '@hapi/hoek@9.3.0':
     resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
 
@@ -11686,6 +11701,8 @@ snapshots:
 
   '@faker-js/faker@9.2.0': {}
 
+  '@figma/plugin-typings@1.108.0': {}
+
   '@hapi/hoek@9.3.0': {}
 
   '@hapi/topo@5.1.0':


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>packages/plugin-figma-codegen/src/index.ts (2)</summary><blockquote>

`1-3`: **조건 체크 시 사용자 친화적인 메시지를 추가하는 것이 좋습니다.**

현재 코드는 조건이 맞지 않을 경우 메시지 없이 플러그인을 종료합니다. 사용자에게 왜 플러그인이 종료되었는지 메시지를 제공하는 것이 더 좋은 사용자 경험을 제공할 수 있습니다.


```diff
-if (figma.editorType !== 'dev' || figma.mode !== 'codegen') {
-  figma.closePlugin();
-}
+if (figma.editorType !== 'dev' || figma.mode !== 'codegen') {
+  figma.closePlugin('이 플러그인은 개발 모드와 코드 생성 모드에서만 작동합니다.');
+}
```

---

`8-19`: **더 풍부한 컴포넌트 코드 생성을 고려해보세요.**

현재 구현은 컴포넌트와 속성만 생성합니다. 실제 사용 시에는 import 문이나 TypeScript 타입 정의 등을 포함하면 더 유용할 수 있습니다.


```diff
     return [
       {
         title: ComponentName,
         language: 'TYPESCRIPT',
-        code: `<${ComponentName} ${result.join(' ')} />`,
+        code: `import { ${ComponentName} } from '@sipe-team/side';
+
+// 이 컴포넌트는 Figma에서 생성되었습니다
+<${ComponentName} ${result.join(' ')} />`,
       },
     ];
```

</blockquote></details>
<details>
<summary>packages/plugin-figma-codegen/package.json (1)</summary><blockquote>

`20-24`: **개발 의존성 버전 번호 확인 권장**  
`"tsup"`과 `"typescript"`의 버전이 `"catalog:"`로 설정되어 있습니다. 이는 의도한 설정인지 확인하시고, 필요하다면 구체적인 버전 번호로 업데이트하는 것을 고려해 주세요.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 28aa922c8ffd688112b43de8367b9b25c9fb7d6d and ef4f22c2b0f1ff0d550e64bde436a5cf2aa1c295.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `pnpm-lock.yaml` is excluded by `!**/pnpm-lock.yaml`

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `packages/plugin-figma-codegen/manifest.json` (1 hunks)
* `packages/plugin-figma-codegen/package.json` (1 hunks)
* `packages/plugin-figma-codegen/src/index.ts` (1 hunks)
* `packages/plugin-figma-codegen/tsconfig.json` (1 hunks)
* `packages/plugin-figma-codegen/tsup.config.ts` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>packages/plugin-figma-codegen/tsup.config.ts (1)</summary>

`1-8`: **빌드 구성이 적절히 설정되었습니다.**

tsup 구성이 명확하고 간결하게 작성되었습니다. 엔트리 포인트, 클린 옵션, 타입 선언 파일 생성 및 모듈 포맷이 잘 설정되었습니다.

</details>
<details>
<summary>packages/plugin-figma-codegen/tsconfig.json (1)</summary>

`1-6`: **타입스크립트 구성이 적절히 설정되었습니다.**

기본 구성을 확장하고 Figma 플러그인 개발에 필요한 타입 정의 경로를 올바르게 지정했습니다.

</details>
<details>
<summary>packages/plugin-figma-codegen/manifest.json (1)</summary>

`1-9`: **매니페스트 설정이 완료되었습니다.**

Figma 플러그인 매니페스트가 올바르게 구성되었습니다. 플러그인 이름, API 버전, 기능(codegen, vscode), 코드 생성 언어 및 메인 엔트리 포인트가 잘 정의되었습니다.

</details>
<details>
<summary>packages/plugin-figma-codegen/package.json (3)</summary>

`1-9`: **메타데이터 및 저장소 설정 확인**  
패키지 이름, 설명, 버전, 라이센스와 저장소 정보가 적절하게 설정되어 있습니다. 저장소 URL이 올바른지 한 번 더 확인하세요.

---

`13-19`: **스크립트 설정 확인**  
빌드, 개발, 린트, 타입체크, prepack 스크립트가 명확하게 정의되어 있습니다. 추후 필요에 따라 스크립트를 확장할 수 있겠습니다.

---

`35-35`: **sideEffects 설정 확인**  
"sideEffects": false 설정은 트리 쉐이킹 최적화를 위한 좋은 선택입니다. 현재 설정은 문제가 없어 보입니다.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-08T04:49:02Z
user: login: froggy1014
body: @noahluftyang 

Figma Dev Seat 결제해야한 사용할 수 있는 것 같아서 제가 리뷰는 제대로 못했지만 그냥 첫 기초공사같아서 넘기겠습니다.

How to 있으면 좋을 것 같은데.. 이건 Docusaurus 에 추가하는게 낫겠죠 ? 하하..

혹시 피그마 dev seat 남으면 초대해주시면 감사하겠습니다. ^_^ 

`clcl6084@gmail.com`



state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T18:04:42Z

Review comments:
diff_hunk: @@ -0,0 +1,22 @@
+if (figma.editorType !== 'dev' || figma.mode !== 'codegen') {
+  figma.closePlugin();
+}
+
+figma.codegen.on('generate', async ({ node }) => {
+  const ComponentName = node.name;
+
+  if (node.type === 'INSTANCE') {
+    const props = node.componentProperties;
+    const result = Object.entries(props).map(([name, { value }]) => `${name}="${value}"`);
+
+    return [
+      {
+        title: ComponentName,
+        language: 'TYPESCRIPT',
+        code: `<${ComponentName} ${result.join(' ')} />`,
+      },
+    ];
+  }
+
+  return [];
+});
path: packages/plugin-figma-codegen/src/index.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**컴포넌트 이름 및 속성 처리를 개선해야 합니다.**

현재 구현에는 몇 가지 잠재적인 문제가 있습니다:

1. 컴포넌트 이름(`node.name`)이 공백이나 특수 문자를 포함할 경우 유효한 React 컴포넌트 이름이 아닐 수 있습니다.
2. 속성 값에 따옴표가 포함된 경우 생성된 코드가 깨질 수 있습니다.
3. 오류 처리가 없어 예상치 못한 값이 있을 경우 플러그인이 중단될 수 있습니다.
4. 언어가 'TYPESCRIPT'로 하드코딩되어 있지만, 매니페스트에서는 'React'를 지원한다고 명시되어 있습니다.



```diff
 figma.codegen.on('generate', async ({ node }) => {
-  const ComponentName = node.name;
+  try {
+    // 컴포넌트 이름 정규화 (공백 제거 및 PascalCase 변환)
+    const componentName = node.name
+      .replace(/[^\w\s]/g, '')
+      .replace(/\s+(\w)/g, (_, c) => c.toUpperCase())
+      .replace(/^\w/, c => c.toUpperCase());
+    
+    if (node.type === 'INSTANCE') {
+      const props = node.componentProperties;
+      const result = Object.entries(props).map(([name, { value }]) => {
+        // 속성 값의 따옴표 이스케이프 처리
+        const escapedValue = value.replace(/"/g, '&quot;');
+        return `${name}="${escapedValue}"`;
+      });

+      return [
+        {
+          title: componentName,
+          language: 'TYPESCRIPT_REACT', // 또는 'REACT'가 지원된다면 사용
+          code: `<${componentName} ${result.join(' ')} />`,
+        },
+      ];
+    }
 
-  if (node.type === 'INSTANCE') {
-    const props = node.componentProperties;
-    const result = Object.entries(props).map(([name, { value }]) => `${name}="${value}"`);
-
-    return [
-      {
-        title: ComponentName,
-        language: 'TYPESCRIPT',
-        code: `<${ComponentName} ${result.join(' ')} />`,
-      },
-    ];
-  }
-
-  return [];
+    return [];
+  } catch (error) {
+    console.error('코드 생성 중 오류 발생:', error);
+    return [
+      {
+        title: '오류',
+        language: 'TYPESCRIPT',
+        code: `// 코드 생성 중 오류가 발생했습니다: ${error.message}`,
+      },
+    ];
+  }
 });
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
figma.codegen.on('generate', async ({ node }) => {
  try {
    // 컴포넌트 이름 정규화 (공백 제거 및 PascalCase 변환)
    const componentName = node.name
      .replace(/[^\w\s]/g, '')
      .replace(/\s+(\w)/g, (_, c) => c.toUpperCase())
      .replace(/^\w/, c => c.toUpperCase());
    
    if (node.type === 'INSTANCE') {
      const props = node.componentProperties;
      const result = Object.entries(props).map(([name, { value }]) => {
        // 속성 값의 따옴표 이스케이프 처리
        const escapedValue = value.replace(/"/g, '&quot;');
        return `${name}="${escapedValue}"`;
      });

      return [
        {
          title: componentName,
          language: 'TYPESCRIPT_REACT', // 또는 'REACT'가 지원된다면 사용
          code: `<${componentName} ${result.join(' ')} />`,
        },
      ];
    }

    return [];
  } catch (error) {
    console.error('코드 생성 중 오류 발생:', error);
    return [
      {
        title: '오류',
        language: 'TYPESCRIPT',
        code: `// 코드 생성 중 오류가 발생했습니다: ${error.message}`,
      },
    ];
  }
});
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T04:49:01Z
author_association: NONE
diff_hunk: @@ -0,0 +1,36 @@
+{
+  "name": "@sipe-team/plugin-figma-codegen",
+  "description": "Figma codegen plugin for Sipe Design System",
+  "version": "0.0.0",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sipe-team/side"
+  },
+  "type": "module",
+  "exports": "./src/index.ts",
+  "files": ["dist", "manifest.json"],
path: packages/plugin-figma-codegen/package.json
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**"exports" 필드 경로 검토 필요**  
현재 "exports" 필드가 소스 파일인 `./src/index.ts`를 가리키고 있습니다. 일반적으로 배포 시에는 빌드된 파일(예, `./dist/index.js`)을 참조하는 것이 안전합니다. 이 점을 반영하여 경로를 재검토해 보시기 바랍니다.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T04:49:02Z
author_association: NONE
diff_hunk: @@ -0,0 +1,36 @@
+{
+  "name": "@sipe-team/plugin-figma-codegen",
+  "description": "Figma codegen plugin for Sipe Design System",
+  "version": "0.0.0",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/sipe-team/side"
+  },
+  "type": "module",
+  "exports": "./src/index.ts",
+  "files": ["dist", "manifest.json"],
+  "scripts": {
+    "build": "tsup",
+    "dev": "pnpm build --watch",
+    "lint": "biome lint .",
+    "typecheck": "tsc",
+    "prepack": "pnpm run build"
+  },
+  "devDependencies": {
+    "@figma/plugin-typings": "^1.108.0",
+    "tsup": "catalog:",
+    "typescript": "catalog:"
+  },
+  "publishConfig": {
+    "access": "public",
+    "registry": "https://npm.pkg.github.com",
+    "exports": {
+      ".": {
+        "types": "./dist/index.d.ts",
+        "default": "./dist/index.js"
+      }
+    }
+  },
path: packages/plugin-figma-codegen/package.json
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**publishConfig 내 "exports" 설정 일관성 검토**  
publishConfig 안에 정의된 "exports"는 배포 파일(`./dist/index.js`, `./dist/index.d.ts`)을 가리키고 있습니다. 루트의 "exports" 필드와 경로가 상이한 점이 우려됩니다. 두 설정 간의 일관성을 유지하도록 조정하는 것을 추천드립니다.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-08T04:49:02Z
author_association: NONE

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-08T04:45:39Z
body: ###  ⚠️  No Changeset found

Latest commit: ef4f22c2b0f1ff0d550e64bde436a5cf2aa1c295

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/sipe-team/side/new/feat/figma-codegen?filename=.changeset/tame-owls-breathe.md&value=---%0A%22%40sipe-team%2Fplugin-figma-codegen%22%3A%20patch%0A---%0A%0Afeat(plugin-figma-codegen)%3A%20add%20figma%20codegen%20plugin%0A)


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-03-08T04:45:42Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
이번 변경사항은 Figma 코드 생성 플러그인을 위한 신규 패키지 구성을 도입합니다.  
플러그인 메타데이터, 패키지 관리, 타입스크립트 설정, 빌드 도구 설정 파일이 각각 새롭게 추가되었습니다.  
또한, `src/index.ts`에 'generate' 이벤트 리스너가 도입되어 INSTANCE 타입 노드의 컴포넌트 속성을 처리, 코드 스니펫을 생성하는 기능이 구현되었습니다.

## Changes
| 파일 경로                                                                                         | 변경 요약                                                                                                          |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `packages/plugin-figma-codegen/{manifest.json, package.json, tsconfig.json, tsup.config.ts}`         | 플러그인 메타데이터, 패키지 관리, 타입스크립트 및 빌드 도구의 구성 파일을 신규로 추가함.                             |
| `packages/plugin-figma-codegen/src/index.ts`                                                      | 'generate' 이벤트 리스너를 추가하여 INSTANCE 노드에서 컴포넌트 이름과 속성을 추출, 코드 스니펫을 생성하는 기능 구현.    |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant F as Figma
    participant P as Plugin (figma.codegen)
    participant H as Event Handler
    F->>P: 'generate' 이벤트 발생 (노드 전달)
    P->>H: 비동기 핸들러 호출
    alt 노드 타입이 INSTANCE인 경우
        H->>H: ComponentName 및 속성 추출
        H->>F: 생성된 코드 (TYPESCRIPT) 반환
    else
        H->>F: 빈 배열 반환
    end
```

## Poem
> 나는 귀여운 토끼, 코드 숲을 달리네,  
> 새 파일들이 피어나는 봄날의 마법 같아,  
> 메타데이터와 스크립트가 춤추며 노래하네,  
> 이벤트의 리듬 따라 코드가 흐르네,  
> 변화의 길 위에 반짝이는 꿈이 피어나네! 🐇🌟

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
> 
> <details>
> <summary>packages/plugin-figma-codegen/src/index.ts</summary>
> 
> 
> Oops! Something went wrong! :(
> 
> ESLint: 9.20.0
> 
> Error: Cannot find module '@eslint/js'
> Require stack:
> - /eslint.config.ts
>     at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
>     at Function.resolve (node:internal/modules/helpers:145:19)
>     at jitiResolve (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:187220)
>     at jitiRequire (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:189288)
>     at import (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:199731)
>     at /eslint.config.ts:2:17
>     at async Function.import (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:199725)
>     at async loadConfigFile (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:187:24)
>     at async ConfigLoader.calculateConfigArray (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:500:32)
>     at async #calculateConfigArray (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:663:29)
>     at async /node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/eslint/eslint.js:760:33
>     at async Promise.all (index 0)
>     at async ESLint.lintFiles (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/eslint/eslint.js:756:25)
>     at async Object.execute (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/cli.js:505:23)
>     at async main (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/bin/eslint.js:158:22)
> 
> </details>
> 
> <details>
> <summary>packages/plugin-figma-codegen/tsup.config.ts</summary>
> 
> 
> Oops! Something went wrong! :(
> 
> ESLint: 9.20.0
> 
> Error: Cannot find module '@eslint/js'
> Require stack:
> - /eslint.config.ts
>     at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
>     at Function.resolve (node:internal/modules/helpers:145:19)
>     at jitiResolve (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:187220)
>     at jitiRequire (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:189288)
>     at import (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:199731)
>     at /eslint.config.ts:2:17
>     at async Function.import (/node_modules/.pnpm/jiti@2.4.1/node_modules/jiti/dist/jiti.cjs:1:199725)
>     at async loadConfigFile (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:187:24)
>     at async ConfigLoader.calculateConfigArray (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:500:32)
>     at async #calculateConfigArray (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/config/config-loader.js:663:29)
>     at async /node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/eslint/eslint.js:760:33
>     at async Promise.all (index 0)
>     at async ESLint.lintFiles (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/eslint/eslint.js:756:25)
>     at async Object.execute (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/lib/cli.js:505:23)
>     at async main (/node_modules/.pnpm/eslint@9.20.0_jiti@2.4.1/node_modules/eslint/bin/eslint.js:158:22)
> 
> </details>
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=sipe-team/side&utm_content=130):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE