å人çã«äœã£ãŠããã¢ããªã§ Feature Sliced Design (FSD) ãšããã¢ãŒããã¯ãã£ãéäžããæ¡çšããŠããŠãå°å ¥ä»¥åã«æžãããã³ãŒãã¯ããã«æ²¿ã£ãŠããªããšããç¶æ ã®ãªããžããªããããä»åããã Cline ã䜿ã£ãŠãã®ç§»è¡ãå®äºãããããšæã£ããèªåã¯ããããèãããšãããŸã§ã¯ãããã©å®éããã®ã¯ã ãããªãã¿ãããªäœæ¥ãã AI ã«ãã£ãŠããããããªãšæã£ãŠããã®ã§é¡æãšããŠã¡ããã©ããæãã ã£ãã
ã©ããªã¢ããªããšãããš Chrome ã®ãµã€ãããã«ãšã¿ãã§åã GitHub ã® Issue/PR/Discussion ãªãŒããŒã§ãåããæ¹ã¯ Jasper ã® Chrome æ¡åŒµçãšã€ã¡ãŒãžããŠãããããšãããšæããå®å šã«èªåçšã«äœã£ãŠããã®ã§ã³ãŒãã®å ¬éãšãã¯åºæ¥ãªãã®ã§ãããŸãããšå¯ããŠã»ãããã¢ããªãããããªããšã話èªäœã¯åããããã«ããŠããã€ããã
åæ
- Tier 4 ã® 3.7 Sonnet
- ãã®ãªããžããªã§ã® AI Coding 㯠Cursor ã§å°ãã ã
- TypeScript ã§ãBiome ã Linter/Formatter ãšããŠäœ¿ã£ãŠãã(ãã)
- Cline ã ãã§ãããã
- Memory Bank ã¯å人ã®ã«ã¹ã¿ãã€ãºãšããŠå©çšããŠãã
ãããããšæã£ãŠããããš
ãã®ãªããžããªãä»åŸ AI ãšæ»ããªãéçºã§ããããç¶æ ã«ããããäžæŠ Cline ã ãšããŠããã®ããã«ã¯æ¬¡ã®èŠçŽ ãå¿ èŠã ãšèãã:
- ãªããžããªã®æ§é ã®å®é
- FSD ã«æ²¿ã£ã ESLint ã®ã«ãŒã«è¿œå
- æ¢åã³ãŒããžã®ãã¹ãã®è¿œå
- .clinerules ã®æŽå
çŸç¶ã¯ã AI åãã®ã«ãŒã«ãã¬ãŒãã¬ãŒã«ãäžåååšããŠããªãã®ã§ããããåæã«æŽåããããšãç®æšã«ããã
çŸç¶ãšç®æãç¶æ
ä»ã¯ãããªæãã« FSD ã«æ²¿ã£ãŠæžãããã®ãšããã以åã«å€§ãã lib ãš app(side-panel) ã«åããŠæžããŠãããã®ãæ··åšããŠãã:
src/
âââ entities/ # FSD å°å
¥åŸã«æžãããã®
â âââ github-search-result/
â â âââ model/
â â âââ ui/
â âââ timeline-item/
â âââ model/
â âââ ui/
â
âââ features/ # FSD å°å
¥åŸã«æžãããã®
â âââ timeline/
â âââ model/
â
âââ lib/ # FSD å°å
¥ä»¥åã®ã³ãŒãã¯å€§äœããã«ãã
â âââ github/
â â âââ gql/
â â â âââ fragment/
â â âââ __fixtures__/
â âââ stream.ts # äž»èŠããžãã¯
â
âââ shared/ # FSD
âââ side-panel/ # ãã®äžã« FSD 以åã®ã¢ããªãäœãããŠãã
â âââ components/
â â âââ side-panel-content.tsx
â â âââ side-panel-header.tsx
â â âââ side-panel.tsx
â âââ hooks/
â â âââ use-side-panel.ts
â âââ model/
â â âââ side-panel-model.ts
â â âââ types.ts
â âââ store/
â â âââ side-panel-store.ts
â âââ ui/
â âââ side-panel-ui.tsx
âââ timeline/ # ãšã³ããªãŒãã€ã³ãé¡ã¯ FSD ãåæ ããŠããªã
âââ worker/
ããããããªæãã«æŽçããã:
src/
âââ app/
â âââ entries/
â âââ side-panel/
â â âââ index.html
â â âââ index.tsx
â âââ timeline/
â âââ index.html
â âââ index.tsx
â
âââ entities/
â âââ github-search-result/
â â âââ api/
â â â âââ gql/
â â âââ model/
â â â âââ converters.ts
â â â âââ io.ts
â â â âââ timeline-item.ts
â â â âââ type.ts
â â âââ ui/
â â âââ detail.tsx
â â âââ icons/
â â âââ timeline-item.tsx
â âââ stream/
â â âââ model/
â â âââ keys.ts
â â âââ query-helper.ts
â â âââ type.ts
â âââ timeline/
â âââ model/
â âââ io.ts
â âââ type.ts
â
âââ features/
â âââ stream-notifications/
â â âââ api/
â â â âââ gql/
â â âââ model/
â â âââ events.ts
â â âââ notifications.ts
â â âââ stream-management.ts
â âââ timeline/
â âââ model/
â âââ update-timeline.ts
â âââ use-timeline.ts
â
âââ pages/
â âââ side-panel/
â â âââ model/
â â â âââ use-notification-item.ts
â â âââ ui/
â â âââ page.tsx
â âââ timeline/
â âââ ui/
â âââ page.tsx
â
âââ shared/
â âââ config/
â â âââ types.ts
â âââ lib/
â âââ browser/
â âââ event/
â âââ storage/
â âââ time/
â
âââ worker/
âââ index.ts
åºæ¬çãªäœæ¥ã®æ¹é
é©åœãªäœæ¥ã®åäœã 1 ã«ãŒããšããŠããã®ã«ãŒãã次ã®ãããªæé ã§é²ãã:
- Plan ã§å®è£ ãæ¹ä¿®ã®æ¹éãçžè«ããŠæ±ºãã
- ãã®èšç»ã Markdown ãšããŠä¿åããŠãã
- Act 㧠Markdown ãèšç»ãšããŠå®è¡ãã
- å¿ èŠãªä¿®æ£ãããã°é©å®ã§ä¿®æ£ããé¡ããã
- ã³ã³ããã¹ãã足ããªããªã£ããæåãæªãããªã£ããã Markdown ã䜿ã£ãŠæ°ãã Task ã«åŒãç¶ã
- å¿ èŠãªä¿®æ£ãçµãã£ããããã®å·®åã Markdown ã«æžã蟌ãŸããŠã¢ããããŒã
- update memory bank ãæžã足ããšãããããã° .clinerules ãã¢ããããŒã
- é©åãªã¡ãã»ãŒãžã§ git commit
ç¹åŸŽãšããŠã Plan ã®å
容ãéäž Markdown ãšããŠæ®ããŠããããšãããã®ãããã
ããã¯ãã£ãšå°ããç¯å²ã§è©ŠããŠã¿ãŠãããšã«ããã¥ã¡ã³ããšããŠæ®ãããããããããšããæ觊ããã£ãã®ã§ãããæ¡çšããŠã¿ãããšã«ããã
ãã®ãã¡ã€ã«ã®äœæã«ãŒã«ã¯ .clinerules
ã«æžããŠãã:
## ããã¥ã¡ã³ãèŠçŽ
- `docs/plans/` - èšç»ããã¥ã¡ã³ã
- ãã¡ã€ã«å㯠`{3æ¡ã®éãçªå·}_{kebab-case-name}.md` ã®åœ¢åŒã§ä¿å
ãããããç¶æ ã§ããèšç»ã docs/plans ã«ä¿åããŠããäœæ¥ãå§ããŠãã ããããšãããããªæ瀺㧠ACT ã¢ãŒãã«åãæ¿ãããšããã®èšç»ãä¿åããŠããé²ããŠãããã æçµçã«ã¯æ¬¡ã® 17 åã®èšç»ã§äœæ¥ãçµãã£ã:
plans
âââ 001_migrate-from-biome-to-eslint-prettier.md
âââ 002_monorepo-removal-plan.md
âââ 003_migrate-to-jest-and-react-testing-library.md
âââ 004_feature-sliced-design-eslint-rules.md
âââ 005_test-implementation-plan.md
âââ 006_github-search-result-timeline-restructuring.md
âââ 007_lib-to-fsd-refactoring.md
âââ 008_timeline-to-fsd-refactoring.md
âââ 009_side-panel-to-fsd-refactoring.md
âââ 010_config-stream-type-refactoring.md
âââ 011_update-stream-refactoring.md
âââ 012_entities-to-features-reference-fix.md
âââ 013_created-at-type-fix.md
âââ 014_timeline-items-type-guard.md
âââ 015_other-type-errors-fix.md
âââ 016_side-panel-item-removal.md
âââ 017_timeline-api-call-fix.md
åŸããæã£ãããšãšããŠããã£ãšçŽ°ããåããã¹ãã ã£ãã®ãšãæå®ãšæç³»åã®ææ¡ã楜ã«ãªãã®ã§é£çªã䜿ãããããè€æ°äººã®å Žåã«ã¯ã³ã³ããªã¯ãã®ãªã¹ã¯ãããã äœæ¥ãããŠããäžã§ãå ã ã®èšç»ãšã®ãºã¬ãçãŸããã Markdown ã«ãã®å·®åãè¿œèšããŠããã£ãŠãã:
ä»åã®å®è£
ã«ãèšç»ãšã®å·®åãããã° @mdfile ã«è¿œèšãè¡ã£ãŠãã ããã
ä»ã«æèããããšãšããŠãåžžã« .clinerules
ãæŽæ°ããããšãçµã¿èŸŒãã§ããã
ãããäœæ¥ãçµãã£ãããšã«æ¬¡ã®ãããªããã³ããã§æŽæ°ããŠãã:
ä»åã®äœæ¥å
容ã§ã @.clinerules ã«èšèŒãã¹ãããšãããã°è¿œèšããŠãã ããã
ããã¯ããçšåºŠã¯ãŒã¯ããŠããããã«æãããããã¯çµ¶å¯Ÿå ¥ããŠã»ãããªãšããã«ãŒã«ãçãŸãããšãã¯ããã®æšãéæãé¡ãããŠããã
æåŸã® git commit ã¯ã .clinerules
ã«ãã©ãŒããããæžããŠçœ®ãããšã§ãcommit ããŠããšããã ãã§ããæãã«ã³ãããã¡ãã»ãŒãžãäœã£ãŠãããããã«ããŠãã:
### ã³ãããã¡ãã»ãŒãžèŠçŽ
```
<type>(<scope>): <é©åãªã¡ãã»ãŒãž>
- <詳现ãªå€æŽå
容>
- <詳现ãªå€æŽå
容>
```
å®éã®äœæ¥ã§ç¹çãã¹ããšãã
倧ããã®ãã€ã³ããè©°ãŸã£ããšããããã®è§£æ±ºãæç²ããŠæžããããããã现ãã解説ããŠããããã§ã¯ãªãã
ESLint ã®ã«ãŒã«äœæé¢é£
001_migrate-from-biome-to-eslint-prettier
Biome ãã ESLint ãš Prettier ã«ç§»è¡ãããçç±ãšããŠã¯ã«ã¹ã¿ã ã«ãŒã«ãäœãããããã ã£ãããã ã¢ãžã¥ãŒã«é¢é£ã®å°é·ãå€å°èžã¿ãªãããæ»ããªã移è¡ã§ããŠããããããããã®ã¯åŸæãšããæãã ã£ãã
004_feature-sliced-design-eslint-rules
ãã®åŸãFSD ã«æ²¿ã£ãã¢ãŒããã¯ãã£ã«ãªããã ESLint ã®ã«ãŒã«ã Cline ã«äœã£ãŠããã£ãã FSD ã®ããã¥ã¡ã³ããããããæç²ããå 容ãæž¡ããŠå°ãé·ãã® Prompt ããå§ããã
ãã®ãªããžããªã¯ Feature Sliced Design (FSD) ã®èãæ¹ãåã蟌ãã æ§é ã«ãªã£ãŠãããçŸåšã¯æ¢åã®ã³ãŒããããã«åããŠç§»è¡ããŠããæäžã§ããFSD ã«ã€ããŠã¯ @https://feature-sliced.design/docs ã @https://feature-sliced.design/docs/get-started/overview ãåç
§ããŠãã ããã
移è¡äœæ¥ãé²ããåã«ã ESLint ã§ã³ãŒãã®é
眮ã«é¢ããã«ãŒã«ãäœæããŸãã
次ã®ã«ãŒã«ãäœæããŠãã ãã:
- Layers ã¯äžããäžã«ããåç
§ã§ããªãã«ãŒã«
- Layers é
äžã«ã¯ Slices ãé
眮ãããããã«ãã®é
äžã« Segments ãé
眮ãããé©åãªã³ãŒãã眮ãããã«ãŒã«
ãã ããçŸåšã³ãŒãã移è¡äžã®ãããã«ãŒã«ã«è©²åœããªããã£ã¬ã¯ããªã«ããã³ãŒãã¯ãã¹ãŠç¡èŠããŠãã ããã
## Layers ã¯äžããäžã«ããåç
§ã§ããªãã«ãŒã«
ã³ãŒãã¯æ¬¡ã®ããããã®ã¬ã€ã€ãŒã«é
眮ãããŸã:
- app* â everything that makes the app run â routing, entrypoints, global styles, providers.
- pages â full pages or large parts of a page in nested routing.
- features â reused implementations of entire product features, i.e. actions that bring business value to the user.
- entities â business entities that the project works with, like user or product.
- shared* â reusable functionality, especially when it's detached from the specifics of the project/business, though not necessarily.
ãã㯠FSD ã®èãæ¹ãã widgets ãš processes ãçç¥ãããã®ã§ãã
ã¬ã€ã€ãŒéã®åç
§ã¯äžããäžã«ããè¡ãããšãåºæ¥ããäŸãã° pages ãã features ã®ã¢ãžã¥ãŒã«ã import ããããšã¯åºæ¥ãŸããããã®éã¯åºæ¥ãŸãããåãã¬ã€ã€ãŒã§ã®æšªã®åç
§ã¯èš±å¯ãããŸãã
ãã®ã«ãŒã«ãå®ãããŠããããšã ESLint ã§ãã§ãã¯ã§ããããã«ããŠãã ããã
## Layers é
äžã«ã¯ Slices ãé
眮ãããããã«ãã®é
äžã« Segments ãé
眮ãããé©åãªã³ãŒãã眮ãããã«ãŒã«
FSD ã§ã¯ pages, features, entities ã¬ã€ã€ãŒã®äžã« Slice ãé
眮ãããããã«ãã®é
äžã« Segment ãé
眮ãããŸãã
ã³ãŒãã¯ä»»æã®å Žæã«é
眮åºæ¥ãªãããããã®ã«ãŒã«ãå®ãããšã ESLint ã§ãã§ãã¯ã§ããããã«ããŠãã ããã
å
¬åŒããåŒçšããã«ãŒã«ã¯æ¬¡ã®ããã«ãªããŸã:
Slices
Next up are slices, which partition the code by business domain. You're free to choose any names for them, and create as many as you wish. Slices make your codebase easier to navigate by keeping logically related modules close together.
Slices cannot use other slices on the same layer, and that helps with high cohesion and low coupling.
Segments
Slices, as well as layers App and Shared, consist of segments, and segments group your code by its purpose. Segment names are not constrained by the standard, but there are several conventional names for the most common purposes:
ui â everything related to UI display: UI components, date formatters, styles, etc.
api â backend interactions: request functions, data types, mappers, etc.
model â the data model: schemas, interfaces, stores, and business logic.
lib â library code that other modules on this slice need.
config â configuration files and feature flags.
Usually these segments are enough for most layers, you would only create your own segments in Shared or App, but this is not a rule.
Cline ãšçžè«ããŠãæçµçã« 5 ã€ã®ã«ãŒã«ãäœãããšã«ãªã£ã:
# Feature Sliced Design (FSD) ã«åºã¥ããESLintã«ãŒã«ã®å®è£
Feature Sliced Design (FSD) ã¢ãŒããã¯ãã£ã«åºã¥ããESLintã«ãŒã«ãå®è£
ããŸãããããã«ãããã³ãŒãããŒã¹ãFSDã®ååã«åŸã£ãŠããããèªåçã«ãã§ãã¯ã§ããããã«ãªããŸãã
## å®è£
ããã«ãŒã«
###ã¬ã€ã€ãŒéã®åç
§ã«ãŒã«
- äžäœã¬ã€ã€ãŒããäžäœã¬ã€ã€ãŒãžã®åç
§ã®ã¿èš±å¯
- app â pages â features â entities â shared ã®é ã§åç
§å¯èœ
### åäžã¬ã€ã€ãŒå
ã®Sliceéåç
§çŠæ¢
- äŸïŒentities/userããentities/productãžã®åç
§ã¯çŠæ¢
### ã¬ã€ã€ãŒæ§é ã«ãŒã«
- appãšsharedã¬ã€ã€ãŒã¯çŽæ¥Segmentsãé
眮
- pages, features, entitiesã¬ã€ã€ãŒã¯Slicesé
äžã«Segmentsãé
眮
### Public API匷å¶ã«ãŒã«
- Sliceã®å
éšå®è£
ãçŽæ¥åç
§ãããå
¬éAPIã®ã¿ãéããŠåç
§
- äŸïŒimport { Something } from '@src/entities/user'ã¯èš±å¯
- äŸïŒimport { Something } from '@src/entities/user/model/something'ã¯çŠæ¢
### ãã¬ã«ãã¡ã€ã«å
容æ€èšŒã«ãŒã«
- index.tsãã¡ã€ã«ã¯importãšexportã®ã¿ãå«ãã¹ã
- ããžãã¯ãå®è£
詳现ã¯å«ããªã
泚æç¹ãšããŠãESLint ãäœãããšãããšãã«åºã䜿ãããŠãã TIPS ãåã蟌ãã ãã ESLint ã®ãã©ã°ã€ã³ã ãšèªèããŠããããããããæ±çšçãªã³ãŒããæžããããåŸåãããããã«æãã
åè
ãšããŠã¯ã @src
ã®ãããªãããã paths
ããã®ãªããžããªã§ã¯æ¡çšããŠããªãã£ããããããæ¡çšãããŠãããã®ãããªã³ãŒããæžããŠããã
åŸè
ã¯ãäŸãã°èšå®ã eslint.config.js
ã§åºæ¥ããããªã³ãŒããæžãããšããŠãçµæè€éã«ãªãäžã«åäœããªããããªç¶æ
ã«ãªã£ãŠããã
ããã¯ãèšå®ãã¡ã€ã«ã§åºæ¥ãå¿
èŠã¯ãªãããã·ã³ãã«ã«ãã¿æžãã§å®è£
ããã°ãããããšãããããªæ瀺ãããŠããããšãèããããšãæžãã®ãã¡ãããšåãã³ãŒããåºãŠãã
ãããªãããªã§ ESLint ãå®è¡ãããšã«ãŒã«ãé©çšããã Cline ãèªèº«ã®æžããã³ãŒãã®èª€ããæ€åºã§ããããã«ãªã£ã:
/workspaces/chrome-github-plugin/src/entities/github-search-result/ui/detail.tsx
1:1 error Sliceã®å
éšå®è£
ãçŽæ¥åç
§ãããå
¬éAPI(features/timeline)ãéããŠåç
§ããŠãã ãããåSliceã¯index.tsã§ã®ã¿å€éšã«å
¬éãããã¹ãã§ãã fsd/public-api
1:1 error ã¬ã€ã€ãŒ 'entities' ããäžäœã¬ã€ã€ãŒ 'features' ãžã®åç
§ã¯çŠæ¢ãããŠããŸããã¬ã€ã€ãŒã¯äžããäžã«ã®ã¿åç
§å¯èœã§ãã fsd/layer-imports
2:1 error åäžã¬ã€ã€ãŒ 'entities' å
ã®ç°ãªãã¹ã©ã€ã¹éã®åç
§ã¯çŠæ¢ãããŠããŸããã¹ã©ã€ã¹ 'github-search-result' ãã 'timeline-item' ãžã®åç
§ã¯ã§ããŸããã fsd/slice-imports
ãã¹ããäœã£ãŠããã
003_migrate-to-jest-and-react-testing-library
ãã¹ããå šãç¡ãã£ãããã§ã¯ãªããåäœç¢ºèªçšåºŠã« Node ã®çµã¿èŸŒã¿ã©ã³ããŒã§ãã¹ãã¯æžããŠãããã AI ãæžããŠããããªã React ãããããšããããšã§ Jest ãš React Testing Library ãžç§»è¡ããŠããã£ããäŸã«ãã£ãŠã¢ãžã¥ãŒã«é¢é£ã§ãŽãã£ãããšããããã®ã®ãæŠãåŸæã
005_test-implementation-plan
å šéšã®ã³ãŒãã®ãã¹ããæžããŠãããèšç»ãç«ãŠãããšã¯ãããå ã ãã¹ããæžãããšãèããŠæžããŠããªãã³ãŒããªã®ã§ãã³ãŒããå€æŽããªããšæžããªãã®ã§ããã°ç¡èŠããŠããããšããã«ãŒã«ã«ãã:
src 以äžã®ãã¹ããæžãããŠããªãã³ãŒãã«å¯ŸããŠåäœãã¹ããè¿œå ããŸãã
ãŸããnode:test ãã Jest ãžã®ç§»è¡ãåºæ¥ãŠããªããã¹ããããã°ãããã Jest ãžç§»è¡ããŠãã ããã
å
ã®ã³ãŒããå€æŽããããšã¯ããããã¹ãã®ããã«ã³ãŒããå€æŽããããšã¯é¿ããŠãã ããã
ãã¹ããæžãããšãé£ãããã°ãç¡èŠããŠæ§ããŸããã
ããå®éã«ã¯ã现ããåããããã¹ãã§ããããªã®ã§åããŸããïŒããšåããŠããããšãããã€ããã
ãã¹ãã®å 容ãæžããŠããããããªãã®ã§ããã¯å²æããããã¹ãã®çæèªäœã¯å šäœçã«ã¯ãããšããŸãããããèšç»ã®å®è¡æ¹æ³ã«åé¡ãããããã¹ãŠã®ãã¹ããæžãã®ã§ãããªãã®èšç»ã«ãªã£ãŠããã®ã ãããèšç»ãå®è¡ããŠãã ãããã ãšéäžã§åæã«æºè¶³ããŠçµãã£ãŠããŸããšããããšããã£ãããããã€ãã®ãã¡ã€ã«ã«å¯ŸããŠãã¹ããè¿œå ã»ç§»è¡ããããšãã§ããŸããããã§ã¯ãªãå šéšãã£ãŠã»ãã:
# ãã¹ãè¿œå ã»ç§»è¡å®äºã¬ããŒã
ãã¹ãè¿œå ã»ç§»è¡èšç»ã«åºã¥ããŠäœæ¥ãé²ããããã€ãã®ãã¡ã€ã«ã«å¯ŸããŠãã¹ããè¿œå ã»ç§»è¡ããããšãã§ããŸããã
ããã§ã¯è§£æ±ºçãšããŠããã¹ãŠã®ã¹ããããçµãããŸã§ç¶ããŠããšã©ã®çšåºŠãã£ãŠã»ããã®ããæ確ã«äŒããããšã§ã¯ãŒã¯ããã®ã ããããšã§æã£ãããšãšããŠãã£ãšã¿ã¹ã¯ãåå²ããã¹ãã ã£ãããšããã®ããããããã¯èŸ»è€åãããã§ãŒãºã§ã¯ãã®åœ¢ãåãããšã«ããã
ã³ãŒãã®ç§»åãåå²
ããå šè¬ã«èšããããšãšããŠããã¹ããLintãåãã§ãã¯ãä»®ã§ãããã®ã§å šãŠéããŠãããã®äœæ¥ã«å ¥ãã¹ãã ã£ãããšããåçãããã
éå»ã®çµéšãããå€å°ãã¹ãã Lint ãèœã¡ãŠããç¶æ ã§ãããã® Task ã«é¢ä¿ããªããã®ã¯ããŸãç¡èŠåºæ¥ãŠããäºãå€ããä»åããããããŸãåããŠæåŸã«èŸ»è€ãåãããã°ããã ããããšèããŠãããä»å㯠ã³ã¢ãã¡ã€ã³ã®ç§»å â ããã䜿ãã¢ããªã®ç§»åããšããé çªã§ç§»è¡ãé²ããŠããã®ã§ãã³ã¢ãã¡ã€ã³ã移åããããšã§ã¢ããªããã®åç §ãåããŠããã«ããéããªãã£ããåãã§ã ã¯ãèœã¡ãã®ã¯æ³å®å ãã ãããããä»åãšã¯é¢ä¿ãªããšã©ãŒããšèªèããŠããããšãããªãå€ããããã¯ãªãã¹ãä¿®æ£ããªããé²ãã§ã»ããã£ãã
çµæãšããŠã¯æåŸã®èŸ»è€åããã§å€§ããèŠåŽã¯ãªãã移è¡ãšããŠã¯æåããŠããã®ã ããéäžã§ã»ãšãã©ãã«ããåºæ¥ãªãã£ãããšãã£ããšããã§ãããªãã«äžäŸ¿ããã£ãããšã¯ããæåŸã«ã¡ãããšåããªãå šäœãšããŠã¿ãã°ããã£ããšãèšããã®ã§ãå°ãããããããšããã ãªãšæãããŸããã®ãããã¯äººéãããå Žåã§ãå€ãããªãã®ã§ã¯ïŒãšèšãããã°ãããªã®ã ãã
002_monorepo-removal-plan
ãã®ãªããžããªã¯å ã Monorepo ã«ãªã£ãŠããã®ã ãããã®ã¿ã€ãã³ã°ã§ã«ãŒããžçµ±åããã倧éã«ãã¡ã€ã«ã移åããã AI ã«ããããã¯ç¡é§ã ãšããèæããã£ãã®ã§ã移åã¯ãã¡ãã§ãããšããããšãæ瀺ããŠèšç»ãç«ãŠãŠããã£ãã
007_lib-to-fsd-refactoring
ä»åã®èã§ãé©åœã«æžããŠããã³ãŒãã FSD ã«æ²¿ã£ãŠåå²ããªããåé 眮ãããã±ã£ãšã€ã¡ãŒãžããã£ãããã§ã¯ãªãã®ã§ãåæããŠèšç»ã倧ãŸãã«ç«ãŠãŠããããšããããå§ããã
@/src/lib/ 以äžã®ã³ãŒãã FSD ã®ã«ãŒã«ã«ãã£ãŠé©åãªæ§æã«äœãå€ããŸãã
ãŸãã¯å€§ãŸãã«ãã©ã³ãèããŠãã ããã
ããããçžè«ããŠãã£ãã®ã ãèŠç¹ãšããŠã¯ä»¥äž:
- 䌌ããããªæŠå¿µã FSD ãš lib ããããã«ååšããŠããŠãããããå¥ã ã®ãã®ãšããŠæ±ãããšããŠããã®ã§ãçµ±åããŠãããããã«ãã
- ã¢ããªã®ãã¡ã€ã³ç¥èã足ããã« Notification ãäžè¬çãªéç¥æ©èœã ãšæã蟌ã¿ç¬ç«ãããããšããŠãããããã¯ãã®ã¢ããªã§ã¯å°ãéãæŠå¿µãªã®ã§è»éä¿®æ£ãã
- ããã¯ã¢ããªå ã§ã¯ãæŽæ°ããã£ãIssueããããã®æå³ã§äœ¿ãããŠãã
- GraphQL ã® query ã®æ±ãæ¹ãçžè«ããŠæ±ºãã
èšç»ãåºæ¥ããã现ããã¹ãããã«åå²ããŠãšãé¡ãããåŸã«ãé©åœãªåäœã§ git commit ããããã«ãé¡ãããŠãã(ãã㯠.clinerules
ã«å«ãã以åã®è©±):
èšç»ã®è©³çŽ°ãã¯ç¶æãããŸãŸå°ããã¹ãããã«åå²ããŠ
åã¹ããã㧠git commit ãè¡ãããã«ããŠãã ããããã©ãŒãããã¯ä»¥äž
git add .
git commit -am "refactor: <é©åãªã¡ãã»ãŒãž>
- 詳现
- 詳现
- 詳现
"
ã§ããããããŸãè¡ã£ãããšãããšåè¿°ããéãããŸãããŸããããªããŠãéäžãŸã§é²ããŠæºè¶³ããã®ãæ¢ãŸã£ãŠããŸãã ã¹ãããããšã® git commit ãéäžãŸã§ã¯ããŸãè¡ã£ãŠããã®ã ãã©ãäžåºŠæ¢ãŸã£ãããšã«åéããããšãã®æ瀺ã Markdown ã«å«ãŸããŠããã®ã«ããããããå¿ããŠããŸã£ããã§ããã¬ã¬ãšããæãã ã£ãã ä»å㯠Cline èªäœã®æ€èšŒãå ŒããŠããã®ã§ãæºè¶³è¡ããããªåãããããŸã§ãã®ãã§ãŒãºãäœåºŠãããçŽããŠããŠãå®è£ ãã§ãŒãºã®å®è¡ã ãã§åèš $30 ãããå¹ãé£ãã§ãã£ããã€ããã
çµæãšããŠã¯ããã¯ããã§ãã¯ãªã¹ããå¥ãã¡ã€ã«ãšããŠäœã£ãŠã¢ããããŒãããªãããã£ãŠããšããã®ãããçšåºŠã¯ãŒã¯ããŠããŠããåãããšã¯åºæ¥ãã®ã ããæŽæ°ã®ã¿ã€ãã³ã°ããŸã¡ãŸã¡ã ã£ããããŠããŸãããããã§ããæãã§ã¯ãªãã£ããã¡ãããšæŽæ°ã®ã«ãŒã«ãã€ããŠããããšããRoo Code ã§ããã°ãããã Mode ãäœãã°ããŸããããããšããæãã¯ããããããŸãããããã§ããªãæãããããªããã³ããã§ãã£ãŠãã:
@/docs/plans/007_lib-to-fsd-refactoring.md ã«æ²¿ã£ãŠã src/lib 以äžã FSD ã«æºããã³ãŒãã«ããäœæ¥ãé²ããŸãã
æåã« docs/checklist.md ãšããŠè©³çŽ°ãªäœæ¥ã®ãã§ãã¯ãªã¹ããäœã£ãŠãã ãããã¹ãããæ¯ã®äœæ¥ã¯ä»¥äžã®æé ã§é²ããããã«ããŠãã ããã
```
1. pnpm test ãå®è¡ããåã®äœæ¥ãåé¡ãæ®ããŠããªãããšã確èªãã
2. åã¹ãããã®å®è£
ãè¡ã
3. åäœãã¹ã: `pnpm test -- <äœæ¥ãããã£ã¬ã¯ããª>`
4. åãã§ãã¯: `pnpm tsc --noEmit`
5. ãªã³ãã£ã³ã°: `pnpm lint <äœæ¥ãããã£ã¬ã¯ããª>`
6. é¢é£ãã¹ã: äœæ¥å
容ã«åœ±é¿ãåããå¯èœæ§ã®ããä»ã®ãã¹ããå®è¡
7. 以äžã®åœ¢åŒã§å€æŽããã¹ãŠ git commit
refactor: <é©åãªã¡ãã»ãŒãž>
- 詳现ãªå€æŽç¹
- 詳现ãªå€æŽç¹
- 詳现ãªå€æŽç¹
```
以åŸäœãäœæ¥ãé²ããããšã«å¿
ããã®ãã§ãã¯ãªã¹ããæŽæ°ããªããé²ããŸãã
æºåãåºæ¥ããããã¹ãŠã®ã¹ãããã®äœæ¥ãå®äºãããŸã§äœæ¥ãç¶ããŠãã ããã
äžæ¹ã§ã¢ãã«ã®çµ±åã¯èšç»ã§æéãæžãããããããŸããã£ãŠãããŠããããããã ããšã¯ãã¹ãã移è¡ããã®ãå¿ããã®ã§ãã¡ãããšæ瀺ã«å«ããã»ããããããã ã£ãã
蟻è€åãããã§ãŒãº
010 以éãããã«ããããåè¿°éãèšç»ã倧ããããåçã掻ãããŠã Plan ãšããŠã¯ãpnpm eslint ãå®è¡ããŠå šéšçŽããŠããããã®ãã®ããå§ããããèšç»ãä¿åãããšãã«å ·äœçãªå 容ã§åå²ããŠä¿åããããã«ãã:
deleteLogic ãš ConfigStream ãžã®ãªããŒã ã«é¢ããäœæ¥èšç»ãšã updateStreamã®åŒã³åºãã«é¢ããäœæ¥èšç»ããããã docs/plans ã«æžãåºããŠãã ãã
ãããããš 010 ãš 011 ã«èšç»ãåããŠãããã®ã§ãå°ãããªã£ãåå¥ã® Task ãããããå®è¡ãããŠå®äºãããŠãã£ããçªå·ã®ã€ãæ¹ã¯ãšããããããã¯çµæ§ããŸãè¡ã£ãããã«æãã
.clinerules
çµç€ã«ãªã£ãŠ .clinerules
ã«ããçšåºŠæ
å ±ãæºãŸã£ãæ¥ããšãã㧠.clinerules
ããã©ãã·ã¥ã¢ããããã:
@/.clinerules ããããããã®ã«ã¢ããããŒãããããšèããŠããŸãã
ããè¯ããšã¯ã次ã®ãããªåºæºã§ãã
- æ確ãã€ç°¡æœã§ããããš
- å
šäœã®ããŒã³ãæã£ãŠããããš
- éèŠãªã¢ãŒããã¯ãã£ã®æ žå¿ã«ã€ããŠã¯ãã詳ããæžãããŠããããš
- ç¹æ®ãªè¡šèšã䜿ãããèŠåºãã段èœãç®æ¡æžãããªã¹ããäžå¿ãšããã人ã«ãèªã¿ãããã·ã³ãã«ãªæ§æ
- èšèŒãããŠããé åºãããç·ŽãããŠãããäžããé ã«èªãã°éçºã«çæã§ãã
ãŸãã次ã®ãããªèŠçŽ ãä»ãå ããããšèããŠããŸãã
- ç°¡åãªã³ãŒããæžãããš
- æ©æãªã¿ãŒã³ãæèããã©ãããªæ§é ã«ãã
- é¢æ°ã§æžãããšãåªå
ãã
- ...
ãããã .clinerules ãäœãããããã³ãŒãããŒã¹ãåèã«ããŠèããŠãã ããã
æçµçã«ã¯æ¬¡ã®ãããªå 容ã«ãªã£ã:
# ãããžã§ã¯ãã«ãŒã«
## éèŠ
1. ã³ãŒãå€æŽåã«ãã¹ãã確èªããå®è¡ãã
2. ãã¹ãã§æåŸ
ããåäœãäºåã«å®çŸ©ãã
3. ã³ãŒãäœæåŸããã¹ããšéç解æãå®è¡
4. 3åé£ç¶ã§åé¡è§£æ±ºã§ããªãå ŽåããŠãŒã¶ãŒã«çžè«ãã
## éçºã¯ãŒã¯ãããŒ
### ã³ãã³ãäžèŠ§
- **éçºãµãŒããŒèµ·å**: `pnpm dev`
- **ãã«ã**: `pnpm build`
- **ãã¹ãå®è¡**: `pnpm test`
- ç¹å®ã®ãã¹ããã¡ã€ã«å®è¡: `pnpm test -- <filename>`
- **ãã¹ãïŒç£èŠã¢ãŒãïŒ**: `pnpm test:watch`
- **ãã¹ãã«ãã¬ããž**: `pnpm test:coverage`
- **ãªã³ãã£ã³ã°**: `pnpm lint`
- ç¹å®ãã¡ã€ã«ã®ãªã³ã: `pnpm lint -- <filename>`
- **ã³ãŒãèªåä¿®æ£**: `pnpm lint:fix`
- **ãã©ãŒããã**: `pnpm format`
### éçºãããŒ
1. **æ©èœå®è£
å**: ãã¹ããå
ã«æžãïŒTDDïŒ
2. **ã³ãŒãå€æŽæ**: æ¢åãã¹ããéãããšã確èª
3. **ã³ãŒãäœæåŸ**: ãã¹ããå®è¡ããŠæåŸ
éãã®åäœã確èª
```bash
pnpm test -- <filename> # ç¹å®ã®ãã¡ã€ã«ã®ãã¹ããå®è¡
# ãŸãã¯
pnpm test # ãã¹ãŠã®ãã¹ããå®è¡
```
4. **ãã¹ã倱ææ**: ãã¹ããéãããã«ã³ãŒããä¿®æ£
5. **ãªãã¡ã¯ã¿ãªã³ã°æ**: ãã¹ããåŒãç¶ãéãããšã確èª
6. **ã³ãããå**: ESLintãå®è¡ããŠã³ãŒãã¹ã¿ã€ã«ã確èª
```bash
pnpm lint
pnpm lint:fix # èªåä¿®æ£å¯èœãªåé¡ãä¿®æ£
```
### æ¡åŒµæ©èœã®ããŒãæ¹æ³
1. Chromeã§`chrome://extensions`ãéã
2. ããããããŒã¢ãŒããæå¹å
3. `packages/extention/dist`ãã£ã¬ã¯ããªãèªã¿èŸŒã
### ã³ãããã¡ãã»ãŒãžèŠçŽ
```
<type>(<scope>): <é©åãªã¡ãã»ãŒãž>
- <詳现ãªå€æŽå
容>
- <詳现ãªå€æŽå
容>
```
## éçºã®åºæ¬åå
### ã³ãŒãå質
- **ã·ã³ãã«ãªã³ãŒã**: è€éãªå®è£
ããèªã¿ãããã³ãŒããåªå
- **æ©æãªã¿ãŒã³**: æ¡ä»¶åå²ã¯ãã¹ããé¿ããæ©æãªã¿ãŒã³ã§ãã©ãããªæ§é ã«
```typescript
// è¯ãäŸ
function processItem(item) {
if (!item) return null;
if (item.isInvalid) return null;
return transformItem(item);
}
// é¿ããã¹ãäŸ
function processItem(item) {
if (item) {
if (!item.isInvalid) {
return transformItem(item);
}
}
return null;
}
```
### é¢æ°åã¢ãããŒã
- **é¢æ°åªå
**: ã¯ã©ã¹ãããé¢æ°ã§å®è£
- **çŽç²é¢æ°**: å¯äœçšãæããªãé¢æ°ãåªå
- **ã«ãŒãåŠç**: `forEach`ãé¿ãã`for...of`ãŸãã¯é
åã¡ãœããã䜿çš
```typescript
// è¯ãäŸïŒéåæåŠçã®å ŽåïŒ
for (const item of items) {
await processItem(item);
}
// è¯ãäŸïŒåæåŠçã®å ŽåïŒ
const results = items.map(item => processItem(item));
// é¿ããã¹ãäŸ
items.forEach(async (item) => {
await processItem(item); // éåæåŠçã®å¶åŸ¡ãé£ãã
});
```
### äŸå管ç
- **äŸåã®æå°å**: å¯èœãªéããªããžããªå
ã®ã³ãŒãã§è§£æ±º
- **äŸåè¿œå æ**: å¿
ããŠãŒã¶ãŒã«ç¢ºèª
- **å€éšäŸåã®ã¢ãã¯**: ãã¹ãæã«å€éšäŸåãé©åã«ã¢ãã¯å
### æœè±¡å
- **é床ãªæœè±¡åãé¿ãã**: å
·äœçã§ç解ããããã³ãŒããåªå
- **Sliceã®å
·äœæ§**: æœè±¡çãªã³ãŒããããå
·äœçãªå®è£
ãåªå
## ã¢ãŒããã¯ãã£ïŒFeature Sliced DesignïŒ
### ã¬ã€ã€ãŒæ§é
1. **app** â ã¢ããªã±ãŒã·ã§ã³å®è¡ã«å¿
èŠãªèŠçŽ
- ãšã³ããªãŒãã€ã³ããã°ããŒãã«ã¹ã¿ã€ã«ãã«ãŒãã£ã³ã°
2. **pages** â å®å
šãªããŒãžãŸãã¯ãã¹ããããããŒãžéšå
3. **features** â ãŠãŒã¶ãŒã«ããžãã¹äŸ¡å€ãããããæ©èœ
4. **entities** â ããžãã¹ãšã³ãã£ãã£ïŒGitHub Search ResultãTimeline Itemãªã©ïŒ
5. **shared** â åå©çšå¯èœãªæ©èœïŒãããžã§ã¯ã/ããžãã¹ããç¬ç«ïŒ
### åç
§ã«ãŒã«
- äžäœã¬ã€ã€ãŒããäžäœã¬ã€ã€ãŒãžã®åç
§ã®ã¿èš±å¯
- `app` â `pages` â `features` â `entities` â `shared`
- äžäœã¬ã€ã€ãŒããäžäœã¬ã€ã€ãŒãžã®åç
§ã¯çŠæ¢
- åäžã¬ã€ã€ãŒå
ã®Sliceéã®åç
§ãçŠæ¢
### Sliceæ§é
- **app**ãš**shared**ã¬ã€ã€ãŒã¯çŽæ¥Segmentsãé
眮
- **pages**, **features**, **entities**ã¬ã€ã€ãŒã¯Slicesé
äžã«Segmentsãé
眮
### Segmentæ§é
- **ui** â UI衚瀺ïŒã³ã³ããŒãã³ããã¹ã¿ã€ã«ãªã©ïŒ
- **model** â ããŒã¿ã¢ãã«ïŒã¹ããŒããããžãã¯ãªã©ïŒ
- **api** â ããã¯ãšã³ãé£æºïŒãªã¯ãšã¹ãé¢æ°ãªã©ïŒ
- **lib** â ä»ã®ã¢ãžã¥ãŒã«ãå¿
èŠãšããã©ã€ãã©ãªã³ãŒã
- **config** â èšå®ãã¡ã€ã«ãšãã©ã°
### Public API
- åSliceã®å
¬éAPIã¯index.tsã§æ瀺çã«ãšã¯ã¹ããŒã
- Sliceã®å
éšå®è£
詳现ãçŽæ¥åç
§ããããšã¯çŠæ¢
- åsliceã®çŽäžã«ã¯å¿
ãindex.tsãã¡ã€ã«ãé
眮
```typescript
// entities/github-search-result/index.ts
export * from './api';
export * from './model/io';
export * from './model/timeline-item';
export * from './model/type';
export * from './ui/detail';
// ...
```
## ã³ãŒãã£ã³ã°èŠçŽ
### TypeScript
- åå®çŸ©ãå³æ Œã«è¡ã
- åã¬ãŒãé¢æ°ã掻çšããŠåå®å
šæ§ã確ä¿
```typescript
function isCommentTimelineItem(item: any): item is CommentTimelineItem {
return item.type === 'IssueComment' && 'bodyText' in item;
}
```
### Reactã³ã³ããŒãã³ã
- é¢æ°ã³ã³ããŒãã³ããšããŠå®è£
- Reactããã¯ã掻çš
- ããããã£ããŒã¹ã®èšèšïŒäžäœã¬ã€ã€ãŒã®ã³ã³ããŒãã³ãã¯äžäœã¬ã€ã€ãŒã®æ©èœãçŽæ¥åç
§ããªãïŒ
### ã¹ã¿ã€ãªã³ã°
- CSSã¢ãžã¥ãŒã«ã䜿çšããŠã¹ã¿ã€ã«ãã³ã³ããŒãã³ãã¹ã³ãŒãã«ä¿ã€
```typescript
import styles from './component.module.css';
function Component() {
return <div className={styles.container}>...</div>;
}
```
### ãã¡ã€ã«åœå
- ãã¡ã€ã«åã¯ãã£ã¡ã«ã±ãŒã¹ã䜿çš
- ãã¹ããã¡ã€ã«ã¯`.spec.ts(x)`ãšããåœåèŠå
### ã€ã³ããŒã
- çžå¯Ÿãã¹ã®ã¿äœ¿çšïŒãšã€ãªã¢ã¹ã¯äœ¿çšããªãïŒ
- ãã¹èšæ³ã¯`./{path}`ã`../{path}`ã®ã¿
```typescript
// è¯ãäŸ
import { Button } from '../../shared/ui/button';
// é¿ããã¹ãäŸ
import { Button } from '@shared/ui/button';
```
## å®è£
ãã¿ãŒã³
### ã¹ããªãŒã æŽæ°ãã¿ãŒã³
- `updateStream`é¢æ°ã§GitHubããããŒã¿ãååŸ
- åã¹ããªãŒã ã¯`onUpdateThisLoop`é¢æ°ã§æŽæ°ã¿ã€ãã³ã°ãå¶åŸ¡
- æŽæ°åŸã¯`notifyUpdated`ã§ã€ãã³ããçºè¡
```typescript
export const updateStream = async (name: keyof typeof streams, storage: Storage) => {
// ããŒã¿ååŸããžãã¯
// ...
// éç¥æ¡ä»¶ã®å€å®
if (item.type === 'Issue' && shouldNotifyIssue(item, 'username', lastUpdated)) {
createNotificationIfNeeds(storage, item.id, lastUpdated);
}
// ã¹ãã¬ãŒãžæŽæ°
await Promise.all([
setToStorage(storage, keyForItem(item.id), item),
setToStorage(storage, keyForStreamItems(stream), newIds),
]);
// ã€ãã³ãçºè¡
notifyUpdated(name, updatedIds);
};
```
### ã¹ãã¬ãŒãžç®¡çãã¿ãŒã³
- ããŒã¯`keyFor*`é¢æ°ã§çæïŒäžè²«æ§ã®ããïŒ
- `getFromStorageOrDefault`ãš`setToStorage`ã䜿çš
- ã¢ã€ãã IDããªã¹ããšããŠä¿åããå®éã®ããŒã¿ã¯åå¥ã«ä¿å
```typescript
const ids = await getFromStorageOrDefault(storage, keyForStreamItems(stream), () => []);
const items = [];
for (const id of ids) {
const item = await getFromStorageOrDefault(storage, keyForItem(id), () => null);
if (item) {
items.push(item);
}
}
```
### éç¥ã·ã¹ãã
- `shouldNotifyIssue`ãš`shouldNotifyDiscussion`ã§éç¥æ¡ä»¶ãå€å®
- `createNotificationIfNeeds`ã§éç¥ãäœæ
- `notifyNotificationUpdated`ã§ã€ãã³ããçºè¡
### ã€ãã³ãåŠç
- ã«ã¹ã¿ã ã€ãã³ãïŒ`stream:updated`ã`notification:updated`ïŒã䜿çš
- `subscribeStreamUpdated`ãš`subscribeNotificationUpdated`ã§è³Œèª
```typescript
// ã€ãã³ãçºè¡
export const notifyUpdated = (name: string, ids: string[], worker = false) => {
dispatchUpdate('stream:updated', { name, ids }, worker);
};
// ã€ãã³ã賌èª
useEffect(() => {
const unsubscribe = subscribeStreamUpdated(({ name }) => {
if (name === streamName) {
fetchData();
}
});
return () => unsubscribe();
}, [streamName, fetchData]);
```
### ããããã£ããŒã¹ã®ã³ã³ããŒãã³ãèšèš
- FSDã¬ã€ã€ãŒéåç
§ã«ãŒã«ã«åŸããããäžäœã¬ã€ã€ãŒïŒentitiesïŒã®ã³ã³ããŒãã³ãã¯äžäœã¬ã€ã€ãŒïŒfeaturesïŒã®æ©èœãçŽæ¥åç
§ããªã
- éç¥ç¶æ
ãªã©ã®æ©èœã¯äžäœã¬ã€ã€ãŒããããããã£ãšããŠæ³šå
¥ãã
- äŸ: `IssueLine`ã³ã³ããŒãã³ãã¯`hasNotification`ã`onDeleteNotification`ãããããã£ãšããŠåãåã
### éåæåŠçãã¿ãŒã³
- async/awaitã䜿çšããèªã¿ãããéåæã³ãŒã
- Promise.allã䜿çšãã䞊ååŠç
- for...ofã«ãŒãã䜿çšããéåæåŠçïŒforEachã§ã¯ãªãïŒ
```typescript
// 䞊ååŠç
const results = await Promise.all(
queries.map(query => fetchData(query))
);
// é 次åŠç
for (const item of items) {
await processItem(item);
}
```
## ãã¹ãæŠç¥
### ãã¹ããã¡ã€ã«ã®é
眮
- å®è£
ãã¡ã€ã«ãšåããã£ã¬ã¯ããªã«é
眮
- `.spec.ts(x)`ãšããåœåèŠåã䜿çš
### ãã¹ããã¡ãŒã¹ã
- ãã¹ããå
ã«æžãããšã§ãä»æ§ãæ確ã«ãã
- å®è£
åã«ãã¹ããæžãããšã§ãAPIãåäœã®èšèšãæŽç·Žããã
- ãã¹ããéãããã«å®è£
ããããšã§ãèŠä»¶ãæºããä¿èšŒã«ãªã
### ãã¹ãã£ã³ã°ãããã£ãŒ
- ãã¹ãã£ã³ã°ãããã£ãŒãæèããé床ãªã¢ãã¯åã¯é¿ãã
- åäœãã¹ããçµ±åãã¹ããE2Eãã¹ãã®ãã©ã³ã¹ãèæ
®
- å®éã®ãŠãŒã¶ãŒäœéšã«è¿ããã¹ããåªå
- ã¢ãã¯ã¯å¿
èŠæå°éã«ãšã©ããå¯èœãªéãå®éã®å®è£
ã䜿çš
### ãã¹ãé¢æ°
- `test`é¢æ°ã䜿çšïŒ`describe`ã`it`ã¯äœ¿çšããªãïŒ
- æ¥æ¬èªã§ãã¹ãå
容ãèšè¿°
```typescript
test('åæç¶æ
ã§ã¯pendingãtrueã§ãããŒã¿ååŸåŸã«falseã«ãªã', async () => {
// ãã¹ãå®è£
});
```
### ã¢ãã¯ã®æŽ»çš
- Jestã®ã¢ãã¯æ©èœã䜿çš
- å€éšäŸåé¢ä¿ãé©åã«ã¢ãã¯å
- é床ãªã¢ãã¯åã¯é¿ããå®éã®åäœãåæ ãããã¹ããå¿ããã
```typescript
jest.mock('../../../entities/timeline/model/io');
jest.mock('../../../shared/lib/event');
beforeEach(() => {
(timelineIO.getTimeline as jest.Mock).mockResolvedValue(mockTimeline);
});
```
### UIã³ã³ããŒãã³ããã¹ã
- React Testing Libraryã䜿çš
- ã¬ã³ããªã³ã°ã®æ€èšŒ
- ãŠãŒã¶ãŒã€ãã³ãã®ã·ãã¥ã¬ãŒã·ã§ã³
- ã¢ã¯ã»ã·ããªãã£ãèæ
®ããã»ã¬ã¯ã¿ã®äœ¿çš
```typescript
test('ãShow all eventsããã¿ã³ãã¯ãªãã¯ãããšãã¹ãŠã®ã€ãã³ãã衚瀺ããã', () => {
render(<TimelineItems items={items} />);
// ãã¿ã³ãã¯ãªãã¯
fireEvent.click(screen.getByText(/Show all events/));
// 衚瀺ãæ€èšŒ
expect(screen.getByText(/testUser commented/)).toBeInTheDocument();
});
```
## ã³ã¡ã³ãèŠçŽ
- `TODO`: å°æ¥çã«å®è£
ãã¹ãæ©èœ
- `MEMO`: å®è£
ã®èæ¯ãçç±ã®èª¬æ
## ããã¥ã¡ã³ãèŠçŽ
- `docs/plans/` - èšç»ããã¥ã¡ã³ã
- ãã¡ã€ã«å㯠`{3æ¡ã®éãçªå·}_{kebab-case-name}.md` ã®åœ¢åŒã§ä¿å
## å¶çŽãšæ³šæç¹
### GitHub APIå¶é
- ã¬ãŒãå¶éã«æ³šæïŒçæéã«å€æ°ã®ãªã¯ãšã¹ããéããªãïŒ
- ãšã©ãŒãã³ããªã³ã°ãé©åã«å®è£
### ãµãŒãã¹ã¯ãŒã«ãŒå¶çŽ
- ãµãŒãã¹ã¯ãŒã«ãŒã®ã©ã€ããµã€ã¯ã«ã«æ³šæïŒé·æéå®è¡ã§ããªãïŒ
- å®æçãªãŠã§ã€ã¯ã¢ãããšåŠçã®åæ£
### æ¢ç¥ã®åé¡
- ãŠãŒã¶ãŒåãããŒãã³ãŒããããŠããç®æãããïŒå°æ¥çã«èšå®ããååŸããããå€æŽäºå®ïŒ
- ååããŒã¿ååŸæã®æåã«å¶éãã
ã¡ãªã¿ã«ãããæžããŠããéäžã« .clinerules
ããã£ã¬ã¯ããªã«ã§ããããã«ãªã£ãã
ææ
èšç»ã®ç®¡çæ¹æ³ãšåºåãæ¹
管çæ¹æ³ã«é¢ããŠã¯çããããŸãèããããŠããªãã®ã ãã©ãèšç»ã® Markdown ãäžå¿ã«åãã®ã¯èªåãšããŠã¯å¥œã¿ã®ãããŒã ã£ãã ãããŒä»¥å€ã«ããæ³å®ããŠããªããšãåäœãããããªã³ãŒããèŠã€ãã£ããšãã«ããããã©ãã§çãŸãããã Markdown ãé¡ã£ãŠæ¢ãã«è¡ã£ãŠãããŠãããããŠãããããæå³ããã£ãã»ããããã®ã ãšã¯æãã ãšã¯ãããã¡ãã£ãšãã bugfix ãŸã§ãã¹ãŠç®¡çãããã®ããšèšããããšããã§ããªãã PR ã®åäœã§äžã€ããã°ãããããªæž©åºŠæãªã®ã§ã Plan ãšãããã㯠Design Doc ã®ãããªæèŠã§æ®ãããšããã®ããªãšæãã
çªå·ã¯æå®ã楜ã«ãªãã®ã§å²ãšã»ãããŠãè€æ°äººã§ç®¡çããå Žåã¯ãã¯ã GitHub Issue ãªã©ã«é£æºã§ãããšããããããããããšããããããŒåãã Roo Code ã®ã«ã¹ã¿ã ã¢ãŒãã䜿ããããªããªããšããæãã ã£ãã
å®éã®ç®¡çæ¹æ³ãã©ã®ããã«ããŠãããã«ãããããèšç»èªäœã¯æã£ãŠãã 3 åãããã¯çŽ°ããããã»ãããããªãšæã£ãã Design Doc ã®ãããªåœ¢ã«ããå Žåã¯ãããŸãåãããããŠããŠãå¹æãèãããªã®ã§ã Git 管çäžã«ãªãå Žæã§å人çã«äœ¿ãã®ãæãããããªãã
Lint 㯠AI ã«æŽåããã
çµæ§ã¡ãããšãããã®ãããã«åºãŠããã®ã§äŸ¿å©ã æ±çšçãªãã®ãäœãããšããåŸåã«ããããã«æãã®ã§ãå±ææé©ããŠè¯ãããšãäŒãããšç²ŸåºŠãäžããããã«æãã
å€åäœãçŽãããã»ãããã
æ¢åã®ã³ãŒãã倧ããæžãæããããããæ¢åã®ã³ãŒãã解æãããŠä»æ§æœåºããã®ä»æ§ãããšã«æ°ããã³ãŒããçæãããæ¹ãåŸæã ãããšæãã®ã§ãä»åã®ããã« Cline ã§ç§»åãããã¿ãããªã®ã¯ãããŸãåããŠããªãæ°ãããã éäžã§ããçŽããŠãããã§ãŒãºãããã€ããããšã¯ãããããåãã®ã«å€§äœ $100 ããã£ãŠããŠããããäœãçŽããã»ããå®ããïŒããšæããªãããã£ãŠããã
ååã暪çããã«ã¡ãããšã€ãã
å¥ã«äººéãã³ãŒããæžãå Žåã§ãå€ãããªã話ã§ã¯ããããæœè±¡åºŠãé«ãååã䜿ã£ãŠãããšåæã«åœ¹å²ãæšæž¬ãããŠãããããªæèŠããã£ãã æ°ããäœãå Žåããã¯ãæ¢åã®ã³ãŒãã解æãããããªãã¡ã¯ã¿ãªã³ã°ãããå Žåã«ããã¯å€§ãã圱é¿ããŠãããããšããèæã