@famgia/omnify-laravel 0.0.88 → 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.
Files changed (49) hide show
  1. package/dist/{chunk-YVVAJA3T.js → chunk-2QSKZS63.js} +188 -12
  2. package/dist/chunk-2QSKZS63.js.map +1 -0
  3. package/dist/index.cjs +190 -11
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +48 -1
  6. package/dist/index.d.ts +48 -1
  7. package/dist/index.js +5 -1
  8. package/dist/plugin.cjs +186 -11
  9. package/dist/plugin.cjs.map +1 -1
  10. package/dist/plugin.js +1 -1
  11. package/package.json +5 -5
  12. package/scripts/postinstall.js +29 -36
  13. package/stubs/ai-guides/README.md.stub +95 -0
  14. package/stubs/ai-guides/claude-agents/architect.md.stub +150 -0
  15. package/stubs/ai-guides/claude-agents/developer.md.stub +190 -0
  16. package/stubs/ai-guides/claude-agents/reviewer.md.stub +134 -0
  17. package/stubs/ai-guides/claude-agents/tester.md.stub +196 -0
  18. package/stubs/ai-guides/claude-checklists/backend.md.stub +112 -0
  19. package/stubs/ai-guides/claude-omnify/antdesign-guide.md.stub +401 -0
  20. package/stubs/ai-guides/claude-omnify/config-guide.md.stub +253 -0
  21. package/stubs/ai-guides/claude-omnify/japan-guide.md.stub +186 -0
  22. package/stubs/ai-guides/claude-omnify/laravel-guide.md.stub +61 -0
  23. package/stubs/ai-guides/claude-omnify/react-form-guide.md.stub +259 -0
  24. package/stubs/ai-guides/claude-omnify/schema-guide.md.stub +115 -0
  25. package/stubs/ai-guides/claude-omnify/typescript-guide.md.stub +310 -0
  26. package/stubs/ai-guides/claude-rules/naming.md.stub +364 -0
  27. package/stubs/ai-guides/claude-rules/performance.md.stub +251 -0
  28. package/stubs/ai-guides/claude-rules/security.md.stub +159 -0
  29. package/stubs/ai-guides/claude-workflows/bug-fix.md.stub +201 -0
  30. package/stubs/ai-guides/claude-workflows/code-review.md.stub +164 -0
  31. package/stubs/ai-guides/claude-workflows/new-feature.md.stub +327 -0
  32. package/stubs/ai-guides/cursor/laravel-controller.mdc.stub +391 -0
  33. package/stubs/ai-guides/cursor/laravel-request.mdc.stub +112 -0
  34. package/stubs/ai-guides/cursor/laravel-resource.mdc.stub +73 -0
  35. package/stubs/ai-guides/cursor/laravel-review.mdc.stub +69 -0
  36. package/stubs/ai-guides/cursor/laravel-testing.mdc.stub +138 -0
  37. package/stubs/ai-guides/cursor/laravel.mdc.stub +82 -0
  38. package/stubs/ai-guides/cursor/omnify.mdc.stub +58 -0
  39. package/stubs/ai-guides/laravel/README.md.stub +59 -0
  40. package/stubs/ai-guides/laravel/architecture.md.stub +424 -0
  41. package/stubs/ai-guides/laravel/controller.md.stub +484 -0
  42. package/stubs/ai-guides/laravel/datetime.md.stub +334 -0
  43. package/stubs/ai-guides/laravel/openapi.md.stub +369 -0
  44. package/stubs/ai-guides/laravel/request.md.stub +450 -0
  45. package/stubs/ai-guides/laravel/resource.md.stub +516 -0
  46. package/stubs/ai-guides/laravel/service.md.stub +503 -0
  47. package/stubs/ai-guides/laravel/testing.md.stub +1504 -0
  48. package/ai-guides/laravel-guide.md +0 -461
  49. package/dist/chunk-YVVAJA3T.js.map +0 -1
