@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.
Files changed (91) hide show
  1. package/README.md +105 -0
  2. package/dist/chunk-RCTEXK7C.js +549 -0
  3. package/dist/chunk-RCTEXK7C.js.map +1 -0
  4. package/dist/config/rules.yaml +524 -0
  5. package/dist/index.cjs +587 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +55 -0
  8. package/dist/index.d.ts +55 -0
  9. package/dist/index.js +26 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/knowledge/agents/architect.md.stub +150 -0
  12. package/dist/knowledge/agents/developer.md.stub +190 -0
  13. package/dist/knowledge/agents/reviewer.md.stub +134 -0
  14. package/dist/knowledge/agents/tester.md.stub +196 -0
  15. package/dist/knowledge/checklists/backend.md.stub +112 -0
  16. package/dist/knowledge/checklists/react.md.stub +108 -0
  17. package/dist/knowledge/claude-rules/laravel-controllers.md.stub +57 -0
  18. package/dist/knowledge/claude-rules/laravel-migrations.md.stub +47 -0
  19. package/dist/knowledge/claude-rules/laravel-tests.md.stub +52 -0
  20. package/dist/knowledge/claude-rules/naming.md.stub +369 -0
  21. package/dist/knowledge/claude-rules/performance.md.stub +256 -0
  22. package/dist/knowledge/claude-rules/php-standards.md.stub +305 -0
  23. package/dist/knowledge/claude-rules/react-components.md.stub +67 -0
  24. package/dist/knowledge/claude-rules/schema-yaml.md.stub +83 -0
  25. package/dist/knowledge/claude-rules/security.md.stub +164 -0
  26. package/dist/knowledge/cursor-rules/antd-deprecations.mdc.stub +62 -0
  27. package/dist/knowledge/cursor-rules/basemodel-readonly.mdc.stub +66 -0
  28. package/dist/knowledge/cursor-rules/baserequest-readonly.mdc.stub +74 -0
  29. package/dist/knowledge/cursor-rules/baseresource-readonly.mdc.stub +78 -0
  30. package/dist/knowledge/cursor-rules/laravel-controller.mdc.stub +421 -0
  31. package/dist/knowledge/cursor-rules/laravel-request.mdc.stub +112 -0
  32. package/dist/knowledge/cursor-rules/laravel-resource.mdc.stub +73 -0
  33. package/dist/knowledge/cursor-rules/laravel-review.mdc.stub +69 -0
  34. package/dist/knowledge/cursor-rules/laravel-testing.mdc.stub +138 -0
  35. package/dist/knowledge/cursor-rules/laravel.mdc.stub +138 -0
  36. package/dist/knowledge/cursor-rules/migrations-workflow.mdc.stub +224 -0
  37. package/dist/knowledge/cursor-rules/model-editable.mdc.stub +120 -0
  38. package/dist/knowledge/cursor-rules/omnify-migrations.mdc.stub +109 -0
  39. package/dist/knowledge/cursor-rules/omnify-schema.mdc.stub +358 -0
  40. package/dist/knowledge/cursor-rules/omnify.mdc.stub +58 -0
  41. package/dist/knowledge/cursor-rules/react-design.mdc.stub +693 -0
  42. package/dist/knowledge/cursor-rules/react-form.mdc.stub +292 -0
  43. package/dist/knowledge/cursor-rules/react-services.mdc.stub +304 -0
  44. package/dist/knowledge/cursor-rules/react.mdc.stub +336 -0
  45. package/dist/knowledge/cursor-rules/request-editable.mdc.stub +111 -0
  46. package/dist/knowledge/cursor-rules/resource-editable.mdc.stub +125 -0
  47. package/dist/knowledge/cursor-rules/schema-create.mdc.stub +440 -0
  48. package/dist/knowledge/cursor-rules/validation-rules.mdc.stub +181 -0
  49. package/dist/knowledge/laravel/README.md.stub +59 -0
  50. package/dist/knowledge/laravel/architecture.md.stub +424 -0
  51. package/dist/knowledge/laravel/authentication.md.stub +588 -0
  52. package/dist/knowledge/laravel/controller.md.stub +484 -0
  53. package/dist/knowledge/laravel/datetime.md.stub +334 -0
  54. package/dist/knowledge/laravel/migrations-team.md.stub +376 -0
  55. package/dist/knowledge/laravel/openapi.md.stub +449 -0
  56. package/dist/knowledge/laravel/request.md.stub +450 -0
  57. package/dist/knowledge/laravel/resource.md.stub +516 -0
  58. package/dist/knowledge/laravel/service.md.stub +503 -0
  59. package/dist/knowledge/laravel/testing.md.stub +1504 -0
  60. package/dist/knowledge/omnify/antdesign-guide.md.stub +401 -0
  61. package/dist/knowledge/omnify/config-guide.md.stub +405 -0
  62. package/dist/knowledge/omnify/japan-guide.md.stub +186 -0
  63. package/dist/knowledge/omnify/laravel-guide.md.stub +61 -0
  64. package/dist/knowledge/omnify/partial-schema-guide.md.stub +353 -0
  65. package/dist/knowledge/omnify/react-form-guide.md.stub +225 -0
  66. package/dist/knowledge/omnify/schema-guide.md.stub +144 -0
  67. package/dist/knowledge/omnify/typescript-guide.md.stub +337 -0
  68. package/dist/knowledge/react/README.md.stub +221 -0
  69. package/dist/knowledge/react/antd-guide.md +528 -0
  70. package/dist/knowledge/react/antd-guide.md.stub +528 -0
  71. package/dist/knowledge/react/checklist.md.stub +108 -0
  72. package/dist/knowledge/react/datetime-guide.md.stub +137 -0
  73. package/dist/knowledge/react/design-philosophy.md.stub +363 -0
  74. package/dist/knowledge/react/i18n-guide.md.stub +211 -0
  75. package/dist/knowledge/react/laravel-integration.md.stub +181 -0
  76. package/dist/knowledge/react/service-pattern.md.stub +180 -0
  77. package/dist/knowledge/react/tanstack-query.md.stub +339 -0
  78. package/dist/knowledge/react/types-guide.md +669 -0
  79. package/dist/knowledge/react/types-guide.md.stub +669 -0
  80. package/dist/knowledge/workflows/bug-fix.md.stub +201 -0
  81. package/dist/knowledge/workflows/code-review.md.stub +164 -0
  82. package/dist/knowledge/workflows/new-feature.md.stub +327 -0
  83. package/dist/plugin-M95GyBll.d.cts +191 -0
  84. package/dist/plugin-M95GyBll.d.ts +191 -0
  85. package/dist/plugin.cjs +573 -0
  86. package/dist/plugin.cjs.map +1 -0
  87. package/dist/plugin.d.cts +2 -0
  88. package/dist/plugin.d.ts +2 -0
  89. package/dist/plugin.js +15 -0
  90. package/dist/plugin.js.map +1 -0
  91. package/package.json +53 -0
