@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,440 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Step-by-step schema creation workflow: 1) Read guide, 2) Create YAML, 3) npx omnify generate, 4) Validate output, 5) Migrate. CRITICAL: String defaults must be plain values without quotes wrapper!"
|
|
3
|
+
globs: ["schemas/**/*.yaml", "schemas/**/*.yml", "{{LARAVEL_ROOT}}database/migrations/**"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Omnify Schema Creation Workflow
|
|
8
|
+
|
|
9
|
+
> **Usage:** Mention `@schema-create` in chat OR this rule auto-applies when editing schema files
|
|
10
|
+
|
|
11
|
+
## 📋 Workflow Steps
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
15
|
+
│ 1. READ GUIDE → Read schema guide documentation │
|
|
16
|
+
│ 2. CREATE SCHEMA → Create/modify YAML schema file │
|
|
17
|
+
│ 3. GENERATE → Run `npx omnify generate` │
|
|
18
|
+
│ 4. VALIDATE → Check generated code matches requirements │
|
|
19
|
+
│ 5. MIGRATE → Run database migration │
|
|
20
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 1: Read Schema Guide 📖
|
|
26
|
+
|
|
27
|
+
**MUST READ before creating schema:**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Read the schema guide
|
|
31
|
+
cat .claude/omnify/guides/omnify/schema-guide.md
|
|
32
|
+
# OR
|
|
33
|
+
cat packages/omnify/ai-guides/schema-guide.md
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Key Documentation:**
|
|
37
|
+
- Schema syntax and property types
|
|
38
|
+
- Relationships (belongsTo, hasMany, etc.)
|
|
39
|
+
- Validation rules (nullable, minLength, maxLength)
|
|
40
|
+
- Display names (ja, en, vi)
|
|
41
|
+
- Special types (JapaneseName, JapaneseAddress, etc.)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 2: Create Schema 📝
|
|
46
|
+
|
|
47
|
+
### Schema File Location
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
schemas/
|
|
51
|
+
├── {domain}/ # Group by domain
|
|
52
|
+
│ ├── {Model}.yaml # PascalCase filename
|
|
53
|
+
│ └── {Enum}.yaml # Enum schemas
|
|
54
|
+
└── shared/ # Shared enums/types
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Basic Schema Template
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
# schemas/{domain}/{ModelName}.yaml
|
|
61
|
+
name: ModelName
|
|
62
|
+
kind: object
|
|
63
|
+
|
|
64
|
+
displayName:
|
|
65
|
+
ja: モデル名
|
|
66
|
+
en: Model Name
|
|
67
|
+
|
|
68
|
+
options:
|
|
69
|
+
timestamps: true # created_at, updated_at
|
|
70
|
+
softDelete: false # deleted_at
|
|
71
|
+
|
|
72
|
+
properties:
|
|
73
|
+
# Required field
|
|
74
|
+
name:
|
|
75
|
+
type: String
|
|
76
|
+
length: 100
|
|
77
|
+
displayName:
|
|
78
|
+
ja: 名前
|
|
79
|
+
en: Name
|
|
80
|
+
placeholder:
|
|
81
|
+
ja: 例:田中太郎
|
|
82
|
+
en: e.g. John Doe
|
|
83
|
+
|
|
84
|
+
# Optional field
|
|
85
|
+
description:
|
|
86
|
+
type: Text
|
|
87
|
+
nullable: true
|
|
88
|
+
displayName:
|
|
89
|
+
ja: 説明
|
|
90
|
+
en: Description
|
|
91
|
+
|
|
92
|
+
# Enum field
|
|
93
|
+
status:
|
|
94
|
+
type: OrderStatus
|
|
95
|
+
default: pending
|
|
96
|
+
displayName:
|
|
97
|
+
ja: ステータス
|
|
98
|
+
en: Status
|
|
99
|
+
|
|
100
|
+
# Relationship
|
|
101
|
+
category:
|
|
102
|
+
type: Category
|
|
103
|
+
relation: belongsTo
|
|
104
|
+
nullable: true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### From SQL/Database Requirements
|
|
108
|
+
|
|
109
|
+
When creating schema from SQL or database design:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
# SQL: VARCHAR(255) NOT NULL
|
|
113
|
+
property_name:
|
|
114
|
+
type: String
|
|
115
|
+
length: 255
|
|
116
|
+
|
|
117
|
+
# SQL: VARCHAR(100) NULL
|
|
118
|
+
property_name:
|
|
119
|
+
type: String
|
|
120
|
+
length: 100
|
|
121
|
+
nullable: true
|
|
122
|
+
|
|
123
|
+
# SQL: TEXT
|
|
124
|
+
property_name:
|
|
125
|
+
type: Text
|
|
126
|
+
|
|
127
|
+
# SQL: INT / BIGINT
|
|
128
|
+
property_name:
|
|
129
|
+
type: Int # or BigInt
|
|
130
|
+
|
|
131
|
+
# SQL: DECIMAL(10,2)
|
|
132
|
+
property_name:
|
|
133
|
+
type: Float
|
|
134
|
+
|
|
135
|
+
# SQL: BOOLEAN DEFAULT false
|
|
136
|
+
property_name:
|
|
137
|
+
type: Boolean
|
|
138
|
+
default: false
|
|
139
|
+
|
|
140
|
+
# SQL: DATE
|
|
141
|
+
property_name:
|
|
142
|
+
type: Date
|
|
143
|
+
|
|
144
|
+
# SQL: DATETIME / TIMESTAMP
|
|
145
|
+
property_name:
|
|
146
|
+
type: DateTime
|
|
147
|
+
|
|
148
|
+
# SQL: ENUM('draft', 'published', 'archived')
|
|
149
|
+
# → Create separate enum schema
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Step 3: Generate Code 🔧
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Generate all code from schemas
|
|
158
|
+
npx omnify generate
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**What gets generated:**
|
|
162
|
+
- TypeScript types & Zod schemas
|
|
163
|
+
- Laravel migrations & models
|
|
164
|
+
- API resources & controllers
|
|
165
|
+
- Form requests & validation
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Step 4: Validate Generated Code ✅
|
|
170
|
+
|
|
171
|
+
### ⚠️ CRITICAL for SQL-based schemas
|
|
172
|
+
|
|
173
|
+
**If creating schema from SQL requirements, MUST verify:**
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# 1. Check generated migration matches SQL design
|
|
177
|
+
cat {{LARAVEL_ROOT}}database/migrations/*_create_{table_name}_table.php
|
|
178
|
+
|
|
179
|
+
# 2. Check TypeScript types match requirements
|
|
180
|
+
cat {{TYPESCRIPT_BASE}}/omnify/schemas/{ModelName}.ts
|
|
181
|
+
|
|
182
|
+
# 3. Check Laravel model relationships
|
|
183
|
+
cat {{LARAVEL_BASE}}/Models/{ModelName}.php
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Validation Checklist
|
|
187
|
+
|
|
188
|
+
| Check | What to Verify |
|
|
189
|
+
| -------------- | -------------------------------------------- |
|
|
190
|
+
| ✅ Column names | snake_case in migration matches schema |
|
|
191
|
+
| ✅ Column types | VARCHAR, TEXT, INT match schema types |
|
|
192
|
+
| ✅ Nullable | NULL/NOT NULL matches `nullable: true/false` |
|
|
193
|
+
| ✅ Defaults | DEFAULT values match `default:` in schema |
|
|
194
|
+
| ✅ Foreign keys | Relationships generate correct FK |
|
|
195
|
+
| ✅ Indexes | Required indexes are present |
|
|
196
|
+
|
|
197
|
+
### If Generated Code is Wrong
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
┌─────────────────────────────────────────┐
|
|
201
|
+
│ Generated code doesn't match SQL? │
|
|
202
|
+
│ │
|
|
203
|
+
│ 1. Fix the YAML schema │
|
|
204
|
+
│ 2. Run `npx omnify generate` again │
|
|
205
|
+
│ 3. Verify generated code │
|
|
206
|
+
│ 4. Repeat until correct │
|
|
207
|
+
└─────────────────────────────────────────┘
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Common fixes:**
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
# Problem: Column should be nullable
|
|
214
|
+
# Fix: Add nullable: true
|
|
215
|
+
property_name:
|
|
216
|
+
type: String
|
|
217
|
+
nullable: true # ← Add this
|
|
218
|
+
|
|
219
|
+
# Problem: Wrong column length
|
|
220
|
+
# Fix: Adjust length
|
|
221
|
+
property_name:
|
|
222
|
+
type: String
|
|
223
|
+
length: 255 # ← Change this
|
|
224
|
+
|
|
225
|
+
# Problem: Missing default value
|
|
226
|
+
# Fix: Add default
|
|
227
|
+
status:
|
|
228
|
+
type: OrderStatus
|
|
229
|
+
default: pending # ← Add this
|
|
230
|
+
|
|
231
|
+
# Problem: Wrong relationship type
|
|
232
|
+
# Fix: Change relation
|
|
233
|
+
category:
|
|
234
|
+
type: Category
|
|
235
|
+
relation: belongsTo # belongsTo, hasMany, hasOne, belongsToMany
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### ⚠️ CRITICAL: DB Functions NOT Allowed in Default
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
# ❌ WRONG - DB functions are NOT allowed
|
|
242
|
+
failed_at:
|
|
243
|
+
type: Timestamp
|
|
244
|
+
default: CURRENT_TIMESTAMP # ERROR!
|
|
245
|
+
|
|
246
|
+
# ✅ CORRECT - Use useCurrent option
|
|
247
|
+
failed_at:
|
|
248
|
+
type: Timestamp
|
|
249
|
+
useCurrent: true # Equivalent to CURRENT_TIMESTAMP
|
|
250
|
+
|
|
251
|
+
updated_at:
|
|
252
|
+
type: Timestamp
|
|
253
|
+
useCurrent: true
|
|
254
|
+
useCurrentOnUpdate: true # ON UPDATE CURRENT_TIMESTAMP
|
|
255
|
+
|
|
256
|
+
# ❌ WRONG - UUID() function
|
|
257
|
+
external_id:
|
|
258
|
+
type: Uuid
|
|
259
|
+
default: UUID() # ERROR!
|
|
260
|
+
|
|
261
|
+
# ✅ CORRECT - Static value or nullable
|
|
262
|
+
external_id:
|
|
263
|
+
type: Uuid
|
|
264
|
+
nullable: true # Let application generate
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Step 5: Run Migration 🗄️
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Run migration
|
|
273
|
+
php artisan migrate
|
|
274
|
+
|
|
275
|
+
# If migration fails, rollback and fix
|
|
276
|
+
php artisan migrate:rollback
|
|
277
|
+
# Fix schema, regenerate, try again
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 🔄 Complete Workflow Example
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# 1. Read guide
|
|
286
|
+
cat .claude/omnify/guides/omnify/schema-guide.md
|
|
287
|
+
|
|
288
|
+
# 2. Create schema file
|
|
289
|
+
# schemas/shop/Product.yaml
|
|
290
|
+
|
|
291
|
+
# 3. Generate code
|
|
292
|
+
npx omnify generate
|
|
293
|
+
|
|
294
|
+
# 4. Validate (especially for SQL-based requirements)
|
|
295
|
+
cat {{LARAVEL_ROOT}}database/migrations/*_create_products_table.php
|
|
296
|
+
# If wrong: fix schema → regenerate → validate again
|
|
297
|
+
|
|
298
|
+
# 5. Run migration
|
|
299
|
+
php artisan migrate
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 📌 Quick Reference
|
|
305
|
+
|
|
306
|
+
### Property Types
|
|
307
|
+
|
|
308
|
+
| Type | SQL | TypeScript |
|
|
309
|
+
| ---------- | -------- | ------------------------- |
|
|
310
|
+
| `String` | VARCHAR | `string` |
|
|
311
|
+
| `Text` | TEXT | `string` |
|
|
312
|
+
| `LongText` | LONGTEXT | `string` |
|
|
313
|
+
| `Int` | INT | `number` |
|
|
314
|
+
| `BigInt` | BIGINT | `number` |
|
|
315
|
+
| `Float` | DECIMAL | `number` |
|
|
316
|
+
| `Boolean` | BOOLEAN | `boolean` |
|
|
317
|
+
| `Date` | DATE | `string` |
|
|
318
|
+
| `DateTime` | DATETIME | `string` |
|
|
319
|
+
| `Email` | VARCHAR | `string` |
|
|
320
|
+
| `Url` | VARCHAR | `string` |
|
|
321
|
+
| `Json` | JSON | `Record<string, unknown>` |
|
|
322
|
+
|
|
323
|
+
### Japanese Compound Types
|
|
324
|
+
|
|
325
|
+
| Type | Fields Generated |
|
|
326
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
327
|
+
| `JapaneseName` | `{prefix}_lastname`, `{prefix}_firstname`, `{prefix}_kana_lastname`, `{prefix}_kana_firstname` |
|
|
328
|
+
| `JapaneseAddress` | `{prefix}_postal_code`, `{prefix}_prefecture`, `{prefix}_address1`, `{prefix}_address2`, `{prefix}_address3` |
|
|
329
|
+
| `JapaneseBankAccount` | `{prefix}_bank_code`, `{prefix}_bank_name`, `{prefix}_branch_code`, etc. |
|
|
330
|
+
|
|
331
|
+
### Relationship Types
|
|
332
|
+
|
|
333
|
+
| Relation | Description | Foreign Key |
|
|
334
|
+
| --------------- | ----------- | ---------------------------------- |
|
|
335
|
+
| `belongsTo` | N:1 | `{property}_id` on this table |
|
|
336
|
+
| `hasMany` | 1:N | `{this_model}_id` on related table |
|
|
337
|
+
| `hasOne` | 1:1 | `{this_model}_id` on related table |
|
|
338
|
+
| `belongsToMany` | N:N | Pivot table |
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## ⚠️ Common Mistakes
|
|
343
|
+
|
|
344
|
+
```yaml
|
|
345
|
+
# ❌ CRITICAL: String defaults with quotes produce CURLY QUOTES!
|
|
346
|
+
default: "'cloud'" # ❌ Produces: ''cloud'' (broken!)
|
|
347
|
+
default: "'member'" # ❌ Produces: ''member'' (broken!)
|
|
348
|
+
|
|
349
|
+
# ✅ CORRECT: Just the value, no quotes wrapper
|
|
350
|
+
default: cloud # ✅ Produces: 'cloud'
|
|
351
|
+
default: member # ✅ Produces: 'member'
|
|
352
|
+
|
|
353
|
+
# ❌ Wrong: Missing displayName for non-English projects
|
|
354
|
+
name:
|
|
355
|
+
type: String
|
|
356
|
+
# Missing displayName!
|
|
357
|
+
|
|
358
|
+
# ✅ Correct: Always add displayName
|
|
359
|
+
name:
|
|
360
|
+
type: String
|
|
361
|
+
displayName:
|
|
362
|
+
ja: 名前
|
|
363
|
+
en: Name
|
|
364
|
+
|
|
365
|
+
# ❌ Wrong: Hardcoded enum values in property
|
|
366
|
+
status:
|
|
367
|
+
type: String
|
|
368
|
+
enum: [draft, published] # Don't do this
|
|
369
|
+
|
|
370
|
+
# ✅ Correct: Create separate enum schema
|
|
371
|
+
status:
|
|
372
|
+
type: PostStatus # Reference enum schema
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 🔌 Partial Schema (Package Extensions)
|
|
378
|
+
|
|
379
|
+
Partial schemas allow packages to extend or provide default schemas.
|
|
380
|
+
|
|
381
|
+
**Target = Filename** (no `target` field needed):
|
|
382
|
+
|
|
383
|
+
```yaml
|
|
384
|
+
# packages/sso-client/schemas/User.yaml
|
|
385
|
+
kind: partial
|
|
386
|
+
priority: 10 # Lower = higher priority
|
|
387
|
+
|
|
388
|
+
properties:
|
|
389
|
+
sso_token:
|
|
390
|
+
type: String
|
|
391
|
+
nullable: true
|
|
392
|
+
console_user_id:
|
|
393
|
+
type: BigInt
|
|
394
|
+
nullable: true
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Behavior
|
|
398
|
+
|
|
399
|
+
| Scenario | Result |
|
|
400
|
+
| --------------------------- | --------------------------- |
|
|
401
|
+
| Main app has `User.yaml` | Partial merges into main |
|
|
402
|
+
| Main app has NO `User.yaml` | Partial becomes User schema |
|
|
403
|
+
|
|
404
|
+
### Priority System
|
|
405
|
+
|
|
406
|
+
```yaml
|
|
407
|
+
priority: 10 # High (1-49): Core packages
|
|
408
|
+
priority: 50 # Default: Feature modules
|
|
409
|
+
priority: 90 # Low (51-100): Customizations
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**For detailed guide:** See `.claude/omnify/guides/omnify/partial-schema-guide.md`
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 📦 Load Schemas from Laravel Package
|
|
417
|
+
|
|
418
|
+
Configure additional schema paths in `omnify.config.ts`:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
const config: OmnifyConfig = {
|
|
422
|
+
schemasDir: './schemas',
|
|
423
|
+
|
|
424
|
+
// Additional schema paths from packages
|
|
425
|
+
additionalSchemaPaths: [
|
|
426
|
+
{
|
|
427
|
+
path: './packages/your-package/database/schemas',
|
|
428
|
+
namespace: 'YourPackage',
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
|
|
432
|
+
// ... other config
|
|
433
|
+
};
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Then generate:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
npx omnify generate
|
|
440
|
+
```
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Omnify validation rules - Type-specific rules for Zod/Laravel validation"
|
|
3
|
+
globs: ["schemas/**/*.yaml", "schemas/**/*.yml"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Omnify Validation Rules
|
|
8
|
+
|
|
9
|
+
Validation rules in Omnify schema generate Zod schemas (TypeScript) and Laravel validation rules.
|
|
10
|
+
|
|
11
|
+
## ⚠️ Important: Type Compatibility
|
|
12
|
+
|
|
13
|
+
**Each rule is ONLY valid for specific property types!**
|
|
14
|
+
Using a rule on wrong type will cause **schema validation error**.
|
|
15
|
+
|
|
16
|
+
## Quick Reference
|
|
17
|
+
|
|
18
|
+
| Rule | Valid Types | Zod Output | Laravel Output |
|
|
19
|
+
|------|-------------|------------|----------------|
|
|
20
|
+
| `required` | **All** | (no `.optional()`) | `required` |
|
|
21
|
+
| `minLength` | String types | `.min(n)` | `min:n` |
|
|
22
|
+
| `maxLength` | String types | `.max(n)` | `max:n` |
|
|
23
|
+
| `url` | String types | `z.url()` | `url` |
|
|
24
|
+
| `uuid` | String types | `z.uuid()` | `uuid` |
|
|
25
|
+
| `ip` | String types | `z.ip()` | `ip` |
|
|
26
|
+
| `ipv4` | String types | `z.ipv4()` | `ipv4` |
|
|
27
|
+
| `ipv6` | String types | `z.ipv6()` | `ipv6` |
|
|
28
|
+
| `alpha` | String types | `.regex()` | `alpha` |
|
|
29
|
+
| `alphaNum` | String types | `.regex()` | `alpha_num` |
|
|
30
|
+
| `alphaDash` | String types | `.regex()` | `alpha_dash` |
|
|
31
|
+
| `numeric` | String types | `.regex()` | `numeric` |
|
|
32
|
+
| `digits` | String types | `.length().regex()` | `digits:n` |
|
|
33
|
+
| `digitsBetween` | String types | `.min().max().regex()` | `digits_between:min,max` |
|
|
34
|
+
| `startsWith` | String types | `.startsWith()` | `starts_with:x` |
|
|
35
|
+
| `endsWith` | String types | `.endsWith()` | `ends_with:x` |
|
|
36
|
+
| `lowercase` | String types | `.refine()` | `lowercase` |
|
|
37
|
+
| `uppercase` | String types | `.refine()` | `uppercase` |
|
|
38
|
+
| `min` | Numeric types | `.gte(n)` | `min:n` |
|
|
39
|
+
| `max` | Numeric types | `.lte(n)` | `max:n` |
|
|
40
|
+
| `between` | Numeric types | `.gte().lte()` | `between:min,max` |
|
|
41
|
+
| `gt` | Numeric types | `.gt(n)` | `gt:n` |
|
|
42
|
+
| `lt` | Numeric types | `.lt(n)` | `lt:n` |
|
|
43
|
+
| `multipleOf` | Numeric types | `.multipleOf(n)` | `multiple_of:n` |
|
|
44
|
+
|
|
45
|
+
## Type Groups
|
|
46
|
+
|
|
47
|
+
### String Types
|
|
48
|
+
`String`, `Text`, `MediumText`, `LongText`, `Password`, `Email`
|
|
49
|
+
|
|
50
|
+
### Numeric Types
|
|
51
|
+
`TinyInt`, `Int`, `BigInt`, `Float`, `Decimal`
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
### ✅ Correct Usage
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
properties:
|
|
59
|
+
# String with URL validation
|
|
60
|
+
website:
|
|
61
|
+
type: String
|
|
62
|
+
nullable: true
|
|
63
|
+
rules:
|
|
64
|
+
url: true # ✅ String type → url works
|
|
65
|
+
|
|
66
|
+
# String with pattern validation
|
|
67
|
+
username:
|
|
68
|
+
type: String
|
|
69
|
+
rules:
|
|
70
|
+
minLength: 3
|
|
71
|
+
maxLength: 20
|
|
72
|
+
alphaDash: true # ✅ Only letters, numbers, dash, underscore
|
|
73
|
+
lowercase: true # ✅ Must be lowercase
|
|
74
|
+
|
|
75
|
+
# Numeric with range validation
|
|
76
|
+
quantity:
|
|
77
|
+
type: Int
|
|
78
|
+
rules:
|
|
79
|
+
min: 0 # ✅ Int type → min works
|
|
80
|
+
max: 1000
|
|
81
|
+
multipleOf: 5 # ✅ Must be multiple of 5
|
|
82
|
+
|
|
83
|
+
# Decimal with precision
|
|
84
|
+
price:
|
|
85
|
+
type: Decimal
|
|
86
|
+
precision: 10
|
|
87
|
+
scale: 2
|
|
88
|
+
rules:
|
|
89
|
+
min: 0.01 # ✅ Decimal is numeric
|
|
90
|
+
max: 999999.99
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### ❌ Wrong Usage (Causes Validation Error)
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
properties:
|
|
97
|
+
# WRONG: url on Int
|
|
98
|
+
port:
|
|
99
|
+
type: Int
|
|
100
|
+
rules:
|
|
101
|
+
url: true # ❌ ERROR: Int cannot use url rule
|
|
102
|
+
|
|
103
|
+
# WRONG: min on String
|
|
104
|
+
name:
|
|
105
|
+
type: String
|
|
106
|
+
rules:
|
|
107
|
+
min: 5 # ❌ ERROR: String cannot use min rule (use minLength)
|
|
108
|
+
|
|
109
|
+
# WRONG: startsWith on Float
|
|
110
|
+
rate:
|
|
111
|
+
type: Float
|
|
112
|
+
rules:
|
|
113
|
+
startsWith: "0." # ❌ ERROR: Float cannot use startsWith
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Common Patterns
|
|
117
|
+
|
|
118
|
+
### Password Field
|
|
119
|
+
```yaml
|
|
120
|
+
password:
|
|
121
|
+
type: Password
|
|
122
|
+
rules:
|
|
123
|
+
required: true
|
|
124
|
+
minLength: 8
|
|
125
|
+
maxLength: 255
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Slug Field
|
|
129
|
+
```yaml
|
|
130
|
+
slug:
|
|
131
|
+
type: String
|
|
132
|
+
length: 100
|
|
133
|
+
unique: true
|
|
134
|
+
rules:
|
|
135
|
+
alphaDash: true
|
|
136
|
+
lowercase: true
|
|
137
|
+
minLength: 3
|
|
138
|
+
maxLength: 100
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Phone Number (String of digits)
|
|
142
|
+
```yaml
|
|
143
|
+
phone:
|
|
144
|
+
type: String
|
|
145
|
+
length: 15
|
|
146
|
+
rules:
|
|
147
|
+
numeric: true # Only digits
|
|
148
|
+
digitsBetween: [10, 15]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Positive Integer
|
|
152
|
+
```yaml
|
|
153
|
+
quantity:
|
|
154
|
+
type: Int
|
|
155
|
+
rules:
|
|
156
|
+
min: 0
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Percentage (0-100)
|
|
160
|
+
```yaml
|
|
161
|
+
discount:
|
|
162
|
+
type: Int
|
|
163
|
+
rules:
|
|
164
|
+
between: [0, 100]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Price with Step
|
|
168
|
+
```yaml
|
|
169
|
+
price:
|
|
170
|
+
type: Decimal
|
|
171
|
+
precision: 10
|
|
172
|
+
scale: 2
|
|
173
|
+
rules:
|
|
174
|
+
min: 0
|
|
175
|
+
multipleOf: 0.01
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## See Also
|
|
179
|
+
|
|
180
|
+
- `omnify-schema.mdc` - Full schema reference
|
|
181
|
+
- `schema-create.mdc` - Creating new schemas
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Backend Guides
|
|
2
|
+
|
|
3
|
+
> Laravel 12, PHP 8.4, MySQL 8
|
|
4
|
+
|
|
5
|
+
## Quick Navigation
|
|
6
|
+
|
|
7
|
+
| Guide | Description |
|
|
8
|
+
| ------------------------------------ | --------------------------------------------- |
|
|
9
|
+
| [architecture.md](./architecture.md) | Design philosophy, when to use Service/Action |
|
|
10
|
+
| [controller.md](./controller.md) | Thin controller pattern, CRUD template |
|
|
11
|
+
| [request.md](./request.md) | Form validation, FormRequest |
|
|
12
|
+
| [resource.md](./resource.md) | API response format, dates |
|
|
13
|
+
| [service.md](./service.md) | When & how to use services |
|
|
14
|
+
| [testing.md](./testing.md) | PEST, 正常系/異常系 |
|
|
15
|
+
| [openapi.md](./openapi.md) | Swagger documentation |
|
|
16
|
+
| [datetime.md](./datetime.md) | Carbon, UTC handling |
|
|
17
|
+
|
|
18
|
+
## Related
|
|
19
|
+
|
|
20
|
+
| Topic | Location |
|
|
21
|
+
| ------------------------ | ----------------------------------------------------------- |
|
|
22
|
+
| **Security rules** | [/rules/security.md](../../rules/security.md) |
|
|
23
|
+
| **Performance rules** | [/rules/performance.md](../../rules/performance.md) |
|
|
24
|
+
| **Naming conventions** | [/rules/naming.md](../../rules/naming.md) |
|
|
25
|
+
| **Checklist** | [/checklists/backend.md](../../checklists/backend.md) |
|
|
26
|
+
| **New feature workflow** | [/workflows/new-feature.md](../../workflows/new-feature.md) |
|
|
27
|
+
|
|
28
|
+
## Quick Patterns
|
|
29
|
+
|
|
30
|
+
### Thin Controller
|
|
31
|
+
|
|
32
|
+
```php
|
|
33
|
+
public function store(UserStoreRequest $request): UserResource
|
|
34
|
+
{
|
|
35
|
+
return new UserResource(User::create($request->validated()));
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Resource with Dates
|
|
40
|
+
|
|
41
|
+
```php
|
|
42
|
+
public function toArray($request): array
|
|
43
|
+
{
|
|
44
|
+
return [
|
|
45
|
+
'id' => $this->id,
|
|
46
|
+
'name' => $this->name,
|
|
47
|
+
'created_at' => $this->created_at?->toISOString(),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### When to Use What
|
|
53
|
+
|
|
54
|
+
| Question | Answer |
|
|
55
|
+
| -------------------------- | --------------- |
|
|
56
|
+
| Simple CRUD? | Controller only |
|
|
57
|
+
| Multi-step business logic? | Service |
|
|
58
|
+
| Single reusable action? | Action class |
|
|
59
|
+
| Async task? | Job |
|