@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,609 @@
|
|
|
1
|
+
# スキーマ設計
|
|
2
|
+
|
|
3
|
+
TODO
|
|
4
|
+
以下はサンプルで、まだDBは未作成です。
|
|
5
|
+
|
|
6
|
+
## 概要
|
|
7
|
+
|
|
8
|
+
このドキュメントでは、Prismaを使用したデータベーススキーマ設計と、テーブル定義、リレーション設計、マイグレーション戦略について説明します。
|
|
9
|
+
|
|
10
|
+
PostgreSQLをデータベースとして使用し、Prismaをグローバルキャッシュパターンで運用します。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 目次
|
|
15
|
+
|
|
16
|
+
1. [データベース技術スタック](#1-データベース技術スタック)
|
|
17
|
+
2. [ERD(エンティティ関連図)](#2-erdエンティティ関連図)
|
|
18
|
+
3. [Prismaスキーマ定義](#3-prismaスキーマ定義)
|
|
19
|
+
4. [テーブル定義](#4-テーブル定義)
|
|
20
|
+
5. [リレーション設計](#5-リレーション設計)
|
|
21
|
+
6. [インデックス設計](#6-インデックス設計)
|
|
22
|
+
7. [Prisma Client設定](#7-prisma-client設定)
|
|
23
|
+
8. [マイグレーション戦略](#8-マイグレーション戦略)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. データベース技術スタック
|
|
28
|
+
|
|
29
|
+
| カテゴリ | 技術 | 用途 |
|
|
30
|
+
|---------|------|------|
|
|
31
|
+
| データベース | PostgreSQL | リレーショナルデータベース |
|
|
32
|
+
| ORM | Prisma | データベースアクセス |
|
|
33
|
+
| クライアント | @prisma/client | Prisma Client |
|
|
34
|
+
| CLI | prisma | マイグレーション、生成 |
|
|
35
|
+
|
|
36
|
+
**Prismaの利点**:
|
|
37
|
+
- 型安全なデータベースアクセス
|
|
38
|
+
- 自動生成されたクライアント
|
|
39
|
+
- マイグレーション管理
|
|
40
|
+
- クエリの最適化
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. ERD(エンティティ関連図)
|
|
45
|
+
|
|
46
|
+
```mermaid
|
|
47
|
+
erDiagram
|
|
48
|
+
User {
|
|
49
|
+
string id PK
|
|
50
|
+
string email UK
|
|
51
|
+
string name
|
|
52
|
+
datetime createdAt
|
|
53
|
+
datetime updatedAt
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Account {
|
|
57
|
+
string id PK
|
|
58
|
+
string userId FK
|
|
59
|
+
string provider
|
|
60
|
+
string providerAccountId UK
|
|
61
|
+
string accessToken
|
|
62
|
+
string refreshToken
|
|
63
|
+
datetime expiresAt
|
|
64
|
+
datetime createdAt
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Session {
|
|
68
|
+
string id PK
|
|
69
|
+
string userId FK
|
|
70
|
+
string token UK
|
|
71
|
+
datetime expiresAt
|
|
72
|
+
datetime createdAt
|
|
73
|
+
datetime lastActivity
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Post {
|
|
77
|
+
string id PK
|
|
78
|
+
string userId FK
|
|
79
|
+
string title
|
|
80
|
+
string content
|
|
81
|
+
string status
|
|
82
|
+
datetime publishedAt
|
|
83
|
+
datetime createdAt
|
|
84
|
+
datetime updatedAt
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
User ||--o{ Account : has
|
|
88
|
+
User ||--o{ Session : has
|
|
89
|
+
User ||--o{ Post : creates
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**エンティティ間のリレーション**:
|
|
93
|
+
- **User → Account**: 1対多(1ユーザーは複数のアカウント(OAuth)を持つ)
|
|
94
|
+
- **User → Session**: 1対多(1ユーザーは複数のセッションを持つ)
|
|
95
|
+
- **User → Post**: 1対多(1ユーザーは複数の投稿を作成)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 3. Prismaスキーマ定義
|
|
100
|
+
|
|
101
|
+
### スキーマファイル
|
|
102
|
+
|
|
103
|
+
**配置場所**: `packages/server-core/src/infrastructure/database/prisma/schema.prisma`
|
|
104
|
+
|
|
105
|
+
### generator設定
|
|
106
|
+
|
|
107
|
+
```prisma
|
|
108
|
+
generator client {
|
|
109
|
+
provider = "prisma-client-js"
|
|
110
|
+
output = "../../../../node_modules/.prisma/client"
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**設計ポイント**:
|
|
115
|
+
- `provider`: Prisma Clientの生成に使用
|
|
116
|
+
- `output`: モノレポ対応のため、クライアント生成先を `node_modules/.prisma/client` に設定
|
|
117
|
+
|
|
118
|
+
### datasource設定
|
|
119
|
+
|
|
120
|
+
```prisma
|
|
121
|
+
datasource db {
|
|
122
|
+
provider = "postgresql"
|
|
123
|
+
url = env("DATABASE_URL")
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**設計ポイント**:
|
|
128
|
+
- `provider`: PostgreSQLを使用
|
|
129
|
+
- `url`: 環境変数 `DATABASE_URL` で接続URL指定
|
|
130
|
+
|
|
131
|
+
### 完全なスキーマ定義
|
|
132
|
+
|
|
133
|
+
```prisma
|
|
134
|
+
// packages/server-core/src/infrastructure/database/prisma/schema.prisma
|
|
135
|
+
|
|
136
|
+
generator client {
|
|
137
|
+
provider = "prisma-client-js"
|
|
138
|
+
output = "../../../../node_modules/.prisma/client"
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
datasource db {
|
|
142
|
+
provider = "postgresql"
|
|
143
|
+
url = env("DATABASE_URL")
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
model User {
|
|
147
|
+
id String @id @default(cuid())
|
|
148
|
+
email String @unique
|
|
149
|
+
name String?
|
|
150
|
+
createdAt DateTime @default(now())
|
|
151
|
+
updatedAt DateTime @updatedAt
|
|
152
|
+
|
|
153
|
+
accounts Account[]
|
|
154
|
+
sessions Session[]
|
|
155
|
+
posts Post[]
|
|
156
|
+
|
|
157
|
+
@@index([email])
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
model Account {
|
|
161
|
+
id String @id @default(cuid())
|
|
162
|
+
userId String
|
|
163
|
+
provider String
|
|
164
|
+
providerAccountId String
|
|
165
|
+
accessToken String?
|
|
166
|
+
refreshToken String?
|
|
167
|
+
expiresAt DateTime?
|
|
168
|
+
createdAt DateTime @default(now())
|
|
169
|
+
|
|
170
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
171
|
+
|
|
172
|
+
@@unique([provider, providerAccountId])
|
|
173
|
+
@@index([userId])
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
model Session {
|
|
177
|
+
id String @id @default(cuid())
|
|
178
|
+
userId String
|
|
179
|
+
token String @unique
|
|
180
|
+
expiresAt DateTime
|
|
181
|
+
createdAt DateTime @default(now())
|
|
182
|
+
lastActivity DateTime @default(now())
|
|
183
|
+
|
|
184
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
185
|
+
|
|
186
|
+
@@index([userId])
|
|
187
|
+
@@index([token])
|
|
188
|
+
@@index([expiresAt])
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
model Post {
|
|
192
|
+
id String @id @default(cuid())
|
|
193
|
+
userId String
|
|
194
|
+
title String
|
|
195
|
+
content String
|
|
196
|
+
status String @default("draft")
|
|
197
|
+
publishedAt DateTime?
|
|
198
|
+
createdAt DateTime @default(now())
|
|
199
|
+
updatedAt DateTime @updatedAt
|
|
200
|
+
|
|
201
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
202
|
+
|
|
203
|
+
@@index([userId])
|
|
204
|
+
@@index([status])
|
|
205
|
+
@@index([publishedAt])
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 4. テーブル定義
|
|
212
|
+
|
|
213
|
+
### Userテーブル
|
|
214
|
+
|
|
215
|
+
| カラム | 型 | 制約 | 説明 |
|
|
216
|
+
|--------|----|----|------|
|
|
217
|
+
| id | String | PK, @default(cuid()) | ユーザーID(CUID) |
|
|
218
|
+
| email | String | UNIQUE, NOT NULL | メールアドレス |
|
|
219
|
+
| name | String | NULLABLE | ユーザー名 |
|
|
220
|
+
| createdAt | DateTime | @default(now()) | 作成日時 |
|
|
221
|
+
| updatedAt | DateTime | @updatedAt | 更新日時 |
|
|
222
|
+
|
|
223
|
+
**インデックス**:
|
|
224
|
+
- `email` - ログイン時の検索を高速化
|
|
225
|
+
|
|
226
|
+
**リレーション**:
|
|
227
|
+
- `accounts` - Account[] (1対多)
|
|
228
|
+
- `sessions` - Session[] (1対多)
|
|
229
|
+
- `posts` - Post[] (1対多)
|
|
230
|
+
|
|
231
|
+
### Accountテーブル
|
|
232
|
+
|
|
233
|
+
| カラム | 型 | 制約 | 説明 |
|
|
234
|
+
|--------|----|----|------|
|
|
235
|
+
| id | String | PK, @default(cuid()) | アカウントID |
|
|
236
|
+
| userId | String | FK, NOT NULL | ユーザーID |
|
|
237
|
+
| provider | String | NOT NULL | OAuth プロバイダ (google, github等) |
|
|
238
|
+
| providerAccountId | String | NOT NULL | プロバイダ側のアカウントID |
|
|
239
|
+
| accessToken | String | NULLABLE | アクセストークン |
|
|
240
|
+
| refreshToken | String | NULLABLE | リフレッシュトークン |
|
|
241
|
+
| expiresAt | DateTime | NULLABLE | トークン有効期限 |
|
|
242
|
+
| createdAt | DateTime | @default(now()) | 作成日時 |
|
|
243
|
+
|
|
244
|
+
**ユニーク制約**:
|
|
245
|
+
- `[provider, providerAccountId]` - プロバイダごとに一意
|
|
246
|
+
|
|
247
|
+
**インデックス**:
|
|
248
|
+
- `userId` - ユーザーのアカウント一覧取得を高速化
|
|
249
|
+
|
|
250
|
+
**リレーション**:
|
|
251
|
+
- `user` - User (多対1, onDelete: Cascade)
|
|
252
|
+
|
|
253
|
+
### Sessionテーブル
|
|
254
|
+
|
|
255
|
+
| カラム | 型 | 制約 | 説明 |
|
|
256
|
+
|--------|----|----|------|
|
|
257
|
+
| id | String | PK, @default(cuid()) | セッションID |
|
|
258
|
+
| userId | String | FK, NOT NULL | ユーザーID |
|
|
259
|
+
| token | String | UNIQUE, NOT NULL | セッショントークン |
|
|
260
|
+
| expiresAt | DateTime | NOT NULL | セッション有効期限 |
|
|
261
|
+
| createdAt | DateTime | @default(now()) | 作成日時 |
|
|
262
|
+
| lastActivity | DateTime | @default(now()) | 最終アクティビティ日時 |
|
|
263
|
+
|
|
264
|
+
**インデックス**:
|
|
265
|
+
- `userId` - ユーザーのセッション一覧取得を高速化
|
|
266
|
+
- `token` - トークンによるセッション検索を高速化
|
|
267
|
+
- `expiresAt` - 期限切れセッションのクリーンアップを高速化
|
|
268
|
+
|
|
269
|
+
**リレーション**:
|
|
270
|
+
- `user` - User (多対1, onDelete: Cascade)
|
|
271
|
+
|
|
272
|
+
### Postテーブル
|
|
273
|
+
|
|
274
|
+
| カラム | 型 | 制約 | 説明 |
|
|
275
|
+
|--------|----|----|------|
|
|
276
|
+
| id | String | PK, @default(cuid()) | 投稿ID |
|
|
277
|
+
| userId | String | FK, NOT NULL | 作成者ID |
|
|
278
|
+
| title | String | NOT NULL | タイトル |
|
|
279
|
+
| content | String | NOT NULL | 本文 |
|
|
280
|
+
| status | String | @default("draft") | ステータス (draft, published, archived) |
|
|
281
|
+
| publishedAt | DateTime | NULLABLE | 公開日時 |
|
|
282
|
+
| createdAt | DateTime | @default(now()) | 作成日時 |
|
|
283
|
+
| updatedAt | DateTime | @updatedAt | 更新日時 |
|
|
284
|
+
|
|
285
|
+
**インデックス**:
|
|
286
|
+
- `userId` - ユーザーの投稿一覧取得を高速化
|
|
287
|
+
- `status` - ステータスによる投稿検索を高速化
|
|
288
|
+
- `publishedAt` - 公開日時順のソートを高速化
|
|
289
|
+
|
|
290
|
+
**リレーション**:
|
|
291
|
+
- `user` - User (多対1, onDelete: Cascade)
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 5. リレーション設計
|
|
296
|
+
|
|
297
|
+
### リレーションの種類
|
|
298
|
+
|
|
299
|
+
#### 1対多リレーション
|
|
300
|
+
|
|
301
|
+
**User → Post**:
|
|
302
|
+
|
|
303
|
+
```prisma
|
|
304
|
+
model User {
|
|
305
|
+
id String @id
|
|
306
|
+
posts Post[]
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
model Post {
|
|
310
|
+
id String @id
|
|
311
|
+
userId String
|
|
312
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**削除時の動作** (`onDelete: Cascade`):
|
|
317
|
+
- ユーザーを削除すると、関連する投稿もすべて削除される
|
|
318
|
+
|
|
319
|
+
#### 外部キー制約
|
|
320
|
+
|
|
321
|
+
すべての外部キーには、以下のポリシーを適用:
|
|
322
|
+
|
|
323
|
+
| ポリシー | 説明 |
|
|
324
|
+
|---------|------|
|
|
325
|
+
| onDelete: Cascade | 親レコード削除時に子レコードも削除 |
|
|
326
|
+
| onUpdate: Cascade | 親レコード更新時に子レコードも更新(Prismaのデフォルト) |
|
|
327
|
+
|
|
328
|
+
**理由**:
|
|
329
|
+
- データ整合性の保証
|
|
330
|
+
- 孤立レコードの防止
|
|
331
|
+
- アプリケーションロジックの簡素化
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## 6. インデックス設計
|
|
336
|
+
|
|
337
|
+
### インデックス戦略
|
|
338
|
+
|
|
339
|
+
#### 検索頻度の高いカラム
|
|
340
|
+
|
|
341
|
+
**Userテーブル**:
|
|
342
|
+
- `email` - ログイン時の検索
|
|
343
|
+
|
|
344
|
+
**Sessionテーブル**:
|
|
345
|
+
- `token` - トークンによるセッション検索
|
|
346
|
+
- `userId` - ユーザーのセッション一覧
|
|
347
|
+
- `expiresAt` - 期限切れセッションのクリーンアップ
|
|
348
|
+
|
|
349
|
+
**Postテーブル**:
|
|
350
|
+
- `userId` - ユーザーの投稿一覧
|
|
351
|
+
- `status` - ステータスによる投稿検索
|
|
352
|
+
- `publishedAt` - 公開日時順のソート
|
|
353
|
+
|
|
354
|
+
#### ユニークインデックス
|
|
355
|
+
|
|
356
|
+
**Userテーブル**:
|
|
357
|
+
- `email` - メールアドレスの重複防止
|
|
358
|
+
|
|
359
|
+
**Accountテーブル**:
|
|
360
|
+
- `[provider, providerAccountId]` - プロバイダごとのアカウントID重複防止
|
|
361
|
+
|
|
362
|
+
**Sessionテーブル**:
|
|
363
|
+
- `token` - セッショントークンの重複防止
|
|
364
|
+
|
|
365
|
+
### インデックスのパフォーマンス影響
|
|
366
|
+
|
|
367
|
+
| 操作 | インデックスあり | インデックスなし |
|
|
368
|
+
|------|---------------|--------------|
|
|
369
|
+
| SELECT (WHERE句) | O(log n) | O(n) |
|
|
370
|
+
| INSERT | O(log n) | O(1) |
|
|
371
|
+
| UPDATE (インデックスカラム) | O(log n) | O(1) |
|
|
372
|
+
|
|
373
|
+
**トレードオフ**:
|
|
374
|
+
- 検索速度の向上 vs 挿入/更新速度の低下
|
|
375
|
+
- 本プロジェクトでは、読み取り頻度が高いため、インデックス作成を優先
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 7. Prisma Client設定
|
|
380
|
+
|
|
381
|
+
### グローバルキャッシュパターン
|
|
382
|
+
|
|
383
|
+
**目的**: 開発環境でのHot Reload対応
|
|
384
|
+
|
|
385
|
+
**実装ファイル**: `packages/server-core/src/infrastructure/database/client.ts`
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { PrismaClient } from '@prisma/client'
|
|
389
|
+
|
|
390
|
+
declare global {
|
|
391
|
+
// eslint-disable-next-line no-var
|
|
392
|
+
var prisma: PrismaClient | undefined
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export const prisma =
|
|
396
|
+
global.prisma ||
|
|
397
|
+
new PrismaClient({
|
|
398
|
+
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
402
|
+
global.prisma = prisma
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**設計ポイント**:
|
|
407
|
+
- **開発環境**: globalオブジェクトにキャッシュし、Hot Reload時に再利用
|
|
408
|
+
- **本番環境**: 通常のインスタンス化(グローバル化しない)
|
|
409
|
+
- **ログレベル**: 開発環境では `query`, `error`, `warn`、本番環境では `error` のみ
|
|
410
|
+
|
|
411
|
+
### ログ設定
|
|
412
|
+
|
|
413
|
+
| 環境 | ログレベル | 用途 |
|
|
414
|
+
|------|-----------|------|
|
|
415
|
+
| development | query, error, warn | デバッグ、パフォーマンス分析 |
|
|
416
|
+
| production | error | エラー監視 |
|
|
417
|
+
|
|
418
|
+
**クエリログの例**:
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
prisma:query SELECT "User"."id", "User"."email" FROM "User" WHERE "User"."email" = $1
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 8. マイグレーション戦略
|
|
427
|
+
|
|
428
|
+
### マイグレーションコマンド
|
|
429
|
+
|
|
430
|
+
**開発環境での実行**:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
# マイグレーション作成
|
|
434
|
+
pnpm db:migrate:dev
|
|
435
|
+
|
|
436
|
+
# マイグレーション適用(本番環境)
|
|
437
|
+
pnpm db:migrate:deploy
|
|
438
|
+
|
|
439
|
+
# Prisma Client再生成
|
|
440
|
+
pnpm db:generate
|
|
441
|
+
|
|
442
|
+
# Prisma Studio起動(GUIでデータ確認)
|
|
443
|
+
pnpm db:studio
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**package.json定義**:
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"scripts": {
|
|
451
|
+
"db:migrate:dev": "dotenv -e .env -e .env.local -- prisma migrate dev --schema=packages/server-core/src/infrastructure/database/prisma/schema.prisma",
|
|
452
|
+
"db:migrate:deploy": "dotenv -e .env -- prisma migrate deploy --schema=packages/server-core/src/infrastructure/database/prisma/schema.prisma",
|
|
453
|
+
"db:generate": "prisma generate --schema=packages/server-core/src/infrastructure/database/prisma/schema.prisma",
|
|
454
|
+
"db:studio": "dotenv -e .env -e .env.local -- prisma studio --schema=packages/server-core/src/infrastructure/database/prisma/schema.prisma",
|
|
455
|
+
"db:push": "dotenv -e .env -e .env.local -- prisma db push --schema=packages/server-core/src/infrastructure/database/prisma/schema.prisma",
|
|
456
|
+
"db:seed": "dotenv -e .env -e .env.local -- tsx packages/server-core/src/infrastructure/database/seed.ts"
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### マイグレーションワークフロー
|
|
462
|
+
|
|
463
|
+
#### 開発環境
|
|
464
|
+
|
|
465
|
+
```mermaid
|
|
466
|
+
graph LR
|
|
467
|
+
A[スキーマ変更] --> B[pnpm db:migrate:dev]
|
|
468
|
+
B --> C[マイグレーションファイル生成]
|
|
469
|
+
C --> D[DB適用]
|
|
470
|
+
D --> E[Prisma Client再生成]
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
**実行例**:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
# 1. schema.prismaを編集
|
|
477
|
+
|
|
478
|
+
# 2. マイグレーション作成
|
|
479
|
+
pnpm db:migrate:dev --name add_post_table
|
|
480
|
+
|
|
481
|
+
# 3. 確認
|
|
482
|
+
pnpm db:studio
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### 本番環境
|
|
486
|
+
|
|
487
|
+
```mermaid
|
|
488
|
+
graph LR
|
|
489
|
+
A[マイグレーションファイル<br/>リポジトリにコミット] --> B[本番デプロイ]
|
|
490
|
+
B --> C[pnpm db:migrate:deploy]
|
|
491
|
+
C --> D[DB適用]
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**実行例** (CIパイプライン):
|
|
495
|
+
|
|
496
|
+
```yaml
|
|
497
|
+
# .github/workflows/deploy.yml
|
|
498
|
+
- name: Run migrations
|
|
499
|
+
run: pnpm db:migrate:deploy
|
|
500
|
+
env:
|
|
501
|
+
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### マイグレーションファイル
|
|
505
|
+
|
|
506
|
+
**配置場所**: `packages/server-core/src/infrastructure/database/prisma/migrations/`
|
|
507
|
+
|
|
508
|
+
**例**:
|
|
509
|
+
|
|
510
|
+
```
|
|
511
|
+
migrations/
|
|
512
|
+
├── 20231201120000_init/
|
|
513
|
+
│ └── migration.sql
|
|
514
|
+
├── 20231205130000_add_post_table/
|
|
515
|
+
│ └── migration.sql
|
|
516
|
+
└── migration_lock.toml
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**migration.sql例**:
|
|
520
|
+
|
|
521
|
+
```sql
|
|
522
|
+
-- CreateTable
|
|
523
|
+
CREATE TABLE "Post" (
|
|
524
|
+
"id" TEXT NOT NULL,
|
|
525
|
+
"userId" TEXT NOT NULL,
|
|
526
|
+
"title" TEXT NOT NULL,
|
|
527
|
+
"content" TEXT NOT NULL,
|
|
528
|
+
"status" TEXT NOT NULL DEFAULT 'draft',
|
|
529
|
+
"publishedAt" TIMESTAMP(3),
|
|
530
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
531
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
532
|
+
|
|
533
|
+
CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
-- CreateIndex
|
|
537
|
+
CREATE INDEX "Post_userId_idx" ON "Post"("userId");
|
|
538
|
+
|
|
539
|
+
-- CreateIndex
|
|
540
|
+
CREATE INDEX "Post_status_idx" ON "Post"("status");
|
|
541
|
+
|
|
542
|
+
-- CreateIndex
|
|
543
|
+
CREATE INDEX "Post_publishedAt_idx" ON "Post"("publishedAt");
|
|
544
|
+
|
|
545
|
+
-- AddForeignKey
|
|
546
|
+
ALTER TABLE "Post" ADD CONSTRAINT "Post_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### シード(初期データ投入)
|
|
550
|
+
|
|
551
|
+
**シードファイル**: `packages/server-core/src/infrastructure/database/seed.ts`
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
import { prisma } from './client'
|
|
555
|
+
|
|
556
|
+
async function main() {
|
|
557
|
+
console.log('Seeding database...')
|
|
558
|
+
|
|
559
|
+
// ユーザー作成
|
|
560
|
+
const user = await prisma.user.create({
|
|
561
|
+
data: {
|
|
562
|
+
email: 'admin@example.com',
|
|
563
|
+
name: 'Admin User',
|
|
564
|
+
},
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
// 投稿作成
|
|
568
|
+
await prisma.post.create({
|
|
569
|
+
data: {
|
|
570
|
+
userId: user.id,
|
|
571
|
+
title: 'Welcome Post',
|
|
572
|
+
content: 'This is the first post',
|
|
573
|
+
status: 'published',
|
|
574
|
+
publishedAt: new Date(),
|
|
575
|
+
},
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
console.log('Seeding complete!')
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
main()
|
|
582
|
+
.catch(e => {
|
|
583
|
+
console.error(e)
|
|
584
|
+
process.exit(1)
|
|
585
|
+
})
|
|
586
|
+
.finally(async () => {
|
|
587
|
+
await prisma.$disconnect()
|
|
588
|
+
})
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**実行**:
|
|
592
|
+
|
|
593
|
+
```bash
|
|
594
|
+
pnpm db:seed
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## まとめ
|
|
600
|
+
|
|
601
|
+
このスキーマ設計ドキュメントに従うことで、以下を実現できます:
|
|
602
|
+
|
|
603
|
+
1. **データ整合性**: 外部キー制約とCascadeポリシーによる整合性保証
|
|
604
|
+
2. **パフォーマンス**: 適切なインデックス設計による高速検索
|
|
605
|
+
3. **型安全性**: Prismaによる型安全なデータベースアクセス
|
|
606
|
+
4. **保守性**: マイグレーション管理とシードデータによる環境再現性
|
|
607
|
+
5. **スケーラビリティ**: PostgreSQLとPrismaの組み合わせによる高いスケーラビリティ
|
|
608
|
+
|
|
609
|
+
すべてのスキーマ変更は、このガイドラインに従って実装してください。
|