@@ -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,115 @@
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
+ ## Associations
71
+
72
+ ```yaml
73
+ # Many-to-One (belongsTo)
74
+ author:
75
+ type: Association
76
+ relation: ManyToOne
77
+ target: User
78
+ onDelete: CASCADE
79
+
80
+ # One-to-Many (hasMany)
81
+ posts:
82
+ type: Association
83
+ relation: OneToMany
84
+ target: Post
85
+
86
+ # Many-to-Many (belongsToMany)
87
+ tags:
88
+ type: Association
89
+ relation: ManyToMany
90
+ target: Tag
91
+ joinTable: post_tags
92
+
93
+ # Polymorphic
94
+ commentable:
95
+ type: Association
96
+ relation: MorphTo
97
+ ```
98
+
99
+ ## Indexes
100
+
101
+ ```yaml
102
+ indexes:
103
+ - columns: [status, published_at]
104
+ - columns: [email]
105
+ unique: true
106
+ ```
107
+
108
+ ## Schema Options
109
+
110
+ ```yaml
111
+ options:
112
+ timestamps: true # Add created_at, updated_at
113
+ softDelete: true # Add deleted_at
114
+ idType: BigInt # Primary key type (Int, BigInt, Uuid)
115
+ ```
@@ -0,0 +1,310 @@
1
+ # Omnify TypeScript Generator Guide
2
+
3
+ This guide covers TypeScript-specific features and generated code patterns for Omnify.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Create new project (recommended)
9
+ npx @famgia/omnify create-laravel-project my-app
10
+ cd my-app
11
+
12
+ # Or initialize in existing project
13
+ npx @famgia/omnify init
14
+
15
+ # Generate TypeScript types
16
+ npx @famgia/omnify generate
17
+ ```
18
+
19
+ ## Generated Files
20
+
21
+ When you run `npx @famgia/omnify generate`, the following TypeScript files are generated:
22
+
23
+ - `base/*.ts` - Base model interfaces
24
+ - `enum/*.ts` - Enum types with multi-locale labels
25
+ - `rules/*.ts` - Ant Design compatible validation rules
26
+
27
+ ## Type Generation
28
+
29
+ ### Object Schema → Interface
30
+
31
+ ```yaml
32
+ # yaml-language-server: $schema=./node_modules/.omnify/combined-schema.json
33
+ name: User
34
+ properties:
35
+ id:
36
+ type: BigInt
37
+ required: true
38
+ name:
39
+ type: String
40
+ required: true
41
+ maxLength: 255
42
+ email:
43
+ type: String
44
+ required: true
45
+ unique: true
46
+ profile:
47
+ type: Json
48
+ createdAt:
49
+ type: DateTime
50
+ ```
51
+
52
+ Generated:
53
+ ```typescript
54
+ export interface User {
55
+ id: number;
56
+ name: string;
57
+ email: string;
58
+ profile: Record<string, unknown> | null;
59
+ createdAt: Date | null;
60
+ }
61
+ ```
62
+
63
+ ## Type Mapping
64
+
65
+ | Schema Type | TypeScript Type |
66
+ |-------------|-----------------|
67
+ | `String` | `string` |
68
+ | `Text` | `string` |
69
+ | `MediumText` | `string` |
70
+ | `LongText` | `string` |
71
+ | `TinyInt` | `number` |
72
+ | `Int` | `number` |
73
+ | `BigInt` | `number` |
74
+ | `Float` | `number` |
75
+ | `Decimal` | `number` |
76
+ | `Boolean` | `boolean` |
77
+ | `Date` | `Date` |
78
+ | `DateTime` | `Date` |
79
+ | `Timestamp` | `Date` |
80
+ | `Json` | `Record<string, unknown>` |
81
+ | `EnumRef` | Generated enum type |
82
+ | `Association` | Related model type / array |
83
+
84
+ ## Hidden Schemas
85
+
86
+ Schemas with `options.hidden: true` are skipped for TypeScript generation:
87
+
88
+ ```yaml
89
+ name: AppCache
90
+ options:
91
+ hidden: true # No TypeScript interface generated
92
+ ```
93
+
94
+ Use cases:
95
+ - System tables (cache, sessions, jobs)
96
+ - Tables that don't need frontend types
97
+
98
+ ## Enum Generation (Multi-locale)
99
+
100
+ ```yaml
101
+ # schemas/PostStatus.yaml
102
+ name: PostStatus
103
+ kind: enum
104
+ displayName:
105
+ ja: 投稿ステータス
106
+ en: Post Status
107
+ values:
108
+ draft:
109
+ ja: 下書き
110
+ en: Draft
111
+ published:
112
+ ja: 公開済み
113
+ en: Published
114
+ archived:
115
+ ja: アーカイブ
116
+ en: Archived
117
+ ```
118
+
119
+ Generated:
120
+ ```typescript
121
+ export const PostStatus = {
122
+ draft: 'draft',
123
+ published: 'published',
124
+ archived: 'archived',
125
+ } as const;
126
+
127
+ export type PostStatus = typeof PostStatus[keyof typeof PostStatus];
128
+
129
+ // Multi-locale labels
130
+ export const PostStatusLabels: Record<PostStatus, Record<string, string>> = {
131
+ draft: { ja: '下書き', en: 'Draft' },
132
+ published: { ja: '公開済み', en: 'Published' },
133
+ archived: { ja: 'アーカイブ', en: 'Archived' },
134
+ };
135
+
136
+ // Get label for specific locale
137
+ export function getPostStatusLabel(value: PostStatus, locale: string = 'en'): string {
138
+ return PostStatusLabels[value]?.[locale] ?? PostStatusLabels[value]?.['en'] ?? value;
139
+ }
140
+
141
+ // Helper functions
142
+ export const PostStatusValues = Object.values(PostStatus);
143
+ export function isPostStatus(value: unknown): value is PostStatus {
144
+ return PostStatusValues.includes(value as PostStatus);
145
+ }
146
+ ```
147
+
148
+ ## Validation Rules (Ant Design)
149
+
150
+ Omnify generates Ant Design compatible validation rules in `rules/` directory.
151
+
152
+ **See detailed guide:** `.claude/omnify/antdesign-guide.md`
153
+
154
+ Quick example:
155
+ ```tsx
156
+ import { Form, Input } from 'antd';
157
+ import { getUserRules, getUserPropertyDisplayName } from './types/model/rules/User.rules';
158
+
159
+ function UserForm({ locale = 'ja' }) {
160
+ const rules = getUserRules(locale);
161
+ return (
162
+ <Form>
163
+ <Form.Item name="name" label={getUserPropertyDisplayName('name', locale)} rules={rules.name}>
164
+ <Input />
165
+ </Form.Item>
166
+ </Form>
167
+ );
168
+ }
169
+ ```
170
+
171
+ ## Association Types
172
+
173
+ ### ManyToOne
174
+ ```yaml
175
+ author:
176
+ type: Association
177
+ relation: ManyToOne
178
+ target: User
179
+ ```
180
+
181
+ Generated:
182
+ ```typescript
183
+ export interface Post {
184
+ authorId: number;
185
+ author?: User; // Optional: loaded relation
186
+ }
187
+ ```
188
+
189
+ ### OneToMany
190
+ ```yaml
191
+ posts:
192
+ type: Association
193
+ relation: OneToMany
194
+ target: Post
195
+ ```
196
+
197
+ Generated:
198
+ ```typescript
199
+ export interface User {
200
+ posts?: Post[]; // Optional: loaded relation array
201
+ }
202
+ ```
203
+
204
+ ### ManyToMany
205
+ ```yaml
206
+ tags:
207
+ type: Association
208
+ relation: ManyToMany
209
+ target: Tag
210
+ ```
211
+
212
+ Generated:
213
+ ```typescript
214
+ export interface Post {
215
+ tags?: Tag[]; // Optional: loaded relation array
216
+ }
217
+ ```
218
+
219
+ ## Nullable Fields
220
+
221
+ Fields without `required: true` are nullable:
222
+
223
+ ```yaml
224
+ description:
225
+ type: LongText # No required: true
226
+ ```
227
+
228
+ Generated:
229
+ ```typescript
230
+ description: string | null;
231
+ ```
232
+
233
+ ## Using Generated Types
234
+
235
+ ```typescript
236
+ import { User, Post, PostStatus, isPostStatus } from './types/omnify-types';
237
+
238
+ // Type-safe object creation
239
+ const user: User = {
240
+ id: 1,
241
+ name: 'John',
242
+ email: 'john@example.com',
243
+ profile: null,
244
+ createdAt: new Date(),
245
+ };
246
+
247
+ // Enum usage
248
+ const status: PostStatus = PostStatus.draft;
249
+
250
+ // Type guard
251
+ function handleStatus(value: unknown) {
252
+ if (isPostStatus(value)) {
253
+ console.log('Valid status:', value);
254
+ }
255
+ }
256
+ ```
257
+
258
+ ## Commands
259
+
260
+ ```bash
261
+ # Create new project
262
+ npx @famgia/omnify create-laravel-project my-app
263
+
264
+ # Generate TypeScript types
265
+ npx @famgia/omnify generate
266
+
267
+ # Force regenerate all files
268
+ npx @famgia/omnify generate --force
269
+
270
+ # Only generate TypeScript types
271
+ npx @famgia/omnify generate --types-only
272
+
273
+ # Validate schemas
274
+ npx @famgia/omnify validate
275
+ ```
276
+
277
+ ## Configuration
278
+
279
+ ```typescript
280
+ // omnify.config.ts
281
+ import { defineConfig } from '@famgia/omnify';
282
+ import typescript from '@famgia/omnify-typescript/plugin';
283
+
284
+ export default defineConfig({
285
+ schemasDir: './schemas',
286
+ lockFilePath: './.omnify.lock',
287
+
288
+ plugins: [
289
+ typescript({
290
+ // Output path for TypeScript files
291
+ path: './resources/ts/types/models',
292
+
293
+ // Generate Ant Design validation rules
294
+ generateRules: true,
295
+ }),
296
+ ],
297
+
298
+ locale: {
299
+ locales: ['ja', 'en'],
300
+ defaultLocale: 'ja',
301
+ },
302
+ });
303
+ ```
304
+
305
+ ### Configuration Options
306
+
307
+ | Option | Type | Default | Description |
308
+ |--------|------|---------|-------------|
309
+ | `path` | `string` | `./src/types/model` | TypeScript output directory |
310
+ | `generateRules` | `boolean` | `true` | Generate Ant Design validation rules |