@famgia/omnify-laravel 0.0.87 → 0.0.89

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 (46) hide show
  1. package/dist/{chunk-YVVAJA3T.js → chunk-V7LWJ6OM.js} +178 -12
  2. package/dist/chunk-V7LWJ6OM.js.map +1 -0
  3. package/dist/index.cjs +180 -11
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +48 -1
  6. package/dist/index.d.ts +48 -1
  7. package/dist/index.js +5 -1
  8. package/dist/plugin.cjs +176 -11
  9. package/dist/plugin.cjs.map +1 -1
  10. package/dist/plugin.js +1 -1
  11. package/package.json +5 -5
  12. package/scripts/postinstall.js +29 -36
  13. package/stubs/ai-guides/claude-agents/architect.md.stub +150 -0
  14. package/stubs/ai-guides/claude-agents/developer.md.stub +190 -0
  15. package/stubs/ai-guides/claude-agents/reviewer.md.stub +134 -0
  16. package/stubs/ai-guides/claude-agents/tester.md.stub +196 -0
  17. package/stubs/ai-guides/claude-checklists/backend.md.stub +112 -0
  18. package/stubs/ai-guides/claude-omnify/antdesign-guide.md.stub +401 -0
  19. package/stubs/ai-guides/claude-omnify/config-guide.md.stub +253 -0
  20. package/stubs/ai-guides/claude-omnify/japan-guide.md.stub +186 -0
  21. package/stubs/ai-guides/claude-omnify/laravel-guide.md.stub +61 -0
  22. package/stubs/ai-guides/claude-omnify/schema-guide.md.stub +115 -0
  23. package/stubs/ai-guides/claude-omnify/typescript-guide.md.stub +310 -0
  24. package/stubs/ai-guides/claude-rules/naming.md.stub +364 -0
  25. package/stubs/ai-guides/claude-rules/performance.md.stub +251 -0
  26. package/stubs/ai-guides/claude-rules/security.md.stub +159 -0
  27. package/stubs/ai-guides/claude-workflows/bug-fix.md.stub +201 -0
  28. package/stubs/ai-guides/claude-workflows/code-review.md.stub +164 -0
  29. package/stubs/ai-guides/claude-workflows/new-feature.md.stub +327 -0
  30. package/stubs/ai-guides/cursor/laravel-controller.mdc.stub +391 -0
  31. package/stubs/ai-guides/cursor/laravel-request.mdc.stub +112 -0
  32. package/stubs/ai-guides/cursor/laravel-resource.mdc.stub +73 -0
  33. package/stubs/ai-guides/cursor/laravel-review.mdc.stub +69 -0
  34. package/stubs/ai-guides/cursor/laravel-testing.mdc.stub +138 -0
  35. package/stubs/ai-guides/cursor/laravel.mdc.stub +82 -0
  36. package/stubs/ai-guides/laravel/README.md.stub +59 -0
  37. package/stubs/ai-guides/laravel/architecture.md.stub +424 -0
  38. package/stubs/ai-guides/laravel/controller.md.stub +484 -0
  39. package/stubs/ai-guides/laravel/datetime.md.stub +334 -0
  40. package/stubs/ai-guides/laravel/openapi.md.stub +369 -0
  41. package/stubs/ai-guides/laravel/request.md.stub +450 -0
  42. package/stubs/ai-guides/laravel/resource.md.stub +516 -0
  43. package/stubs/ai-guides/laravel/service.md.stub +503 -0
  44. package/stubs/ai-guides/laravel/testing.md.stub +1504 -0
  45. package/ai-guides/laravel-guide.md +0 -461
  46. package/dist/chunk-YVVAJA3T.js.map +0 -1
@@ -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 `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
+ // app/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
+ // app/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
+ // app/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