@@ -0,0 +1,201 @@
1
+ # Bug Fix Workflow
2
+
3
+ > Step-by-step guide for fixing bugs.
4
+
5
+ ## Overview
6
+
7
+ ```mermaid
8
+ flowchart LR
9
+ Reproduce --> Locate --> Fix --> Test --> PR
10
+ ```
11
+
12
+ | Step | Action | Output |
13
+ | ---- | --------------------- | ------------------------------ |
14
+ | 1 | Reproduce the bug | Clear reproduction steps |
15
+ | 2 | Locate the cause | File(s) and line(s) identified |
16
+ | 3 | Write failing test | Test that reproduces bug |
17
+ | 4 | Fix the bug | Code changes |
18
+ | 5 | Verify test passes | `./artisan test` |
19
+ | 6 | Check for regressions | All tests pass |
20
+ | 7 | Create PR | Pull request |
21
+
22
+ ---
23
+
24
+ ## Step 1: Reproduce
25
+
26
+ Before fixing, confirm you can reproduce:
27
+
28
+ ```bash
29
+ # Check logs
30
+ tail -f backend/storage/logs/laravel.log
31
+
32
+ # Test the endpoint
33
+ curl -X GET https://api.boilerplate.app/api/users
34
+ ```
35
+
36
+ **Document:**
37
+ - Steps to reproduce
38
+ - Expected behavior
39
+ - Actual behavior
40
+ - Error message/stack trace
41
+
42
+ ---
43
+
44
+ ## Step 2: Locate the Cause
45
+
46
+ ### Common Locations
47
+
48
+ | Symptom | Check |
49
+ | ------------------- | -------------------------------- |
50
+ | 500 error | `storage/logs/laravel.log` |
51
+ | 422 validation | `*Request.php` rules |
52
+ | Wrong data returned | `*Resource.php` |
53
+ | 404 not found | `routes/api.php` + model binding |
54
+ | N+1 queries | Missing `with()` in controller |
55
+ | Date format wrong | Missing `->toISOString()` |
56
+
57
+ ### Debug Commands
58
+
59
+ ```bash
60
+ # Check route exists
61
+ ./artisan route:list | grep users
62
+
63
+ # Check model
64
+ ./artisan tinker
65
+ >>> User::find(1)
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Step 3: Write Failing Test
71
+
72
+ **ALWAYS write a test that reproduces the bug first.**
73
+
74
+ ```php
75
+ // tests/Feature/Api/UserControllerTest.php
76
+
77
+ it('異常: bug #123 - returns 500 when name is null', function () {
78
+ // This should NOT happen but currently does
79
+ $response = $this->postJson('/api/users', [
80
+ 'email' => 'test@example.com',
81
+ 'password' => 'password123',
82
+ // name is missing - should return 422, not 500
83
+ ]);
84
+
85
+ $response->assertUnprocessable(); // Currently fails with 500
86
+ });
87
+ ```
88
+
89
+ Run test to confirm it fails:
90
+
91
+ ```bash
92
+ ./artisan test --filter="bug #123"
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Step 4: Fix the Bug
98
+
99
+ Make the minimal change to fix the issue.
100
+
101
+ **Don't:**
102
+ - Refactor unrelated code
103
+ - Add features
104
+ - Change coding style
105
+
106
+ **Do:**
107
+ - Fix only the bug
108
+ - Keep changes focused
109
+ - Follow existing patterns
110
+
111
+ ---
112
+
113
+ ## Step 5: Verify Fix
114
+
115
+ ```bash
116
+ # Run the specific test
117
+ ./artisan test --filter="bug #123"
118
+
119
+ # Run all tests for the affected controller
120
+ ./artisan test --filter=UserControllerTest
121
+
122
+ # Run all tests
123
+ ./artisan test
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Step 6: Check for Regressions
129
+
130
+ ```bash
131
+ # All backend tests
132
+ ./artisan test
133
+
134
+ # Specific test file
135
+ ./artisan test tests/Feature/Api/UserControllerTest.php
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Step 7: Create PR
141
+
142
+ ### PR Title Format
143
+
144
+ ```
145
+ fix: [#issue] brief description
146
+ ```
147
+
148
+ Example: `fix: [#123] return 422 instead of 500 when name is missing`
149
+
150
+ ### PR Description
151
+
152
+ ```markdown
153
+ ## Bug
154
+
155
+ [Link to issue or description]
156
+
157
+ ## Root Cause
158
+
159
+ [Explanation of what caused the bug]
160
+
161
+ ## Fix
162
+
163
+ [Description of the fix]
164
+
165
+ ## Test
166
+
167
+ - [ ] Added test that reproduces bug
168
+ - [ ] Test passes after fix
169
+ - [ ] All existing tests pass
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Debugging Tips
175
+
176
+ ### Laravel Logs
177
+
178
+ ```php
179
+ // Add temporary logging
180
+ Log::info('Debug', ['user' => $user, 'request' => $request->all()]);
181
+ ```
182
+
183
+ ### Database Queries
184
+
185
+ ```php
186
+ // Enable query log
187
+ DB::enableQueryLog();
188
+
189
+ // ... your code ...
190
+
191
+ // Dump queries
192
+ dd(DB::getQueryLog());
193
+ ```
194
+
195
+ ### Tinker
196
+
197
+ ```bash
198
+ ./artisan tinker
199
+ >>> User::where('email', 'test@example.com')->first()
200
+ >>> app(UserService::class)->someMethod()
201
+ ```
@@ -0,0 +1,164 @@
1
+ # Code Review Workflow
2
+
3
+ > Checklist for reviewing pull requests.
4
+
5
+ ## Overview
6
+
7
+ ```mermaid
8
+ flowchart LR
9
+ Read --> Security --> Performance --> Quality --> Test --> Approve
10
+ ```
11
+
12
+ ---
13
+
14
+ ## 1. Understand the Change
15
+
16
+ - [ ] Read PR description
17
+ - [ ] Understand the purpose
18
+ - [ ] Check linked issue/ticket
19
+
20
+ ---
21
+
22
+ ## 2. Security Review
23
+
24
+ > **Reference:** [/rules/security.md](../rules/security.md)
25
+
26
+ ### Must Check
27
+
28
+ | Item | Look For |
29
+ | --------------- | --------------------------------------------------- |
30
+ | Mass Assignment | Using `$request->validated()` not `$request->all()` |
31
+ | SQL Injection | No raw SQL with user input |
32
+ | `$fillable` | Defined in models, no sensitive fields |
33
+ | `$hidden` | Password and tokens hidden |
34
+ | XSS | No `{!! $userInput !!}` in Blade |
35
+
36
+ ### Code Review
37
+
38
+ ```php
39
+ // ❌ REJECT: Mass assignment vulnerability
40
+ User::create($request->all());
41
+
42
+ // ✅ APPROVE: Using validated data
43
+ User::create($request->validated());
44
+ ```
45
+
46
+ ---
47
+
48
+ ## 3. Performance Review
49
+
50
+ > **Reference:** [/rules/performance.md](../rules/performance.md)
51
+
52
+ ### Must Check
53
+
54
+ | Item | Look For |
55
+ | ------------- | -------------------------------- |
56
+ | N+1 Queries | `with()` used for relationships |
57
+ | Pagination | List endpoints use `paginate()` |
58
+ | Resources | `whenLoaded()` for relationships |
59
+ | Eager Loading | No lazy loading in loops |
60
+
61
+ ### Code Review
62
+
63
+ ```php
64
+ // ❌ REJECT: N+1 problem
65
+ $posts = Post::all();
66
+ foreach ($posts as $post) {
67
+ echo $post->author->name;
68
+ }
69
+
70
+ // ✅ APPROVE: Eager loaded
71
+ $posts = Post::with('author')->get();
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 4. Code Quality Review
77
+
78
+ ### Must Check
79
+
80
+ | Item | Look For |
81
+ | ------------- | ---------------------------------- |
82
+ | Validation | FormRequest not inline validation |
83
+ | Response | Resource not raw model |
84
+ | Route binding | `User $user` not `findOrFail($id)` |
85
+ | Dates | `->toISOString()` in Resources |
86
+ | Types | Return type hints on methods |
87
+
88
+ ### Naming
89
+
90
+ > **Reference:** [/rules/naming.md](../rules/naming.md)
91
+
92
+ | Type | Pattern |
93
+ | ---------- | ------------------------ |
94
+ | Controller | `{Model}Controller` |
95
+ | Request | `{Model}{Action}Request` |
96
+ | Resource | `{Model}Resource` |
97
+ | Test | `{Model}ControllerTest` |
98
+
99
+ ---
100
+
101
+ ## 5. Test Review
102
+
103
+ ### Must Have
104
+
105
+ | Endpoint | 正常系 | 異常系 |
106
+ | -------- | ------------------ | --------------------- |
107
+ | index | List, filter, sort | Empty, invalid params |
108
+ | store | Creates → 201 | 422 (validation) |
109
+ | show | Returns → 200 | 404 |
110
+ | update | Updates → 200 | 404, 422 |
111
+ | destroy | Deletes → 204 | 404 |
112
+
113
+ ### Test Naming
114
+
115
+ ```php
116
+ // ✅ Good naming
117
+ it('正常: creates user with valid data')
118
+ it('異常: fails to create user with invalid email')
119
+ it('異常: returns 404 when user not found')
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 6. Final Checks
125
+
126
+ - [ ] All tests pass
127
+ - [ ] No debug code (`dd()`, `dump()`, `Log::debug()`)
128
+ - [ ] No commented-out code
129
+ - [ ] No console.log or debug statements
130
+ - [ ] Follows existing patterns in codebase
131
+
132
+ ---
133
+
134
+ ## Review Decision
135
+
136
+ ### ✅ Approve If
137
+
138
+ - All security checks pass
139
+ - All performance checks pass
140
+ - Tests cover 正常系 + 異常系
141
+ - Code follows conventions
142
+
143
+ ### 🔄 Request Changes If
144
+
145
+ - Security vulnerability found
146
+ - Performance issue (N+1, no pagination)
147
+ - Missing tests
148
+ - Naming/pattern violations
149
+
150
+ ### Example Comments
151
+
152
+ ```markdown
153
+ ## Security Issue
154
+ ❌ Line 45: Using `$request->all()` - please use `$request->validated()`
155
+
156
+ ## Performance Issue
157
+ ❌ Line 23: Missing `with('author')` - will cause N+1 queries
158
+
159
+ ## Missing Test
160
+ ❌ No test for 422 validation error case
161
+
162
+ ## Naming
163
+ ❌ `UserCreateRequest` should be `UserStoreRequest` (Laravel convention)
164
+ ```
@@ -0,0 +1,327 @@
1
+ # New Feature Workflow
2
+
3
+ > Step-by-step guide for implementing a complete feature (Backend + Frontend).
4
+
5
+ ## Overview
6
+
7
+ ```mermaid
8
+ flowchart LR
9
+ Schema --> Generate --> Migrate --> Backend --> Tests --> OpenAPI --> Frontend
10
+ ```
11
+
12
+ | Step | Command/Action | Output |
13
+ | ---- | --------------------- | --------------------------------------- |
14
+ | 1 | Create schema | `.omnify/schemas/{Module}/{Model}.yaml` |
15
+ | 2 | `npx omnify generate` | Migration + Types + Requests |
16
+ | 3 | `./artisan migrate` | Database tables |
17
+ | 4 | Create Backend | Model, Controller, Resource, Routes |
18
+ | 5 | Write Tests | `tests/Feature/Api/*Test.php` |
19
+ | 6 | `./artisan test` | All tests pass |
20
+ | 7 | Add OpenAPI | Swagger documentation |
21
+ | 8 | Build Frontend | Service, Hooks, Components |
22
+
23
+ ---
24
+
25
+ ## Step 1: Schema
26
+
27
+ Create `.omnify/schemas/{Module}/{Model}.yaml`:
28
+
29
+ ```yaml
30
+ # .omnify/schemas/Blog/Post.yaml
31
+ name: Post
32
+ tableName: posts
33
+ properties:
34
+ title:
35
+ type: String
36
+ maxLength: 255
37
+ content:
38
+ type: Text
39
+ user_id:
40
+ type: ForeignId
41
+ references: users
42
+ published_at:
43
+ type: DateTime
44
+ nullable: true
45
+ options:
46
+ timestamps: true
47
+ ```
48
+
49
+ > **Guide**: [guides/omnify/schema-guide.md](../guides/omnify/schema-guide.md)
50
+
51
+ ---
52
+
53
+ ## Step 2-3: Generate & Migrate
54
+
55
+ ```bash
56
+ npx omnify generate # Generate migration + types
57
+ ./artisan migrate # Create database tables
58
+ ```
59
+
60
+ **Verify**:
61
+ - [ ] Check `{{LARAVEL_ROOT}}database/migrations/omnify/` for new migration
62
+ - [ ] Check `frontend/src/types/model/` for TypeScript types
63
+
64
+ ---
65
+
66
+ ## Step 4: Backend Implementation
67
+
68
+ ### 4.1 Model
69
+
70
+ ```php
71
+ // {{LARAVEL_BASE}}/Models/Post.php
72
+ class Post extends PostBaseModel
73
+ {
74
+ // $fillable, $casts inherited from base
75
+
76
+ public function author(): BelongsTo
77
+ {
78
+ return $this->belongsTo(User::class, 'user_id');
79
+ }
80
+
81
+ public function scopePublished($query)
82
+ {
83
+ return $query->whereNotNull('published_at');
84
+ }
85
+ }
86
+ ```
87
+
88
+ ### 4.2 Controller (Thin!)
89
+
90
+ ```php
91
+ // {{LARAVEL_BASE}}/Http/Controllers/PostController.php
92
+ class PostController extends Controller
93
+ {
94
+ public function index(Request $request)
95
+ {
96
+ $posts = Post::with('author')
97
+ ->when($request->search, fn($q, $s) => $q->where('title', 'like', "%{$s}%"))
98
+ ->paginate($request->input('per_page', 15));
99
+
100
+ return PostResource::collection($posts);
101
+ }
102
+
103
+ public function store(PostStoreRequest $request): PostResource
104
+ {
105
+ $post = Post::create($request->validated());
106
+ return new PostResource($post);
107
+ }
108
+
109
+ public function show(Post $post): PostResource
110
+ {
111
+ return new PostResource($post->load('author'));
112
+ }
113
+
114
+ public function update(PostUpdateRequest $request, Post $post): PostResource
115
+ {
116
+ $post->update($request->validated());
117
+ return new PostResource($post);
118
+ }
119
+
120
+ public function destroy(Post $post): Response
121
+ {
122
+ $post->delete();
123
+ return response()->noContent();
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### 4.3 Resource
129
+
130
+ ```php
131
+ // {{LARAVEL_BASE}}/Http/Resources/PostResource.php
132
+ class PostResource extends PostResourceBase
133
+ {
134
+ public function toArray($request): array
135
+ {
136
+ return array_merge($this->schemaArray(), [
137
+ 'author' => new UserResource($this->whenLoaded('author')),
138
+ ]);
139
+ }
140
+ }
141
+ ```
142
+
143
+ ### 4.4 Routes
144
+
145
+ ```php
146
+ // routes/api.php
147
+ Route::apiResource('posts', PostController::class);
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Step 5: Tests
153
+
154
+ Create `tests/Feature/Api/PostControllerTest.php`:
155
+
156
+ ```php
157
+ describe('GET /api/posts', function () {
158
+ it('正常: returns paginated posts', function () {
159
+ Post::factory()->count(20)->create();
160
+
161
+ $response = $this->getJson('/api/posts');
162
+
163
+ $response->assertOk()
164
+ ->assertJsonCount(15, 'data')
165
+ ->assertJsonStructure(['data', 'meta', 'links']);
166
+ });
167
+ });
168
+
169
+ describe('POST /api/posts', function () {
170
+ it('正常: creates post with valid data', function () {
171
+ $data = ['title' => 'Test', 'content' => 'Content'];
172
+
173
+ $response = $this->postJson('/api/posts', $data);
174
+
175
+ $response->assertCreated();
176
+ $this->assertDatabaseHas('posts', $data);
177
+ });
178
+
179
+ it('異常: fails with missing title', function () {
180
+ $response = $this->postJson('/api/posts', ['content' => 'Content']);
181
+
182
+ $response->assertUnprocessable()
183
+ ->assertJsonValidationErrors(['title']);
184
+ });
185
+ });
186
+
187
+ describe('GET /api/posts/{id}', function () {
188
+ it('正常: returns post by id', function () {
189
+ $post = Post::factory()->create();
190
+
191
+ $this->getJson("/api/posts/{$post->id}")
192
+ ->assertOk()
193
+ ->assertJsonPath('data.id', $post->id);
194
+ });
195
+
196
+ it('異常: returns 404 when not found', function () {
197
+ $this->getJson('/api/posts/99999')
198
+ ->assertNotFound();
199
+ });
200
+ });
201
+ ```
202
+
203
+ Run tests:
204
+
205
+ ```bash
206
+ ./artisan test --filter=PostControllerTest
207
+ ```
208
+
209
+ > **Full guide**: [guides/laravel/testing.md](../guides/laravel/testing.md)
210
+
211
+ ---
212
+
213
+ ## Step 6: OpenAPI Documentation
214
+
215
+ Add to controller:
216
+
217
+ ```php
218
+ #[OA\Tag(name: 'Posts', description: 'Post management')]
219
+ class PostController extends Controller
220
+ {
221
+ #[OA\Get(
222
+ path: '/api/posts',
223
+ summary: 'List all posts',
224
+ tags: ['Posts'],
225
+ parameters: [
226
+ new OA\Parameter(ref: '#/components/parameters/QuerySearch'),
227
+ new OA\Parameter(ref: '#/components/parameters/QueryPage'),
228
+ ],
229
+ responses: [
230
+ new OA\Response(ref: '#/components/responses/Success', response: 200),
231
+ ]
232
+ )]
233
+ public function index() { ... }
234
+ }
235
+ ```
236
+
237
+ Generate:
238
+
239
+ ```bash
240
+ ./artisan l5-swagger:generate
241
+ ```
242
+
243
+ > **Full guide**: [guides/laravel/openapi.md](../guides/laravel/openapi.md)
244
+
245
+ ---
246
+
247
+ ## Step 7: Frontend
248
+
249
+ ### 7.1 Service
250
+
251
+ ```typescript
252
+ // services/posts.ts
253
+ export const postService = {
254
+ list: async (params?: PostListParams): Promise<PaginatedResponse<Post>> => {
255
+ const { data } = await api.get('/api/posts', { params });
256
+ return data;
257
+ },
258
+
259
+ create: async (input: PostCreate): Promise<Post> => {
260
+ const { data } = await api.post('/api/posts', input);
261
+ return data.data ?? data;
262
+ },
263
+
264
+ get: async (id: number): Promise<Post> => {
265
+ const { data } = await api.get(`/api/posts/${id}`);
266
+ return data.data ?? data;
267
+ },
268
+
269
+ update: async (id: number, input: PostUpdate): Promise<Post> => {
270
+ const { data } = await api.put(`/api/posts/${id}`, input);
271
+ return data.data ?? data;
272
+ },
273
+
274
+ delete: async (id: number): Promise<void> => {
275
+ await api.delete(`/api/posts/${id}`);
276
+ },
277
+ };
278
+ ```
279
+
280
+ ### 7.2 Query Keys
281
+
282
+ ```typescript
283
+ // lib/queryKeys.ts
284
+ export const queryKeys = {
285
+ posts: {
286
+ all: ['posts'] as const,
287
+ list: (params?: PostListParams) => ['posts', 'list', params] as const,
288
+ detail: (id: number) => ['posts', 'detail', id] as const,
289
+ },
290
+ };
291
+ ```
292
+
293
+ ### 7.3 Usage in Component
294
+
295
+ ```typescript
296
+ // List
297
+ const { data, isLoading } = useQuery({
298
+ queryKey: queryKeys.posts.list(filters),
299
+ queryFn: () => postService.list(filters),
300
+ });
301
+
302
+ // Create
303
+ const createMutation = useMutation({
304
+ mutationFn: postService.create,
305
+ onSuccess: () => {
306
+ queryClient.invalidateQueries({ queryKey: queryKeys.posts.all });
307
+ message.success('Created!');
308
+ },
309
+ });
310
+ ```
311
+
312
+ > **Full guide**: [guides/react/README.md](../guides/react/README.md)
313
+
314
+ ---
315
+
316
+ ## Checklist Summary
317
+
318
+ - [ ] Schema created and generated
319
+ - [ ] Migration verified and run
320
+ - [ ] Model with relationships
321
+ - [ ] Controller (thin, uses FormRequest)
322
+ - [ ] Resource (ISO 8601 dates)
323
+ - [ ] Routes added
324
+ - [ ] Tests written (正常系 + 異常系)
325
+ - [ ] Tests pass
326
+ - [ ] OpenAPI documented
327
+ - [ ] Frontend service + hooks