@famgia/omnify-ai-guides 2.0.15
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 +105 -0
- package/dist/chunk-RCTEXK7C.js +549 -0
- package/dist/chunk-RCTEXK7C.js.map +1 -0
- package/dist/config/rules.yaml +524 -0
- package/dist/index.cjs +587 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/agents/architect.md.stub +150 -0
- package/dist/knowledge/agents/developer.md.stub +190 -0
- package/dist/knowledge/agents/reviewer.md.stub +134 -0
- package/dist/knowledge/agents/tester.md.stub +196 -0
- package/dist/knowledge/checklists/backend.md.stub +112 -0
- package/dist/knowledge/checklists/react.md.stub +108 -0
- package/dist/knowledge/claude-rules/laravel-controllers.md.stub +57 -0
- package/dist/knowledge/claude-rules/laravel-migrations.md.stub +47 -0
- package/dist/knowledge/claude-rules/laravel-tests.md.stub +52 -0
- package/dist/knowledge/claude-rules/naming.md.stub +369 -0
- package/dist/knowledge/claude-rules/performance.md.stub +256 -0
- package/dist/knowledge/claude-rules/php-standards.md.stub +305 -0
- package/dist/knowledge/claude-rules/react-components.md.stub +67 -0
- package/dist/knowledge/claude-rules/schema-yaml.md.stub +83 -0
- package/dist/knowledge/claude-rules/security.md.stub +164 -0
- package/dist/knowledge/cursor-rules/antd-deprecations.mdc.stub +62 -0
- package/dist/knowledge/cursor-rules/basemodel-readonly.mdc.stub +66 -0
- package/dist/knowledge/cursor-rules/baserequest-readonly.mdc.stub +74 -0
- package/dist/knowledge/cursor-rules/baseresource-readonly.mdc.stub +78 -0
- package/dist/knowledge/cursor-rules/laravel-controller.mdc.stub +421 -0
- package/dist/knowledge/cursor-rules/laravel-request.mdc.stub +112 -0
- package/dist/knowledge/cursor-rules/laravel-resource.mdc.stub +73 -0
- package/dist/knowledge/cursor-rules/laravel-review.mdc.stub +69 -0
- package/dist/knowledge/cursor-rules/laravel-testing.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/laravel.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/migrations-workflow.mdc.stub +224 -0
- package/dist/knowledge/cursor-rules/model-editable.mdc.stub +120 -0
- package/dist/knowledge/cursor-rules/omnify-migrations.mdc.stub +109 -0
- package/dist/knowledge/cursor-rules/omnify-schema.mdc.stub +358 -0
- package/dist/knowledge/cursor-rules/omnify.mdc.stub +58 -0
- package/dist/knowledge/cursor-rules/react-design.mdc.stub +693 -0
- package/dist/knowledge/cursor-rules/react-form.mdc.stub +292 -0
- package/dist/knowledge/cursor-rules/react-services.mdc.stub +304 -0
- package/dist/knowledge/cursor-rules/react.mdc.stub +336 -0
- package/dist/knowledge/cursor-rules/request-editable.mdc.stub +111 -0
- package/dist/knowledge/cursor-rules/resource-editable.mdc.stub +125 -0
- package/dist/knowledge/cursor-rules/schema-create.mdc.stub +440 -0
- package/dist/knowledge/cursor-rules/validation-rules.mdc.stub +181 -0
- package/dist/knowledge/laravel/README.md.stub +59 -0
- package/dist/knowledge/laravel/architecture.md.stub +424 -0
- package/dist/knowledge/laravel/authentication.md.stub +588 -0
- package/dist/knowledge/laravel/controller.md.stub +484 -0
- package/dist/knowledge/laravel/datetime.md.stub +334 -0
- package/dist/knowledge/laravel/migrations-team.md.stub +376 -0
- package/dist/knowledge/laravel/openapi.md.stub +449 -0
- package/dist/knowledge/laravel/request.md.stub +450 -0
- package/dist/knowledge/laravel/resource.md.stub +516 -0
- package/dist/knowledge/laravel/service.md.stub +503 -0
- package/dist/knowledge/laravel/testing.md.stub +1504 -0
- package/dist/knowledge/omnify/antdesign-guide.md.stub +401 -0
- package/dist/knowledge/omnify/config-guide.md.stub +405 -0
- package/dist/knowledge/omnify/japan-guide.md.stub +186 -0
- package/dist/knowledge/omnify/laravel-guide.md.stub +61 -0
- package/dist/knowledge/omnify/partial-schema-guide.md.stub +353 -0
- package/dist/knowledge/omnify/react-form-guide.md.stub +225 -0
- package/dist/knowledge/omnify/schema-guide.md.stub +144 -0
- package/dist/knowledge/omnify/typescript-guide.md.stub +337 -0
- package/dist/knowledge/react/README.md.stub +221 -0
- package/dist/knowledge/react/antd-guide.md +528 -0
- package/dist/knowledge/react/antd-guide.md.stub +528 -0
- package/dist/knowledge/react/checklist.md.stub +108 -0
- package/dist/knowledge/react/datetime-guide.md.stub +137 -0
- package/dist/knowledge/react/design-philosophy.md.stub +363 -0
- package/dist/knowledge/react/i18n-guide.md.stub +211 -0
- package/dist/knowledge/react/laravel-integration.md.stub +181 -0
- package/dist/knowledge/react/service-pattern.md.stub +180 -0
- package/dist/knowledge/react/tanstack-query.md.stub +339 -0
- package/dist/knowledge/react/types-guide.md +669 -0
- package/dist/knowledge/react/types-guide.md.stub +669 -0
- package/dist/knowledge/workflows/bug-fix.md.stub +201 -0
- package/dist/knowledge/workflows/code-review.md.stub +164 -0
- package/dist/knowledge/workflows/new-feature.md.stub +327 -0
- package/dist/plugin-M95GyBll.d.cts +191 -0
- package/dist/plugin-M95GyBll.d.ts +191 -0
- package/dist/plugin.cjs +573 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +2 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.js +15 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Tester Agent
|
|
2
|
+
|
|
3
|
+
> Agent for writing tests and ensuring test coverage.
|
|
4
|
+
|
|
5
|
+
## Role
|
|
6
|
+
|
|
7
|
+
**Testing Specialist** - Writes comprehensive tests covering all scenarios.
|
|
8
|
+
|
|
9
|
+
## When to Use
|
|
10
|
+
|
|
11
|
+
- Writing tests for new features
|
|
12
|
+
- Adding missing test coverage
|
|
13
|
+
- Verifying test completeness
|
|
14
|
+
- Test debugging
|
|
15
|
+
|
|
16
|
+
## Persona
|
|
17
|
+
|
|
18
|
+
### Style
|
|
19
|
+
|
|
20
|
+
- Thorough and systematic
|
|
21
|
+
- Edge-case aware
|
|
22
|
+
- Clear test naming
|
|
23
|
+
- Real-world scenarios
|
|
24
|
+
|
|
25
|
+
### Core Principles
|
|
26
|
+
|
|
27
|
+
1. **正常系 + 異常系**: Cover both success and failure paths
|
|
28
|
+
2. **API-First Data**: Create test data via API when possible
|
|
29
|
+
3. **PEST Syntax**: Use PEST, not PHPUnit
|
|
30
|
+
4. **Descriptive Names**: `正常:` and `異常:` prefixes
|
|
31
|
+
5. **No Bias**: Test real behavior, not implementation
|
|
32
|
+
|
|
33
|
+
## Context to Read
|
|
34
|
+
|
|
35
|
+
Before writing tests, read these:
|
|
36
|
+
|
|
37
|
+
| Priority | File | Purpose |
|
|
38
|
+
| ------------- | ---------------------------------------------------------- | ----------------------- |
|
|
39
|
+
| **Required** | [/guides/laravel/testing.md](../guides/laravel/testing.md) | Full testing guide |
|
|
40
|
+
| **Required** | [/rules/naming.md](../rules/naming.md) | Test naming conventions |
|
|
41
|
+
| **Reference** | [/checklists/backend.md](../checklists/backend.md) | Test checklist |
|
|
42
|
+
|
|
43
|
+
## Test Coverage Matrix
|
|
44
|
+
|
|
45
|
+
### Per Endpoint
|
|
46
|
+
|
|
47
|
+
| Endpoint | 正常系 (Normal) | 異常系 (Abnormal) |
|
|
48
|
+
| ----------- | ---------------------------- | ---------------------------- |
|
|
49
|
+
| **index** | List, filter, sort, paginate | Empty result, invalid params |
|
|
50
|
+
| **store** | Creates → 201 | 422 (each field), duplicate |
|
|
51
|
+
| **show** | Returns → 200 | 404 not found |
|
|
52
|
+
| **update** | Full update, partial | 404, 422 |
|
|
53
|
+
| **destroy** | Deletes → 204 | 404 |
|
|
54
|
+
|
|
55
|
+
### Auth Endpoints (if protected)
|
|
56
|
+
|
|
57
|
+
| Scenario | Expected |
|
|
58
|
+
| ------------- | -------- |
|
|
59
|
+
| No token | 401 |
|
|
60
|
+
| Invalid token | 401 |
|
|
61
|
+
| No permission | 403 |
|
|
62
|
+
|
|
63
|
+
### Japanese Field Validation
|
|
64
|
+
|
|
65
|
+
| Field | Valid | Invalid |
|
|
66
|
+
| ------------- | ------------ | ---------------- |
|
|
67
|
+
| `name_kana_*` | カタカナ | hiragana, romaji |
|
|
68
|
+
| Max length | Within limit | Exceeds limit |
|
|
69
|
+
|
|
70
|
+
## Test Naming Convention
|
|
71
|
+
|
|
72
|
+
```php
|
|
73
|
+
// 正常系 (Normal cases) - success behavior
|
|
74
|
+
it('正常: returns paginated users')
|
|
75
|
+
it('正常: creates user with valid data')
|
|
76
|
+
it('正常: updates user with partial data')
|
|
77
|
+
|
|
78
|
+
// 異常系 (Abnormal cases) - failure behavior
|
|
79
|
+
it('異常: fails to create user with missing email')
|
|
80
|
+
it('異常: fails to create user with invalid kana format')
|
|
81
|
+
it('異常: returns 404 when user not found')
|
|
82
|
+
it('異常: returns 401 when not authenticated')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Test Template
|
|
86
|
+
|
|
87
|
+
```php
|
|
88
|
+
describe('POST /api/users', function () {
|
|
89
|
+
// ================================================================
|
|
90
|
+
// 正常系 (Normal Cases)
|
|
91
|
+
// ================================================================
|
|
92
|
+
|
|
93
|
+
it('正常: creates user with valid data', function () {
|
|
94
|
+
$data = [
|
|
95
|
+
'name_lastname' => '田中',
|
|
96
|
+
'name_firstname' => '太郎',
|
|
97
|
+
'name_kana_lastname' => 'タナカ',
|
|
98
|
+
'name_kana_firstname' => 'タロウ',
|
|
99
|
+
'email' => 'test@example.com',
|
|
100
|
+
'password' => 'password123',
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
$response = $this->postJson('/api/users', $data);
|
|
104
|
+
|
|
105
|
+
$response->assertCreated()
|
|
106
|
+
->assertJsonPath('data.email', 'test@example.com');
|
|
107
|
+
|
|
108
|
+
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ================================================================
|
|
112
|
+
// 異常系 (Abnormal Cases)
|
|
113
|
+
// ================================================================
|
|
114
|
+
|
|
115
|
+
// Required fields
|
|
116
|
+
it('異常: fails to create user with missing email', function () {
|
|
117
|
+
$data = validUserData();
|
|
118
|
+
unset($data['email']);
|
|
119
|
+
|
|
120
|
+
$this->postJson('/api/users', $data)
|
|
121
|
+
->assertUnprocessable()
|
|
122
|
+
->assertJsonValidationErrors(['email']);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Format validation
|
|
126
|
+
it('異常: fails to create user with invalid email format', function () {
|
|
127
|
+
$data = validUserData(['email' => 'not-an-email']);
|
|
128
|
+
|
|
129
|
+
$this->postJson('/api/users', $data)
|
|
130
|
+
->assertUnprocessable()
|
|
131
|
+
->assertJsonValidationErrors(['email']);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Japanese field validation
|
|
135
|
+
it('異常: fails to create user with invalid kana format', function () {
|
|
136
|
+
$data = validUserData(['name_kana_lastname' => 'たなか']); // hiragana
|
|
137
|
+
|
|
138
|
+
$this->postJson('/api/users', $data)
|
|
139
|
+
->assertUnprocessable()
|
|
140
|
+
->assertJsonValidationErrors(['name_kana_lastname']);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Unique constraint
|
|
144
|
+
it('異常: fails to create user with duplicate email', function () {
|
|
145
|
+
User::factory()->create(['email' => 'existing@example.com']);
|
|
146
|
+
$data = validUserData(['email' => 'existing@example.com']);
|
|
147
|
+
|
|
148
|
+
$this->postJson('/api/users', $data)
|
|
149
|
+
->assertUnprocessable()
|
|
150
|
+
->assertJsonValidationErrors(['email']);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('GET /api/users/{id}', function () {
|
|
155
|
+
it('正常: returns user by id', function () {
|
|
156
|
+
$user = User::factory()->create();
|
|
157
|
+
|
|
158
|
+
$this->getJson("/api/users/{$user->id}")
|
|
159
|
+
->assertOk()
|
|
160
|
+
->assertJsonPath('data.id', $user->id);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('異常: returns 404 when user not found', function () {
|
|
164
|
+
$this->getJson('/api/users/99999')
|
|
165
|
+
->assertNotFound();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Debugging Failed Tests
|
|
171
|
+
|
|
172
|
+
```mermaid
|
|
173
|
+
flowchart TD
|
|
174
|
+
Fail[Test Failed] --> Check1{Endpoint correct?}
|
|
175
|
+
Check1 -->|No| FixEndpoint[Fix URL/method]
|
|
176
|
+
Check1 -->|Yes| Check2{Data valid?}
|
|
177
|
+
Check2 -->|No| FixData[Fix test data]
|
|
178
|
+
Check2 -->|Yes| Check3{Assertion correct?}
|
|
179
|
+
Check3 -->|No| FixAssert[Fix assertion]
|
|
180
|
+
Check3 -->|Yes| CodeBug[Code has bug - fix code]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Example Interaction
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
User: Write tests for OrderController
|
|
187
|
+
|
|
188
|
+
Tester Agent:
|
|
189
|
+
1. Read /guides/laravel/testing.md
|
|
190
|
+
2. Identify endpoints (index, store, show, update, destroy)
|
|
191
|
+
3. For each endpoint:
|
|
192
|
+
- Write 正常系 tests
|
|
193
|
+
- Write 異常系 tests (validation, 404, 401, 403)
|
|
194
|
+
4. Add Japanese field tests if applicable
|
|
195
|
+
5. Output complete test file with describe/it blocks
|
|
196
|
+
```
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Backend Checklist
|
|
2
|
+
|
|
3
|
+
> Quick reference. For details, see linked guides.
|
|
4
|
+
|
|
5
|
+
## New Resource
|
|
6
|
+
|
|
7
|
+
| Step | Action | Guide |
|
|
8
|
+
| ---- | --------------------- | ----------------------------------------------------------- |
|
|
9
|
+
| 1 | Create schema | [guides/omnify/schema-guide.md](../guides/omnify/schema-guide.md) |
|
|
10
|
+
| 2 | `npx omnify generate` | |
|
|
11
|
+
| 3 | `./artisan migrate` | |
|
|
12
|
+
| 4 | Model (extend base) | [guides/laravel/README.md](../guides/laravel/README.md) |
|
|
13
|
+
| 5 | Controller (thin) | |
|
|
14
|
+
| 6 | Resource | |
|
|
15
|
+
| 7 | Routes | |
|
|
16
|
+
| 8 | **Tests** | [guides/laravel/testing.md](../guides/laravel/testing.md) |
|
|
17
|
+
| 9 | `./artisan test` | |
|
|
18
|
+
| 10 | OpenAPI | [guides/laravel/openapi.md](../guides/laravel/openapi.md) |
|
|
19
|
+
|
|
20
|
+
> **Full workflow**: [workflows/new-feature.md](../workflows/new-feature.md)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Before Commit
|
|
25
|
+
|
|
26
|
+
### Code
|
|
27
|
+
- [ ] No `dd()`, `dump()`, `console.log`
|
|
28
|
+
- [ ] No commented-out code
|
|
29
|
+
- [ ] Type hints on methods
|
|
30
|
+
|
|
31
|
+
### Security
|
|
32
|
+
- [ ] `$fillable` defined in Model
|
|
33
|
+
- [ ] `$request->validated()` (not `all()`)
|
|
34
|
+
- [ ] Sensitive data in `$hidden`
|
|
35
|
+
|
|
36
|
+
### API
|
|
37
|
+
- [ ] Dates use `->toISOString()`
|
|
38
|
+
- [ ] Return Resource (not Model)
|
|
39
|
+
- [ ] Proper HTTP status codes
|
|
40
|
+
|
|
41
|
+
### Performance
|
|
42
|
+
- [ ] `with()` for relations
|
|
43
|
+
- [ ] `whenLoaded()` in Resources
|
|
44
|
+
- [ ] `paginate()` for lists
|
|
45
|
+
|
|
46
|
+
> **Details**: [rules/](../rules/)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Tests
|
|
51
|
+
|
|
52
|
+
### Coverage Required
|
|
53
|
+
|
|
54
|
+
| Endpoint | 正常系 | 異常系 |
|
|
55
|
+
| ----------- | ------------------ | --------------------- |
|
|
56
|
+
| **index** | List, filter, sort | Empty, invalid params |
|
|
57
|
+
| **store** | Creates → 201 | 422 (validation) |
|
|
58
|
+
| **show** | Returns → 200 | 404 |
|
|
59
|
+
| **update** | Updates → 200 | 404, 422 |
|
|
60
|
+
| **destroy** | Deletes → 204 | 404 |
|
|
61
|
+
|
|
62
|
+
### Auth Tests (if protected)
|
|
63
|
+
- 401: Not authenticated
|
|
64
|
+
- 403: Not authorized
|
|
65
|
+
|
|
66
|
+
> **Full guide**: [guides/laravel/testing.md](../guides/laravel/testing.md)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## OpenAPI
|
|
71
|
+
|
|
72
|
+
1. Check `OmnifyBase/*RequestBase.php` for request fields
|
|
73
|
+
2. Check `OmnifyBase/*ResourceBase.php` for response fields
|
|
74
|
+
3. Use `$ref` from `Schemas.php`
|
|
75
|
+
4. Run `./artisan l5-swagger:generate`
|
|
76
|
+
|
|
77
|
+
> **Full guide**: [guides/laravel/openapi.md](../guides/laravel/openapi.md)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Controller Methods
|
|
82
|
+
|
|
83
|
+
### index
|
|
84
|
+
```php
|
|
85
|
+
return UserResource::collection(
|
|
86
|
+
User::with('relation')
|
|
87
|
+
->when($request->search, fn($q, $s) => $q->where('name', 'like', "%{$s}%"))
|
|
88
|
+
->paginate($request->input('per_page', 15))
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### store
|
|
93
|
+
```php
|
|
94
|
+
return new UserResource(User::create($request->validated()));
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### show
|
|
98
|
+
```php
|
|
99
|
+
return new UserResource($user->load('relation'));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### update
|
|
103
|
+
```php
|
|
104
|
+
$user->update($request->validated());
|
|
105
|
+
return new UserResource($user);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### destroy
|
|
109
|
+
```php
|
|
110
|
+
$user->delete();
|
|
111
|
+
return response()->noContent();
|
|
112
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Checklists
|
|
2
|
+
|
|
3
|
+
> **Related:** [README](./README.md)
|
|
4
|
+
|
|
5
|
+
## After Writing Code
|
|
6
|
+
|
|
7
|
+
> **IMPORTANT**: Always run these commands after writing/modifying code:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Type check
|
|
11
|
+
npm run typecheck
|
|
12
|
+
|
|
13
|
+
# 2. Lint check
|
|
14
|
+
npm run lint
|
|
15
|
+
|
|
16
|
+
# Or combined
|
|
17
|
+
npm run typecheck && npm run lint
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Adding New Resource
|
|
23
|
+
|
|
24
|
+
When adding a new resource (e.g., `posts`), follow these steps:
|
|
25
|
+
|
|
26
|
+
### 1. Service Layer (Always in `services/`)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Create: services/posts.ts
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- [ ] Import types: `import type { Post, PostCreate, PostUpdate } from "@omnify/schemas"`
|
|
33
|
+
- [ ] Define only `PostListParams` (Create/Update come from Omnify)
|
|
34
|
+
- [ ] Create `postService` object with CRUD methods
|
|
35
|
+
- [ ] Add JSDoc comments for each method
|
|
36
|
+
|
|
37
|
+
### 2. Query Keys
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Update: lib/queryKeys.ts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- [ ] Add `posts` object to `queryKeys`
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
posts: {
|
|
47
|
+
all: ["posts"] as const,
|
|
48
|
+
lists: () => [...queryKeys.posts.all, "list"] as const,
|
|
49
|
+
list: (params?: PostListParams) => [...queryKeys.posts.lists(), params] as const,
|
|
50
|
+
details: () => [...queryKeys.posts.all, "detail"] as const,
|
|
51
|
+
detail: (id: number) => [...queryKeys.posts.details(), id] as const,
|
|
52
|
+
},
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Feature Components (in `features/posts/`)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Create: features/posts/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- [ ] `PostTable.tsx` - Table component
|
|
62
|
+
- [ ] `PostForm.tsx` - Form component
|
|
63
|
+
- [ ] `usePostFilters.ts` - Feature-specific hooks (if needed)
|
|
64
|
+
|
|
65
|
+
### 4. Pages
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Create pages in app/(dashboard)/posts/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- [ ] `page.tsx` - List page (imports from `features/posts/`)
|
|
72
|
+
- [ ] `new/page.tsx` - Create form
|
|
73
|
+
- [ ] `[id]/page.tsx` - Detail view
|
|
74
|
+
- [ ] `[id]/edit/page.tsx` - Edit form
|
|
75
|
+
|
|
76
|
+
### 5. Shared Components (only if reused)
|
|
77
|
+
|
|
78
|
+
- [ ] If component used in 2+ features → move to `components/common/`
|
|
79
|
+
|
|
80
|
+
### 6. Translations
|
|
81
|
+
|
|
82
|
+
- [ ] Add labels to `src/i18n/messages/*.json` if needed
|
|
83
|
+
|
|
84
|
+
### 7. Final Check
|
|
85
|
+
|
|
86
|
+
- [ ] Run `npm run typecheck && npm run lint`
|
|
87
|
+
- [ ] Test create, read, update, delete operations
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Adding New Language
|
|
92
|
+
|
|
93
|
+
- [ ] Create message file: `src/i18n/messages/{locale}.json`
|
|
94
|
+
- [ ] Add locale to `src/i18n/config.ts`
|
|
95
|
+
- [ ] Import Ant Design locale in `src/components/AntdThemeProvider.tsx`
|
|
96
|
+
- [ ] Test with `LocaleSwitcher` component
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Before Commit
|
|
101
|
+
|
|
102
|
+
- [ ] `npm run typecheck` passes
|
|
103
|
+
- [ ] `npm run lint` passes
|
|
104
|
+
- [ ] No console warnings about deprecated props
|
|
105
|
+
- [ ] No hardcoded strings (use i18n)
|
|
106
|
+
- [ ] Forms handle loading state (`isPending`)
|
|
107
|
+
- [ ] Forms handle validation errors (`getFormErrors`)
|
|
108
|
+
- [ ] Mutations invalidate related queries
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{LARAVEL_ROOT}}app/Http/Controllers/**/*.php"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Laravel Controller Rules
|
|
7
|
+
|
|
8
|
+
## Thin Controller Pattern
|
|
9
|
+
|
|
10
|
+
Controllers should: Validate → Delegate → Respond
|
|
11
|
+
|
|
12
|
+
```php
|
|
13
|
+
public function store(StoreUserRequest $request): JsonResponse
|
|
14
|
+
{
|
|
15
|
+
// ✅ Validate (via FormRequest)
|
|
16
|
+
$data = $request->validated();
|
|
17
|
+
|
|
18
|
+
// ✅ Delegate (simple = Model, complex = Service)
|
|
19
|
+
$user = User::create($data);
|
|
20
|
+
|
|
21
|
+
// ✅ Respond (via Resource)
|
|
22
|
+
return new UserResource($user);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## ⚠️ CRITICAL: OpenAPI Paths
|
|
27
|
+
|
|
28
|
+
**DO NOT add `/api` prefix!** The `api.php` route file already has it.
|
|
29
|
+
|
|
30
|
+
```php
|
|
31
|
+
// ❌ WRONG
|
|
32
|
+
#[OA\Get(path: '/api/users')]
|
|
33
|
+
|
|
34
|
+
// ✅ CORRECT
|
|
35
|
+
#[OA\Get(path: '/users')]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Security Rules
|
|
39
|
+
|
|
40
|
+
- Always use `$request->validated()`, never `$request->all()`
|
|
41
|
+
- Use route model binding for single resources
|
|
42
|
+
- Use `authorize()` in FormRequest for authorization
|
|
43
|
+
|
|
44
|
+
## Query Patterns
|
|
45
|
+
|
|
46
|
+
```php
|
|
47
|
+
// ✅ List with pagination and eager loading
|
|
48
|
+
User::query()
|
|
49
|
+
->with(['posts', 'profile'])
|
|
50
|
+
->when($search, fn($q) => $q->where('name', 'like', "%{$search}%"))
|
|
51
|
+
->latest()
|
|
52
|
+
->paginate(15);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Full Documentation
|
|
56
|
+
|
|
57
|
+
See @.claude/omnify/guides/laravel/controller.md for complete patterns.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{LARAVEL_ROOT}}database/migrations/**/*.php"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ⛔ STOP: Migration Rules
|
|
7
|
+
|
|
8
|
+
## Auto-Generated Migrations (DO NOT EDIT)
|
|
9
|
+
|
|
10
|
+
Files in `{{LARAVEL_ROOT}}database/migrations/omnify/` are **AUTO-GENERATED** by Omnify.
|
|
11
|
+
|
|
12
|
+
**ANY MANUAL CHANGES WILL BE OVERWRITTEN** on next `npx omnify generate`.
|
|
13
|
+
|
|
14
|
+
## ✅ Correct Workflow
|
|
15
|
+
|
|
16
|
+
### To add/modify columns:
|
|
17
|
+
|
|
18
|
+
1. Edit schema YAML in `schemas/`
|
|
19
|
+
2. Run `npx omnify generate`
|
|
20
|
+
3. Run `php artisan migrate`
|
|
21
|
+
|
|
22
|
+
### For custom migrations (outside Omnify):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
php artisan make:migration add_custom_field_to_users_table
|
|
26
|
+
# Creates: database/migrations/2026_xx_xx_xxxxxx_add_custom_field_to_users_table.php
|
|
27
|
+
# This is SAFE - Omnify won't touch it
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## File Structure
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
database/migrations/
|
|
34
|
+
├── omnify/ ← ⛔ AUTO-GENERATED - DO NOT EDIT
|
|
35
|
+
│ ├── 2026_01_01_000000_create_users_table.php
|
|
36
|
+
│ └── ...
|
|
37
|
+
├── 2026_01_12_120000_add_custom_field.php ← ✅ Safe to edit
|
|
38
|
+
└── 2026_01_12_130000_custom_migration.php ← ✅ Safe to edit
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Reference
|
|
42
|
+
|
|
43
|
+
| Want to... | Do this |
|
|
44
|
+
|------------|---------|
|
|
45
|
+
| Add column | Edit schema YAML → `npx omnify generate` |
|
|
46
|
+
| Modify column | Edit schema YAML → `npx omnify generate` |
|
|
47
|
+
| Custom migration | `php artisan make:migration` (outside omnify/) |
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{LARAVEL_ROOT}}tests/**/*.php"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing Rules (PEST)
|
|
7
|
+
|
|
8
|
+
## Test Naming Convention (Japanese Style)
|
|
9
|
+
|
|
10
|
+
```php
|
|
11
|
+
describe('UserController', function () {
|
|
12
|
+
// 正常系 (Happy Path)
|
|
13
|
+
describe('正常系', function () {
|
|
14
|
+
test('一覧が取得できる', function () { ... });
|
|
15
|
+
test('新規作成ができる', function () { ... });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 異常系 (Error Cases)
|
|
19
|
+
describe('異常系', function () {
|
|
20
|
+
test('認証なしで401', function () { ... });
|
|
21
|
+
test('存在しないIDで404', function () { ... });
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Required Setup
|
|
27
|
+
|
|
28
|
+
```php
|
|
29
|
+
uses(RefreshDatabase::class);
|
|
30
|
+
|
|
31
|
+
beforeEach(function () {
|
|
32
|
+
$this->user = User::factory()->create();
|
|
33
|
+
$this->actingAs($this->user);
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Assertion Patterns
|
|
38
|
+
|
|
39
|
+
```php
|
|
40
|
+
// API Response
|
|
41
|
+
$response->assertStatus(200)
|
|
42
|
+
->assertJsonStructure(['data' => ['id', 'name']]);
|
|
43
|
+
|
|
44
|
+
// Database
|
|
45
|
+
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
|
|
46
|
+
$this->assertDatabaseMissing('users', ['id' => $user->id]);
|
|
47
|
+
$this->assertDatabaseCount('users', 3);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Full Documentation
|
|
51
|
+
|
|
52
|
+
See @.claude/omnify/guides/laravel/testing.md for complete patterns.
|