@famgia/omnify-laravel 0.0.89 → 0.0.90

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/dist/plugin.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  laravelPlugin
3
- } from "./chunk-V7LWJ6OM.js";
3
+ } from "./chunk-2QSKZS63.js";
4
4
  export {
5
5
  laravelPlugin as default,
6
6
  laravelPlugin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@famgia/omnify-laravel",
3
- "version": "0.0.89",
3
+ "version": "0.0.90",
4
4
  "description": "Laravel migration and TypeScript type generator for omnify-schema",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,9 +25,9 @@
25
25
  "README.md"
26
26
  ],
27
27
  "dependencies": {
28
- "@famgia/omnify-types": "0.0.78",
29
- "@famgia/omnify-atlas": "0.0.74",
30
- "@famgia/omnify-core": "0.0.80"
28
+ "@famgia/omnify-types": "0.0.79",
29
+ "@famgia/omnify-core": "0.0.81",
30
+ "@famgia/omnify-atlas": "0.0.75"
31
31
  },
32
32
  "scripts": {
33
33
  "build": "tsup",
@@ -0,0 +1,95 @@
1
+ # .claude/omnify Documentation
2
+
3
+ > AI-focused documentation for Omnify projects. Navigate by PURPOSE.
4
+
5
+ ## Quick Navigation
6
+
7
+ | Purpose | Folder | When to Read |
8
+ | ------------------------ | ---------------------------- | --------------------------------- |
9
+ | **AI Personas** | [agents/](./agents/) | Select agent for task |
10
+ | **HOW to do tasks** | [workflows/](./workflows/) | New feature, bug fix, code review |
11
+ | **WHAT rules to follow** | [rules/](./rules/) | Security, performance, naming |
12
+ | **HOW to implement** | [guides/](./guides/) | Controller, Resource, Testing |
13
+ | **Quick verify** | [checklists/](./checklists/) | Before commit, PR review |
14
+
15
+ ## Agents
16
+
17
+ | Agent | Role | When to Use |
18
+ | ----------------------------------- | -------------- | ------------------------- |
19
+ | [@developer](./agents/developer.md) | Implementation | Writing code, features |
20
+ | [@reviewer](./agents/reviewer.md) | Code Review | PR review, security audit |
21
+ | [@architect](./agents/architect.md) | System Design | Schema, API design |
22
+ | [@tester](./agents/tester.md) | Testing | Writing tests |
23
+
24
+ ---
25
+
26
+ ## Structure
27
+
28
+ ```
29
+ .claude/omnify/
30
+ ├── agents/ # AI Personas (WHO)
31
+ │ ├── developer.md # Implementation agent
32
+ │ ├── reviewer.md # Code review agent
33
+ │ ├── architect.md # System design agent
34
+ │ └── tester.md # Testing agent
35
+
36
+ ├── workflows/ # Step-by-step processes (HOW)
37
+ │ ├── new-feature.md # Create new feature
38
+ │ ├── bug-fix.md # Fix a bug
39
+ │ └── code-review.md # Review PR
40
+
41
+ ├── rules/ # Must-follow rules (WHAT)
42
+ │ ├── security.md # Security rules
43
+ │ ├── performance.md # Performance & quality rules
44
+ │ └── naming.md # Naming conventions
45
+
46
+ ├── guides/ # Implementation guides (REFERENCE)
47
+ │ ├── omnify/ # Omnify tool documentation
48
+ │ ├── laravel/ # Laravel implementation
49
+ │ └── react/ # React implementation
50
+
51
+ └── checklists/ # Quick verification (QA)
52
+ ├── backend.md
53
+ └── react.md
54
+ ```
55
+
56
+ ---
57
+
58
+ ## By Task Type
59
+
60
+ ### New Feature
61
+
62
+ 1. Read [workflows/new-feature.md](./workflows/new-feature.md)
63
+ 2. Follow step-by-step: Schema → API → Tests → OpenAPI → Frontend
64
+
65
+ ### Bug Fix
66
+
67
+ 1. Read [workflows/bug-fix.md](./workflows/bug-fix.md)
68
+ 2. Reproduce → Locate → Test → Fix → Verify
69
+
70
+ ### Code Review
71
+
72
+ 1. Read [workflows/code-review.md](./workflows/code-review.md)
73
+ 2. Security → Performance → Quality → Tests → Approve
74
+
75
+ ---
76
+
77
+ ## Debugging Quick Reference
78
+
79
+ | Issue | Check |
80
+ | ---------------------- | ------------------------------ |
81
+ | API returns wrong data | `guides/laravel/resource.md` |
82
+ | Validation fails | `guides/laravel/request.md` |
83
+ | 404 error | Route + Model binding |
84
+ | N+1 queries | `rules/performance.md` |
85
+ | Security concern | `rules/security.md` |
86
+
87
+ ---
88
+
89
+ ## Key Principles
90
+
91
+ 1. **Schema-First**: Start with `schemas/` folder
92
+ 2. **Thin Controllers**: Validate → Delegate → Respond
93
+ 3. **UTC Everywhere**: Store UTC, send ISO 8601
94
+ 4. **Test Everything**: 正常系 + 異常系
95
+ 5. **Don't Over-Engineer**: Simple CRUD = Controller + Model
@@ -0,0 +1,259 @@
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
+ ## Quick Start
6
+
7
+ ```tsx
8
+ import { Form } from 'antd';
9
+ import { useFormMutation } from '@/omnify/hooks';
10
+ import { type CustomerCreate } from '@/omnify/schemas';
11
+ import { CustomerForm } from '@/features/customers';
12
+ import { api } from '@/lib/api';
13
+
14
+ function CreateCustomerPage() {
15
+ const [form] = Form.useForm<CustomerCreate>();
16
+
17
+ const mutation = useFormMutation<CustomerCreate>({
18
+ form,
19
+ mutationFn: (data) => api.post('/customers', data),
20
+ invalidateKeys: [['customers']],
21
+ successMessage: 'Customer created successfully',
22
+ onSuccess: () => form.resetFields(),
23
+ });
24
+
25
+ return (
26
+ <CustomerForm
27
+ form={form}
28
+ onSubmit={mutation.mutate}
29
+ loading={mutation.isPending}
30
+ />
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## useFormMutation Hook
36
+
37
+ Location: `resources/ts/omnify/hooks/use-form-mutation.ts`
38
+
39
+ ### Usage with Types
40
+
41
+ ```tsx
42
+ import { useFormMutation } from '@/omnify/hooks';
43
+ import { type CustomerCreate } from '@/omnify/schemas';
44
+
45
+ // With type parameter for type safety
46
+ const mutation = useFormMutation<CustomerCreate>({
47
+ form,
48
+ mutationFn: (data) => api.post('/customers', data),
49
+ invalidateKeys: [['customers']],
50
+ successMessage: 'Saved successfully',
51
+ onSuccess: () => form.resetFields(),
52
+ });
53
+ ```
54
+
55
+ ### Options
56
+
57
+ | Option | Type | Description |
58
+ |--------|------|-------------|
59
+ | `form` | `FormInstance<T>` | Ant Design form instance (required) |
60
+ | `mutationFn` | `(data: T) => Promise` | API call function (required) |
61
+ | `invalidateKeys` | `string[][]` | Query keys to invalidate on success |
62
+ | `successMessage` | `string` | Toast message on success |
63
+ | `onSuccess` | `(data) => void` | Callback after success |
64
+ | `onError` | `(error) => void` | Callback after error |
65
+
66
+ ### Laravel Error Handling
67
+
68
+ The hook automatically handles Laravel validation errors (422):
69
+
70
+ ```json
71
+ {
72
+ "message": "The given data was invalid.",
73
+ "errors": {
74
+ "email": ["The email has already been taken."]
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Japanese Form Components
80
+
81
+ Omnify provides specialized components for Japanese data input.
82
+
83
+ ### OmnifyForm.JapaneseName
84
+
85
+ ```tsx
86
+ import { OmnifyForm } from '@/omnify/components';
87
+
88
+ <OmnifyForm.JapaneseName
89
+ schemas={customerSchemas}
90
+ i18n={customerI18n}
91
+ prefix="name" // name_lastname, name_firstname, etc.
92
+ required // Show required asterisk
93
+ showKana={true} // Show kana fields (default)
94
+ />
95
+ ```
96
+
97
+ **Fields:** `{prefix}_lastname`, `{prefix}_firstname`, `{prefix}_kana_lastname`, `{prefix}_kana_firstname`
98
+
99
+ ### OmnifyForm.JapaneseAddress
100
+
101
+ ```tsx
102
+ import { OmnifyForm } from '@/omnify/components';
103
+
104
+ <OmnifyForm.JapaneseAddress
105
+ form={form}
106
+ schemas={customerSchemas}
107
+ i18n={customerI18n}
108
+ prefix="address"
109
+ enablePostalLookup={true} // Postal code → address lookup
110
+ />
111
+ ```
112
+
113
+ **Fields:** `{prefix}_postal_code`, `{prefix}_prefecture`, `{prefix}_address1`, `{prefix}_address2`, `{prefix}_address3`
114
+
115
+ **Options:**
116
+ - `enablePostalLookup` - Enable postal code search
117
+ - `autoSearch` - Auto-search when 7 digits entered
118
+ - `usePrefectureId` - Use numeric ID instead of string enum
119
+
120
+ ### OmnifyForm.JapaneseBank
121
+
122
+ ```tsx
123
+ import { OmnifyForm } from '@/omnify/components';
124
+
125
+ <OmnifyForm.JapaneseBank
126
+ schemas={customerSchemas}
127
+ i18n={customerI18n}
128
+ prefix="bank"
129
+ />
130
+ ```
131
+
132
+ **Fields:** `{prefix}_bank_code`, `{prefix}_branch_code`, `{prefix}_account_type`, `{prefix}_account_number`, `{prefix}_account_holder`
133
+
134
+ Account type options auto-loaded from `BankAccountType` enum with i18n.
135
+
136
+ ## Complete Form Example
137
+
138
+ ```tsx
139
+ import { Form, Input, Button, Card, Space, Divider } from 'antd';
140
+ import type { FormInstance } from 'antd';
141
+ import { zodRule, setZodLocale } from '@/omnify/lib';
142
+ import { OmnifyForm } from '@/omnify/components';
143
+ import {
144
+ type Customer, type CustomerCreate,
145
+ customerSchemas, customerI18n,
146
+ getCustomerFieldLabel, getCustomerFieldPlaceholder,
147
+ } from '@/omnify/schemas';
148
+
149
+ const LOCALE = 'ja';
150
+
151
+ interface CustomerFormProps {
152
+ form: FormInstance<CustomerCreate>;
153
+ initialValues?: Partial<Customer>;
154
+ onSubmit: (values: CustomerCreate) => void;
155
+ loading?: boolean;
156
+ isEdit?: boolean;
157
+ }
158
+
159
+ export function CustomerForm({ form, initialValues, onSubmit, loading, isEdit }: CustomerFormProps) {
160
+ setZodLocale(LOCALE);
161
+
162
+ const label = (key: string) => getCustomerFieldLabel(key, LOCALE);
163
+ const placeholder = (key: string) => getCustomerFieldPlaceholder(key, LOCALE);
164
+ const rule = (key: keyof typeof customerSchemas) => zodRule(customerSchemas[key], label(key));
165
+
166
+ return (
167
+ <Card>
168
+ <Form form={form} layout="horizontal" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}
169
+ initialValues={initialValues} onFinish={onSubmit} style={{ maxWidth: 800 }}>
170
+
171
+ <Divider orientation="left">Name</Divider>
172
+ <OmnifyForm.JapaneseName schemas={customerSchemas} i18n={customerI18n} prefix="name" required />
173
+
174
+ <Divider orientation="left">Contact</Divider>
175
+ <Form.Item name="phone" label={label('phone')} rules={[rule('phone')]}>
176
+ <Input placeholder={placeholder('phone')} />
177
+ </Form.Item>
178
+ <Form.Item name="email" label={label('email')} rules={[rule('email')]}>
179
+ <Input type="email" placeholder={placeholder('email')} />
180
+ </Form.Item>
181
+
182
+ <Divider orientation="left">Address</Divider>
183
+ <OmnifyForm.JapaneseAddress form={form} schemas={customerSchemas} i18n={customerI18n}
184
+ prefix="address" enablePostalLookup={true} />
185
+
186
+ <Divider orientation="left">Bank Account</Divider>
187
+ <OmnifyForm.JapaneseBank schemas={customerSchemas} i18n={customerI18n} prefix="bank" />
188
+
189
+ <Form.Item wrapperCol={{ offset: 6, span: 18 }}>
190
+ <Space>
191
+ <Button type="primary" htmlType="submit" loading={loading}>
192
+ {isEdit ? 'Update' : 'Create'}
193
+ </Button>
194
+ </Space>
195
+ </Form.Item>
196
+ </Form>
197
+ </Card>
198
+ );
199
+ }
200
+ ```
201
+
202
+ ## Zod Validation with i18n
203
+
204
+ ```tsx
205
+ import { zodRule, setZodLocale } from '@/omnify/lib';
206
+
207
+ // Set locale once at component level
208
+ setZodLocale('ja');
209
+
210
+ // Use zodRule for field validation
211
+ <Form.Item name="email" label={label('email')} rules={[zodRule(customerSchemas.email, label('email'))]}>
212
+ <Input />
213
+ </Form.Item>
214
+ ```
215
+
216
+ ## Kana Validation Rules
217
+
218
+ ```tsx
219
+ import { kanaString, KATAKANA_PATTERN } from '@/omnify/lib/rules';
220
+
221
+ // Full-width katakana (default)
222
+ const kanaSchema = kanaString();
223
+
224
+ // Custom options
225
+ const kanaSchema = kanaString({
226
+ fullWidthKatakana: true,
227
+ hiragana: true,
228
+ allowNumbers: true,
229
+ });
230
+ ```
231
+
232
+ ## File Structure
233
+
234
+ ```
235
+ resources/ts/omnify/
236
+ ├── components/
237
+ │ ├── JapaneseNameField.tsx
238
+ │ ├── JapaneseAddressField.tsx
239
+ │ └── JapaneseBankField.tsx
240
+ ├── enum/
241
+ │ └── plugin/
242
+ │ ├── Prefecture.ts
243
+ │ └── BankAccountType.ts
244
+ ├── hooks/
245
+ │ └── use-form-mutation.ts
246
+ ├── lib/
247
+ │ ├── form-validation.ts
248
+ │ ├── zod-i18n.ts
249
+ │ └── rules/kana.ts
250
+ └── schemas/
251
+ ```
252
+
253
+ ## Tips
254
+
255
+ 1. **Use type generics** - `useFormMutation<CustomerCreate>` for type safety
256
+ 2. **Use `setZodLocale`** - Call once for localized validation messages
257
+ 3. **Use OmnifyForm.* components** - Built-in i18n, validation, postal lookup
258
+ 4. **Set `invalidateKeys`** - Auto-refresh lists after mutations
259
+ 5. **Don't pass `form` to Name/Bank components** - Only Address needs it for postal lookup
@@ -0,0 +1,58 @@
1
+ ---
2
+ description: "Omnify schema-driven code generation rules"
3
+ globs: ["schemas/**/*.yaml", "omnify.config.ts"]
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Omnify Schema Rules
8
+
9
+ This project uses Omnify for schema-driven code generation.
10
+
11
+ ## Documentation
12
+
13
+ Read these files in `.claude/omnify/guides/omnify/`:
14
+
15
+ | File | Content |
16
+ | --------------------- | -------------------------------- |
17
+ | `schema-guide.md` | Base schema format |
18
+ | `config-guide.md` | Configuration (omnify.config.ts) |
19
+ | `laravel-guide.md` | Laravel generator |
20
+ | `typescript-guide.md` | TypeScript generator |
21
+ | `japan-guide.md` | Japanese field types |
22
+
23
+ ## Commands
24
+
25
+ ```bash
26
+ npx omnify generate # Generate code from schemas
27
+ npx omnify validate # Validate all schemas
28
+ ```
29
+
30
+ ## Important
31
+
32
+ - **DO NOT** manually edit files in `database/migrations/omnify/`
33
+ - **DO NOT** manually edit files in `resources/ts/omnify/schemas/base/`
34
+ - **DO NOT** manually edit files in `app/Models/OmnifyBase/`
35
+ - Schema changes → Run `npx omnify generate`
36
+
37
+ ## Schema Quick Reference
38
+
39
+ ```yaml
40
+ name: User
41
+ displayName:
42
+ ja: ユーザー
43
+ en: User
44
+
45
+ properties:
46
+ email:
47
+ type: Email
48
+ unique: true
49
+ name:
50
+ type: String
51
+ role:
52
+ type: EnumRef
53
+ target: UserRole
54
+
55
+ options:
56
+ timestamps: true
57
+ softDelete: true
58
+ ```