@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,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Laravel FormRequest rules: OpenAPI schema MUST match schemaRules(), extend OmnifyBase for auto-generated validation, never use $request->all(). Apply when editing Request classes."
|
|
3
|
+
globs: ["{{LARAVEL_BASE}}/Http/Requests/**/*.php"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Request Rules
|
|
8
|
+
|
|
9
|
+
## Golden Rule: Schema MUST Match Validation Rules
|
|
10
|
+
|
|
11
|
+
OpenAPI Schema properties MUST match the actual `schemaRules()` fields.
|
|
12
|
+
|
|
13
|
+
## Before Editing Request
|
|
14
|
+
|
|
15
|
+
1. **Read `OmnifyBase/*RequestBase.php`** to see actual validation rules
|
|
16
|
+
2. **Compare with `#[OA\Schema]`** properties
|
|
17
|
+
3. **Ensure `required` array matches** required validation rules
|
|
18
|
+
4. **Match constraints** (maxLength, minLength, format)
|
|
19
|
+
|
|
20
|
+
## Checklist
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
// Check OmnifyBase/*StoreRequestBase.php → schemaRules()
|
|
24
|
+
return [
|
|
25
|
+
'name_lastname' => ['required', 'string', 'max:50'],
|
|
26
|
+
'name_firstname' => ['required', 'string', 'max:50'],
|
|
27
|
+
'email' => ['required', 'string', 'max:255', 'unique:users'],
|
|
28
|
+
'password' => ['required', 'string', 'max:255'],
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
// #[OA\Schema] MUST match
|
|
32
|
+
#[OA\Schema(
|
|
33
|
+
schema: 'UserStoreRequest',
|
|
34
|
+
required: ['name_lastname', 'name_firstname', 'email', 'password'], // ← Match 'required' rules
|
|
35
|
+
properties: [
|
|
36
|
+
new OA\Property(property: 'name_lastname', type: 'string', maxLength: 50), // ← max:50
|
|
37
|
+
new OA\Property(property: 'name_firstname', type: 'string', maxLength: 50),
|
|
38
|
+
new OA\Property(property: 'email', type: 'string', format: 'email', maxLength: 255),
|
|
39
|
+
new OA\Property(property: 'password', type: 'string', format: 'password', maxLength: 255),
|
|
40
|
+
]
|
|
41
|
+
)]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Mapping Validation Rules to OpenAPI
|
|
45
|
+
|
|
46
|
+
| Laravel Rule | OpenAPI Property |
|
|
47
|
+
| ------------ | --------------------------- |
|
|
48
|
+
| `required` | Add to `required: []` array |
|
|
49
|
+
| `max:50` | `maxLength: 50` |
|
|
50
|
+
| `min:8` | `minLength: 8` |
|
|
51
|
+
| `email` | `format: 'email'` |
|
|
52
|
+
| `string` | `type: 'string'` |
|
|
53
|
+
| `integer` | `type: 'integer'` |
|
|
54
|
+
| `boolean` | `type: 'boolean'` |
|
|
55
|
+
| `nullable` | `nullable: true` |
|
|
56
|
+
|
|
57
|
+
## StoreRequest vs UpdateRequest
|
|
58
|
+
|
|
59
|
+
| Type | `required` | Notes |
|
|
60
|
+
| ---------------- | ------------------- | ---------------------- |
|
|
61
|
+
| `*StoreRequest` | All required fields | Creating new resource |
|
|
62
|
+
| `*UpdateRequest` | Empty or partial | Partial update allowed |
|
|
63
|
+
|
|
64
|
+
```php
|
|
65
|
+
// StoreRequest - all fields required
|
|
66
|
+
#[OA\Schema(
|
|
67
|
+
schema: 'UserStoreRequest',
|
|
68
|
+
required: ['name_lastname', 'name_firstname', 'email', 'password'],
|
|
69
|
+
...
|
|
70
|
+
)]
|
|
71
|
+
|
|
72
|
+
// UpdateRequest - no required (partial update)
|
|
73
|
+
#[OA\Schema(
|
|
74
|
+
schema: 'UserUpdateRequest',
|
|
75
|
+
// No 'required' array - all fields optional
|
|
76
|
+
properties: [...]
|
|
77
|
+
)]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Common Mistakes
|
|
81
|
+
|
|
82
|
+
| Mistake | Fix |
|
|
83
|
+
| ----------------------- | ------------------------------------ |
|
|
84
|
+
| Missing field in schema | Check *RequestBase.php schemaRules() |
|
|
85
|
+
| Wrong maxLength | Match `max:X` rule |
|
|
86
|
+
| Missing required | Check if rule has `required` |
|
|
87
|
+
| Extra field in schema | Remove if not in rules |
|
|
88
|
+
|
|
89
|
+
## Custom Rules in Child Class
|
|
90
|
+
|
|
91
|
+
If you override rules in the child Request class, update schema accordingly:
|
|
92
|
+
|
|
93
|
+
```php
|
|
94
|
+
// UserStoreRequest.php
|
|
95
|
+
public function rules(): array
|
|
96
|
+
{
|
|
97
|
+
return array_merge($this->schemaRules(), [
|
|
98
|
+
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], // Added 'email' format
|
|
99
|
+
'password' => ['required', 'string', 'min:8', 'max:255'], // Added min:8
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Update schema to match
|
|
104
|
+
new OA\Property(property: 'email', type: 'string', format: 'email'), // ← Added format
|
|
105
|
+
new OA\Property(property: 'password', type: 'string', minLength: 8), // ← Added minLength
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## After Editing
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
./artisan l5-swagger:generate
|
|
112
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Laravel API Resource rules: OpenAPI schema MUST match toArray() output, extend OmnifyBase for auto-generated fields, use whenLoaded() for relations. Apply when editing Resource classes."
|
|
3
|
+
globs: ["{{LARAVEL_BASE}}/Http/Resources/**/*.php"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Resource Rules
|
|
8
|
+
|
|
9
|
+
## Golden Rule: Schema MUST Match Output
|
|
10
|
+
|
|
11
|
+
OpenAPI Schema properties MUST match the actual `toArray()` / `schemaArray()` output.
|
|
12
|
+
|
|
13
|
+
## Before Editing Resource
|
|
14
|
+
|
|
15
|
+
1. **Read `OmnifyBase/*ResourceBase.php`** to see actual fields
|
|
16
|
+
2. **Compare with `#[OA\Schema]`** properties
|
|
17
|
+
3. **Add missing fields** to schema
|
|
18
|
+
4. **Remove non-existent fields** from schema
|
|
19
|
+
|
|
20
|
+
## Checklist
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
// Check OmnifyBase/*ResourceBase.php → schemaArray()
|
|
24
|
+
return [
|
|
25
|
+
'id' => $this->id,
|
|
26
|
+
'name_lastname' => $this->name_lastname,
|
|
27
|
+
'name_full_name' => $this->name_full_name, // ← Computed field!
|
|
28
|
+
'email' => $this->email,
|
|
29
|
+
'created_at' => $this->created_at?->toISOString(),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// #[OA\Schema] MUST have ALL these properties
|
|
33
|
+
#[OA\Schema(
|
|
34
|
+
properties: [
|
|
35
|
+
new OA\Property(property: 'id', ...),
|
|
36
|
+
new OA\Property(property: 'name_lastname', ...),
|
|
37
|
+
new OA\Property(property: 'name_full_name', ...), // ← Don't forget!
|
|
38
|
+
new OA\Property(property: 'email', ...),
|
|
39
|
+
new OA\Property(property: 'created_at', ...),
|
|
40
|
+
]
|
|
41
|
+
)]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Common Mistakes
|
|
45
|
+
|
|
46
|
+
| Mistake | Fix |
|
|
47
|
+
| ---------------------------------------- | ----------------------- |
|
|
48
|
+
| Missing computed fields (name_full_name) | Check *ResourceBase.php |
|
|
49
|
+
| Schema has field not in output | Remove from schema |
|
|
50
|
+
| Field type mismatch | Match actual PHP type |
|
|
51
|
+
| Missing nullable | Check if `?->` used |
|
|
52
|
+
|
|
53
|
+
## JapaneseName Type Fields
|
|
54
|
+
|
|
55
|
+
JapaneseName expands to multiple fields including computed ones:
|
|
56
|
+
|
|
57
|
+
```php
|
|
58
|
+
// All these come from JapaneseName type
|
|
59
|
+
'name_lastname' => $this->name_lastname,
|
|
60
|
+
'name_firstname' => $this->name_firstname,
|
|
61
|
+
'name_kana_lastname' => $this->name_kana_lastname,
|
|
62
|
+
'name_kana_firstname' => $this->name_kana_firstname,
|
|
63
|
+
'name_full_name' => $this->name_full_name, // Computed!
|
|
64
|
+
'name_full_name_kana' => $this->name_full_name_kana, // Computed!
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**MUST include ALL in OpenAPI Schema!**
|
|
68
|
+
|
|
69
|
+
## After Editing
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
./artisan l5-swagger:generate
|
|
73
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Code review checklist for Laravel: security ($request->validated, SQL injection), performance (eager loading, N+1), and quality standards. Mention @laravel-review in chat to invoke."
|
|
3
|
+
globs: []
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Code Review Rules
|
|
8
|
+
|
|
9
|
+
> Review process for Laravel code
|
|
10
|
+
|
|
11
|
+
## Review Process
|
|
12
|
+
|
|
13
|
+
1. Security Check → 2. Performance Check → 3. Quality Check → 4. Test Check
|
|
14
|
+
|
|
15
|
+
## Security Checklist
|
|
16
|
+
|
|
17
|
+
| Check | Look For |
|
|
18
|
+
| --------------- | ---------------------------- |
|
|
19
|
+
| Mass Assignment | `$request->validated()` |
|
|
20
|
+
| SQL Injection | No raw SQL |
|
|
21
|
+
| `$fillable` | Defined, no sensitive fields |
|
|
22
|
+
| `$hidden` | Password hidden |
|
|
23
|
+
|
|
24
|
+
## Performance Checklist
|
|
25
|
+
|
|
26
|
+
| Check | Look For |
|
|
27
|
+
| ---------- | ---------------------- |
|
|
28
|
+
| N+1 | `with()` for relations |
|
|
29
|
+
| Pagination | `paginate()` for lists |
|
|
30
|
+
| Resources | `whenLoaded()` |
|
|
31
|
+
|
|
32
|
+
## Quality Checklist
|
|
33
|
+
|
|
34
|
+
| Check | Look For |
|
|
35
|
+
| ---------- | --------------- |
|
|
36
|
+
| Validation | FormRequest |
|
|
37
|
+
| Response | Resource |
|
|
38
|
+
| Dates | `toISOString()` |
|
|
39
|
+
|
|
40
|
+
## Code Style Checklist
|
|
41
|
+
|
|
42
|
+
| Check | Look For |
|
|
43
|
+
| ----------- | -------------------------------------- |
|
|
44
|
+
| **Imports** | No FQCN inline (`\Full\Path\Class`) |
|
|
45
|
+
| Use | All classes imported with `use` at top |
|
|
46
|
+
| Naming | Follows conventions |
|
|
47
|
+
|
|
48
|
+
## Test Checklist
|
|
49
|
+
|
|
50
|
+
| Endpoint | 正常系 | 異常系 |
|
|
51
|
+
| -------- | ------ | -------- |
|
|
52
|
+
| store | 201 | 422 |
|
|
53
|
+
| show | 200 | 404 |
|
|
54
|
+
| update | 200 | 404, 422 |
|
|
55
|
+
| destroy | 204 | 404 |
|
|
56
|
+
|
|
57
|
+
## Output Format
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
## Security
|
|
61
|
+
✅ Using `$request->validated()`
|
|
62
|
+
❌ Missing `$hidden` for password
|
|
63
|
+
|
|
64
|
+
## Performance
|
|
65
|
+
✅ Eager loading
|
|
66
|
+
❌ Missing pagination
|
|
67
|
+
|
|
68
|
+
## Recommendation: Request Changes
|
|
69
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "PEST testing guide: 正常系 (happy path) + 異常系 (error cases), Japanese naming conventions, RefreshDatabase trait, and factory usage. Apply when writing or reviewing tests."
|
|
3
|
+
globs: ["{{LARAVEL_ROOT}}tests/**/*.php"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Testing Rules (PEST)
|
|
8
|
+
|
|
9
|
+
> **Agent:** Act as **@tester** agent
|
|
10
|
+
> - Read `.claude/omnify/guides/laravel/testing.md` for full guide
|
|
11
|
+
|
|
12
|
+
## How to Run Tests
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Run ALL tests (from project root - uses Docker wrapper)
|
|
16
|
+
./artisan test
|
|
17
|
+
|
|
18
|
+
# Run specific test file
|
|
19
|
+
./artisan test --filter=UserControllerTest
|
|
20
|
+
|
|
21
|
+
# Run specific test method
|
|
22
|
+
./artisan test --filter="creates user with valid data"
|
|
23
|
+
|
|
24
|
+
# Run with coverage (if xdebug installed)
|
|
25
|
+
./artisan test --coverage
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
> **Note:** The root `./artisan` script is a wrapper that runs commands inside Docker container.
|
|
29
|
+
|
|
30
|
+
## Testing Process
|
|
31
|
+
|
|
32
|
+
1. **Before writing tests:**
|
|
33
|
+
- Read the Controller to understand endpoints
|
|
34
|
+
- Read the Request to understand validation rules
|
|
35
|
+
- Read the Resource to understand response structure
|
|
36
|
+
|
|
37
|
+
2. **Write tests covering:**
|
|
38
|
+
- 正常系 (Normal cases) - success scenarios
|
|
39
|
+
- 異常系 (Abnormal cases) - failure scenarios
|
|
40
|
+
|
|
41
|
+
3. **Run tests to verify:**
|
|
42
|
+
```bash
|
|
43
|
+
cd backend && ./artisan test
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
4. **All tests must pass before committing**
|
|
47
|
+
|
|
48
|
+
## Critical Rules
|
|
49
|
+
|
|
50
|
+
1. **PEST Syntax** - Use `describe()` + `it()`, not PHPUnit
|
|
51
|
+
2. **正常系 + 異常系** - Cover both success and failure
|
|
52
|
+
3. **Naming** - Use `正常:` and `異常:` prefixes
|
|
53
|
+
4. **Coverage** - All endpoints, all validation rules
|
|
54
|
+
5. **RefreshDatabase** - MUST use for SQLite in-memory
|
|
55
|
+
|
|
56
|
+
## Database Trait - IMPORTANT
|
|
57
|
+
|
|
58
|
+
```php
|
|
59
|
+
// ✅ CORRECT - Use RefreshDatabase for SQLite in-memory
|
|
60
|
+
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
61
|
+
uses(RefreshDatabase::class);
|
|
62
|
+
|
|
63
|
+
// ❌ WRONG - DatabaseTransactions doesn't run migrations
|
|
64
|
+
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
65
|
+
uses(DatabaseTransactions::class); // Will fail with "no such table"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| Trait | When to Use | Notes |
|
|
69
|
+
| ---------------------- | --------------------------------- | ------------------------------- |
|
|
70
|
+
| `RefreshDatabase` | SQLite in-memory (default) | Runs migrations, then truncates |
|
|
71
|
+
| `DatabaseTransactions` | MySQL/PostgreSQL with existing DB | Only wraps in transaction |
|
|
72
|
+
|
|
73
|
+
## Test Naming
|
|
74
|
+
|
|
75
|
+
```php
|
|
76
|
+
// 正常系 (Normal) - success behavior
|
|
77
|
+
it('正常: returns paginated users')
|
|
78
|
+
it('正常: creates user with valid data')
|
|
79
|
+
it('正常: deletes user')
|
|
80
|
+
|
|
81
|
+
// 異常系 (Abnormal) - failure behavior
|
|
82
|
+
it('異常: fails to create user with missing email')
|
|
83
|
+
it('異常: fails to create user with invalid kana format')
|
|
84
|
+
it('異常: returns 404 when user not found')
|
|
85
|
+
it('異常: returns 401 when not authenticated')
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Coverage Matrix
|
|
89
|
+
|
|
90
|
+
| Endpoint | 正常系 | 異常系 |
|
|
91
|
+
| -------- | ------------------ | --------------------- |
|
|
92
|
+
| index | List, filter, sort | Empty, invalid params |
|
|
93
|
+
| store | Creates → 201 | 422 (each field) |
|
|
94
|
+
| show | Returns → 200 | 404 |
|
|
95
|
+
| update | Updates → 200 | 404, 422 |
|
|
96
|
+
| destroy | Deletes → 204 | 404 |
|
|
97
|
+
|
|
98
|
+
## Template
|
|
99
|
+
|
|
100
|
+
```php
|
|
101
|
+
describe('POST /api/users', function () {
|
|
102
|
+
// 正常系
|
|
103
|
+
it('正常: creates user with valid data', function () {
|
|
104
|
+
$response = $this->postJson('/api/users', validUserData());
|
|
105
|
+
|
|
106
|
+
$response->assertCreated();
|
|
107
|
+
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// 異常系 - Required fields
|
|
111
|
+
it('異常: fails to create user with missing email', function () {
|
|
112
|
+
$data = validUserData();
|
|
113
|
+
unset($data['email']);
|
|
114
|
+
|
|
115
|
+
$this->postJson('/api/users', $data)
|
|
116
|
+
->assertUnprocessable()
|
|
117
|
+
->assertJsonValidationErrors(['email']);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 異常系 - Format validation
|
|
121
|
+
it('異常: fails to create user with invalid email format', function () {
|
|
122
|
+
$this->postJson('/api/users', validUserData(['email' => 'invalid']))
|
|
123
|
+
->assertUnprocessable()
|
|
124
|
+
->assertJsonValidationErrors(['email']);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Japanese Field Tests
|
|
130
|
+
|
|
131
|
+
```php
|
|
132
|
+
it('異常: fails with hiragana in kana field', function () {
|
|
133
|
+
$this->postJson('/api/users', validUserData([
|
|
134
|
+
'name_kana_lastname' => 'たなか' // hiragana - should fail
|
|
135
|
+
]))->assertUnprocessable()
|
|
136
|
+
->assertJsonValidationErrors(['name_kana_lastname']);
|
|
137
|
+
});
|
|
138
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Laravel backend rules for Omnify projects: schema-first migrations, thin controllers, security patterns, and code generation. Apply when working with Laravel controllers, models, migrations, or API endpoints."
|
|
3
|
+
globs: ["{{LARAVEL_BASE}}/**/*.php"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Laravel Rules
|
|
8
|
+
|
|
9
|
+
> **Documentation:** `.claude/omnify/guides/laravel/`
|
|
10
|
+
> **Team Migration Guide:** `.claude/omnify/guides/laravel/migrations-team.md`
|
|
11
|
+
> **Specific Rules:** See also `laravel-controller.mdc`, `laravel-resource.mdc`, `laravel-request.mdc`, `laravel-testing.mdc`, `migrations-workflow.mdc`, `omnify-migrations.mdc`
|
|
12
|
+
|
|
13
|
+
## ⛔ CRITICAL: DO NOT EDIT
|
|
14
|
+
|
|
15
|
+
| Path | Reason |
|
|
16
|
+
|------|--------|
|
|
17
|
+
| `{{LARAVEL_ROOT}}database/migrations/omnify/**` | Auto-generated by Omnify - will be overwritten! |
|
|
18
|
+
| `{{LARAVEL_BASE}}/Models/OmnifyBase/**` | Auto-generated base models |
|
|
19
|
+
| `{{LARAVEL_BASE}}/Http/Requests/OmnifyBase/**` | Auto-generated request bases |
|
|
20
|
+
| `{{LARAVEL_BASE}}/Http/Resources/OmnifyBase/**` | Auto-generated resource bases |
|
|
21
|
+
|
|
22
|
+
**To modify schema:** Edit YAML in `schemas/` → run `npx omnify generate`
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Critical Rules
|
|
27
|
+
|
|
28
|
+
1. **Thin Controller** - Validate → Delegate → Respond (see `laravel-controller.mdc`)
|
|
29
|
+
2. **🚨 Schema-First** - **NEVER** run `php artisan make:migration`! Use Omnify schemas instead (see `migrations-workflow.mdc`)
|
|
30
|
+
3. **Security** - Always use `$request->validated()`, never `$request->all()`
|
|
31
|
+
4. **Performance** - Use `with()` for relations, `paginate()` for lists
|
|
32
|
+
5. **Dates** - Store UTC, return `->toISOString()`
|
|
33
|
+
6. **Testing** - Write 正常系 + 異常系 tests (see `laravel-testing.mdc`)
|
|
34
|
+
7. **Imports** - Always `use` and short class names, never FQCN inline
|
|
35
|
+
8. **OpenAPI Paths** - NO `/api` prefix! `api.php` already has it (see `laravel-controller.mdc`)
|
|
36
|
+
|
|
37
|
+
## ⛔ FORBIDDEN: Manual Migrations
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# ❌ NEVER DO THIS
|
|
41
|
+
php artisan make:migration create_xxx_table
|
|
42
|
+
php artisan make:migration add_xxx_to_xxx_table
|
|
43
|
+
|
|
44
|
+
# ✅ ALWAYS DO THIS
|
|
45
|
+
# 1. Edit/Create YAML schema in schemas/
|
|
46
|
+
# 2. Run: npx omnify generate
|
|
47
|
+
# 3. Run: php artisan migrate
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
See `migrations-workflow.mdc` for complete guide.
|
|
51
|
+
|
|
52
|
+
## File-Specific Rules
|
|
53
|
+
|
|
54
|
+
| File Type | Rule File | Key Focus |
|
|
55
|
+
| ---------- | ----------------------- | ---------------------------- |
|
|
56
|
+
| Controller | `laravel-controller.mdc` | Thin, Query Builder, OpenAPI |
|
|
57
|
+
| Resource | `laravel-resource.mdc` | Schema matches output |
|
|
58
|
+
| Request | `laravel-request.mdc` | Schema matches validation |
|
|
59
|
+
| Test | `laravel-testing.mdc` | 正常系 + 異常系 coverage |
|
|
60
|
+
|
|
61
|
+
## Security Checklist
|
|
62
|
+
|
|
63
|
+
- [ ] `$fillable` defined in Model
|
|
64
|
+
- [ ] `$hidden` for sensitive fields
|
|
65
|
+
- [ ] `$request->validated()` not `$request->all()`
|
|
66
|
+
- [ ] No raw SQL with user input
|
|
67
|
+
- [ ] `with()` for eager loading
|
|
68
|
+
- [ ] `whenLoaded()` in Resources
|
|
69
|
+
- [ ] `paginate()` for list endpoints
|
|
70
|
+
|
|
71
|
+
## When to Use What
|
|
72
|
+
|
|
73
|
+
| Scenario | Solution |
|
|
74
|
+
| ---------------- | ------------------ |
|
|
75
|
+
| Simple CRUD | Controller + Model |
|
|
76
|
+
| Multi-step logic | Service |
|
|
77
|
+
| Reusable action | Action class |
|
|
78
|
+
| Async task | Job |
|
|
79
|
+
|
|
80
|
+
## Authentication Models
|
|
81
|
+
|
|
82
|
+
When `authenticatable: true` is set in schema, model extends `Authenticatable`:
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
# schemas/auth/User.yaml
|
|
86
|
+
options:
|
|
87
|
+
authenticatable: true
|
|
88
|
+
authenticatableLoginIdField: email
|
|
89
|
+
authenticatablePasswordField: password
|
|
90
|
+
authenticatableGuardName: web # Optional: for multi-guard
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Required `config/auth.php` for custom guards:**
|
|
94
|
+
|
|
95
|
+
```php
|
|
96
|
+
'guards' => [
|
|
97
|
+
'admin' => ['driver' => 'session', 'provider' => 'admins'],
|
|
98
|
+
],
|
|
99
|
+
'providers' => [
|
|
100
|
+
'admins' => ['driver' => 'eloquent', 'model' => App\Models\Admin::class],
|
|
101
|
+
],
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**See:** `.claude/omnify/guides/omnify/schema-guide.md` → "Authenticatable Option - Detailed Guide"
|
|
105
|
+
|
|
106
|
+
## Pre-Edit Checklist
|
|
107
|
+
|
|
108
|
+
**BEFORE editing any file, MUST:**
|
|
109
|
+
|
|
110
|
+
1. **Read the file first** - Check existing imports, patterns, style
|
|
111
|
+
2. **Check imports** - Add `use` if class not imported
|
|
112
|
+
3. **Follow existing style** - Match indentation, naming, patterns
|
|
113
|
+
4. **Never use FQCN inline** - Always import first
|
|
114
|
+
|
|
115
|
+
## Imports Rule
|
|
116
|
+
|
|
117
|
+
```php
|
|
118
|
+
// ❌ WRONG: Inline FQCN
|
|
119
|
+
public function store(): \Illuminate\Http\JsonResponse
|
|
120
|
+
|
|
121
|
+
// ✅ CORRECT: Import and use short name
|
|
122
|
+
use Illuminate\Http\JsonResponse;
|
|
123
|
+
public function store(): JsonResponse
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Don't Over-Engineer
|
|
127
|
+
|
|
128
|
+
| ❌ DON'T | ✅ DO |
|
|
129
|
+
| ----------------------------------- | ------------------------- |
|
|
130
|
+
| Add workaround to hide bugs | Fix root cause or report |
|
|
131
|
+
| Repository for simple CRUD | Use Eloquent directly |
|
|
132
|
+
| Service that just wraps Model | Controller + Model |
|
|
133
|
+
| Interface with 1 implementation | Concrete class |
|
|
134
|
+
| Manual 404 check with route binding | Trust framework |
|
|
135
|
+
| "Improve" unrelated code | Change only what's needed |
|
|
136
|
+
| Build for future "just in case" | YAGNI - build when needed |
|
|
137
|
+
|
|
138
|
+
**Full examples:** `.claude/omnify/guides/laravel/architecture.md`
|