@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,449 @@
|
|
|
1
|
+
# OpenAPI Documentation Guide
|
|
2
|
+
|
|
3
|
+
> **Related:** [README](./README.md) | [Controller Guide](./controller-guide.md) | [Checklist](./checklist.md)
|
|
4
|
+
|
|
5
|
+
## ⚠️ CRITICAL: Check Route Prefix BEFORE Writing OpenAPI Path
|
|
6
|
+
|
|
7
|
+
### Step 1: Check Which Route File the Controller Uses
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Find where your route is registered
|
|
11
|
+
grep -r "UserController" routes/
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Step 2: Check the Route Prefix in That File
|
|
15
|
+
|
|
16
|
+
```php
|
|
17
|
+
// bootstrap/app.php hoặc app/Providers/RouteServiceProvider.php
|
|
18
|
+
// Tìm xem route file có prefix gì
|
|
19
|
+
|
|
20
|
+
// Ví dụ Laravel 11+: bootstrap/app.php
|
|
21
|
+
->withRouting(
|
|
22
|
+
api: __DIR__.'/../routes/api.php', // ← /api prefix tự động!
|
|
23
|
+
web: __DIR__.'/../routes/web.php',
|
|
24
|
+
apiPrefix: 'api', // ← Đây là prefix!
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
// Ví dụ Laravel 10: app/Providers/RouteServiceProvider.php
|
|
28
|
+
Route::middleware('api')
|
|
29
|
+
->prefix('api') // ← Đây là prefix!
|
|
30
|
+
->group(base_path('routes/api.php'));
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Step 3: Write OpenAPI Path = Actual Route Path (KHÔNG có prefix)
|
|
34
|
+
|
|
35
|
+
| Route File | Route Definition | Prefix | OpenAPI Path | Final URL |
|
|
36
|
+
|------------|------------------|--------|--------------|-----------|
|
|
37
|
+
| `api.php` | `Route::get('/users', ...)` | `/api` | `path: '/users'` | `/api/users` |
|
|
38
|
+
| `api.php` | `Route::get('/users/{id}', ...)` | `/api` | `path: '/users/{id}'` | `/api/users/1` |
|
|
39
|
+
| `web.php` | `Route::get('/dashboard', ...)` | (none) | `path: '/dashboard'` | `/dashboard` |
|
|
40
|
+
| `admin.php` | `Route::get('/stats', ...)` | `/admin/api` | `path: '/stats'` | `/admin/api/stats` |
|
|
41
|
+
|
|
42
|
+
### ❌ CRITICAL BUG - Duplicate Prefix
|
|
43
|
+
|
|
44
|
+
```php
|
|
45
|
+
// Route trong api.php (đã có prefix /api)
|
|
46
|
+
Route::get('/users', [UserController::class, 'index']);
|
|
47
|
+
|
|
48
|
+
// ❌ SAI - Viết thêm /api vào path
|
|
49
|
+
#[OA\Get(path: '/api/users')] // → /api/api/users !!
|
|
50
|
+
|
|
51
|
+
// ✅ ĐÚNG - Chỉ viết path sau prefix
|
|
52
|
+
#[OA\Get(path: '/users')] // → /api/users ✓
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Quick Reference: Common Prefixes
|
|
56
|
+
|
|
57
|
+
| Route File | Default Prefix | OpenAPI Server URL |
|
|
58
|
+
|------------|----------------|-------------------|
|
|
59
|
+
| `api.php` | `/api` | `#[OA\Server(url: '/api')]` |
|
|
60
|
+
| `web.php` | (none) | `#[OA\Server(url: '/')]` |
|
|
61
|
+
| Custom | Check RouteServiceProvider | Match the prefix |
|
|
62
|
+
|
|
63
|
+
### Checklist Before Writing OpenAPI
|
|
64
|
+
|
|
65
|
+
- [ ] Check route file (`api.php` / `web.php` / custom)
|
|
66
|
+
- [ ] Check prefix in `RouteServiceProvider` or `bootstrap/app.php`
|
|
67
|
+
- [ ] OpenAPI path = Route path (WITHOUT prefix)
|
|
68
|
+
- [ ] `#[OA\Server(url: ...)]` matches the prefix
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚠️ CRITICAL: L5-Swagger Configuration
|
|
73
|
+
|
|
74
|
+
**MUST set `use_absolute_path` to `false`** in `config/l5-swagger.php`:
|
|
75
|
+
|
|
76
|
+
```php
|
|
77
|
+
// config/l5-swagger.php
|
|
78
|
+
'use_absolute_path' => env('L5_SWAGGER_USE_ABSOLUTE_PATH', false),
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Without this, Swagger UI will fail to load the API documentation correctly.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Overview
|
|
86
|
+
|
|
87
|
+
This project uses [L5-Swagger](https://github.com/DarkaOnLine/L5-Swagger) with PHP 8 Attributes.
|
|
88
|
+
|
|
89
|
+
**Key files:**
|
|
90
|
+
- `app/OpenApi/Schemas.php` - Reusable components (parameters, responses)
|
|
91
|
+
- `{{LARAVEL_BASE}}/Http/Controllers/*Controller.php` - Endpoint documentation
|
|
92
|
+
|
|
93
|
+
## Commands
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
./artisan l5-swagger:generate # Generate OpenAPI JSON
|
|
97
|
+
# View at: https://api.{folder}.app/api/documentation
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Architecture
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
app/OpenApi/
|
|
106
|
+
└── Schemas.php ← Define reusable components HERE
|
|
107
|
+
|
|
108
|
+
{{LARAVEL_BASE}}/Http/Controllers/
|
|
109
|
+
└── UserController.php ← Use $ref to reference components
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Step 1: Define Reusable Components
|
|
115
|
+
|
|
116
|
+
**File:** `app/OpenApi/Schemas.php`
|
|
117
|
+
|
|
118
|
+
```php
|
|
119
|
+
<?php
|
|
120
|
+
|
|
121
|
+
namespace App\OpenApi;
|
|
122
|
+
|
|
123
|
+
use OpenApi\Attributes as OA;
|
|
124
|
+
|
|
125
|
+
#[OA\Info(
|
|
126
|
+
version: '1.0.0',
|
|
127
|
+
title: 'My API',
|
|
128
|
+
description: 'API documentation'
|
|
129
|
+
)]
|
|
130
|
+
#[OA\Server(url: '/api', description: 'API Server')]
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// COMMON PARAMETERS
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
#[OA\Parameter(
|
|
137
|
+
parameter: 'QuerySearch',
|
|
138
|
+
name: 'search',
|
|
139
|
+
in: 'query',
|
|
140
|
+
description: 'Search term',
|
|
141
|
+
schema: new OA\Schema(type: 'string')
|
|
142
|
+
)]
|
|
143
|
+
#[OA\Parameter(
|
|
144
|
+
parameter: 'QueryPage',
|
|
145
|
+
name: 'page',
|
|
146
|
+
in: 'query',
|
|
147
|
+
description: 'Page number',
|
|
148
|
+
schema: new OA\Schema(type: 'integer', default: 1, minimum: 1)
|
|
149
|
+
)]
|
|
150
|
+
#[OA\Parameter(
|
|
151
|
+
parameter: 'QueryPerPage',
|
|
152
|
+
name: 'per_page',
|
|
153
|
+
in: 'query',
|
|
154
|
+
description: 'Items per page',
|
|
155
|
+
schema: new OA\Schema(type: 'integer', default: 10, minimum: 1, maximum: 100)
|
|
156
|
+
)]
|
|
157
|
+
#[OA\Parameter(
|
|
158
|
+
parameter: 'QuerySortBy',
|
|
159
|
+
name: 'sort_by',
|
|
160
|
+
in: 'query',
|
|
161
|
+
description: 'Sort field',
|
|
162
|
+
schema: new OA\Schema(type: 'string', default: 'id')
|
|
163
|
+
)]
|
|
164
|
+
#[OA\Parameter(
|
|
165
|
+
parameter: 'QuerySortOrder',
|
|
166
|
+
name: 'sort_order',
|
|
167
|
+
in: 'query',
|
|
168
|
+
description: 'Sort direction',
|
|
169
|
+
schema: new OA\Schema(type: 'string', enum: ['asc', 'desc'], default: 'desc')
|
|
170
|
+
)]
|
|
171
|
+
#[OA\Parameter(
|
|
172
|
+
parameter: 'PathId',
|
|
173
|
+
name: 'id',
|
|
174
|
+
in: 'path',
|
|
175
|
+
required: true,
|
|
176
|
+
description: 'Resource ID',
|
|
177
|
+
schema: new OA\Schema(type: 'integer', minimum: 1)
|
|
178
|
+
)]
|
|
179
|
+
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// COMMON RESPONSES
|
|
182
|
+
// ============================================================================
|
|
183
|
+
|
|
184
|
+
#[OA\Response(response: 'Success', description: 'Successful operation')]
|
|
185
|
+
#[OA\Response(response: 'Created', description: 'Resource created successfully')]
|
|
186
|
+
#[OA\Response(response: 'NoContent', description: 'Successfully deleted')]
|
|
187
|
+
#[OA\Response(response: 'NotFound', description: 'Resource not found')]
|
|
188
|
+
#[OA\Response(response: 'Unauthorized', description: 'Unauthenticated')]
|
|
189
|
+
#[OA\Response(response: 'Forbidden', description: 'Forbidden')]
|
|
190
|
+
#[OA\Response(
|
|
191
|
+
response: 'ValidationError',
|
|
192
|
+
description: 'Validation failed',
|
|
193
|
+
content: new OA\JsonContent(
|
|
194
|
+
properties: [
|
|
195
|
+
new OA\Property(property: 'message', type: 'string', example: 'The given data was invalid.'),
|
|
196
|
+
new OA\Property(property: 'errors', type: 'object', example: ['email' => ['The email has already been taken.']]),
|
|
197
|
+
]
|
|
198
|
+
)
|
|
199
|
+
)]
|
|
200
|
+
class Schemas
|
|
201
|
+
{
|
|
202
|
+
// This class exists only to hold OpenAPI attributes
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Step 2: Use $ref in Controllers
|
|
209
|
+
|
|
210
|
+
### Index (GET list)
|
|
211
|
+
|
|
212
|
+
```php
|
|
213
|
+
#[OA\Get(
|
|
214
|
+
path: '/users', // ⚠️ NO /api prefix! api.php already has it
|
|
215
|
+
summary: 'List users',
|
|
216
|
+
description: 'Paginated list with search and sorting',
|
|
217
|
+
tags: ['Users'],
|
|
218
|
+
parameters: [
|
|
219
|
+
new OA\Parameter(ref: '#/components/parameters/QuerySearch'),
|
|
220
|
+
new OA\Parameter(ref: '#/components/parameters/QueryPage'),
|
|
221
|
+
new OA\Parameter(ref: '#/components/parameters/QueryPerPage'),
|
|
222
|
+
new OA\Parameter(ref: '#/components/parameters/QuerySortBy'),
|
|
223
|
+
new OA\Parameter(ref: '#/components/parameters/QuerySortOrder'),
|
|
224
|
+
],
|
|
225
|
+
responses: [
|
|
226
|
+
new OA\Response(ref: '#/components/responses/Success', response: 200),
|
|
227
|
+
]
|
|
228
|
+
)]
|
|
229
|
+
public function index(Request $request): AnonymousResourceCollection
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Store (POST)
|
|
233
|
+
|
|
234
|
+
```php
|
|
235
|
+
#[OA\Post(
|
|
236
|
+
path: '/users', // ⚠️ NO /api prefix!
|
|
237
|
+
summary: 'Create user',
|
|
238
|
+
description: 'Create a new user account',
|
|
239
|
+
tags: ['Users'],
|
|
240
|
+
requestBody: new OA\RequestBody(
|
|
241
|
+
required: true,
|
|
242
|
+
content: new OA\JsonContent(
|
|
243
|
+
required: ['name_lastname', 'name_firstname', 'email', 'password'],
|
|
244
|
+
properties: [
|
|
245
|
+
new OA\Property(property: 'name_lastname', type: 'string', maxLength: 50, example: '田中'),
|
|
246
|
+
new OA\Property(property: 'name_firstname', type: 'string', maxLength: 50, example: '太郎'),
|
|
247
|
+
new OA\Property(property: 'email', type: 'string', format: 'email', example: 'tanaka@example.com'),
|
|
248
|
+
new OA\Property(property: 'password', type: 'string', format: 'password', minLength: 8),
|
|
249
|
+
]
|
|
250
|
+
)
|
|
251
|
+
),
|
|
252
|
+
responses: [
|
|
253
|
+
new OA\Response(ref: '#/components/responses/Created', response: 201),
|
|
254
|
+
new OA\Response(ref: '#/components/responses/ValidationError', response: 422),
|
|
255
|
+
]
|
|
256
|
+
)]
|
|
257
|
+
public function store(UserStoreRequest $request): UserResource
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Show (GET single)
|
|
261
|
+
|
|
262
|
+
```php
|
|
263
|
+
#[OA\Get(
|
|
264
|
+
path: '/users/{id}', // ⚠️ NO /api prefix!
|
|
265
|
+
summary: 'Get user',
|
|
266
|
+
description: 'Get user by ID',
|
|
267
|
+
tags: ['Users'],
|
|
268
|
+
parameters: [
|
|
269
|
+
new OA\Parameter(ref: '#/components/parameters/PathId'),
|
|
270
|
+
],
|
|
271
|
+
responses: [
|
|
272
|
+
new OA\Response(ref: '#/components/responses/Success', response: 200),
|
|
273
|
+
new OA\Response(ref: '#/components/responses/NotFound', response: 404),
|
|
274
|
+
]
|
|
275
|
+
)]
|
|
276
|
+
public function show(User $user): UserResource
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Update (PUT)
|
|
280
|
+
|
|
281
|
+
```php
|
|
282
|
+
#[OA\Put(
|
|
283
|
+
path: '/users/{id}', // ⚠️ NO /api prefix!
|
|
284
|
+
summary: 'Update user',
|
|
285
|
+
description: 'Update user (partial update supported)',
|
|
286
|
+
tags: ['Users'],
|
|
287
|
+
parameters: [
|
|
288
|
+
new OA\Parameter(ref: '#/components/parameters/PathId'),
|
|
289
|
+
],
|
|
290
|
+
requestBody: new OA\RequestBody(
|
|
291
|
+
content: new OA\JsonContent(
|
|
292
|
+
properties: [
|
|
293
|
+
new OA\Property(property: 'name_lastname', type: 'string', maxLength: 50),
|
|
294
|
+
new OA\Property(property: 'name_firstname', type: 'string', maxLength: 50),
|
|
295
|
+
new OA\Property(property: 'email', type: 'string', format: 'email'),
|
|
296
|
+
new OA\Property(property: 'password', type: 'string', format: 'password', minLength: 8),
|
|
297
|
+
]
|
|
298
|
+
)
|
|
299
|
+
),
|
|
300
|
+
responses: [
|
|
301
|
+
new OA\Response(ref: '#/components/responses/Success', response: 200),
|
|
302
|
+
new OA\Response(ref: '#/components/responses/NotFound', response: 404),
|
|
303
|
+
new OA\Response(ref: '#/components/responses/ValidationError', response: 422),
|
|
304
|
+
]
|
|
305
|
+
)]
|
|
306
|
+
public function update(UserUpdateRequest $request, User $user): UserResource
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Destroy (DELETE)
|
|
310
|
+
|
|
311
|
+
```php
|
|
312
|
+
#[OA\Delete(
|
|
313
|
+
path: '/users/{id}', // ⚠️ NO /api prefix!
|
|
314
|
+
summary: 'Delete user',
|
|
315
|
+
description: 'Permanently delete user',
|
|
316
|
+
tags: ['Users'],
|
|
317
|
+
parameters: [
|
|
318
|
+
new OA\Parameter(ref: '#/components/parameters/PathId'),
|
|
319
|
+
],
|
|
320
|
+
responses: [
|
|
321
|
+
new OA\Response(ref: '#/components/responses/NoContent', response: 204),
|
|
322
|
+
new OA\Response(ref: '#/components/responses/NotFound', response: 404),
|
|
323
|
+
]
|
|
324
|
+
)]
|
|
325
|
+
public function destroy(User $user): JsonResponse
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Available Components
|
|
331
|
+
|
|
332
|
+
### Parameters (use with `ref: '#/components/parameters/...'`)
|
|
333
|
+
|
|
334
|
+
| Name | Description |
|
|
335
|
+
| ---------------- | -------------------------------------- |
|
|
336
|
+
| `QuerySearch` | Search term |
|
|
337
|
+
| `QueryPage` | Page number (default: 1) |
|
|
338
|
+
| `QueryPerPage` | Items per page (default: 10, max: 100) |
|
|
339
|
+
| `QuerySortBy` | Sort field (default: id) |
|
|
340
|
+
| `QuerySortOrder` | Sort direction (asc/desc) |
|
|
341
|
+
| `PathId` | Resource ID in path |
|
|
342
|
+
|
|
343
|
+
### Responses (use with `ref: '#/components/responses/...'`)
|
|
344
|
+
|
|
345
|
+
| Name | HTTP Code | Description |
|
|
346
|
+
| ----------------- | --------- | -------------------- |
|
|
347
|
+
| `Success` | 200 | Successful operation |
|
|
348
|
+
| `Created` | 201 | Resource created |
|
|
349
|
+
| `NoContent` | 204 | Successfully deleted |
|
|
350
|
+
| `NotFound` | 404 | Resource not found |
|
|
351
|
+
| `ValidationError` | 422 | Validation failed |
|
|
352
|
+
| `Unauthorized` | 401 | Unauthenticated |
|
|
353
|
+
| `Forbidden` | 403 | Forbidden |
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## ⚠️ Important: Verify Fields Before Writing
|
|
358
|
+
|
|
359
|
+
**DO NOT make up fields!** Check these files first:
|
|
360
|
+
|
|
361
|
+
| What to Document | Check This File |
|
|
362
|
+
| ------------------- | ------------------------------------------------------------------- |
|
|
363
|
+
| Request body fields | `{{LARAVEL_BASE}}/Http/Requests/OmnifyBase/*RequestBase.php` → `schemaRules()` |
|
|
364
|
+
| Response fields | `{{LARAVEL_BASE}}/Http/Resources/OmnifyBase/*ResourceBase.php` → `schemaArray()` |
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Adding New Components
|
|
369
|
+
|
|
370
|
+
### New Parameter
|
|
371
|
+
|
|
372
|
+
```php
|
|
373
|
+
// In app/OpenApi/Schemas.php
|
|
374
|
+
#[OA\Parameter(
|
|
375
|
+
parameter: 'QueryStatus', // Unique name
|
|
376
|
+
name: 'status', // Query param name
|
|
377
|
+
in: 'query',
|
|
378
|
+
description: 'Filter by status',
|
|
379
|
+
schema: new OA\Schema(type: 'string', enum: ['active', 'inactive'])
|
|
380
|
+
)]
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### New Response
|
|
384
|
+
|
|
385
|
+
```php
|
|
386
|
+
// In app/OpenApi/Schemas.php
|
|
387
|
+
#[OA\Response(
|
|
388
|
+
response: 'PaymentRequired',
|
|
389
|
+
description: 'Payment required'
|
|
390
|
+
)]
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Checklist
|
|
396
|
+
|
|
397
|
+
### Before Writing
|
|
398
|
+
|
|
399
|
+
- [ ] Check `OmnifyBase/*RequestBase.php` for request fields
|
|
400
|
+
- [ ] Check `OmnifyBase/*ResourceBase.php` for response fields
|
|
401
|
+
- [ ] DON'T make up fields that don't exist!
|
|
402
|
+
|
|
403
|
+
### Writing OpenAPI
|
|
404
|
+
|
|
405
|
+
- [ ] Add `#[OA\Tag]` to controller class
|
|
406
|
+
- [ ] Use `$ref` for common parameters (QuerySearch, QueryPage, etc.)
|
|
407
|
+
- [ ] Use `$ref` for common responses (Success, NotFound, etc.)
|
|
408
|
+
- [ ] Only write `requestBody` properties manually (match FormRequest)
|
|
409
|
+
- [ ] Use Japanese examples for JapaneseName fields
|
|
410
|
+
|
|
411
|
+
### After Writing
|
|
412
|
+
|
|
413
|
+
- [ ] Run `./artisan l5-swagger:generate`
|
|
414
|
+
- [ ] Verify at `/api/documentation`
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Anti-Patterns
|
|
419
|
+
|
|
420
|
+
```php
|
|
421
|
+
// ❌ BAD: Repeating common parameters
|
|
422
|
+
parameters: [
|
|
423
|
+
new OA\Parameter(name: 'page', in: 'query', schema: new OA\Schema(type: 'integer')),
|
|
424
|
+
new OA\Parameter(name: 'per_page', in: 'query', schema: new OA\Schema(type: 'integer')),
|
|
425
|
+
]
|
|
426
|
+
|
|
427
|
+
// ✅ GOOD: Use $ref
|
|
428
|
+
parameters: [
|
|
429
|
+
new OA\Parameter(ref: '#/components/parameters/QueryPage'),
|
|
430
|
+
new OA\Parameter(ref: '#/components/parameters/QueryPerPage'),
|
|
431
|
+
]
|
|
432
|
+
|
|
433
|
+
// ❌ BAD: Repeating response definitions
|
|
434
|
+
responses: [
|
|
435
|
+
new OA\Response(response: 404, description: 'Resource not found'),
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
// ✅ GOOD: Use $ref
|
|
439
|
+
responses: [
|
|
440
|
+
new OA\Response(ref: '#/components/responses/NotFound', response: 404),
|
|
441
|
+
]
|
|
442
|
+
|
|
443
|
+
// ❌ BAD: Making up fields
|
|
444
|
+
new OA\Property(property: 'username', ...) // Does this exist?
|
|
445
|
+
|
|
446
|
+
// ✅ GOOD: Check OmnifyBase first, then write
|
|
447
|
+
// Checked: OmnifyBase/UserStoreRequestBase.php has name_lastname, name_firstname...
|
|
448
|
+
new OA\Property(property: 'name_lastname', type: 'string', example: '田中'),
|
|
449
|
+
```
|