@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,353 @@
|
|
|
1
|
+
# Partial Schema Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Partial schemas (`kind: partial`) allow packages to extend or provide default schemas without modifying main application files.
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
# packages/sso-client/schemas/User.yaml
|
|
9
|
+
kind: partial
|
|
10
|
+
priority: 10
|
|
11
|
+
|
|
12
|
+
properties:
|
|
13
|
+
sso_token:
|
|
14
|
+
type: String
|
|
15
|
+
nullable: true
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Key Concepts
|
|
19
|
+
|
|
20
|
+
### Target is Inferred from Filename
|
|
21
|
+
|
|
22
|
+
**No `target` field needed.** The target schema is determined by the filename:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
User.yaml → targets User schema
|
|
26
|
+
Permission.yaml → targets Permission schema
|
|
27
|
+
Team.yaml → targets Team schema
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Merge Behavior
|
|
31
|
+
|
|
32
|
+
| Scenario | Result |
|
|
33
|
+
| --------------------------------------------------------------- | --------------------------- |
|
|
34
|
+
| Main app has `User.yaml` + Package has `User.yaml` (partial) | Merge into main User |
|
|
35
|
+
| Main app has NO `User.yaml` + Package has `User.yaml` (partial) | Partial becomes User schema |
|
|
36
|
+
| Multiple packages have `User.yaml` (partial) | Merge via priority |
|
|
37
|
+
|
|
38
|
+
## Priority System
|
|
39
|
+
|
|
40
|
+
Lower number = Higher priority = Merged first = Wins conflicts
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
kind: partial
|
|
44
|
+
priority: 10 # High priority (1-49)
|
|
45
|
+
priority: 50 # Default priority
|
|
46
|
+
priority: 90 # Low priority (51-100)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Priority Ranges
|
|
50
|
+
|
|
51
|
+
| Range | Use For |
|
|
52
|
+
| ------ | ------------------------- |
|
|
53
|
+
| 1-20 | Core system packages |
|
|
54
|
+
| 21-40 | Feature modules |
|
|
55
|
+
| 41-60 | Business logic extensions |
|
|
56
|
+
| 61-80 | Tenant customizations |
|
|
57
|
+
| 81-100 | Development/testing |
|
|
58
|
+
|
|
59
|
+
## Use Cases
|
|
60
|
+
|
|
61
|
+
### 1. Package Provides Default Schema
|
|
62
|
+
|
|
63
|
+
SSO package provides default User schema if main app has none:
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
# packages/sso-client/schemas/User.yaml
|
|
67
|
+
kind: partial
|
|
68
|
+
priority: 10
|
|
69
|
+
|
|
70
|
+
displayName:
|
|
71
|
+
ja: ユーザー
|
|
72
|
+
en: User
|
|
73
|
+
|
|
74
|
+
options:
|
|
75
|
+
timestamps: true
|
|
76
|
+
authenticatable: true
|
|
77
|
+
|
|
78
|
+
properties:
|
|
79
|
+
email:
|
|
80
|
+
type: Email
|
|
81
|
+
unique: true
|
|
82
|
+
name:
|
|
83
|
+
type: String
|
|
84
|
+
console_user_id:
|
|
85
|
+
type: BigInt
|
|
86
|
+
nullable: true
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Result:**
|
|
90
|
+
- Apps WITH existing User.yaml → SSO fields merge into their User
|
|
91
|
+
- Apps WITHOUT User.yaml → Package's User becomes the User schema
|
|
92
|
+
|
|
93
|
+
### 2. Package Extends Existing Schema
|
|
94
|
+
|
|
95
|
+
Add fields to main app's User:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
# packages/billing/schemas/User.yaml
|
|
99
|
+
kind: partial
|
|
100
|
+
priority: 50
|
|
101
|
+
|
|
102
|
+
properties:
|
|
103
|
+
stripe_customer_id:
|
|
104
|
+
type: String
|
|
105
|
+
nullable: true
|
|
106
|
+
subscription_status:
|
|
107
|
+
type: String
|
|
108
|
+
nullable: true
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Result:** User schema has all original properties + billing properties
|
|
112
|
+
|
|
113
|
+
### 3. Multiple Packages Extend Same Schema
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
Main App: schemas/auth/User.yaml (regular schema)
|
|
117
|
+
├─ SSO Package: User.yaml (partial, priority: 10)
|
|
118
|
+
└─ Billing Package: User.yaml (partial, priority: 50)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Merge Order:**
|
|
122
|
+
1. SSO Package (priority 10) merges first
|
|
123
|
+
2. Billing Package (priority 50) merges second
|
|
124
|
+
3. Main app properties always win over partials
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
### omnify.config.ts
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const config: OmnifyConfig = {
|
|
132
|
+
schemasDir: './schemas',
|
|
133
|
+
|
|
134
|
+
additionalSchemaPaths: [
|
|
135
|
+
{
|
|
136
|
+
path: './packages/sso-client/database/schemas',
|
|
137
|
+
namespace: 'Sso',
|
|
138
|
+
// Optional: Package-specific output
|
|
139
|
+
output: {
|
|
140
|
+
laravel: {
|
|
141
|
+
base: './packages/sso-client',
|
|
142
|
+
modelsNamespace: 'Vendor\\SsoClient\\Models',
|
|
143
|
+
modelsPath: 'src/Models',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
};
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## File Structure Examples
|
|
152
|
+
|
|
153
|
+
### Package with Partial Schemas
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
packages/sso-client/
|
|
157
|
+
├── database/
|
|
158
|
+
│ └── schemas/
|
|
159
|
+
│ ├── User.yaml # kind: partial (extends/provides User)
|
|
160
|
+
│ ├── Permission.yaml # kind: partial (provides Permission)
|
|
161
|
+
│ ├── Role.yaml # regular schema (package-only)
|
|
162
|
+
│ └── RolePermission.yaml
|
|
163
|
+
├── src/
|
|
164
|
+
│ └── Models/
|
|
165
|
+
└── composer.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Main App Schemas
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
schemas/
|
|
172
|
+
├── auth/
|
|
173
|
+
│ └── User.yaml # Main User schema (takes priority)
|
|
174
|
+
├── blog/
|
|
175
|
+
│ ├── Post.yaml
|
|
176
|
+
│ └── Comment.yaml
|
|
177
|
+
└── shop/
|
|
178
|
+
└── Product.yaml
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Property Merge Rules
|
|
182
|
+
|
|
183
|
+
| Scenario | Result |
|
|
184
|
+
| ----------------------------- | ---------------------------- |
|
|
185
|
+
| Property only in main | Main property used |
|
|
186
|
+
| Property only in partial | Partial property added |
|
|
187
|
+
| Property in both | **Main wins** |
|
|
188
|
+
| Property in multiple partials | Higher priority partial wins |
|
|
189
|
+
|
|
190
|
+
### Example: Property Conflict
|
|
191
|
+
|
|
192
|
+
```yaml
|
|
193
|
+
# Main app User.yaml
|
|
194
|
+
properties:
|
|
195
|
+
name:
|
|
196
|
+
type: String
|
|
197
|
+
length: 100
|
|
198
|
+
|
|
199
|
+
# Package User.yaml (partial)
|
|
200
|
+
properties:
|
|
201
|
+
name: # Same property!
|
|
202
|
+
type: Text # Different type
|
|
203
|
+
nullable: true
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Result:** `name` remains `String(100)` from main app
|
|
207
|
+
|
|
208
|
+
## What Partials Can Define
|
|
209
|
+
|
|
210
|
+
| ✅ Allowed | ❌ Not Allowed |
|
|
211
|
+
| ----------- | ------------------ |
|
|
212
|
+
| properties | options.id |
|
|
213
|
+
| displayName | options.timestamps |
|
|
214
|
+
| priority | options.softDelete |
|
|
215
|
+
| - | options.tableName |
|
|
216
|
+
|
|
217
|
+
## Best Practices
|
|
218
|
+
|
|
219
|
+
### 1. Use Descriptive Filenames
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
✅ User.yaml # Clear: extends/provides User
|
|
223
|
+
✅ Permission.yaml # Clear: extends/provides Permission
|
|
224
|
+
❌ UserExtension.yaml # Confusing (targets UserExtension, not User)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 2. Prefix Package-Specific Fields
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# ✅ Good: Unique, prefixed names
|
|
231
|
+
sso_token:
|
|
232
|
+
billing_status:
|
|
233
|
+
console_user_id:
|
|
234
|
+
|
|
235
|
+
# ❌ Bad: Generic names that might conflict
|
|
236
|
+
token:
|
|
237
|
+
status:
|
|
238
|
+
user_id:
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 3. Document Dependencies
|
|
242
|
+
|
|
243
|
+
```yaml
|
|
244
|
+
# User.yaml
|
|
245
|
+
# Package: @famgia/sso-client
|
|
246
|
+
# Requires: Role schema from same package
|
|
247
|
+
# Priority: 10 (core system)
|
|
248
|
+
|
|
249
|
+
kind: partial
|
|
250
|
+
priority: 10
|
|
251
|
+
|
|
252
|
+
properties:
|
|
253
|
+
role:
|
|
254
|
+
type: Association
|
|
255
|
+
relation: ManyToOne
|
|
256
|
+
target: Role
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 4. Keep Partials Focused
|
|
260
|
+
|
|
261
|
+
```yaml
|
|
262
|
+
# ✅ Good: Single responsibility
|
|
263
|
+
# sso-client/User.yaml - Only SSO fields
|
|
264
|
+
kind: partial
|
|
265
|
+
properties:
|
|
266
|
+
sso_token:
|
|
267
|
+
type: String
|
|
268
|
+
console_user_id:
|
|
269
|
+
type: BigInt
|
|
270
|
+
|
|
271
|
+
# ❌ Bad: Mixed responsibilities
|
|
272
|
+
# Don't put billing + SSO + notifications in one partial
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Troubleshooting
|
|
276
|
+
|
|
277
|
+
### Partial Not Merging
|
|
278
|
+
|
|
279
|
+
**Problem:** Package partial not appearing in generated model
|
|
280
|
+
|
|
281
|
+
**Check:**
|
|
282
|
+
1. Package path in `additionalSchemaPaths`?
|
|
283
|
+
2. Filename matches target? (User.yaml → User)
|
|
284
|
+
3. `kind: partial` set correctly?
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Verify schemas loaded
|
|
288
|
+
npx omnify generate --verbose
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Property Conflict
|
|
292
|
+
|
|
293
|
+
**Problem:** Partial property being ignored
|
|
294
|
+
|
|
295
|
+
**Reason:** Main app has same property (main always wins)
|
|
296
|
+
|
|
297
|
+
**Solution:**
|
|
298
|
+
- Use different property name in partial
|
|
299
|
+
- Or remove from main app if partial should own it
|
|
300
|
+
|
|
301
|
+
### Priority Not Working
|
|
302
|
+
|
|
303
|
+
**Problem:** Wrong partial winning in conflict
|
|
304
|
+
|
|
305
|
+
**Check:**
|
|
306
|
+
```yaml
|
|
307
|
+
# Lower number = higher priority
|
|
308
|
+
priority: 10 # Wins over
|
|
309
|
+
priority: 50 # This one
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Generate Output
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
npx omnify generate
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Console shows:**
|
|
319
|
+
```
|
|
320
|
+
→ Loading schemas from /app/schemas
|
|
321
|
+
→ Loading schemas from 1 additional path(s)
|
|
322
|
+
• ./packages/sso-client/schemas [Sso]: 2 schema(s) + 2 partial(s)
|
|
323
|
+
→ Validating schemas...
|
|
324
|
+
✓ Generation complete!
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Quick Reference
|
|
328
|
+
|
|
329
|
+
```yaml
|
|
330
|
+
# Minimal partial schema
|
|
331
|
+
kind: partial
|
|
332
|
+
properties:
|
|
333
|
+
new_field:
|
|
334
|
+
type: String
|
|
335
|
+
|
|
336
|
+
# Full partial schema
|
|
337
|
+
kind: partial
|
|
338
|
+
priority: 10
|
|
339
|
+
|
|
340
|
+
displayName:
|
|
341
|
+
ja: 拡張
|
|
342
|
+
en: Extension
|
|
343
|
+
|
|
344
|
+
properties:
|
|
345
|
+
field1:
|
|
346
|
+
type: String
|
|
347
|
+
displayName:
|
|
348
|
+
ja: フィールド1
|
|
349
|
+
en: Field 1
|
|
350
|
+
field2:
|
|
351
|
+
type: Int
|
|
352
|
+
nullable: true
|
|
353
|
+
```
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Omnify React Form Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to build forms using Omnify generated schemas with **Ant Design** and **TanStack Query**.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Install the runtime package:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @famgia/omnify-react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// omnify.config.ts
|
|
15
|
+
import typescriptPlugin from '@famgia/omnify-typescript/plugin';
|
|
16
|
+
|
|
17
|
+
export default defineConfig({
|
|
18
|
+
plugins: [
|
|
19
|
+
typescriptPlugin({
|
|
20
|
+
modelsPath: 'node_modules/.omnify/schemas',
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { Form, Button } from 'antd';
|
|
30
|
+
import {
|
|
31
|
+
useFormMutation,
|
|
32
|
+
JapaneseNameField,
|
|
33
|
+
setZodLocale,
|
|
34
|
+
zodRule,
|
|
35
|
+
} from '@famgia/omnify-react';
|
|
36
|
+
import { customerSchemas, customerI18n, type CustomerCreate } from './.omnify/schemas';
|
|
37
|
+
import { api } from '@/lib/api';
|
|
38
|
+
|
|
39
|
+
function CreateCustomerPage() {
|
|
40
|
+
const [form] = Form.useForm<CustomerCreate>();
|
|
41
|
+
setZodLocale('ja');
|
|
42
|
+
|
|
43
|
+
const mutation = useFormMutation<CustomerCreate>({
|
|
44
|
+
form,
|
|
45
|
+
mutationFn: (data) => api.post('/customers', data),
|
|
46
|
+
invalidateKeys: [['customers']],
|
|
47
|
+
successMessage: 'Customer created successfully',
|
|
48
|
+
onSuccess: () => form.resetFields(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Form form={form} onFinish={mutation.mutate}>
|
|
53
|
+
<JapaneseNameField
|
|
54
|
+
schemas={customerSchemas}
|
|
55
|
+
i18n={customerI18n}
|
|
56
|
+
prefix="name"
|
|
57
|
+
showKana
|
|
58
|
+
/>
|
|
59
|
+
<Button loading={mutation.isPending}>Save</Button>
|
|
60
|
+
</Form>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## useFormMutation Hook
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useFormMutation } from '@famgia/omnify-react';
|
|
69
|
+
|
|
70
|
+
const mutation = useFormMutation<CustomerCreate>({
|
|
71
|
+
form,
|
|
72
|
+
mutationFn: (data) => api.post('/customers', data),
|
|
73
|
+
invalidateKeys: [['customers']],
|
|
74
|
+
successMessage: 'Saved successfully',
|
|
75
|
+
onSuccess: () => form.resetFields(),
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Options
|
|
80
|
+
|
|
81
|
+
| Option | Type | Description |
|
|
82
|
+
| ---------------- | ---------------------- | ----------------------------------- |
|
|
83
|
+
| `form` | `FormInstance<T>` | Ant Design form instance (required) |
|
|
84
|
+
| `mutationFn` | `(data: T) => Promise` | API call function (required) |
|
|
85
|
+
| `invalidateKeys` | `string[][]` | Query keys to invalidate on success |
|
|
86
|
+
| `successMessage` | `string` | Toast message on success |
|
|
87
|
+
| `onSuccess` | `(data) => void` | Callback after success |
|
|
88
|
+
| `onError` | `(error) => void` | Callback after error |
|
|
89
|
+
|
|
90
|
+
### Laravel Error Handling
|
|
91
|
+
|
|
92
|
+
The hook automatically handles Laravel validation errors (422):
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"message": "The given data was invalid.",
|
|
97
|
+
"errors": {
|
|
98
|
+
"email": ["The email has already been taken."]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Japanese Form Components
|
|
104
|
+
|
|
105
|
+
### JapaneseNameField
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { JapaneseNameField } from '@famgia/omnify-react';
|
|
109
|
+
|
|
110
|
+
<JapaneseNameField
|
|
111
|
+
schemas={customerSchemas}
|
|
112
|
+
i18n={customerI18n}
|
|
113
|
+
prefix="name" // name_lastname, name_firstname, etc.
|
|
114
|
+
required // Show required asterisk
|
|
115
|
+
showKana={true} // Show kana fields (default)
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Fields:** `{prefix}_lastname`, `{prefix}_firstname`, `{prefix}_kana_lastname`, `{prefix}_kana_firstname`
|
|
120
|
+
|
|
121
|
+
### JapaneseAddressField
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { JapaneseAddressField } from '@famgia/omnify-react';
|
|
125
|
+
|
|
126
|
+
<JapaneseAddressField
|
|
127
|
+
form={form}
|
|
128
|
+
schemas={customerSchemas}
|
|
129
|
+
i18n={customerI18n}
|
|
130
|
+
prefix="address"
|
|
131
|
+
prefectureOptions={prefectureOptions} // Required for Select
|
|
132
|
+
enablePostalLookup={true} // Postal code → address lookup
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Fields:** `{prefix}_postal_code`, `{prefix}_prefecture`, `{prefix}_address1`, `{prefix}_address2`, `{prefix}_address3`
|
|
137
|
+
|
|
138
|
+
**Options:**
|
|
139
|
+
- `prefectureOptions` - Select options for prefecture dropdown
|
|
140
|
+
- `enablePostalLookup` - Enable postal code search
|
|
141
|
+
- `autoSearch` - Auto-search when 7 digits entered
|
|
142
|
+
- `usePrefectureId` - Use numeric ID instead of string enum
|
|
143
|
+
|
|
144
|
+
### JapaneseBankField
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { JapaneseBankField } from '@famgia/omnify-react';
|
|
148
|
+
|
|
149
|
+
<JapaneseBankField
|
|
150
|
+
schemas={customerSchemas}
|
|
151
|
+
i18n={customerI18n}
|
|
152
|
+
prefix="bank"
|
|
153
|
+
accountTypeOptions={accountTypeOptions} // Required for Select
|
|
154
|
+
/>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Fields:** `{prefix}_bank_code`, `{prefix}_branch_code`, `{prefix}_account_type`, `{prefix}_account_number`, `{prefix}_account_holder`
|
|
158
|
+
|
|
159
|
+
## Zod Validation with i18n
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { zodRule, setZodLocale } from '@famgia/omnify-react';
|
|
163
|
+
|
|
164
|
+
// Set locale once at component level
|
|
165
|
+
setZodLocale('ja');
|
|
166
|
+
|
|
167
|
+
// Use zodRule for field validation
|
|
168
|
+
<Form.Item
|
|
169
|
+
name="email"
|
|
170
|
+
label="メールアドレス"
|
|
171
|
+
rules={[zodRule(customerSchemas.email, 'メールアドレス')]}
|
|
172
|
+
>
|
|
173
|
+
<Input />
|
|
174
|
+
</Form.Item>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Kana Validation Rules
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { kanaString, KATAKANA_PATTERN } from '@famgia/omnify-react';
|
|
181
|
+
|
|
182
|
+
// Full-width katakana (default)
|
|
183
|
+
const kanaSchema = kanaString();
|
|
184
|
+
|
|
185
|
+
// Custom options
|
|
186
|
+
const kanaSchema = kanaString({
|
|
187
|
+
fullWidthKatakana: true,
|
|
188
|
+
hiragana: true,
|
|
189
|
+
allowNumbers: true,
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Kana Presets
|
|
194
|
+
|
|
195
|
+
| Preset | Description |
|
|
196
|
+
| ----------------------- | ---------------------- |
|
|
197
|
+
| `KATAKANA_FULL_WIDTH` | 全角カタカナ (default) |
|
|
198
|
+
| `KATAKANA_HALF_WIDTH` | 半角カタカナ |
|
|
199
|
+
| `HIRAGANA` | ひらがな |
|
|
200
|
+
| `KANA_ANY` | All kana types |
|
|
201
|
+
| `KATAKANA_WITH_NUMBERS` | カタカナ + numbers |
|
|
202
|
+
|
|
203
|
+
## File Structure
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
node_modules/
|
|
207
|
+
├── @famgia/omnify-react/ # Runtime package (npm)
|
|
208
|
+
│ ├── components/ # JapaneseNameField, etc.
|
|
209
|
+
│ ├── hooks/ # useFormMutation
|
|
210
|
+
│ └── lib/ # zodRule, kanaString, etc.
|
|
211
|
+
└── .omnify/ # Generated (regeneratable)
|
|
212
|
+
├── schemas/
|
|
213
|
+
│ ├── Customer.ts
|
|
214
|
+
│ └── Post.ts
|
|
215
|
+
└── enum/
|
|
216
|
+
└── PostStatus.ts
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Tips
|
|
220
|
+
|
|
221
|
+
1. **Use type generics** - `useFormMutation<CustomerCreate>` for type safety
|
|
222
|
+
2. **Use `setZodLocale`** - Call once for localized validation messages
|
|
223
|
+
3. **Use Japanese components** - Built-in i18n, validation, postal lookup
|
|
224
|
+
4. **Set `invalidateKeys`** - Auto-refresh lists after mutations
|
|
225
|
+
5. **Provide options for Select** - Components need `prefectureOptions` or `accountTypeOptions`
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Omnify Schema Guide
|
|
2
|
+
|
|
3
|
+
## Schema File Format
|
|
4
|
+
|
|
5
|
+
Schemas are YAML files defining data models. Each file represents one entity.
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
name: User
|
|
9
|
+
displayName:
|
|
10
|
+
ja: ユーザー
|
|
11
|
+
en: User
|
|
12
|
+
kind: object
|
|
13
|
+
|
|
14
|
+
properties:
|
|
15
|
+
email:
|
|
16
|
+
type: Email
|
|
17
|
+
unique: true
|
|
18
|
+
name:
|
|
19
|
+
type: String
|
|
20
|
+
bio:
|
|
21
|
+
type: Text
|
|
22
|
+
nullable: true
|
|
23
|
+
|
|
24
|
+
options:
|
|
25
|
+
timestamps: true
|
|
26
|
+
softDelete: true
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Property Types
|
|
30
|
+
|
|
31
|
+
### String Types
|
|
32
|
+
- `String` - VARCHAR(255)
|
|
33
|
+
- `Text` - TEXT
|
|
34
|
+
- `LongText` - LONGTEXT
|
|
35
|
+
- `Email` - VARCHAR(255) for email addresses
|
|
36
|
+
- `Password` - VARCHAR(255), hidden in serialization
|
|
37
|
+
|
|
38
|
+
### Numeric Types
|
|
39
|
+
- `Int` - INTEGER
|
|
40
|
+
- `BigInt` - BIGINT
|
|
41
|
+
- `TinyInt` - TINYINT
|
|
42
|
+
- `Float` - DOUBLE
|
|
43
|
+
- `Decimal` - DECIMAL(precision, scale)
|
|
44
|
+
|
|
45
|
+
### Date/Time Types
|
|
46
|
+
- `Date` - DATE
|
|
47
|
+
- `Time` - TIME
|
|
48
|
+
- `DateTime` - DATETIME
|
|
49
|
+
- `Timestamp` - TIMESTAMP
|
|
50
|
+
|
|
51
|
+
### Other Types
|
|
52
|
+
- `Boolean` - BOOLEAN
|
|
53
|
+
- `Json` - JSON
|
|
54
|
+
- `Enum` - ENUM with values
|
|
55
|
+
- `EnumRef` - Reference to enum schema
|
|
56
|
+
|
|
57
|
+
## Property Options
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
propertyName:
|
|
61
|
+
type: String
|
|
62
|
+
nullable: true # Can be NULL
|
|
63
|
+
unique: true # Unique constraint
|
|
64
|
+
default: "value" # Default value
|
|
65
|
+
length: 100 # VARCHAR length
|
|
66
|
+
hidden: true # Hide from JSON output
|
|
67
|
+
fillable: false # Exclude from mass assignment
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## ⚠️ Default Value Rules
|
|
71
|
+
|
|
72
|
+
**DB functions NOT allowed in default:**
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
# ❌ WRONG
|
|
76
|
+
failed_at:
|
|
77
|
+
type: Timestamp
|
|
78
|
+
default: CURRENT_TIMESTAMP # ERROR!
|
|
79
|
+
|
|
80
|
+
# ✅ CORRECT
|
|
81
|
+
failed_at:
|
|
82
|
+
type: Timestamp
|
|
83
|
+
useCurrent: true # = CURRENT_TIMESTAMP
|
|
84
|
+
|
|
85
|
+
updated_at:
|
|
86
|
+
type: Timestamp
|
|
87
|
+
useCurrent: true
|
|
88
|
+
useCurrentOnUpdate: true # ON UPDATE CURRENT_TIMESTAMP
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Type | Valid Default | Invalid |
|
|
92
|
+
|------|---------------|---------|
|
|
93
|
+
| Int | 0, 100, -1 | AUTO_INCREMENT, RAND() |
|
|
94
|
+
| Date | 2024-01-01 | CURRENT_DATE |
|
|
95
|
+
| Time | 14:30:00 | CURRENT_TIME |
|
|
96
|
+
| Timestamp | use `useCurrent` | CURRENT_TIMESTAMP |
|
|
97
|
+
| Uuid | static UUID | UUID() |
|
|
98
|
+
|
|
99
|
+
## Associations
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
# Many-to-One (belongsTo)
|
|
103
|
+
author:
|
|
104
|
+
type: Association
|
|
105
|
+
relation: ManyToOne
|
|
106
|
+
target: User
|
|
107
|
+
onDelete: CASCADE
|
|
108
|
+
|
|
109
|
+
# One-to-Many (hasMany)
|
|
110
|
+
posts:
|
|
111
|
+
type: Association
|
|
112
|
+
relation: OneToMany
|
|
113
|
+
target: Post
|
|
114
|
+
|
|
115
|
+
# Many-to-Many (belongsToMany)
|
|
116
|
+
tags:
|
|
117
|
+
type: Association
|
|
118
|
+
relation: ManyToMany
|
|
119
|
+
target: Tag
|
|
120
|
+
joinTable: post_tags
|
|
121
|
+
|
|
122
|
+
# Polymorphic
|
|
123
|
+
commentable:
|
|
124
|
+
type: Association
|
|
125
|
+
relation: MorphTo
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Indexes
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
indexes:
|
|
132
|
+
- columns: [status, published_at]
|
|
133
|
+
- columns: [email]
|
|
134
|
+
unique: true
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Schema Options
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
options:
|
|
141
|
+
timestamps: true # Add created_at, updated_at
|
|
142
|
+
softDelete: true # Add deleted_at
|
|
143
|
+
idType: BigInt # Primary key type (Int, BigInt, Uuid)
|
|
144
|
+
```
|