@einja/dev-cli 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +49 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +243 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +23 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/sync.d.ts +7 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +294 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/sync.test.d.ts +2 -0
- package/dist/commands/sync.test.d.ts.map +1 -0
- package/dist/commands/sync.test.js +593 -0
- package/dist/commands/sync.test.js.map +1 -0
- package/dist/commands/task-loop.d.ts +11 -0
- package/dist/commands/task-loop.d.ts.map +1 -0
- package/dist/commands/task-loop.js +81 -0
- package/dist/commands/task-loop.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/file-system.d.ts +39 -0
- package/dist/lib/file-system.d.ts.map +1 -0
- package/dist/lib/file-system.js +79 -0
- package/dist/lib/file-system.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +43 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +109 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/mcp-config.test.d.ts +2 -0
- package/dist/lib/mcp-config.test.d.ts.map +1 -0
- package/dist/lib/mcp-config.test.js +285 -0
- package/dist/lib/mcp-config.test.js.map +1 -0
- package/dist/lib/merger.d.ts +41 -0
- package/dist/lib/merger.d.ts.map +1 -0
- package/dist/lib/merger.js +164 -0
- package/dist/lib/merger.js.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.d.ts +35 -0
- package/dist/lib/preset-update/cli-repo-detector.d.ts.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.js +83 -0
- package/dist/lib/preset-update/cli-repo-detector.js.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.test.d.ts +2 -0
- package/dist/lib/preset-update/cli-repo-detector.test.d.ts.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.test.js +120 -0
- package/dist/lib/preset-update/cli-repo-detector.test.js.map +1 -0
- package/dist/lib/preset-update/file-copier.d.ts +59 -0
- package/dist/lib/preset-update/file-copier.d.ts.map +1 -0
- package/dist/lib/preset-update/file-copier.js +220 -0
- package/dist/lib/preset-update/file-copier.js.map +1 -0
- package/dist/lib/preset-update/file-copier.test.d.ts +2 -0
- package/dist/lib/preset-update/file-copier.test.d.ts.map +1 -0
- package/dist/lib/preset-update/file-copier.test.js +297 -0
- package/dist/lib/preset-update/file-copier.test.js.map +1 -0
- package/dist/lib/preset-update/preset-finder.d.ts +39 -0
- package/dist/lib/preset-update/preset-finder.d.ts.map +1 -0
- package/dist/lib/preset-update/preset-finder.js +92 -0
- package/dist/lib/preset-update/preset-finder.js.map +1 -0
- package/dist/lib/preset-update/preset-finder.test.d.ts +2 -0
- package/dist/lib/preset-update/preset-finder.test.d.ts.map +1 -0
- package/dist/lib/preset-update/preset-finder.test.js +128 -0
- package/dist/lib/preset-update/preset-finder.test.js.map +1 -0
- package/dist/lib/preset.d.ts +14 -0
- package/dist/lib/preset.d.ts.map +1 -0
- package/dist/lib/preset.js +52 -0
- package/dist/lib/preset.js.map +1 -0
- package/dist/lib/sync/backup-manager.d.ts +50 -0
- package/dist/lib/sync/backup-manager.d.ts.map +1 -0
- package/dist/lib/sync/backup-manager.js +117 -0
- package/dist/lib/sync/backup-manager.js.map +1 -0
- package/dist/lib/sync/backup-manager.test.d.ts +2 -0
- package/dist/lib/sync/backup-manager.test.d.ts.map +1 -0
- package/dist/lib/sync/backup-manager.test.js +155 -0
- package/dist/lib/sync/backup-manager.test.js.map +1 -0
- package/dist/lib/sync/batch-processor.d.ts +27 -0
- package/dist/lib/sync/batch-processor.d.ts.map +1 -0
- package/dist/lib/sync/batch-processor.js +46 -0
- package/dist/lib/sync/batch-processor.js.map +1 -0
- package/dist/lib/sync/batch-processor.test.d.ts +2 -0
- package/dist/lib/sync/batch-processor.test.d.ts.map +1 -0
- package/dist/lib/sync/batch-processor.test.js +110 -0
- package/dist/lib/sync/batch-processor.test.js.map +1 -0
- package/dist/lib/sync/category-validator.d.ts +36 -0
- package/dist/lib/sync/category-validator.d.ts.map +1 -0
- package/dist/lib/sync/category-validator.js +46 -0
- package/dist/lib/sync/category-validator.js.map +1 -0
- package/dist/lib/sync/category-validator.test.d.ts +2 -0
- package/dist/lib/sync/category-validator.test.d.ts.map +1 -0
- package/dist/lib/sync/category-validator.test.js +89 -0
- package/dist/lib/sync/category-validator.test.js.map +1 -0
- package/dist/lib/sync/conflict-reporter.d.ts +57 -0
- package/dist/lib/sync/conflict-reporter.d.ts.map +1 -0
- package/dist/lib/sync/conflict-reporter.js +81 -0
- package/dist/lib/sync/conflict-reporter.js.map +1 -0
- package/dist/lib/sync/conflict-reporter.test.d.ts +2 -0
- package/dist/lib/sync/conflict-reporter.test.d.ts.map +1 -0
- package/dist/lib/sync/conflict-reporter.test.js +132 -0
- package/dist/lib/sync/conflict-reporter.test.js.map +1 -0
- package/dist/lib/sync/diff-engine.d.ts +28 -0
- package/dist/lib/sync/diff-engine.d.ts.map +1 -0
- package/dist/lib/sync/diff-engine.js +118 -0
- package/dist/lib/sync/diff-engine.js.map +1 -0
- package/dist/lib/sync/diff-engine.test.d.ts +2 -0
- package/dist/lib/sync/diff-engine.test.d.ts.map +1 -0
- package/dist/lib/sync/diff-engine.test.js +133 -0
- package/dist/lib/sync/diff-engine.test.js.map +1 -0
- package/dist/lib/sync/file-filter.d.ts +40 -0
- package/dist/lib/sync/file-filter.d.ts.map +1 -0
- package/dist/lib/sync/file-filter.js +171 -0
- package/dist/lib/sync/file-filter.js.map +1 -0
- package/dist/lib/sync/file-filter.test.d.ts +2 -0
- package/dist/lib/sync/file-filter.test.d.ts.map +1 -0
- package/dist/lib/sync/file-filter.test.js +179 -0
- package/dist/lib/sync/file-filter.test.js.map +1 -0
- package/dist/lib/sync/hash-cache.d.ts +34 -0
- package/dist/lib/sync/hash-cache.d.ts.map +1 -0
- package/dist/lib/sync/hash-cache.js +51 -0
- package/dist/lib/sync/hash-cache.js.map +1 -0
- package/dist/lib/sync/hash-cache.test.d.ts +2 -0
- package/dist/lib/sync/hash-cache.test.d.ts.map +1 -0
- package/dist/lib/sync/hash-cache.test.js +110 -0
- package/dist/lib/sync/hash-cache.test.js.map +1 -0
- package/dist/lib/sync/integration.test.d.ts +2 -0
- package/dist/lib/sync/integration.test.d.ts.map +1 -0
- package/dist/lib/sync/integration.test.js +317 -0
- package/dist/lib/sync/integration.test.js.map +1 -0
- package/dist/lib/sync/marker-processor.d.ts +54 -0
- package/dist/lib/sync/marker-processor.d.ts.map +1 -0
- package/dist/lib/sync/marker-processor.js +208 -0
- package/dist/lib/sync/marker-processor.js.map +1 -0
- package/dist/lib/sync/marker-processor.test.d.ts +2 -0
- package/dist/lib/sync/marker-processor.test.d.ts.map +1 -0
- package/dist/lib/sync/marker-processor.test.js +245 -0
- package/dist/lib/sync/marker-processor.test.js.map +1 -0
- package/dist/lib/sync/metadata-manager.d.ts +46 -0
- package/dist/lib/sync/metadata-manager.d.ts.map +1 -0
- package/dist/lib/sync/metadata-manager.js +129 -0
- package/dist/lib/sync/metadata-manager.js.map +1 -0
- package/dist/lib/sync/metadata-manager.test.d.ts +2 -0
- package/dist/lib/sync/metadata-manager.test.d.ts.map +1 -0
- package/dist/lib/sync/metadata-manager.test.js +137 -0
- package/dist/lib/sync/metadata-manager.test.js.map +1 -0
- package/dist/lib/sync/performance.test.d.ts +2 -0
- package/dist/lib/sync/performance.test.d.ts.map +1 -0
- package/dist/lib/sync/performance.test.js +126 -0
- package/dist/lib/sync/performance.test.js.map +1 -0
- package/dist/types/index.d.ts +59 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/preset-update.d.ts +106 -0
- package/dist/types/preset-update.d.ts.map +1 -0
- package/dist/types/preset-update.js +5 -0
- package/dist/types/preset-update.js.map +1 -0
- package/dist/types/sync.d.ts +169 -0
- package/dist/types/sync.d.ts.map +1 -0
- package/dist/types/sync.js +19 -0
- package/dist/types/sync.js.map +1 -0
- package/package.json +72 -0
- package/presets/minimal/.claude/agents/einja/docs/docs-updater.md +161 -0
- package/presets/minimal/.claude/agents/einja/frontend/design-engineer.md +685 -0
- package/presets/minimal/.claude/agents/einja/frontend/frontend-architect.md +747 -0
- package/presets/minimal/.claude/agents/einja/frontend/frontend-coder.md +441 -0
- package/presets/minimal/.claude/agents/einja/git/conflict-resolver.md +148 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-design-generator.md +462 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-qa-generator.md +466 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-requirements-generator.md +416 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-tasks-generator.md +608 -0
- package/presets/minimal/.claude/agents/einja/task/task-committer.md +82 -0
- package/presets/minimal/.claude/agents/einja/task/task-executer.md +352 -0
- package/presets/minimal/.claude/agents/einja/task/task-modification-analyzer.md +369 -0
- package/presets/minimal/.claude/agents/einja/task/task-qa.md +74 -0
- package/presets/minimal/.claude/agents/einja/task/task-reviewer.md +169 -0
- package/presets/minimal/.claude/commands/einja/frontend-implement.md +322 -0
- package/presets/minimal/.claude/commands/einja/spec-create.md +254 -0
- package/presets/minimal/.claude/commands/einja/start-dev.md +98 -0
- package/presets/minimal/.claude/commands/einja/sync-cursor-commands.md +203 -0
- package/presets/minimal/.claude/commands/einja/task-exec.md +390 -0
- package/presets/minimal/.claude/commands/einja/update-docs-by-task-specs.md +448 -0
- package/presets/minimal/.claude/hooks/einja/biome-format.sh +49 -0
- package/presets/minimal/.claude/hooks/einja/design-doc-check.sh +61 -0
- package/presets/minimal/.claude/hooks/einja/detect-secrets.sh +62 -0
- package/presets/minimal/.claude/hooks/einja/large-file-warning.sh +42 -0
- package/presets/minimal/.claude/hooks/einja/playwright-resize.sh +36 -0
- package/presets/minimal/.claude/hooks/einja/typecheck.sh +37 -0
- package/presets/minimal/.claude/hooks/einja/unset-volta-recursion.sh +32 -0
- package/presets/minimal/.claude/hooks/einja/validate-git-commit.sh +239 -0
- package/presets/minimal/.claude/hooks/einja/warn-index-ts.sh +34 -0
- package/presets/minimal/.claude/hooks/einja/warn-relative-import.sh +48 -0
- package/presets/minimal/.claude/settings.json +174 -0
- package/presets/minimal/.claude/skills/einja/api-development/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/backend-architecture/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/SKILL.md +120 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/naming-conventions.md +107 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/prohibited-patterns.md +169 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/typescript-rules.md +247 -0
- package/presets/minimal/.claude/skills/einja/component-design/SKILL.md +109 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/directory-structure.md +117 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/props-patterns.md +159 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/styling-guide.md +200 -0
- package/presets/minimal/.claude/skills/einja/conflict-resolver/SKILL.md +190 -0
- package/presets/minimal/.claude/skills/einja/frontend-development/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/general-context-loader/SKILL.md +254 -0
- package/presets/minimal/.claude/skills/einja/output-format/SKILL.md +137 -0
- package/presets/minimal/.claude/skills/einja/spec-context-loader/SKILL.md +177 -0
- package/presets/minimal/.claude/skills/einja/task-commit/SKILL.md +269 -0
- package/presets/minimal/.claude/skills/einja/task-qa/SKILL.md +306 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/failure-patterns.md +69 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/troubleshooting.md +65 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/usage-patterns.md +52 -0
- package/presets/minimal/.claude/skills/einja/task-qa/templates/qa-test-template.md +128 -0
- package/presets/minimal/preset.yaml +111 -0
- package/presets/minimal/symlinks.json +45 -0
- package/scaffolds/.mcp.json +45 -0
- package/scaffolds/CLAUDE.md.template +318 -0
- package/scaffolds/steering/README.md +170 -0
- package/scaffolds/steering/acceptance-criteria-and-qa-guide.md +415 -0
- package/scaffolds/steering/architecture.md +481 -0
- package/scaffolds/steering/branch-strategy.md +362 -0
- package/scaffolds/steering/commit-rules.md +217 -0
- package/scaffolds/steering/db-schema-design.md +609 -0
- package/scaffolds/steering/development/api-development.md +783 -0
- package/scaffolds/steering/development/backend-architecture.md +731 -0
- package/scaffolds/steering/development/frontend-development.md +1537 -0
- package/scaffolds/steering/development/review-guidelines.md +365 -0
- package/scaffolds/steering/development/testing-strategy.md +819 -0
- package/scaffolds/steering/development-workflow.md +429 -0
- package/scaffolds/steering/infrastructure/deployment.md +277 -0
- package/scaffolds/steering/infrastructure/environment-variables.md +298 -0
- package/scaffolds/steering/product.md +540 -0
- package/scaffolds/steering/task-management.md +367 -0
- package/templates/README.md +159 -0
- package/templates/design-simple.md.template +172 -0
- package/templates/design.md.template +327 -0
- package/templates/qa-test.md.template +125 -0
- package/templates/requirements.md.template +254 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Coding Standards Skill
|
|
2
|
+
|
|
3
|
+
name: "coding-standards"
|
|
4
|
+
description: "TypeScript/React/Next.jsのコーディング規約とベストプラクティス"
|
|
5
|
+
invocation: "agent-requested"
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
|
|
8
|
+
## 概要
|
|
9
|
+
|
|
10
|
+
このSkillは、プロジェクトのコーディング規約を提供します。一貫性のある高品質なコードを維持し、チーム全体の開発効率を向上させることを目的とします。
|
|
11
|
+
|
|
12
|
+
## 基本原則
|
|
13
|
+
|
|
14
|
+
### 1. 可読性の重視
|
|
15
|
+
- コードは書くよりも読まれることが多い
|
|
16
|
+
- 明確で理解しやすいコードを書く
|
|
17
|
+
- 適切な命名と構造化を心がける
|
|
18
|
+
|
|
19
|
+
### 2. 一貫性の保持
|
|
20
|
+
- プロジェクト全体で統一されたスタイルを維持
|
|
21
|
+
- 既存のコードパターンに従う
|
|
22
|
+
- ツールによる自動化を活用
|
|
23
|
+
|
|
24
|
+
### 3. 保守性の向上
|
|
25
|
+
- 変更に強いコード設計
|
|
26
|
+
- 適切な分離と抽象化
|
|
27
|
+
- テスタブルなコード構造
|
|
28
|
+
|
|
29
|
+
## 詳細ドキュメント
|
|
30
|
+
|
|
31
|
+
各カテゴリの詳細な規約は以下を参照してください:
|
|
32
|
+
|
|
33
|
+
- [TypeScript規約](./reference/typescript-rules.md) - 型安全性、型定義、禁止事項
|
|
34
|
+
- [命名規則](./reference/naming-conventions.md) - 変数・関数・型の命名規則
|
|
35
|
+
- [禁止事項](./reference/prohibited-patterns.md) - 絶対に使用禁止のパターン
|
|
36
|
+
|
|
37
|
+
## クイックリファレンス
|
|
38
|
+
|
|
39
|
+
### 必須チェック項目
|
|
40
|
+
|
|
41
|
+
- [ ] **any型を使用していない**(最重要)
|
|
42
|
+
- [ ] 適切な型定義がされている
|
|
43
|
+
- [ ] 命名規約に従っている
|
|
44
|
+
- [ ] early return パターンを使用している
|
|
45
|
+
- [ ] エラーハンドリングが適切に実装されている
|
|
46
|
+
- [ ] 禁止事項に該当するコードがない
|
|
47
|
+
|
|
48
|
+
### インポート順序
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// 1. Node.js標準ライブラリ
|
|
52
|
+
import { readFile } from 'fs/promises';
|
|
53
|
+
|
|
54
|
+
// 2. 外部ライブラリ
|
|
55
|
+
import React from 'react';
|
|
56
|
+
import { NextRequest } from 'next/server';
|
|
57
|
+
|
|
58
|
+
// 3. 内部ライブラリ(@/から始まる)
|
|
59
|
+
import { Button } from '@/components/ui/button';
|
|
60
|
+
import { auth } from '@/lib/auth';
|
|
61
|
+
|
|
62
|
+
// 4. 相対インポート
|
|
63
|
+
import './styles.css';
|
|
64
|
+
import { localUtil } from '../utils';
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### スタイリング(Panda CSS)
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// ✅ Panda CSS レシピの使用
|
|
71
|
+
import { button } from 'styled-system/recipes';
|
|
72
|
+
|
|
73
|
+
export function Button({ variant, size, children }: ButtonProps) {
|
|
74
|
+
return (
|
|
75
|
+
<button className={button({ variant, size })}>
|
|
76
|
+
{children}
|
|
77
|
+
</button>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ✅ css関数の使用
|
|
82
|
+
import { css } from 'styled-system/css';
|
|
83
|
+
|
|
84
|
+
const customStyles = css({
|
|
85
|
+
padding: '1rem',
|
|
86
|
+
backgroundColor: 'blue.500',
|
|
87
|
+
_hover: {
|
|
88
|
+
backgroundColor: 'blue.600'
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## ツール設定
|
|
94
|
+
|
|
95
|
+
### 必須ツール
|
|
96
|
+
1. **Biome**: linting と formatting
|
|
97
|
+
2. **TypeScript**: 型チェック
|
|
98
|
+
3. **Husky**: Git hooks
|
|
99
|
+
4. **lint-staged**: ステージングファイルのチェック
|
|
100
|
+
|
|
101
|
+
### VS Code 推奨設定
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"editor.codeActionsOnSave": {
|
|
106
|
+
"source.organizeImports": true,
|
|
107
|
+
"source.fixAll": true
|
|
108
|
+
},
|
|
109
|
+
"editor.formatOnSave": true,
|
|
110
|
+
"typescript.preferences.noSemicolons": false,
|
|
111
|
+
"typescript.preferences.quoteStyle": "double"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 関連Skill・ドキュメント
|
|
116
|
+
|
|
117
|
+
- [component-design](../component-design/SKILL.md) - コンポーネント設計ガイドライン
|
|
118
|
+
- `docs/einja/steering/development/testing-strategy.md` - テスト戦略
|
|
119
|
+
- `docs/einja/steering/development/review-guidelines.md` - コードレビューガイドライン
|
|
120
|
+
- `docs/einja/steering/commit-rules.md` - コミットルール
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# 命名規則
|
|
2
|
+
|
|
3
|
+
## ファイル・ディレクトリ命名
|
|
4
|
+
|
|
5
|
+
### 基本的な命名原則
|
|
6
|
+
|
|
7
|
+
- **Reactコンポーネント**: PascalCase(例: `UserProfile.tsx`)
|
|
8
|
+
- **ユーティリティファイル**: camelCase(例: `authConfig.ts`)
|
|
9
|
+
- **Next.jsファイル**: lowercase(例: `page.tsx`, `layout.tsx`)
|
|
10
|
+
|
|
11
|
+
**注意**: shadcn/uiで生成されたコンポーネントはkebab-caseファイル名(例: `button.tsx`, `input.tsx`)を使用しており、この命名規則の例外となります。
|
|
12
|
+
|
|
13
|
+
## 変数・関数命名
|
|
14
|
+
|
|
15
|
+
### 変数名
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// ✅ camelCase
|
|
19
|
+
const userName = 'john';
|
|
20
|
+
const isLoggedIn = true;
|
|
21
|
+
const userList = [];
|
|
22
|
+
|
|
23
|
+
// ✅ boolean値は is/has/can などで開始
|
|
24
|
+
const isVisible = true;
|
|
25
|
+
const hasPermission = false;
|
|
26
|
+
const canEdit = true;
|
|
27
|
+
|
|
28
|
+
// ✅ 定数はSCREAMING_SNAKE_CASE
|
|
29
|
+
const API_ENDPOINT = 'https://api.example.com';
|
|
30
|
+
const MAX_RETRY_COUNT = 3;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 関数名
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// ✅ 動詞で開始
|
|
37
|
+
function getUserById(id: string): User | null { }
|
|
38
|
+
function validateEmail(email: string): boolean { }
|
|
39
|
+
function handleSubmit(): void { }
|
|
40
|
+
|
|
41
|
+
// ✅ イベントハンドラーは "handle" または "on" で開始
|
|
42
|
+
function handleClick(): void { }
|
|
43
|
+
function onUserSelect(user: User): void { }
|
|
44
|
+
|
|
45
|
+
// ✅ 戻り値がbooleanの場合は is/has/can で開始
|
|
46
|
+
function isValidUser(user: User): boolean { }
|
|
47
|
+
function hasPermission(user: User, action: string): boolean { }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### インターフェース・型名
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// ✅ PascalCase
|
|
54
|
+
interface User {
|
|
55
|
+
id: string;
|
|
56
|
+
name: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ✅ Props は "Props" サフィックス
|
|
60
|
+
interface UserCardProps {
|
|
61
|
+
user: User;
|
|
62
|
+
onEdit?: () => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ✅ 型は Type サフィックス(必要に応じて)
|
|
66
|
+
type ApiResponseType<T> = {
|
|
67
|
+
data: T;
|
|
68
|
+
status: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// ✅ Union型は具体的な名前
|
|
72
|
+
type ButtonVariant = 'primary' | 'secondary' | 'danger';
|
|
73
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## コメント規約
|
|
77
|
+
|
|
78
|
+
### JSDoc の使用
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
/**
|
|
82
|
+
* ユーザー情報を取得する
|
|
83
|
+
* @param id - ユーザーID
|
|
84
|
+
* @returns ユーザー情報、見つからない場合はnull
|
|
85
|
+
* @throws {ApiError} API呼び出しが失敗した場合
|
|
86
|
+
*/
|
|
87
|
+
async function getUserById(id: string): Promise<User | null> {
|
|
88
|
+
// 実装
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### インラインコメント
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// ✅ 「なぜ」を説明するコメント
|
|
96
|
+
// Safari では transform-origin が正しく動作しないため、明示的に設定
|
|
97
|
+
element.style.transformOrigin = 'center center';
|
|
98
|
+
|
|
99
|
+
// ✅ 複雑なビジネスロジックの説明
|
|
100
|
+
// 管理者は全てのデータにアクセス可能、
|
|
101
|
+
// 一般ユーザーは自分のデータのみアクセス可能
|
|
102
|
+
const hasAccess = user.role === 'admin' || user.id === resourceOwnerId;
|
|
103
|
+
|
|
104
|
+
// ❌ 「何を」するかのコメント(不要)
|
|
105
|
+
// ユーザー名を取得
|
|
106
|
+
const userName = user.name;
|
|
107
|
+
```
|
package/presets/minimal/.claude/skills/einja/coding-standards/reference/prohibited-patterns.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# 禁止事項
|
|
2
|
+
|
|
3
|
+
## 絶対に使用禁止
|
|
4
|
+
|
|
5
|
+
### 1. any型の使用
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// ❌ 絶対禁止
|
|
9
|
+
const data: any = response;
|
|
10
|
+
function process(input: any): any { }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**理由:**
|
|
14
|
+
- TypeScriptの型チェック機能を完全に無効化
|
|
15
|
+
- ランタイムエラーの主要な原因
|
|
16
|
+
- IDEの補完・リファクタリング機能が働かない
|
|
17
|
+
- コードの可読性・保守性が著しく低下
|
|
18
|
+
|
|
19
|
+
**代替策:**
|
|
20
|
+
- `unknown`型を使用し、型ガードで絞り込む
|
|
21
|
+
- 適切なinterface/typeを定義する
|
|
22
|
+
- Generic型を活用する
|
|
23
|
+
|
|
24
|
+
### 2. eval()関数の使用
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// ❌ セキュリティリスクのため禁止
|
|
28
|
+
eval(userInput);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**理由:**
|
|
32
|
+
- XSS攻撃の主要な原因
|
|
33
|
+
- コードインジェクションのリスク
|
|
34
|
+
- パフォーマンスへの悪影響
|
|
35
|
+
- デバッグが困難
|
|
36
|
+
|
|
37
|
+
### 3. console.log の本番環境への残留
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// ❌ 本番環境では禁止(開発時は可)
|
|
41
|
+
console.log('debug info');
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**理由:**
|
|
45
|
+
- パフォーマンスへの影響
|
|
46
|
+
- 機密情報の漏洩リスク
|
|
47
|
+
- ログの乱雑化
|
|
48
|
+
|
|
49
|
+
**対策:**
|
|
50
|
+
- 開発時のみ使用し、コミット前に削除
|
|
51
|
+
- 必要な場合はロギングライブラリを使用
|
|
52
|
+
|
|
53
|
+
### 4. var キーワードの使用
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// ❌ letまたはconstを使用
|
|
57
|
+
var userName = 'john';
|
|
58
|
+
|
|
59
|
+
// ✅ 推奨
|
|
60
|
+
const userName = 'john';
|
|
61
|
+
let counter = 0;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**理由:**
|
|
65
|
+
- 関数スコープによる予期しない動作
|
|
66
|
+
- ホイスティングによるバグ
|
|
67
|
+
- `let`/`const`はブロックスコープで安全
|
|
68
|
+
|
|
69
|
+
### 5. == 比較演算子の使用
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// ❌ 型強制が発生するため禁止
|
|
73
|
+
if (value == null) { }
|
|
74
|
+
|
|
75
|
+
// ✅ 厳密等価演算子を使用
|
|
76
|
+
if (value === null) { }
|
|
77
|
+
if (value == null) { } // nullとundefinedの両方をチェックする場合のみ例外
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**理由:**
|
|
81
|
+
- 暗黙の型変換による予期しない動作
|
|
82
|
+
- デバッグが困難
|
|
83
|
+
- TypeScriptの型安全性を損なう
|
|
84
|
+
|
|
85
|
+
**唯一の例外:**
|
|
86
|
+
- `value == null` は `value === null || value === undefined` と等価で、これのみ許容
|
|
87
|
+
|
|
88
|
+
## 推奨されない書き方
|
|
89
|
+
|
|
90
|
+
### ネストの深い条件分岐
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// ❌ 避ける
|
|
94
|
+
if (condition1) {
|
|
95
|
+
if (condition2) {
|
|
96
|
+
if (condition3) {
|
|
97
|
+
// 処理
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ✅ 早期リターンを使用
|
|
103
|
+
if (!condition1) return;
|
|
104
|
+
if (!condition2) return;
|
|
105
|
+
if (!condition3) return;
|
|
106
|
+
// 処理
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### マジックナンバー
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// ❌ 避ける
|
|
113
|
+
if (user.age >= 18) { }
|
|
114
|
+
setTimeout(callback, 3000);
|
|
115
|
+
|
|
116
|
+
// ✅ 定数を定義
|
|
117
|
+
const LEGAL_AGE = 18;
|
|
118
|
+
const ANIMATION_DELAY_MS = 3000;
|
|
119
|
+
|
|
120
|
+
if (user.age >= LEGAL_AGE) { }
|
|
121
|
+
setTimeout(callback, ANIMATION_DELAY_MS);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 命名付きエクスポートとデフォルトエクスポートの混在
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// ❌ 避ける
|
|
128
|
+
export function Button() { }
|
|
129
|
+
export default Button;
|
|
130
|
+
|
|
131
|
+
// ✅ どちらか一方を使用
|
|
132
|
+
export function Button() { }
|
|
133
|
+
// または
|
|
134
|
+
export default function Button() { }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## セキュリティ関連の禁止事項
|
|
138
|
+
|
|
139
|
+
### 機密情報のハードコーディング
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// ❌ 絶対禁止
|
|
143
|
+
const API_KEY = 'sk-1234567890abcdef';
|
|
144
|
+
const PASSWORD = 'secret123';
|
|
145
|
+
|
|
146
|
+
// ✅ 環境変数を使用
|
|
147
|
+
const API_KEY = process.env.API_KEY;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### ユーザー入力の直接利用
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// ❌ SQLインジェクションのリスク
|
|
154
|
+
const query = `SELECT * FROM users WHERE id = '${userId}'`;
|
|
155
|
+
|
|
156
|
+
// ✅ パラメータ化クエリを使用
|
|
157
|
+
const query = 'SELECT * FROM users WHERE id = $1';
|
|
158
|
+
await db.query(query, [userId]);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 未検証データの表示
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// ❌ XSSのリスク
|
|
165
|
+
element.innerHTML = userInput;
|
|
166
|
+
|
|
167
|
+
// ✅ サニタイズまたはテキストとして扱う
|
|
168
|
+
element.textContent = userInput;
|
|
169
|
+
```
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# TypeScript 規約
|
|
2
|
+
|
|
3
|
+
## 型安全性
|
|
4
|
+
|
|
5
|
+
### ❌ any型の使用禁止
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// ❌ 禁止
|
|
9
|
+
function processData(data: any) {
|
|
10
|
+
return data.someProperty;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const user: any = getUser();
|
|
14
|
+
|
|
15
|
+
// ✅ 推奨
|
|
16
|
+
interface User {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
email: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function processData(data: User) {
|
|
23
|
+
return data.name;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const user: User = getUser();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**any型が絶対に禁止される理由:**
|
|
30
|
+
- TypeScriptの型チェック機能を無効化
|
|
31
|
+
- ランタイムエラーの原因となる
|
|
32
|
+
- IDEの自動補完・リファクタリング機能が働かない
|
|
33
|
+
- コードの可読性・保守性が著しく低下
|
|
34
|
+
|
|
35
|
+
### 型定義のベストプラクティス
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// ✅ 明確な型定義
|
|
39
|
+
interface ApiResponse<T> {
|
|
40
|
+
data: T;
|
|
41
|
+
status: 'success' | 'error';
|
|
42
|
+
message?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ✅ Union型の活用
|
|
46
|
+
type ButtonVariant = 'primary' | 'secondary' | 'danger';
|
|
47
|
+
|
|
48
|
+
// ✅ Generic型の活用
|
|
49
|
+
function createApiCall<T>(endpoint: string): Promise<ApiResponse<T>> {
|
|
50
|
+
// 実装
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ✅ 型ガードの使用
|
|
54
|
+
function isUser(obj: unknown): obj is User {
|
|
55
|
+
return (
|
|
56
|
+
typeof obj === 'object' &&
|
|
57
|
+
obj !== null &&
|
|
58
|
+
typeof (obj as User).id === 'string'
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### unknown型の活用
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// ✅ anyの代わりにunknownを使用
|
|
67
|
+
function parseJson(json: string): unknown {
|
|
68
|
+
return JSON.parse(json);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ✅ 型ガードと組み合わせて安全に使用
|
|
72
|
+
const data = parseJson(jsonString);
|
|
73
|
+
if (isUser(data)) {
|
|
74
|
+
console.log(data.name); // 型安全
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 厳格な型チェック設定
|
|
79
|
+
|
|
80
|
+
`tsconfig.json`で以下の設定を必須とする:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"compilerOptions": {
|
|
85
|
+
"strict": true,
|
|
86
|
+
"noImplicitAny": true,
|
|
87
|
+
"noImplicitReturns": true,
|
|
88
|
+
"noImplicitThis": true,
|
|
89
|
+
"noUnusedLocals": true,
|
|
90
|
+
"noUnusedParameters": true
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## React / Next.js での型安全性
|
|
96
|
+
|
|
97
|
+
### Props型定義
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// ✅ 明確なProps型定義(any型禁止)
|
|
101
|
+
interface ComponentProps {
|
|
102
|
+
data: UserData; // 具体的な型を指定
|
|
103
|
+
onAction: (id: string) => void; // 関数型も明確に
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ❌ any型の使用禁止
|
|
107
|
+
interface BadProps {
|
|
108
|
+
data: any; // 絶対禁止
|
|
109
|
+
callback: any; // 絶対禁止
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## コード構造・パターン
|
|
114
|
+
|
|
115
|
+
### エクスポート規約
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// ✅ 名前付きエクスポート(推奨)
|
|
119
|
+
export function Button() { }
|
|
120
|
+
export { Button };
|
|
121
|
+
|
|
122
|
+
// ✅ デフォルトエクスポート(Pageコンポーネントのみ)
|
|
123
|
+
export default function HomePage() { }
|
|
124
|
+
|
|
125
|
+
// ❌ 混在は避ける
|
|
126
|
+
export function Button() { }
|
|
127
|
+
export default Button; // 避ける
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 条件分岐
|
|
131
|
+
|
|
132
|
+
#### 早期リターン
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// ✅ 早期リターンパターン
|
|
136
|
+
function processUser(user: User | null): string {
|
|
137
|
+
if (!user) {
|
|
138
|
+
return 'User not found';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!user.isActive) {
|
|
142
|
+
return 'User is inactive';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return `Welcome, ${user.name}!`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ❌ ネストの深い条件分岐
|
|
149
|
+
function processUser(user: User | null): string {
|
|
150
|
+
if (user) {
|
|
151
|
+
if (user.isActive) {
|
|
152
|
+
return `Welcome, ${user.name}!`;
|
|
153
|
+
} else {
|
|
154
|
+
return 'User is inactive';
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
return 'User not found';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Optional Chaining の活用
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// ✅ Optional Chaining
|
|
166
|
+
const userName = user?.profile?.name ?? 'Anonymous';
|
|
167
|
+
const hasAdminRole = user?.roles?.includes('admin') ?? false;
|
|
168
|
+
|
|
169
|
+
// ✅ Nullish Coalescing
|
|
170
|
+
const config = userConfig ?? defaultConfig;
|
|
171
|
+
const port = process.env.PORT ?? 3000;
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## エラーハンドリング
|
|
175
|
+
|
|
176
|
+
### エラー型の定義
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// ✅ カスタムエラークラス
|
|
180
|
+
class ApiError extends Error {
|
|
181
|
+
constructor(
|
|
182
|
+
message: string,
|
|
183
|
+
public statusCode: number,
|
|
184
|
+
public code: string
|
|
185
|
+
) {
|
|
186
|
+
super(message);
|
|
187
|
+
this.name = 'ApiError';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ✅ Result型パターン
|
|
192
|
+
type Result<T, E = Error> =
|
|
193
|
+
| { success: true; data: T }
|
|
194
|
+
| { success: false; error: E };
|
|
195
|
+
|
|
196
|
+
function safeApiCall<T>(fn: () => Promise<T>): Promise<Result<T>> {
|
|
197
|
+
return fn()
|
|
198
|
+
.then(data => ({ success: true as const, data }))
|
|
199
|
+
.catch(error => ({ success: false as const, error }));
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### エラーハンドリングパターン
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// ✅ try-catch の適切な使用
|
|
207
|
+
async function fetchUser(id: string): Promise<User | null> {
|
|
208
|
+
try {
|
|
209
|
+
const response = await api.get(`/users/${id}`);
|
|
210
|
+
return response.data;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
if (error instanceof ApiError && error.statusCode === 404) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
throw error; // 予期しないエラーは再スロー
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ✅ Error Boundary での エラーキャッチ
|
|
220
|
+
export function ErrorBoundary({ children }: { children: React.ReactNode }) {
|
|
221
|
+
return (
|
|
222
|
+
<ErrorBoundaryComponent
|
|
223
|
+
fallback={<ErrorFallback />}
|
|
224
|
+
onError={(error, errorInfo) => {
|
|
225
|
+
console.error('Error caught by boundary:', error, errorInfo);
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
{children}
|
|
229
|
+
</ErrorBoundaryComponent>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## テストでの型安全性
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// ✅ テストでもany型禁止
|
|
238
|
+
interface MockUser {
|
|
239
|
+
id: string;
|
|
240
|
+
name: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const mockUser: MockUser = { id: '1', name: 'Test User' };
|
|
244
|
+
|
|
245
|
+
// ❌ テストでもany型は使用禁止
|
|
246
|
+
const badMockData: any = { /* データ */ }; // 禁止
|
|
247
|
+
```
|