@famgia/omnify-laravel 0.0.125 → 0.0.127
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/{chunk-C3AGVZB4.js → chunk-IIA2I36W.js} +1 -1
- package/dist/chunk-IIA2I36W.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.js +1 -1
- package/package.json +4 -4
- package/stubs/ai-guides/README.md.stub +1 -0
- package/stubs/ai-guides/claude-omnify/schema-guide.md.stub +29 -0
- package/stubs/ai-guides/claude-rules/php-standards.md.stub +305 -0
- package/stubs/ai-guides/claude-rules/schema-yaml.md.stub +14 -0
- package/stubs/ai-guides/cursor/omnify-schema.mdc.stub +19 -0
- package/stubs/ai-guides/cursor/schema-create.mdc.stub +102 -0
- package/dist/chunk-C3AGVZB4.js.map +0 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/migration/schema-builder.ts","../src/migration/generator.ts","../src/migration/alter-generator.ts","../src/model/generator.ts","../src/utils.ts","../src/factory/generator.ts","../src/plugin.ts","../src/request/generator.ts","../src/resource/generator.ts","../src/ai-guides/generator.ts"],"sourcesContent":["/**\n * @famgia/omnify-laravel\n *\n * Laravel migration generator for Omnify schemas.\n */\n\n// Migration generation\nexport {\n // Types\n type MigrationFile,\n type MigrationOptions,\n type ColumnMethod,\n type ColumnModifier,\n type ForeignKeyDefinition,\n type IndexDefinition,\n type TableBlueprint,\n type MigrationOperation,\n type MigrationDefinition,\n type PivotFieldInfo,\n type PivotTableInfo,\n type MorphToManyPivotInfo,\n // Schema builder\n toColumnName,\n toTableName,\n propertyToColumnMethod,\n generatePrimaryKeyColumn,\n generateTimestampColumns,\n generateSoftDeleteColumn,\n generateForeignKey,\n schemaToBlueprint,\n formatColumnMethod,\n formatForeignKey,\n formatIndex,\n generatePivotTableName,\n extractManyToManyRelations,\n generatePivotTableBlueprint,\n extractMorphToManyRelations,\n generateMorphToManyPivotBlueprint,\n // Generator\n generateMigrations,\n generateMigrationFromSchema,\n generateDropMigrationForTable,\n formatMigrationFile,\n getMigrationPath,\n // ALTER migration generator\n generateAlterMigration,\n generateDropTableMigration,\n generateMigrationsFromChanges,\n} from './migration/index.js';\n\n// Model generation\nexport {\n generateModels,\n getModelPath,\n generateProviderRegistration,\n type GeneratedModel,\n type ModelGeneratorOptions,\n type ProviderRegistrationResult,\n} from './model/index.js';\n\n// Factory generation\nexport {\n generateFactories,\n getFactoryPath,\n type FactoryGeneratorOptions,\n type GeneratedFactory,\n} from './factory/index.js';\n\n// Plugin\nexport {\n default as laravelPlugin,\n type LaravelPluginOptions,\n} from './plugin.js';\n\n// AI Guides generation\nexport {\n generateAIGuides,\n shouldGenerateAIGuides,\n type AIGuidesOptions,\n type AIGuidesResult,\n} from './ai-guides/index.js';\n","/**\n * @famgia/omnify-laravel - Schema Builder Converter\n *\n * Converts SQL types and operations to Laravel Schema Builder methods.\n */\n\nimport type { PropertyDefinition, LoadedSchema, SchemaCollection, CustomTypeDefinition, LocalizedString, LocaleResolutionOptions } from '@famgia/omnify-types';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport type {\n ColumnMethod,\n ColumnModifier,\n ForeignKeyDefinition,\n IndexDefinition,\n TableBlueprint,\n} from './types.js';\n\n/**\n * Maps Omnify property types to Laravel column methods.\n */\nconst TYPE_METHOD_MAP: Record<string, string> = {\n String: 'string',\n TinyInt: 'tinyInteger',\n Int: 'integer',\n BigInt: 'bigInteger',\n Float: 'double',\n Decimal: 'decimal',\n Boolean: 'boolean',\n Text: 'text',\n MediumText: 'mediumText',\n LongText: 'longText',\n Date: 'date',\n Time: 'time',\n DateTime: 'dateTime',\n Timestamp: 'timestamp',\n Json: 'json',\n Email: 'string',\n Password: 'string',\n Enum: 'enum',\n EnumRef: 'string', // EnumRef stores the enum value as string (lookup via schema)\n // Note: File type is now polymorphic - no column generated, uses files table\n};\n\n/**\n * Maps primary key types to Laravel methods.\n * Laravel 8+ uses id() for BigInt auto-increment primary keys.\n */\nconst PK_METHOD_MAP: Record<string, string> = {\n Int: 'increments',\n BigInt: 'id',\n Uuid: 'uuid',\n String: 'string',\n};\n\n/**\n * Gets the ID type from schema options.\n */\nfunction getIdType(schema: LoadedSchema): 'Int' | 'BigInt' | 'Uuid' | 'String' {\n return (schema.options?.idType ?? 'BigInt') as 'Int' | 'BigInt' | 'Uuid' | 'String';\n}\n\n/**\n * Checks if the schema should have an auto-generated ID column.\n * Returns false if options.id is explicitly set to false.\n */\nfunction hasAutoId(schema: LoadedSchema): boolean {\n return schema.options?.id !== false;\n}\n\n/**\n * Converts a property name to snake_case column name.\n */\nexport function toColumnName(propertyName: string): string {\n return propertyName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n}\n\n/**\n * Converts schema name to snake_case plural table name.\n */\nexport function toTableName(schemaName: string): string {\n const snakeCase = schemaName\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n\n // Simple pluralization\n if (snakeCase.endsWith('y')) {\n return snakeCase.slice(0, -1) + 'ies';\n } else if (\n snakeCase.endsWith('s') ||\n snakeCase.endsWith('x') ||\n snakeCase.endsWith('ch') ||\n snakeCase.endsWith('sh')\n ) {\n return snakeCase + 'es';\n } else {\n return snakeCase + 's';\n }\n}\n\n/**\n * Options for property to column conversion.\n */\nexport interface PropertyToColumnOptions {\n /** Locale resolution options for displayName */\n locale?: LocaleResolutionOptions;\n}\n\n/**\n * Converts a property to Laravel column method.\n */\nexport function propertyToColumnMethod(\n propertyName: string,\n property: PropertyDefinition,\n options: PropertyToColumnOptions = {}\n): ColumnMethod | null {\n // Skip associations - they're handled separately\n if (property.type === 'Association') {\n return null;\n }\n\n // Skip File type - uses polymorphic relation to files table\n if (property.type === 'File') {\n return null;\n }\n\n const columnName = toColumnName(propertyName);\n const method = TYPE_METHOD_MAP[property.type] ?? 'string';\n const args: (string | number | boolean)[] = [columnName];\n const modifiers: ColumnModifier[] = [];\n\n // Handle length for string types\n const propWithLength = property as { length?: number };\n if (method === 'string' && propWithLength.length) {\n args.push(propWithLength.length);\n } else if (property.type === 'EnumRef') {\n // Default length for EnumRef columns (store enum value, typically short codes)\n args.push(50);\n }\n\n // Handle precision and scale for decimal types\n if (property.type === 'Decimal') {\n const decimalProp = property as { precision?: number; scale?: number };\n const precision = decimalProp.precision ?? 8;\n const scale = decimalProp.scale ?? 2;\n args.push(precision, scale);\n }\n\n // Handle enum values\n if (property.type === 'Enum') {\n const enumProp = property as { enum?: readonly string[] };\n if (enumProp.enum && enumProp.enum.length > 0) {\n args.push(enumProp.enum as unknown as string);\n }\n }\n\n // Add modifiers\n const baseProp = property as {\n nullable?: boolean;\n unique?: boolean;\n default?: unknown;\n unsigned?: boolean;\n primary?: boolean;\n };\n\n // Add primary key modifier (for custom primary keys with id: false)\n if (baseProp.primary) {\n modifiers.push({ method: 'primary' });\n }\n\n if (baseProp.nullable) {\n modifiers.push({ method: 'nullable' });\n }\n\n if (baseProp.unique) {\n modifiers.push({ method: 'unique' });\n }\n\n if (baseProp.default !== undefined && baseProp.default !== null) {\n // Keep native types for proper PHP rendering (boolean false vs string 'false')\n modifiers.push({ method: 'default', args: [baseProp.default as string | number | boolean] });\n }\n\n if (baseProp.unsigned && (method === 'tinyInteger' || method === 'integer' || method === 'bigInteger')) {\n modifiers.push({ method: 'unsigned' });\n }\n\n // Timestamp modifiers: useCurrent and useCurrentOnUpdate\n if (method === 'timestamp') {\n const timestampProp = property as { useCurrent?: boolean; useCurrentOnUpdate?: boolean };\n if (timestampProp.useCurrent) {\n modifiers.push({ method: 'useCurrent' });\n }\n if (timestampProp.useCurrentOnUpdate) {\n modifiers.push({ method: 'useCurrentOnUpdate' });\n }\n }\n\n // Add comment from displayName if available (resolve LocalizedString to string)\n const rawDisplayName = (property as { displayName?: LocalizedString }).displayName;\n if (rawDisplayName) {\n const displayName = resolveLocalizedString(rawDisplayName, options.locale);\n if (displayName) {\n modifiers.push({ method: 'comment', args: [displayName] });\n }\n }\n\n return {\n name: columnName,\n method,\n args,\n modifiers,\n };\n}\n\n/**\n * Generates primary key column method.\n */\nexport function generatePrimaryKeyColumn(\n pkType: 'Int' | 'BigInt' | 'Uuid' | 'String' = 'BigInt'\n): ColumnMethod {\n const method = PK_METHOD_MAP[pkType] ?? 'id';\n\n if (pkType === 'Uuid') {\n return {\n name: 'id',\n method: 'uuid',\n args: ['id'],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n if (pkType === 'String') {\n return {\n name: 'id',\n method: 'string',\n args: ['id', 255],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n // For Int/BigInt, use increments/id which auto-creates primary key\n // $table->id() needs no args, $table->increments('id') needs column name\n return {\n name: 'id',\n method,\n args: method === 'id' ? [] : ['id'],\n modifiers: [],\n };\n}\n\n/**\n * Generates timestamp columns.\n */\nexport function generateTimestampColumns(): ColumnMethod[] {\n return [\n {\n name: 'created_at',\n method: 'timestamp',\n args: ['created_at'],\n modifiers: [{ method: 'nullable' }],\n },\n {\n name: 'updated_at',\n method: 'timestamp',\n args: ['updated_at'],\n modifiers: [{ method: 'nullable' }],\n },\n ];\n}\n\n/**\n * Generates soft delete column.\n */\nexport function generateSoftDeleteColumn(): ColumnMethod {\n return {\n name: 'deleted_at',\n method: 'timestamp',\n args: ['deleted_at'],\n modifiers: [{ method: 'nullable' }],\n };\n}\n\n/**\n * Polymorphic column result with type enum and id column.\n */\nexport interface PolymorphicColumnsResult {\n typeColumn: ColumnMethod;\n idColumn: ColumnMethod;\n indexes: IndexDefinition[];\n}\n\n/**\n * Generates polymorphic columns for MorphTo relations.\n * Creates {name}_type (ENUM) and {name}_id columns.\n */\nexport function generatePolymorphicColumns(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection\n): PolymorphicColumnsResult | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const assocProp = property as {\n relation?: string;\n targets?: readonly string[];\n nullable?: boolean;\n };\n\n // Only handle MorphTo - it creates the type and id columns\n if (assocProp.relation !== 'MorphTo') {\n return null;\n }\n\n // Check if nullable is explicitly set (default: true for MorphTo)\n const isNullable = assocProp.nullable !== false;\n\n const targets = assocProp.targets;\n if (!targets || targets.length === 0) {\n return null;\n }\n\n const columnBaseName = toColumnName(propertyName);\n const typeColumnName = `${columnBaseName}_type`;\n const idColumnName = `${columnBaseName}_id`;\n\n // Generate ENUM type column with target schema names as values\n const typeColumn: ColumnMethod = {\n name: typeColumnName,\n method: 'enum',\n args: [typeColumnName, targets as unknown as string],\n modifiers: isNullable ? [{ method: 'nullable' }] : [],\n };\n\n // For polymorphic id, we need to determine the largest ID type among targets\n // Default to unsignedBigInteger for maximum compatibility\n let idMethod = 'unsignedBigInteger';\n\n // Check if any target uses UUID or String - those take precedence\n for (const targetName of targets) {\n const targetSchema = allSchemas[targetName];\n if (targetSchema) {\n const targetIdType = (targetSchema.options?.idType ?? 'BigInt') as string;\n if (targetIdType === 'Uuid') {\n idMethod = 'uuid';\n break; // UUID takes highest precedence\n } else if (targetIdType === 'String') {\n idMethod = 'string';\n // Don't break - UUID still takes precedence\n }\n }\n }\n\n const idColumn: ColumnMethod = {\n name: idColumnName,\n method: idMethod,\n args: idMethod === 'string' ? [idColumnName, 255] : [idColumnName],\n modifiers: isNullable ? [{ method: 'nullable' }] : [],\n };\n\n // Create composite index for faster polymorphic lookups\n const indexes: IndexDefinition[] = [\n {\n columns: [typeColumnName, idColumnName],\n unique: false,\n },\n ];\n\n return { typeColumn, idColumn, indexes };\n}\n\n/**\n * Generates foreign key column and constraint from association.\n */\nexport function generateForeignKey(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection,\n options: PropertyToColumnOptions = {}\n): { column: ColumnMethod; foreignKey: ForeignKeyDefinition; index: IndexDefinition } | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n onDelete?: string;\n onUpdate?: string;\n mappedBy?: string;\n owningSide?: boolean;\n nullable?: boolean;\n default?: string | number;\n displayName?: LocalizedString;\n };\n\n // Only create FK column for ManyToOne and OneToOne (owning side)\n if (assocProp.relation !== 'ManyToOne' && assocProp.relation !== 'OneToOne') {\n return null;\n }\n\n // Skip inverse side (mappedBy means this is the inverse side)\n if (assocProp.mappedBy) {\n return null;\n }\n\n const columnName = toColumnName(propertyName) + '_id';\n const targetSchema = assocProp.target ? allSchemas[assocProp.target] : undefined;\n const targetTable = assocProp.target ? toTableName(assocProp.target) : 'unknown';\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine column method based on target PK type\n let method = 'unsignedBigInteger';\n if (targetPkType === 'Int') {\n method = 'unsignedInteger';\n } else if (targetPkType === 'Uuid') {\n method = 'uuid';\n } else if (targetPkType === 'String') {\n method = 'string';\n }\n\n // Build modifiers for the column\n const modifiers: ColumnModifier[] = [];\n\n // Add nullable only if explicitly set to true (consistent with other property types)\n if (assocProp.nullable === true) {\n modifiers.push({ method: 'nullable' });\n }\n\n // Add default if specified\n if (assocProp.default !== undefined && assocProp.default !== null) {\n modifiers.push({ method: 'default', args: [assocProp.default] });\n }\n\n // Add comment from displayName if available (resolve LocalizedString to string)\n if (assocProp.displayName) {\n const displayName = resolveLocalizedString(assocProp.displayName, options.locale);\n if (displayName) {\n modifiers.push({ method: 'comment', args: [displayName] });\n }\n }\n\n const column: ColumnMethod = {\n name: columnName,\n method,\n args: [columnName],\n modifiers,\n };\n\n const foreignKey: ForeignKeyDefinition = {\n columns: [columnName],\n references: 'id',\n on: [targetTable],\n onDelete: assocProp.onDelete ?? 'restrict',\n onUpdate: assocProp.onUpdate ?? 'cascade',\n };\n\n // Don't specify index name - let Laravel auto-generate unique names\n const index: IndexDefinition = {\n columns: [columnName],\n unique: false,\n };\n\n return { column, foreignKey, index };\n}\n\n/**\n * Expands compound type properties into multiple columns.\n * Returns the expanded properties or null if not a compound type.\n */\nfunction expandCompoundType(\n propName: string,\n property: PropertyDefinition,\n customTypes: ReadonlyMap<string, CustomTypeDefinition>,\n options: PropertyToColumnOptions = {}\n): { name: string; property: PropertyDefinition }[] | null {\n const typeDef = customTypes.get(property.type);\n\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const expanded: { name: string; property: PropertyDefinition }[] = [];\n const baseProp = property as unknown as Record<string, unknown>;\n\n for (const field of typeDef.expand) {\n // Generate column name: propName + suffix (converted to snake_case)\n const suffixSnake = toColumnName(field.suffix);\n const columnName = `${propName}_${suffixSnake}`;\n\n // Build property definition\n const expandedProp: Record<string, unknown> = {\n type: 'String', // Default type, will be overridden by sql definition\n };\n\n // Check for per-field overrides from schema's `fields` property\n const fieldOverrides = baseProp.fields as Record<string, { nullable?: boolean; hidden?: boolean; fillable?: boolean; length?: number }> | undefined;\n const fieldOverride = fieldOverrides?.[field.suffix];\n\n // Handle enumRef field - reference to enum schema\n const fieldWithEnumRef = field as { enumRef?: string };\n if (fieldWithEnumRef.enumRef) {\n expandedProp.type = 'EnumRef';\n expandedProp.enum = fieldWithEnumRef.enumRef;\n // Inherit nullable from parent property, or use per-field override\n if (fieldOverride?.nullable !== undefined) {\n expandedProp.nullable = fieldOverride.nullable;\n } else if (baseProp.nullable !== undefined) {\n expandedProp.nullable = baseProp.nullable;\n }\n }\n // Map SQL type to Omnify type\n else if (field.sql) {\n const sqlType = field.sql.sqlType.toUpperCase();\n if (sqlType === 'VARCHAR' || sqlType === 'CHAR' || sqlType === 'STRING') {\n expandedProp.type = 'String';\n // Use field override length if provided, otherwise use default from type definition\n if (fieldOverride?.length) {\n expandedProp.length = fieldOverride.length;\n } else if (field.sql.length) {\n expandedProp.length = field.sql.length;\n }\n } else if (sqlType === 'TINYINT') {\n expandedProp.type = 'TinyInt';\n } else if (sqlType === 'INT' || sqlType === 'INTEGER') {\n expandedProp.type = 'Int';\n } else if (sqlType === 'BIGINT') {\n expandedProp.type = 'BigInt';\n } else if (sqlType === 'TEXT') {\n expandedProp.type = 'Text';\n } else if (sqlType === 'BOOLEAN' || sqlType === 'BOOL') {\n expandedProp.type = 'Boolean';\n } else if (sqlType === 'DECIMAL') {\n expandedProp.type = 'Decimal';\n if (field.sql.precision) expandedProp.precision = field.sql.precision;\n if (field.sql.scale) expandedProp.scale = field.sql.scale;\n } else if (sqlType === 'DATE') {\n expandedProp.type = 'Date';\n } else if (sqlType === 'TIMESTAMP' || sqlType === 'DATETIME') {\n expandedProp.type = 'Timestamp';\n }\n\n // Handle unsigned flag for integer types\n if (field.sql.unsigned) {\n expandedProp.unsigned = true;\n }\n\n // Handle default value\n if (field.sql.default !== undefined) {\n expandedProp.default = field.sql.default;\n }\n\n // Handle nullable: priority is per-field override > field.sql.nullable > parent property\n if (field.sql.nullable !== undefined) {\n expandedProp.nullable = field.sql.nullable;\n } else if (baseProp.nullable !== undefined) {\n expandedProp.nullable = baseProp.nullable;\n }\n // Per-field nullable override takes highest priority\n if (fieldOverride?.nullable !== undefined) {\n expandedProp.nullable = fieldOverride.nullable;\n }\n }\n\n // Copy displayName if parent has it (with suffix context)\n // Resolve LocalizedString to string before appending suffix\n if (baseProp.displayName) {\n const resolvedDisplayName = resolveLocalizedString(\n baseProp.displayName as LocalizedString,\n options.locale\n );\n if (resolvedDisplayName) {\n expandedProp.displayName = `${resolvedDisplayName} (${field.suffix})`;\n }\n }\n\n expanded.push({\n name: columnName,\n property: expandedProp as unknown as PropertyDefinition,\n });\n }\n\n return expanded;\n}\n\n/**\n * Options for schema to blueprint conversion.\n */\nexport interface SchemaToBlueprintOptions {\n /** Custom types from plugins (for compound type expansion) */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n /** Locale resolution options for displayName */\n locale?: LocaleResolutionOptions;\n}\n\n/**\n * Generates table blueprint from schema.\n */\nexport function schemaToBlueprint(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: SchemaToBlueprintOptions = {}\n): TableBlueprint {\n const { customTypes = new Map(), locale } = options;\n const columnOptions: PropertyToColumnOptions = { locale };\n // Use options.tableName if specified, otherwise derive from schema name\n const tableName = schema.options?.tableName ?? toTableName(schema.name);\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Primary key (only if id is not disabled)\n if (hasAutoId(schema)) {\n const pkType = getIdType(schema);\n columns.push(generatePrimaryKeyColumn(pkType));\n }\n\n // Process properties\n if (schema.properties) {\n for (const [propName, property] of Object.entries(schema.properties)) {\n // Check for compound type expansion first\n const expandedProps = expandCompoundType(propName, property, customTypes, columnOptions);\n if (expandedProps) {\n // Compound type - process each expanded property\n for (const { name: expandedName, property: expandedProp } of expandedProps) {\n const columnMethod = propertyToColumnMethod(expandedName, expandedProp, columnOptions);\n if (columnMethod) {\n columns.push(columnMethod);\n }\n }\n continue; // Skip normal processing for compound types\n }\n\n // Handle regular columns\n const columnMethod = propertyToColumnMethod(propName, property, columnOptions);\n if (columnMethod) {\n columns.push(columnMethod);\n }\n\n // Handle foreign keys (standard associations)\n const fkResult = generateForeignKey(propName, property, allSchemas, columnOptions);\n if (fkResult) {\n columns.push(fkResult.column);\n foreignKeys.push(fkResult.foreignKey);\n indexes.push(fkResult.index);\n }\n\n // Handle polymorphic columns (MorphTo)\n const polyResult = generatePolymorphicColumns(propName, property, allSchemas);\n if (polyResult) {\n columns.push(polyResult.typeColumn);\n columns.push(polyResult.idColumn);\n indexes.push(...polyResult.indexes);\n }\n }\n }\n\n // Timestamps\n if (schema.options?.timestamps !== false) {\n columns.push(...generateTimestampColumns());\n }\n\n // Soft delete\n if (schema.options?.softDelete) {\n columns.push(generateSoftDeleteColumn());\n }\n\n // Custom indexes\n if (schema.options?.indexes) {\n // Helper to convert property name to column name, considering Association type\n const propToColName = (propName: string): string => {\n const colName = toColumnName(propName);\n const prop = schema.properties?.[propName];\n if (prop?.type === 'Association') {\n const assoc = prop as { relation?: string; mappedBy?: string };\n // Only add _id for owning side (ManyToOne, OneToOne without mappedBy)\n if (\n (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') &&\n !assoc.mappedBy\n ) {\n return colName + '_id';\n }\n }\n return colName;\n };\n\n for (const index of schema.options.indexes) {\n // Handle both shorthand (string) and full object format\n if (typeof index === 'string') {\n // Shorthand: just column name\n indexes.push({\n columns: [propToColName(index)],\n unique: false,\n });\n } else {\n // Full object format\n indexes.push({\n name: index.name,\n columns: index.columns.map(propToColName),\n unique: index.unique ?? false,\n });\n }\n }\n }\n\n // Unique constraints\n if (schema.options?.unique) {\n // Helper to convert property name to column name, considering Association type\n const propToColName = (propName: string): string => {\n const colName = toColumnName(propName);\n const prop = schema.properties?.[propName];\n if (prop?.type === 'Association') {\n const assoc = prop as { relation?: string; mappedBy?: string };\n if (\n (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') &&\n !assoc.mappedBy\n ) {\n return colName + '_id';\n }\n }\n return colName;\n };\n\n const uniqueConstraints = Array.isArray(schema.options.unique[0])\n ? (schema.options.unique as readonly (readonly string[])[])\n : [schema.options.unique as readonly string[]];\n\n for (const constraint of uniqueConstraints) {\n indexes.push({\n columns: constraint.map(propToColName),\n unique: true,\n });\n }\n }\n\n // Deduplicate indexes by columns (keep first occurrence)\n const seenIndexes = new Set<string>();\n const uniqueIndexes = indexes.filter(idx => {\n const key = idx.columns.join(',') + (idx.unique ? ':unique' : '');\n if (seenIndexes.has(key)) {\n return false;\n }\n seenIndexes.add(key);\n return true;\n });\n\n // Determine primary key column(s)\n let primaryKey: string[] | undefined;\n if (hasAutoId(schema)) {\n primaryKey = ['id'];\n } else if (schema.properties) {\n // Find properties marked with primary: true\n const pkColumns: string[] = [];\n for (const [propName, property] of Object.entries(schema.properties)) {\n if ((property as { primary?: boolean }).primary) {\n pkColumns.push(toColumnName(propName));\n }\n }\n if (pkColumns.length > 0) {\n primaryKey = pkColumns;\n }\n }\n\n return {\n tableName,\n columns,\n primaryKey,\n foreignKeys,\n indexes: uniqueIndexes,\n };\n}\n\n/**\n * Formats a column method to PHP code.\n */\nexport function formatColumnMethod(column: ColumnMethod): string {\n const args = column.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n if (Array.isArray(arg)) {\n return `[${(arg as string[]).map(v => `'${v}'`).join(', ')}]`;\n }\n return String(arg);\n }).join(', ');\n\n let code = `$table->${column.method}(${args})`;\n\n for (const modifier of column.modifiers) {\n if (modifier.args && modifier.args.length > 0) {\n const modArgs = modifier.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n if (typeof arg === 'boolean') {\n return arg ? 'true' : 'false';\n }\n if (typeof arg === 'number') {\n return String(arg);\n }\n return String(arg);\n }).join(', ');\n code += `->${modifier.method}(${modArgs})`;\n } else {\n code += `->${modifier.method}()`;\n }\n }\n\n return code + ';';\n}\n\n/**\n * Formats a foreign key to PHP code.\n */\nexport function formatForeignKey(fk: ForeignKeyDefinition): string {\n const column = fk.columns[0];\n const table = fk.on[0];\n let code = `$table->foreign('${column}')->references('${fk.references}')->on('${table}')`;\n\n if (fk.onDelete) {\n code += `->onDelete('${fk.onDelete}')`;\n }\n if (fk.onUpdate) {\n code += `->onUpdate('${fk.onUpdate}')`;\n }\n\n return code + ';';\n}\n\n/**\n * Formats an index to PHP code.\n */\nexport function formatIndex(index: IndexDefinition): string {\n const columns = index.columns.length === 1\n ? `'${index.columns[0]}'`\n : `[${index.columns.map(c => `'${c}'`).join(', ')}]`;\n\n const method = index.unique ? 'unique' : 'index';\n const name = index.name ? `, '${index.name}'` : '';\n\n return `$table->${method}(${columns}${name});`;\n}\n\n/**\n * Pivot field definition (simplified from PropertyDefinition for pivot tables).\n */\nexport interface PivotFieldInfo {\n /** Field name in snake_case */\n name: string;\n /** Property type (String, Int, Boolean, Timestamp, etc.) */\n type: string;\n /** Whether the field can be null */\n nullable?: boolean;\n /** Default value for the field */\n default?: unknown;\n /** String length (for String type) */\n length?: number;\n /** Whether the field is unsigned (for numeric types) */\n unsigned?: boolean;\n}\n\n/**\n * Pivot table information for ManyToMany relationships.\n */\nexport interface PivotTableInfo {\n tableName: string;\n sourceTable: string;\n targetTable: string;\n sourceColumn: string;\n targetColumn: string;\n sourcePkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n targetPkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n onDelete: string | undefined;\n onUpdate: string | undefined;\n /** Additional fields on the pivot table */\n pivotFields?: PivotFieldInfo[];\n}\n\n/**\n * Polymorphic pivot table information for MorphToMany relationships.\n */\nexport interface MorphToManyPivotInfo {\n tableName: string;\n /** The fixed target schema that uses MorphToMany */\n targetTable: string;\n targetColumn: string;\n targetPkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n /** Base name for polymorphic columns (creates {name}_type and {name}_id) */\n morphName: string;\n /** Schema names that can be morphed to */\n morphTargets: readonly string[];\n onDelete: string | undefined;\n onUpdate: string | undefined;\n}\n\n/**\n * Generates pivot table name for ManyToMany relationship.\n * Uses alphabetical ordering for consistency.\n */\nexport function generatePivotTableName(\n sourceTable: string,\n targetTable: string,\n customName?: string\n): string {\n if (customName) {\n return customName;\n }\n\n // Sort alphabetically for consistent naming\n const tables = [sourceTable, targetTable].sort();\n // Remove trailing 's' and join with underscore\n const singular1 = tables[0]!.replace(/ies$/, 'y').replace(/s$/, '');\n const singular2 = tables[1]!.replace(/ies$/, 'y').replace(/s$/, '');\n return `${singular1}_${singular2}`;\n}\n\n/**\n * Extracts ManyToMany relationships from a schema.\n */\nexport function extractManyToManyRelations(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): PivotTableInfo[] {\n const pivotTables: PivotTableInfo[] = [];\n\n if (!schema.properties) {\n return pivotTables;\n }\n\n const sourceTable = toTableName(schema.name);\n const sourcePkType = getIdType(schema);\n\n for (const [, property] of Object.entries(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n joinTable?: string;\n onDelete?: string;\n onUpdate?: string;\n owning?: boolean;\n mappedBy?: string;\n pivotFields?: Record<string, {\n type: string;\n nullable?: boolean;\n default?: unknown;\n length?: number;\n unsigned?: boolean;\n }>;\n };\n\n // Only handle ManyToMany on the owning side (or if not specified, use alphabetical order)\n if (assocProp.relation !== 'ManyToMany') {\n continue;\n }\n\n // Skip inverse side (mappedBy means this is the inverse side)\n if (assocProp.mappedBy) {\n continue;\n }\n\n const targetName = assocProp.target;\n if (!targetName) {\n continue;\n }\n\n const targetSchema = allSchemas[targetName];\n const targetTable = toTableName(targetName);\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine if this side owns the relationship\n // Priority: 1) explicit owning flag, 2) pivotFields presence, 3) inverse side check, 4) alphabetical\n let isOwningSide: boolean;\n\n if (assocProp.owning !== undefined) {\n // Explicit owning flag takes highest priority\n isOwningSide = assocProp.owning;\n } else if (assocProp.pivotFields && Object.keys(assocProp.pivotFields).length > 0) {\n // If this side defines pivotFields, it's the owning side\n isOwningSide = true;\n } else {\n // Check if target schema has an inverse relationship with mappedBy pointing to this schema\n // If so, this side should be the owner\n let targetHasMappedByToThisSide = false;\n if (targetSchema?.properties) {\n for (const [, targetProp] of Object.entries(targetSchema.properties)) {\n if (targetProp.type !== 'Association') continue;\n const targetAssoc = targetProp as { relation?: string; target?: string; mappedBy?: string };\n if (\n targetAssoc.relation === 'ManyToMany' &&\n targetAssoc.target === schema.name &&\n targetAssoc.mappedBy\n ) {\n targetHasMappedByToThisSide = true;\n break;\n }\n }\n }\n\n if (targetHasMappedByToThisSide) {\n // Target has mappedBy pointing to this schema, so this is the owning side\n isOwningSide = true;\n } else {\n // Fall back to alphabetical ordering\n isOwningSide = schema.name < targetName;\n }\n }\n\n if (!isOwningSide) {\n continue; // Skip non-owning side to avoid duplicate pivot tables\n }\n\n const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);\n\n // Column names: singular form of table name + _id\n const sourceColumn = sourceTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n const targetColumn = targetTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n\n // Extract pivot fields\n const pivotFields: PivotFieldInfo[] = [];\n if (assocProp.pivotFields) {\n for (const [fieldName, fieldDef] of Object.entries(assocProp.pivotFields)) {\n pivotFields.push({\n name: toColumnName(fieldName),\n type: fieldDef.type,\n nullable: fieldDef.nullable,\n default: fieldDef.default,\n length: fieldDef.length,\n unsigned: fieldDef.unsigned,\n });\n }\n }\n\n pivotTables.push({\n tableName: pivotTableName,\n sourceTable,\n targetTable,\n sourceColumn,\n targetColumn,\n sourcePkType,\n targetPkType,\n onDelete: assocProp.onDelete,\n onUpdate: assocProp.onUpdate,\n pivotFields: pivotFields.length > 0 ? pivotFields : undefined,\n });\n }\n\n return pivotTables;\n}\n\n/**\n * Converts a pivot field definition to a column method.\n */\nfunction pivotFieldToColumn(field: PivotFieldInfo): ColumnMethod {\n const method = TYPE_METHOD_MAP[field.type] ?? 'string';\n const args: (string | number | boolean)[] = [field.name];\n const modifiers: ColumnModifier[] = [];\n\n // Handle length for string types\n if (method === 'string' && field.length) {\n args.push(field.length);\n }\n\n // Handle nullable\n if (field.nullable) {\n modifiers.push({ method: 'nullable' });\n }\n\n // Handle default value\n if (field.default !== undefined && field.default !== null) {\n modifiers.push({ method: 'default', args: [field.default as string | number | boolean] });\n }\n\n // Handle unsigned for numeric types\n if (field.unsigned && (method === 'tinyInteger' || method === 'integer' || method === 'bigInteger')) {\n modifiers.push({ method: 'unsigned' });\n }\n\n return {\n name: field.name,\n method,\n args,\n modifiers,\n };\n}\n\n/**\n * Generates blueprint for a pivot table.\n */\nexport function generatePivotTableBlueprint(pivot: PivotTableInfo): TableBlueprint {\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Determine column methods based on PK types\n const getMethodForPkType = (pkType: string): string => {\n switch (pkType) {\n case 'Int': return 'unsignedInteger';\n case 'Uuid': return 'uuid';\n case 'String': return 'string';\n default: return 'unsignedBigInteger';\n }\n };\n\n // Source column\n columns.push({\n name: pivot.sourceColumn,\n method: getMethodForPkType(pivot.sourcePkType),\n args: [pivot.sourceColumn],\n modifiers: [],\n });\n\n // Target column\n columns.push({\n name: pivot.targetColumn,\n method: getMethodForPkType(pivot.targetPkType),\n args: [pivot.targetColumn],\n modifiers: [],\n });\n\n // Pivot fields (additional columns on the pivot table)\n if (pivot.pivotFields && pivot.pivotFields.length > 0) {\n for (const field of pivot.pivotFields) {\n columns.push(pivotFieldToColumn(field));\n }\n }\n\n // Timestamps for pivot table (Laravel's withTimestamps())\n columns.push(...generateTimestampColumns());\n\n // Foreign keys\n foreignKeys.push({\n columns: [pivot.sourceColumn],\n references: 'id',\n on: [pivot.sourceTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n foreignKeys.push({\n columns: [pivot.targetColumn],\n references: 'id',\n on: [pivot.targetTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n // Composite primary key / unique constraint\n indexes.push({\n columns: [pivot.sourceColumn, pivot.targetColumn],\n unique: true,\n });\n\n // Individual indexes for faster lookups (no name - let Laravel auto-generate)\n indexes.push({\n columns: [pivot.sourceColumn],\n unique: false,\n });\n\n indexes.push({\n columns: [pivot.targetColumn],\n unique: false,\n });\n\n return {\n tableName: pivot.tableName,\n columns,\n primaryKey: [pivot.sourceColumn, pivot.targetColumn],\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Extracts MorphToMany relationships from a schema.\n * MorphToMany creates a pivot table with polymorphic type/id columns.\n */\nexport function extractMorphToManyRelations(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): MorphToManyPivotInfo[] {\n const morphPivotTables: MorphToManyPivotInfo[] = [];\n\n if (!schema.properties) {\n return morphPivotTables;\n }\n\n for (const [propName, property] of Object.entries(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n joinTable?: string;\n onDelete?: string;\n onUpdate?: string;\n owning?: boolean;\n };\n\n if (assocProp.relation !== 'MorphToMany') {\n continue;\n }\n\n const targetName = assocProp.target;\n if (!targetName) {\n continue;\n }\n\n const targetSchema = allSchemas[targetName];\n const targetTable = toTableName(targetName);\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine if this side owns the relationship\n const isOwningSide = assocProp.owning ?? (schema.name < targetName);\n\n if (!isOwningSide) {\n continue;\n }\n\n // Find all schemas that have MorphedByMany pointing to this target\n // to determine the morphTargets for the ENUM\n const morphTargets: string[] = [];\n\n // The source schema itself is a morph target\n morphTargets.push(schema.name);\n\n // Look for other schemas with MorphToMany to the same target\n for (const [otherName, otherSchema] of Object.entries(allSchemas)) {\n if (otherName === schema.name) continue;\n if (!otherSchema.properties) continue;\n\n for (const otherProp of Object.values(otherSchema.properties)) {\n if (otherProp.type !== 'Association') continue;\n const otherAssoc = otherProp as { relation?: string; target?: string };\n if (otherAssoc.relation === 'MorphToMany' && otherAssoc.target === targetName) {\n if (!morphTargets.includes(otherName)) {\n morphTargets.push(otherName);\n }\n }\n }\n }\n\n // Default table name: taggables (for Tag target), commentables, etc.\n const defaultTableName = targetTable.replace(/s$/, '') + 'ables';\n const tableName = assocProp.joinTable ?? defaultTableName;\n\n // Column name for the target side (e.g., tag_id for Tag)\n const targetColumn = targetTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n\n // MorphName is typically the property name or a convention like 'taggable'\n const morphName = propName.replace(/s$/, '') + 'able';\n\n morphPivotTables.push({\n tableName,\n targetTable,\n targetColumn,\n targetPkType,\n morphName,\n morphTargets,\n onDelete: assocProp.onDelete,\n onUpdate: assocProp.onUpdate,\n });\n }\n\n return morphPivotTables;\n}\n\n/**\n * Generates blueprint for a polymorphic pivot table (MorphToMany).\n */\nexport function generateMorphToManyPivotBlueprint(pivot: MorphToManyPivotInfo): TableBlueprint {\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n const getMethodForPkType = (pkType: string): string => {\n switch (pkType) {\n case 'Int': return 'unsignedInteger';\n case 'Uuid': return 'uuid';\n case 'String': return 'string';\n default: return 'unsignedBigInteger';\n }\n };\n\n // Target column (e.g., tag_id)\n columns.push({\n name: pivot.targetColumn,\n method: getMethodForPkType(pivot.targetPkType),\n args: [pivot.targetColumn],\n modifiers: [],\n });\n\n // Polymorphic type column as ENUM\n const typeColumnName = `${pivot.morphName}_type`;\n columns.push({\n name: typeColumnName,\n method: 'enum',\n args: [typeColumnName, pivot.morphTargets as unknown as string],\n modifiers: [],\n });\n\n // Polymorphic ID column\n const idColumnName = `${pivot.morphName}_id`;\n columns.push({\n name: idColumnName,\n method: 'unsignedBigInteger', // Default to BigInt for polymorphic IDs\n args: [idColumnName],\n modifiers: [],\n });\n\n // Foreign key for target\n foreignKeys.push({\n columns: [pivot.targetColumn],\n references: 'id',\n on: [pivot.targetTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n // Unique constraint for polymorphic pivot (target + morphable)\n indexes.push({\n columns: [pivot.targetColumn, typeColumnName, idColumnName],\n unique: true,\n });\n\n // Index for faster polymorphic lookups\n indexes.push({\n columns: [typeColumnName, idColumnName],\n unique: false,\n });\n\n // Index for target lookups\n indexes.push({\n columns: [pivot.targetColumn],\n unique: false,\n });\n\n return {\n tableName: pivot.tableName,\n columns,\n primaryKey: [pivot.targetColumn, typeColumnName, idColumnName],\n foreignKeys,\n indexes,\n };\n}\n\n// Note: File schema functions (hasFileProperties, schemasHaveFileProperties, generateFilesTableBlueprint)\n// have been moved to @famgia/omnify-core's schema/loader.ts\n// The File table is now managed as a proper schema (File.yaml) instead of being auto-generated in code.\n","/**\n * @famgia/omnify-laravel - Migration Generator\n *\n * Generates Laravel migration files from schemas.\n */\n\nimport type { LoadedSchema, SchemaCollection } from '@famgia/omnify-types';\nimport type {\n MigrationFile,\n MigrationOptions,\n TableBlueprint,\n} from './types.js';\nimport {\n schemaToBlueprint,\n formatColumnMethod,\n formatForeignKey,\n formatIndex,\n extractManyToManyRelations,\n generatePivotTableBlueprint,\n} from './schema-builder.js';\n\n/**\n * Generates timestamp prefix for migration file name.\n */\nfunction generateTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;\n}\n\n/**\n * Converts table name to Laravel migration class name.\n */\nfunction toClassName(tableName: string, type: 'create' | 'alter' | 'drop'): string {\n const pascalCase = tableName\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n\n switch (type) {\n case 'create':\n return `Create${pascalCase}Table`;\n case 'alter':\n return `Alter${pascalCase}Table`;\n case 'drop':\n return `Drop${pascalCase}Table`;\n }\n}\n\n/**\n * Generates file name for migration.\n */\nfunction generateFileName(\n tableName: string,\n type: 'create' | 'alter' | 'drop',\n timestamp?: string\n): string {\n const ts = timestamp ?? generateTimestamp();\n const action = type === 'create' ? 'create' : type === 'drop' ? 'drop' : 'update';\n return `${ts}_${action}_${tableName}_table.php`;\n}\n\n/**\n * Renders the up method body for a create table operation.\n */\nfunction renderCreateTableUp(blueprint: TableBlueprint): string {\n const lines: string[] = [];\n\n // Column definitions\n for (const column of blueprint.columns) {\n lines.push(` ${formatColumnMethod(column)}`);\n }\n\n // Foreign keys (separate for Laravel best practices)\n // Note: Foreign keys should be in a separate migration or at the end\n // We'll include them in the same migration for simplicity\n\n return lines.join('\\n');\n}\n\n/**\n * Renders foreign key constraints (usually added after all columns).\n */\nfunction renderForeignKeys(blueprint: TableBlueprint): string {\n if (blueprint.foreignKeys.length === 0) {\n return '';\n }\n\n const lines = blueprint.foreignKeys.map(fk => ` ${formatForeignKey(fk)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Renders indexes.\n */\nfunction renderIndexes(blueprint: TableBlueprint): string {\n // Filter out indexes that are already handled (primary key, unique columns)\n const customIndexes = blueprint.indexes.filter(idx => {\n // Skip single-column unique indexes (handled by column modifier)\n if (idx.unique && idx.columns.length === 1) {\n return false;\n }\n return true;\n });\n\n if (customIndexes.length === 0) {\n return '';\n }\n\n const lines = customIndexes.map(idx => ` ${formatIndex(idx)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Generates a create table migration.\n */\nfunction generateCreateMigration(\n blueprint: TableBlueprint,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(blueprint.tableName, 'create');\n const fileName = generateFileName(blueprint.tableName, 'create', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const upContent = renderCreateTableUp(blueprint);\n const foreignKeyContent = renderForeignKeys(blueprint);\n const indexContent = renderIndexes(blueprint);\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * To modify the schema, edit the corresponding YAML file in schemas/\n * and run: npx omnify generate\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::create('${blueprint.tableName}', function (Blueprint $table) {\n${upContent}${foreignKeyContent}${indexContent}\n });\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n Schema::dropIfExists('${blueprint.tableName}');\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [blueprint.tableName],\n type: 'create',\n };\n}\n\n/**\n * Generates a drop table migration.\n */\nfunction generateDropMigration(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(tableName, 'drop');\n const fileName = generateFileName(tableName, 'drop', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::dropIfExists('${tableName}');\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n // Cannot recreate table without schema information\n // This is a one-way migration\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [tableName],\n type: 'drop',\n };\n}\n\n/**\n * Extracts FK dependencies from a schema.\n * Returns array of schema names that this schema depends on.\n */\nfunction extractDependencies(schema: LoadedSchema): string[] {\n const deps: string[] = [];\n\n if (!schema.properties) {\n return deps;\n }\n\n for (const property of Object.values(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n mappedBy?: string;\n };\n\n // ManyToOne and OneToOne (owning side) create FK columns\n if (\n (assocProp.relation === 'ManyToOne' || assocProp.relation === 'OneToOne') &&\n !assocProp.mappedBy &&\n assocProp.target\n ) {\n deps.push(assocProp.target);\n }\n }\n\n return deps;\n}\n\n/**\n * Topological sort of schemas based on FK dependencies.\n * Returns schemas in order where dependencies come before dependents.\n */\nfunction topologicalSort(schemas: SchemaCollection): LoadedSchema[] {\n const schemaList = Object.values(schemas).filter(s => s.kind !== 'enum');\n const sorted: LoadedSchema[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>(); // For cycle detection\n\n function visit(schema: LoadedSchema): void {\n if (visited.has(schema.name)) {\n return;\n }\n\n if (visiting.has(schema.name)) {\n // Circular dependency - just continue (FK can be nullable)\n return;\n }\n\n visiting.add(schema.name);\n\n // Visit dependencies first\n const deps = extractDependencies(schema);\n for (const depName of deps) {\n const depSchema = schemas[depName];\n if (depSchema && depSchema.kind !== 'enum') {\n visit(depSchema);\n }\n }\n\n visiting.delete(schema.name);\n visited.add(schema.name);\n sorted.push(schema);\n }\n\n // Visit all schemas\n for (const schema of schemaList) {\n visit(schema);\n }\n\n return sorted;\n}\n\n/**\n * Generates migrations for all schemas.\n */\nexport function generateMigrations(\n schemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile[] {\n const migrations: MigrationFile[] = [];\n const pivotTablesGenerated = new Set<string>();\n let timestampOffset = 0;\n\n // Note: File table (for polymorphic file storage) is now managed as a proper schema (File.yaml)\n // It will be processed like any other schema in the topological sort below.\n // Use ensureFileSchema() from @famgia/omnify-core to auto-generate File.yaml when needed.\n\n // Sort schemas by FK dependencies (topological sort)\n const sortedSchemas = topologicalSort(schemas);\n\n // Generate main table migrations in dependency order\n for (const schema of sortedSchemas) {\n // Generate timestamp with offset to ensure unique filenames\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = schemaToBlueprint(schema, schemas, {\n customTypes: options.customTypes,\n locale: options.locale,\n });\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n\n // Third pass: generate pivot table migrations for ManyToMany (always last)\n for (const schema of sortedSchemas) {\n const pivotTables = extractManyToManyRelations(schema, schemas);\n\n for (const pivot of pivotTables) {\n // Skip if already generated\n if (pivotTablesGenerated.has(pivot.tableName)) {\n continue;\n }\n pivotTablesGenerated.add(pivot.tableName);\n\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = generatePivotTableBlueprint(pivot);\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n }\n\n return migrations;\n}\n\n/**\n * Increments a timestamp by seconds.\n */\nfunction incrementTimestamp(timestamp: string, seconds: number): string {\n if (seconds === 0) return timestamp;\n\n // Parse timestamp: YYYY_MM_DD_HHMMSS\n const parts = timestamp.split('_');\n if (parts.length < 4) {\n // Invalid format, return original\n return timestamp;\n }\n\n const yearPart = parts[0] ?? '2024';\n const monthPart = parts[1] ?? '01';\n const dayPart = parts[2] ?? '01';\n const timePart = parts[3] ?? '000000';\n\n const year = parseInt(yearPart, 10);\n const month = parseInt(monthPart, 10) - 1;\n const day = parseInt(dayPart, 10);\n const hours = parseInt(timePart.substring(0, 2), 10);\n const minutes = parseInt(timePart.substring(2, 4), 10);\n const secs = parseInt(timePart.substring(4, 6), 10);\n\n const date = new Date(year, month, day, hours, minutes, secs + seconds);\n\n const newYear = date.getFullYear();\n const newMonth = String(date.getMonth() + 1).padStart(2, '0');\n const newDay = String(date.getDate()).padStart(2, '0');\n const newHours = String(date.getHours()).padStart(2, '0');\n const newMinutes = String(date.getMinutes()).padStart(2, '0');\n const newSecs = String(date.getSeconds()).padStart(2, '0');\n\n return `${newYear}_${newMonth}_${newDay}_${newHours}${newMinutes}${newSecs}`;\n}\n\n/**\n * Generates migration from a single schema.\n */\nexport function generateMigrationFromSchema(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile {\n const blueprint = schemaToBlueprint(schema, allSchemas);\n return generateCreateMigration(blueprint, options);\n}\n\n/**\n * Generates drop migration for a table.\n */\nexport function generateDropMigrationForTable(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n return generateDropMigration(tableName, options);\n}\n\n/**\n * Formats migration content for writing to file.\n */\nexport function formatMigrationFile(migration: MigrationFile): string {\n return migration.content;\n}\n\n/**\n * Gets the output path for a migration file.\n */\nexport function getMigrationPath(\n migration: MigrationFile,\n outputDir: string = 'database/migrations'\n): string {\n return `${outputDir}/${migration.fileName}`;\n}\n","/**\n * @famgia/omnify-laravel - ALTER Migration Generator\n *\n * Generates Laravel migration files for ALTER table operations.\n */\n\nimport type { SchemaChange, PropertySnapshot } from '@famgia/omnify-atlas';\nimport type { MigrationFile, MigrationOptions } from './types.js';\nimport { toTableName, toColumnName } from './schema-builder.js';\n\n/**\n * Maps Omnify property types to Laravel column methods.\n */\nconst TYPE_METHOD_MAP: Record<string, string> = {\n String: 'string',\n TinyInt: 'tinyInteger',\n Int: 'integer',\n BigInt: 'bigInteger',\n Float: 'double',\n Decimal: 'decimal',\n Boolean: 'boolean',\n Text: 'text',\n MediumText: 'mediumText',\n LongText: 'longText',\n Date: 'date',\n Time: 'time',\n DateTime: 'dateTime',\n Timestamp: 'timestamp',\n Json: 'json',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'json',\n Enum: 'enum',\n Select: 'string',\n Lookup: 'unsignedBigInteger',\n};\n\n/**\n * Generates timestamp prefix for migration file name.\n */\nfunction generateTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;\n}\n\n/**\n * Formats a column addition.\n */\nfunction formatAddColumn(columnName: string, prop: PropertySnapshot): string {\n const snakeColumn = toColumnName(columnName);\n const method = TYPE_METHOD_MAP[prop.type] ?? 'string';\n\n let code: string;\n\n // Handle decimal with precision and scale\n if (prop.type === 'Decimal') {\n const precision = prop.precision ?? 8;\n const scale = prop.scale ?? 2;\n code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;\n } else {\n code = `$table->${method}('${snakeColumn}')`;\n }\n\n // Add modifiers\n if (prop.nullable) code += '->nullable()';\n if (prop.unique) code += '->unique()';\n if (prop.default !== undefined) {\n const defaultValue = typeof prop.default === 'string'\n ? `'${prop.default}'`\n : JSON.stringify(prop.default);\n code += `->default(${defaultValue})`;\n }\n\n return code + ';';\n}\n\n/**\n * Formats a column removal.\n */\nfunction formatDropColumn(columnName: string): string {\n const snakeColumn = toColumnName(columnName);\n return `$table->dropColumn('${snakeColumn}');`;\n}\n\n/**\n * Formats a column rename.\n * Note: Requires doctrine/dbal package in Laravel.\n */\nfunction formatRenameColumn(oldName: string, newName: string): string {\n const oldSnake = toColumnName(oldName);\n const newSnake = toColumnName(newName);\n return `$table->renameColumn('${oldSnake}', '${newSnake}');`;\n}\n\n/**\n * Formats a column modification.\n * Note: Requires doctrine/dbal package in Laravel.\n */\nfunction formatModifyColumn(\n columnName: string,\n _prevProp: PropertySnapshot,\n currProp: PropertySnapshot\n): string {\n const snakeColumn = toColumnName(columnName);\n const method = TYPE_METHOD_MAP[currProp.type] ?? 'string';\n\n let code: string;\n\n // Handle decimal with precision and scale\n if (currProp.type === 'Decimal') {\n const precision = currProp.precision ?? 8;\n const scale = currProp.scale ?? 2;\n code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;\n } else {\n code = `$table->${method}('${snakeColumn}')`;\n }\n\n // Add modifiers\n if (currProp.nullable) code += '->nullable()';\n if (currProp.unique) code += '->unique()';\n if (currProp.default !== undefined) {\n const defaultValue = typeof currProp.default === 'string'\n ? `'${currProp.default}'`\n : JSON.stringify(currProp.default);\n code += `->default(${defaultValue})`;\n }\n\n return code + '->change();';\n}\n\n/**\n * Formats an index addition.\n */\nfunction formatAddIndex(columns: readonly string[], unique: boolean): string {\n const snakeColumns = columns.map(toColumnName);\n const method = unique ? 'unique' : 'index';\n const colsArg = snakeColumns.length === 1\n ? `'${snakeColumns[0]}'`\n : `[${snakeColumns.map(c => `'${c}'`).join(', ')}]`;\n\n return `$table->${method}(${colsArg});`;\n}\n\n/**\n * Formats an index removal.\n */\nfunction formatDropIndex(tableName: string, columns: readonly string[], unique: boolean): string {\n const snakeColumns = columns.map(toColumnName);\n const method = unique ? 'dropUnique' : 'dropIndex';\n\n // Laravel generates index names as: {table}_{columns}_{type}\n const suffix = unique ? 'unique' : 'index';\n const indexName = `${tableName}_${snakeColumns.join('_')}_${suffix}`;\n\n return `$table->${method}('${indexName}');`;\n}\n\n/**\n * Generates ALTER migration content for a schema change.\n */\nfunction generateAlterMigrationContent(\n tableName: string,\n change: SchemaChange,\n options: MigrationOptions = {}\n): string {\n const upLines: string[] = [];\n const downLines: string[] = [];\n\n // Column changes\n if (change.columnChanges) {\n for (const col of change.columnChanges) {\n if (col.changeType === 'added' && col.currentDef) {\n upLines.push(` ${formatAddColumn(col.column, col.currentDef)}`);\n downLines.push(` ${formatDropColumn(col.column)}`);\n } else if (col.changeType === 'removed' && col.previousDef) {\n upLines.push(` ${formatDropColumn(col.column)}`);\n downLines.push(` ${formatAddColumn(col.column, col.previousDef)}`);\n } else if (col.changeType === 'modified' && col.previousDef && col.currentDef) {\n upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);\n downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);\n } else if (col.changeType === 'renamed' && col.previousColumn) {\n // Rename column\n upLines.push(` ${formatRenameColumn(col.previousColumn, col.column)}`);\n downLines.push(` ${formatRenameColumn(col.column, col.previousColumn)}`);\n\n // If there are also property modifications, apply them after rename\n if (col.modifications && col.modifications.length > 0 && col.previousDef && col.currentDef) {\n upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);\n downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);\n }\n }\n }\n }\n\n // Index changes\n if (change.indexChanges) {\n for (const idx of change.indexChanges) {\n if (idx.changeType === 'added') {\n upLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);\n downLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);\n } else {\n upLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);\n downLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);\n }\n }\n }\n\n // Option changes (timestamps, softDelete)\n if (change.optionChanges) {\n if (change.optionChanges.timestamps) {\n const { from, to } = change.optionChanges.timestamps;\n if (to && !from) {\n upLines.push(` $table->timestamps();`);\n downLines.push(` $table->dropTimestamps();`);\n } else if (from && !to) {\n upLines.push(` $table->dropTimestamps();`);\n downLines.push(` $table->timestamps();`);\n }\n }\n\n if (change.optionChanges.softDelete) {\n const { from, to } = change.optionChanges.softDelete;\n if (to && !from) {\n upLines.push(` $table->softDeletes();`);\n downLines.push(` $table->dropSoftDeletes();`);\n } else if (from && !to) {\n upLines.push(` $table->dropSoftDeletes();`);\n downLines.push(` $table->softDeletes();`);\n }\n }\n }\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n return `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * To modify the schema, edit the corresponding YAML file in schemas/\n * and run: npx omnify generate\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::table('${tableName}', function (Blueprint $table) {\n${upLines.join('\\n')}\n });\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n Schema::table('${tableName}', function (Blueprint $table) {\n${downLines.join('\\n')}\n });\n }\n};\n`;\n}\n\n/**\n * Generates ALTER migration for a modified schema.\n */\nexport function generateAlterMigration(\n change: SchemaChange,\n options: MigrationOptions = {}\n): MigrationFile | null {\n if (change.changeType !== 'modified') {\n return null;\n }\n\n // Check if there are actual changes to migrate\n const hasChanges =\n (change.columnChanges && change.columnChanges.length > 0) ||\n (change.indexChanges && change.indexChanges.length > 0) ||\n (change.optionChanges &&\n (change.optionChanges.timestamps ||\n change.optionChanges.softDelete));\n\n if (!hasChanges) {\n return null;\n }\n\n const tableName = toTableName(change.schemaName);\n const timestamp = options.timestamp ?? generateTimestamp();\n const fileName = `${timestamp}_update_${tableName}_table.php`;\n\n const content = generateAlterMigrationContent(tableName, change, options);\n\n return {\n fileName,\n className: `Update${change.schemaName}Table`,\n content,\n tables: [tableName],\n type: 'alter',\n };\n}\n\n/**\n * Generates DROP migration for a removed schema.\n */\nexport function generateDropTableMigration(\n schemaName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n const tableName = toTableName(schemaName);\n const timestamp = options.timestamp ?? generateTimestamp();\n const fileName = `${timestamp}_drop_${tableName}_table.php`;\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::dropIfExists('${tableName}');\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n // Cannot recreate table without full schema\n // Consider restoring from backup if needed\n }\n};\n`;\n\n return {\n fileName,\n className: `Drop${schemaName}Table`,\n content,\n tables: [tableName],\n type: 'drop',\n };\n}\n\n/**\n * Generates migrations for all schema changes.\n */\nexport function generateMigrationsFromChanges(\n changes: readonly SchemaChange[],\n options: MigrationOptions = {}\n): MigrationFile[] {\n const migrations: MigrationFile[] = [];\n let timestampOffset = 0;\n\n const getNextTimestamp = () => {\n const ts = options.timestamp ?? generateTimestamp();\n const offset = timestampOffset++;\n if (offset === 0) return ts;\n\n // Increment seconds\n const parts = ts.split('_');\n if (parts.length >= 4) {\n const timePart = parts[3] ?? '000000';\n const secs = parseInt(timePart.substring(4, 6), 10) + offset;\n const newSecs = String(secs % 60).padStart(2, '0');\n parts[3] = timePart.substring(0, 4) + newSecs;\n return parts.join('_');\n }\n return ts;\n };\n\n for (const change of changes) {\n if (change.changeType === 'modified') {\n const migration = generateAlterMigration(change, {\n ...options,\n timestamp: getNextTimestamp(),\n });\n if (migration) {\n migrations.push(migration);\n }\n } else if (change.changeType === 'removed') {\n migrations.push(\n generateDropTableMigration(change.schemaName, {\n ...options,\n timestamp: getNextTimestamp(),\n })\n );\n }\n // 'added' changes are handled by the regular CREATE migration generator\n }\n\n return migrations;\n}\n","/**\n * Laravel Model Generator\n *\n * Generates Eloquent model classes from Omnify schemas.\n * Creates base models (auto-generated) and user models (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, AssociationDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { pluralize, toSnakeCase, toPascalCase, toCamelCase } from '../utils.js';\n\n/**\n * Options for model generation.\n */\nexport interface ModelGeneratorOptions {\n /**\n * Base model namespace.\n * @default 'App\\\\Models\\\\OmnifyBase'\n */\n baseModelNamespace?: string;\n\n /**\n * User model namespace.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Base model class name.\n * @default 'BaseModel'\n */\n baseModelClassName?: string;\n\n /**\n * Output path for base models.\n * @default 'app/Models/OmnifyBase'\n */\n baseModelPath?: string;\n\n /**\n * Output path for user models.\n * @default 'app/Models'\n */\n modelPath?: string;\n\n /**\n * Output path for service provider files.\n * @default 'app/Providers'\n */\n providersPath?: string;\n\n /**\n * Custom types registered by plugins.\n * Used to expand compound types in fillable array.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Generated model output.\n */\nexport interface GeneratedModel {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Model type */\n type: 'base-model' | 'entity-base' | 'entity' | 'service-provider' | 'provider-registration' | 'trait' | 'locales';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n}\n\n/**\n * Provider registration result.\n */\nexport interface ProviderRegistrationResult {\n /** Path to the provider registration file */\n path: string;\n /** Modified content */\n content: string;\n /** Laravel version type */\n laravelVersion: 'laravel11+' | 'laravel10-';\n /** Whether registration was already present */\n alreadyRegistered: boolean;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseModelNamespace: string;\n modelNamespace: string;\n baseModelClassName: string;\n baseModelPath: string;\n modelPath: string;\n providersPath: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseModelNamespace: 'App\\\\Models\\\\OmnifyBase',\n modelNamespace: 'App\\\\Models',\n baseModelClassName: 'BaseModel',\n baseModelPath: 'app/Models/OmnifyBase',\n modelPath: 'app/Models',\n providersPath: 'app/Providers',\n customTypes: new Map(),\n};\n\n/**\n * Generate PHP array entries for localized display names.\n * Converts LocalizedString to PHP array format.\n */\nfunction generateLocalizedDisplayNames(displayName: LocalizedString | undefined, indent: string = ' '): string {\n if (displayName === undefined) {\n return '';\n }\n\n if (typeof displayName === 'string') {\n // Single string - use 'en' as default locale\n return `${indent}'en' => '${escapePhpString(displayName)}',`;\n }\n\n if (isLocaleMap(displayName)) {\n const entries = Object.entries(displayName)\n .map(([locale, value]) => `${indent}'${locale}' => '${escapePhpString(value)}',`)\n .join('\\n');\n return entries;\n }\n\n return '';\n}\n\n/**\n * Generate PHP array entries for property localized display names.\n */\nfunction generatePropertyLocalizedDisplayNames(\n schema: LoadedSchema,\n indent: string = ' '\n): string {\n const properties = schema.properties ?? {};\n const entries: string[] = [];\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n const displayName = (propDef as { displayName?: LocalizedString }).displayName;\n\n if (displayName === undefined) {\n continue;\n }\n\n const innerIndent = indent + ' ';\n\n if (typeof displayName === 'string') {\n entries.push(`${indent}'${snakeName}' => [\\n${innerIndent}'en' => '${escapePhpString(displayName)}',\\n${indent}],`);\n } else if (isLocaleMap(displayName)) {\n const localeEntries = Object.entries(displayName)\n .map(([locale, value]) => `${innerIndent}'${locale}' => '${escapePhpString(value)}',`)\n .join('\\n');\n entries.push(`${indent}'${snakeName}' => [\\n${localeEntries}\\n${indent}],`);\n }\n }\n\n return entries.join('\\n');\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: ModelGeneratorOptions): ResolvedOptions {\n return {\n baseModelNamespace: options?.baseModelNamespace ?? DEFAULT_OPTIONS.baseModelNamespace,\n modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,\n baseModelClassName: options?.baseModelClassName ?? DEFAULT_OPTIONS.baseModelClassName,\n baseModelPath: options?.baseModelPath ?? DEFAULT_OPTIONS.baseModelPath,\n modelPath: options?.modelPath ?? DEFAULT_OPTIONS.modelPath,\n providersPath: options?.providersPath ?? DEFAULT_OPTIONS.providersPath,\n customTypes: options?.customTypes ?? new Map(),\n };\n}\n\n/**\n * Get PHP type for casting.\n */\nfunction getCastType(propDef: PropertyDefinition): string | null {\n switch (propDef.type) {\n case 'Boolean':\n return 'boolean';\n case 'Int':\n case 'BigInt':\n return 'integer';\n case 'Float':\n return 'float';\n case 'Decimal':\n return 'decimal:' + ((propDef as any).scale ?? 2);\n case 'Json':\n return 'array';\n case 'Date':\n return 'date';\n case 'DateTime':\n case 'Timestamp':\n return 'datetime';\n case 'Password':\n return 'hashed';\n default:\n return null;\n }\n}\n\n/**\n * Check if a property definition is nullable.\n * For associations, check the 'nullable' field if it exists as an extension.\n */\nfunction isNullable(propDef: PropertyDefinition): boolean {\n // BasePropertyDefinition has nullable, AssociationDefinition does not\n // But some schemas may define nullable on associations as an extension\n return 'nullable' in propDef && propDef.nullable === true;\n}\n\n/**\n * Get PHP doc type for a property.\n */\nfunction getPhpDocType(propDef: PropertyDefinition, schemas: SchemaCollection): string {\n const nullable = isNullable(propDef);\n\n switch (propDef.type) {\n case 'String':\n case 'Text':\n case 'LongText':\n case 'Email':\n case 'Password':\n return 'string' + (nullable ? '|null' : '');\n case 'Int':\n case 'BigInt':\n return 'int' + (nullable ? '|null' : '');\n case 'Float':\n case 'Decimal':\n return 'float' + (nullable ? '|null' : '');\n case 'Boolean':\n return 'bool' + (nullable ? '|null' : '');\n case 'Date':\n case 'DateTime':\n case 'Time':\n case 'Timestamp':\n return '\\\\Carbon\\\\Carbon' + (nullable ? '|null' : '');\n case 'Json':\n return 'array' + (nullable ? '|null' : '');\n case 'Enum':\n case 'EnumRef':\n return 'string' + (nullable ? '|null' : '');\n case 'Association': {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n const className = toPascalCase(assoc.target);\n switch (assoc.relation) {\n case 'OneToMany':\n case 'ManyToMany':\n case 'MorphMany':\n case 'MorphToMany':\n case 'MorphedByMany':\n return `\\\\Illuminate\\\\Database\\\\Eloquent\\\\Collection<${className}>`;\n default:\n // ManyToOne, OneToOne - typically nullable unless owning\n return className + '|null';\n }\n }\n return 'mixed';\n }\n default:\n return 'mixed';\n }\n}\n\n/**\n * Expand compound type property into field names.\n * Returns array of field names (snake_case) or null if not a compound type.\n */\nfunction expandCompoundTypeFields(\n propName: string,\n propType: string,\n customTypes: ReadonlyMap<string, CustomTypeDefinition>\n): string[] | null {\n const typeDef = customTypes.get(propType);\n\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const snakeName = toSnakeCase(propName);\n const fields: string[] = [];\n\n for (const field of typeDef.expand) {\n // Convert suffix to snake_case and combine with property name\n const suffixSnake = toSnakeCase(field.suffix);\n fields.push(`${snakeName}_${suffixSnake}`);\n }\n\n return fields;\n}\n\n/**\n * Generate the shared BaseModel class.\n */\nfunction generateBaseModel(\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Build model map\n const modelMap = Object.values(schemas)\n .filter(s => s.kind !== 'enum')\n .map(s => {\n const className = toPascalCase(s.name);\n return ` '${s.name}' => \\\\${options.modelNamespace}\\\\${className}::class,`;\n })\n .join('\\n');\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{BASE_MODEL_CLASS\\}\\}/g, options.baseModelClassName)\n .replace(/\\{\\{MODEL_MAP\\}\\}/g, modelMap);\n\n return {\n path: `${options.baseModelPath}/${options.baseModelClassName}.php`,\n content,\n type: 'base-model',\n overwrite: true,\n schemaName: '__base__',\n };\n}\n\n/**\n * Generate entity base model (auto-generated).\n */\nfunction generateEntityBaseModel(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string,\n authStubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n const isAuth = schema.options?.authenticatable ?? false;\n\n // Determine primary key\n // Check if id is disabled and we need to find a custom primary key\n const hasAutoId = schema.options?.id !== false;\n let primaryKey = 'id';\n let isStringKey = false;\n let isUuid = false;\n let isNonIncrementing = false;\n\n if (hasAutoId) {\n // Standard auto-incrementing or UUID id\n const idType = schema.options?.idType ?? 'BigInt';\n isUuid = idType === 'Uuid';\n isStringKey = idType === 'Uuid' || idType === 'String';\n isNonIncrementing = isUuid;\n } else {\n // Custom primary key - find the property with primary: true\n const properties = schema.properties ?? {};\n for (const [propName, propDef] of Object.entries(properties)) {\n if ((propDef as { primary?: boolean }).primary === true) {\n primaryKey = toSnakeCase(propName);\n // Determine if it's a string-type key\n const propType = propDef.type;\n isStringKey = propType === 'String' || propType === 'Text' || propType === 'Email';\n isNonIncrementing = true; // Custom primary keys are not auto-incrementing\n break;\n }\n }\n }\n\n // Build imports, traits, fillable, hidden, casts, relations\n const imports: string[] = [];\n const traits: string[] = [];\n const fillable: string[] = [];\n const hidden: string[] = [];\n const appends: string[] = [];\n const casts: string[] = [];\n const relations: string[] = [];\n const docProperties: string[] = [];\n\n // Add soft delete\n if (schema.options?.softDelete) {\n imports.push('use Illuminate\\\\Database\\\\Eloquent\\\\SoftDeletes;');\n traits.push(' use SoftDeletes;');\n }\n\n // Process properties\n const properties = schema.properties ?? {};\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Check if this is a compound type (defer docProperties to expanded fields)\n const typeDef = options.customTypes.get(propDef.type);\n const isCompoundType = typeDef?.compound && typeDef.expand;\n\n // Add to doc comments (skip for compound types - they'll be added per field)\n if (!isCompoundType) {\n const phpType = getPhpDocType(propDef, schemas);\n docProperties.push(` * @property ${phpType} $${snakeName}`);\n }\n\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n imports.push(`use ${options.modelNamespace}\\\\${toPascalCase(assoc.target)};`);\n }\n relations.push(generateRelation(propName, assoc, schema, schemas, options));\n\n // Add foreign key to fillable for belongsTo relations\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (!assoc.mappedBy) {\n const fkName = toSnakeCase(propName) + '_id';\n fillable.push(` '${fkName}',`);\n docProperties.push(` * @property int|null $${fkName}`);\n }\n }\n } else if (propDef.type === 'Password') {\n // Check if fillable: false is set\n const propWithFillable = propDef as { fillable?: boolean };\n if (propWithFillable.fillable !== false) {\n fillable.push(` '${snakeName}',`);\n }\n hidden.push(` '${snakeName}',`);\n const cast = getCastType(propDef);\n if (cast) {\n casts.push(` '${snakeName}' => '${cast}',`);\n }\n } else if (propDef.type === 'File') {\n // File properties don't add to fillable (polymorphic)\n const relMethod = generateFileRelation(propName, propDef as any);\n relations.push(relMethod);\n } else {\n // Check for fillable property (default: true)\n const propWithOptions = propDef as { fillable?: boolean; hidden?: boolean; fields?: Record<string, { nullable?: boolean; hidden?: boolean; fillable?: boolean }> };\n const isFillable = propWithOptions.fillable !== false;\n const isHidden = propWithOptions.hidden === true;\n\n // Check if this is a compound type that should be expanded\n const typeDef = options.customTypes.get(propDef.type);\n const isCompoundType = typeDef?.compound && typeDef.expand;\n\n if (isCompoundType && typeDef.expand) {\n // Compound type - process each expanded field with per-field overrides\n const fieldOverrides = propWithOptions.fields ?? {};\n const basePropWithNullable = propDef as { nullable?: boolean };\n\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const override = fieldOverrides[field.suffix];\n\n // Determine nullable for PHP type\n const fieldNullable = override?.nullable ?? basePropWithNullable.nullable ?? false;\n const phpType = field.typescript?.type === 'number' ? 'int' : 'string';\n const nullSuffix = fieldNullable ? '|null' : '';\n docProperties.push(` * @property ${phpType}${nullSuffix} $${fieldName}`);\n\n // Determine fillable: use field override if set, otherwise use property-level setting\n const fieldFillable = override?.fillable !== undefined ? override.fillable : isFillable;\n if (fieldFillable) {\n fillable.push(` '${fieldName}',`);\n }\n\n // Determine hidden: use field override if set, otherwise use property-level setting\n const fieldHidden = override?.hidden !== undefined ? override.hidden : isHidden;\n if (fieldHidden) {\n hidden.push(` '${fieldName}',`);\n }\n }\n } else {\n // Regular property\n if (isFillable) {\n fillable.push(` '${snakeName}',`);\n }\n\n const cast = getCastType(propDef);\n if (cast) {\n casts.push(` '${snakeName}' => '${cast}',`);\n }\n\n // Check for hidden: true property (for non-Password types)\n if (isHidden) {\n hidden.push(` '${snakeName}',`);\n }\n }\n\n // Check for compound type accessors (reuse typeDef from above)\n if (typeDef?.compound && typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n // Generate accessor name with property prefix\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n appends.push(` '${accessorName}',`);\n\n // Generate accessor method\n const methodName = toPascalCase(accessorName);\n const separator = accessor.separator ?? ' ';\n\n // Build field references\n const fieldRefs = accessor.fields.map(field => {\n const fieldName = `${snakeName}_${toSnakeCase(field)}`;\n return `$this->${fieldName}`;\n });\n\n // Generate accessor method with null filtering for optional fields\n const accessorMethod = ` /**\n * Get the ${accessor.name.replace(/_/g, ' ')} attribute.\n */\n public function get${methodName}Attribute(): ?string\n {\n $parts = array_filter([${fieldRefs.join(', ')}], fn($v) => $v !== null && $v !== '');\n return count($parts) > 0 ? implode('${separator}', $parts) : null;\n }`;\n relations.push(accessorMethod);\n }\n }\n }\n }\n\n // Build doc comment\n const docComment = `/**\n * ${className}BaseModel\n *\n${docProperties.join('\\n')}\n */`;\n\n // Choose stub based on authenticatable\n const stub = isAuth ? authStubContent : stubContent;\n\n // Build key type and incrementing\n const keyType = isStringKey ? ` /**\n * The \"type\" of the primary key ID.\n */\n protected $keyType = 'string';\n\n` : '';\n\n const incrementing = isNonIncrementing ? ` /**\n * Indicates if the IDs are auto-incrementing.\n */\n public $incrementing = false;\n\n` : '';\n\n // Add UUID trait if needed\n if (isUuid) {\n imports.push('use Illuminate\\\\Database\\\\Eloquent\\\\Concerns\\\\HasUuids;');\n traits.push(' use HasUuids;');\n }\n\n const content = stub\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{BASE_MODEL_CLASS\\}\\}/g, options.baseModelClassName)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className)\n .replace(/\\{\\{TABLE_NAME\\}\\}/g, tableName)\n .replace(/\\{\\{PRIMARY_KEY\\}\\}/g, primaryKey)\n .replace(/\\{\\{KEY_TYPE\\}\\}/g, keyType)\n .replace(/\\{\\{INCREMENTING\\}\\}/g, incrementing)\n .replace(/\\{\\{TIMESTAMPS\\}\\}/g, schema.options?.timestamps !== false ? 'true' : 'false')\n .replace(/\\{\\{IMPORTS\\}\\}/g, [...new Set(imports)].sort().join('\\n'))\n .replace(/\\{\\{TRAITS\\}\\}/g, traits.join('\\n'))\n .replace(/\\{\\{DOC_COMMENT\\}\\}/g, docComment)\n .replace(/\\{\\{FILLABLE\\}\\}/g, fillable.join('\\n'))\n .replace(/\\{\\{HIDDEN\\}\\}/g, hidden.join('\\n'))\n .replace(/\\{\\{APPENDS\\}\\}/g, appends.join('\\n'))\n .replace(/\\{\\{CASTS\\}\\}/g, casts.join('\\n'))\n .replace(/\\{\\{RELATIONS\\}\\}/g, relations.join('\\n\\n'));\n\n return {\n path: `${options.baseModelPath}/${className}BaseModel.php`,\n content,\n type: 'entity-base',\n overwrite: true,\n schemaName: schema.name,\n };\n}\n\n/**\n * Find the inverse ManyToOne relationship on target schema that points back to current schema.\n */\nfunction findInverseRelation(\n currentSchemaName: string,\n targetSchemaName: string,\n schemas: SchemaCollection\n): string | null {\n const targetSchema = schemas[targetSchemaName];\n if (!targetSchema || !targetSchema.properties) {\n return null;\n }\n\n for (const [propName, propDef] of Object.entries(targetSchema.properties)) {\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' && assoc.target === currentSchemaName) {\n return propName;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Generate relation method.\n */\nfunction generateRelation(\n propName: string,\n assoc: AssociationDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string {\n const methodName = toCamelCase(propName);\n const targetClass = assoc.target ? toPascalCase(assoc.target) : '';\n const fkName = toSnakeCase(propName) + '_id';\n\n switch (assoc.relation) {\n case 'ManyToOne':\n return ` /**\n * Get the ${propName} that owns this model.\n */\n public function ${methodName}(): BelongsTo\n {\n return $this->belongsTo(${targetClass}::class, '${fkName}');\n }`;\n\n case 'OneToOne':\n if (assoc.mappedBy) {\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): HasOne\n {\n return $this->hasOne(${targetClass}::class, '${toSnakeCase(assoc.mappedBy)}_id');\n }`;\n }\n return ` /**\n * Get the ${propName} that owns this model.\n */\n public function ${methodName}(): BelongsTo\n {\n return $this->belongsTo(${targetClass}::class, '${fkName}');\n }`;\n\n case 'OneToMany': {\n // Find the inverse ManyToOne relationship on target to determine correct FK\n let foreignKey: string;\n if (assoc.inversedBy) {\n // If inversedBy is specified, use it\n foreignKey = toSnakeCase(assoc.inversedBy) + '_id';\n } else if (assoc.target) {\n // Look up the inverse relationship on the target schema\n const inverseRelation = findInverseRelation(schema.name, assoc.target, schemas);\n if (inverseRelation) {\n foreignKey = toSnakeCase(inverseRelation) + '_id';\n } else {\n // Fallback: use the current schema name as snake_case + _id\n foreignKey = toSnakeCase(schema.name) + '_id';\n }\n } else {\n foreignKey = toSnakeCase(propName) + '_id';\n }\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): HasMany\n {\n return $this->hasMany(${targetClass}::class, '${foreignKey}');\n }`;\n }\n\n case 'ManyToMany': {\n const pivotTable = assoc.joinTable ?? `${toSnakeCase(propName)}_pivot`;\n \n // Generate withPivot() for pivot fields\n // First check this side's pivotFields, then check the inverse side if mappedBy is specified\n let pivotFieldNames: string[] = [];\n \n if (assoc.pivotFields && Object.keys(assoc.pivotFields).length > 0) {\n // This is the owning side with pivotFields defined\n pivotFieldNames = Object.keys(assoc.pivotFields).map(f => toSnakeCase(f));\n } else if (assoc.mappedBy && assoc.target) {\n // This is the inverse side - look up pivotFields from the owning side\n const targetSchema = schemas[assoc.target];\n if (targetSchema?.properties) {\n const owningProp = targetSchema.properties[assoc.mappedBy];\n if (owningProp?.type === 'Association') {\n const owningAssoc = owningProp as AssociationDefinition;\n if (owningAssoc.pivotFields && Object.keys(owningAssoc.pivotFields).length > 0) {\n pivotFieldNames = Object.keys(owningAssoc.pivotFields).map(f => toSnakeCase(f));\n }\n }\n }\n }\n \n const pivotFieldsCode = pivotFieldNames.length > 0\n ? pivotFieldNames.map(f => `'${f}'`).join(', ')\n : null;\n \n const withPivotLine = pivotFieldsCode\n ? `\\n ->withPivot(${pivotFieldsCode})`\n : '';\n \n return ` /**\n * The ${propName} that belong to this model.\n */\n public function ${methodName}(): BelongsToMany\n {\n return $this->belongsToMany(${targetClass}::class, '${pivotTable}')${withPivotLine}\n ->withTimestamps();\n }`;\n }\n\n case 'MorphTo':\n return ` /**\n * Get the parent ${propName} model.\n */\n public function ${methodName}(): MorphTo\n {\n return $this->morphTo('${methodName}');\n }`;\n\n case 'MorphOne':\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): MorphOne\n {\n return $this->morphOne(${targetClass}::class, '${assoc.morphName ?? propName}');\n }`;\n\n case 'MorphMany':\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): MorphMany\n {\n return $this->morphMany(${targetClass}::class, '${assoc.morphName ?? propName}');\n }`;\n\n default:\n return ` // TODO: Implement ${assoc.relation} relation for ${propName}`;\n }\n}\n\n/**\n * Generate file relation method.\n */\nfunction generateFileRelation(propName: string, propDef: { multiple?: boolean }): string {\n const methodName = toCamelCase(propName);\n const relationType = propDef.multiple ? 'MorphMany' : 'MorphOne';\n const relationMethod = propDef.multiple ? 'morphMany' : 'morphOne';\n\n return ` /**\n * Get the ${propName} file(s) for this model.\n */\n public function ${methodName}(): ${relationType}\n {\n return $this->${relationMethod}(FileUpload::class, 'uploadable')\n ->where('attribute_name', '${propName}');\n }`;\n}\n\n/**\n * Generate user model (created once, not overwritten).\n */\nfunction generateEntityModel(\n schema: LoadedSchema,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{MODEL_NAMESPACE\\}\\}/g, options.modelNamespace)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className);\n\n return {\n path: `${options.modelPath}/${className}.php`,\n content,\n type: 'entity',\n overwrite: false, // Never overwrite user models\n schemaName: schema.name,\n };\n}\n\n/**\n * Read stub file content.\n */\nfunction getStubContent(stubName: string): string {\n // Stubs are embedded as strings since this runs in Node.js\n const stubs: Record<string, string> = {\n 'base-model': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * Base model class for all Omnify-generated models.\n * Contains model mapping for polymorphic relations.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Eloquent\\\\Model;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation;\n\nabstract class {{BASE_MODEL_CLASS}} extends Model\n{\n /**\n * Model class map for polymorphic relations.\n */\n protected static array $modelMap = [\n{{MODEL_MAP}}\n ];\n\n /**\n * Boot the model and register morph map.\n */\n protected static function boot(): void\n {\n parent::boot();\n\n // Register morph map for polymorphic relations\n Relation::enforceMorphMap(static::$modelMap);\n }\n\n /**\n * Get the model class for a given morph type.\n */\n public static function getModelClass(string $morphType): ?string\n {\n return static::$modelMap[$morphType] ?? null;\n }\n}\n`,\n\n 'entity-base': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Collection as EloquentCollection;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Traits\\\\HasLocalizedDisplayName;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Locales\\\\{{CLASS_NAME}}Locales;\n{{IMPORTS}}\n\n{{DOC_COMMENT}}\nclass {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}\n{\n use HasLocalizedDisplayName;\n{{TRAITS}}\n /**\n * The table associated with the model.\n */\n protected $table = '{{TABLE_NAME}}';\n\n /**\n * The primary key for the model.\n */\n protected $primaryKey = '{{PRIMARY_KEY}}';\n\n{{KEY_TYPE}}\n{{INCREMENTING}}\n /**\n * Indicates if the model should be timestamped.\n */\n public $timestamps = {{TIMESTAMPS}};\n\n /**\n * Localized display names for this model.\n *\n * @var array<string, string>\n */\n protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;\n\n /**\n * The attributes that are mass assignable.\n */\n protected $fillable = [\n{{FILLABLE}}\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n */\n protected $hidden = [\n{{HIDDEN}}\n ];\n\n /**\n * The accessors to append to the model's array form.\n */\n protected $appends = [\n{{APPENDS}}\n ];\n\n /**\n * Get the attributes that should be cast.\n */\n protected function casts(): array\n {\n return [\n{{CASTS}}\n ];\n }\n\n{{RELATIONS}}\n}\n`,\n\n 'entity-base-auth': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Foundation\\\\Auth\\\\User as Authenticatable;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Collection as EloquentCollection;\nuse Illuminate\\\\Notifications\\\\Notifiable;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Traits\\\\HasLocalizedDisplayName;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Locales\\\\{{CLASS_NAME}}Locales;\n{{IMPORTS}}\n\n{{DOC_COMMENT}}\nclass {{CLASS_NAME}}BaseModel extends Authenticatable\n{\n use Notifiable;\n use HasLocalizedDisplayName;\n{{TRAITS}}\n /**\n * The table associated with the model.\n */\n protected $table = '{{TABLE_NAME}}';\n\n /**\n * The primary key for the model.\n */\n protected $primaryKey = '{{PRIMARY_KEY}}';\n\n{{KEY_TYPE}}\n{{INCREMENTING}}\n /**\n * Indicates if the model should be timestamped.\n */\n public $timestamps = {{TIMESTAMPS}};\n\n /**\n * Localized display names for this model.\n *\n * @var array<string, string>\n */\n protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;\n\n /**\n * The attributes that are mass assignable.\n */\n protected $fillable = [\n{{FILLABLE}}\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n */\n protected $hidden = [\n{{HIDDEN}}\n ];\n\n /**\n * The accessors to append to the model's array form.\n */\n protected $appends = [\n{{APPENDS}}\n ];\n\n /**\n * Get the attributes that should be cast.\n */\n protected function casts(): array\n {\n return [\n{{CASTS}}\n ];\n }\n\n{{RELATIONS}}\n}\n`,\n\n 'entity': `<?php\n\nnamespace {{MODEL_NAMESPACE}};\n\nuse {{BASE_MODEL_NAMESPACE}}\\\\{{CLASS_NAME}}BaseModel;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Factories\\\\HasFactory;\n\n/**\n * {{CLASS_NAME}} Model\n *\n * This file is generated once and can be customized.\n * Add your custom methods and logic here.\n */\nclass {{CLASS_NAME}} extends {{CLASS_NAME}}BaseModel\n{\n use HasFactory;\n\n /**\n * Create a new model instance.\n */\n public function __construct(array $attributes = [])\n {\n parent::__construct($attributes);\n }\n\n // Add your custom methods here\n}\n`,\n\n 'service-provider': `<?php\n\nnamespace App\\\\Providers;\n\nuse App\\\\Support\\\\Omnify;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation;\nuse Illuminate\\\\Support\\\\ServiceProvider;\n\n/**\n * Omnify Service Provider\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * - Loads Omnify migrations from database/migrations/omnify\n * - Registers morph map for polymorphic relationships\n * - Exports schema paths for CLI consumption\n *\n * @generated by @famgia/omnify-laravel\n */\nclass OmnifyServiceProvider extends ServiceProvider\n{\n /**\n * Register any application services.\n */\n public function register(): void\n {\n //\n }\n\n /**\n * Bootstrap any application services.\n */\n public function boot(): void\n {\n // Load Omnify migrations from custom directory\n $this->loadMigrationsFrom(database_path('migrations/omnify'));\n\n // Register morph map for polymorphic relationships\n Relation::enforceMorphMap([\n{{MORPH_MAP}}\n ]);\n\n // Export registered schema paths for CLI (only when running artisan commands)\n if ($this->app->runningInConsole()) {\n Omnify::exportPaths();\n }\n }\n}\n`,\n\n 'has-localized-display-name': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}}\\\\Traits;\n\n/**\n * Trait for localized display names.\n * Uses Laravel's app()->getLocale() for locale resolution.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\ntrait HasLocalizedDisplayName\n{\n /**\n * Get the localized display name for this model.\n *\n * @param string|null $locale Locale code (defaults to app locale)\n * @return string\n */\n public static function displayName(?string $locale = null): string\n {\n $locale = $locale ?? app()->getLocale();\n $displayNames = static::$localizedDisplayNames ?? [];\n\n return $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? class_basename(static::class);\n }\n\n /**\n * Get all localized display names for this model.\n *\n * @return array<string, string>\n */\n public static function allDisplayNames(): array\n {\n return static::$localizedDisplayNames ?? [];\n }\n\n /**\n * Get the localized display name for a property.\n *\n * @param string $property Property name\n * @param string|null $locale Locale code (defaults to app locale)\n * @return string\n */\n public static function propertyDisplayName(string $property, ?string $locale = null): string\n {\n $locale = $locale ?? app()->getLocale();\n $displayNames = static::$localizedPropertyDisplayNames[$property] ?? [];\n\n return $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? $property;\n }\n\n /**\n * Get all localized display names for a property.\n *\n * @param string $property Property name\n * @return array<string, string>\n */\n public static function allPropertyDisplayNames(string $property): array\n {\n return static::$localizedPropertyDisplayNames[$property] ?? [];\n }\n\n /**\n * Get all property display names for a given locale.\n *\n * @param string|null $locale Locale code (defaults to app locale)\n * @return array<string, string>\n */\n public static function allPropertyDisplayNamesForLocale(?string $locale = null): array\n {\n $locale = $locale ?? app()->getLocale();\n $result = [];\n\n foreach (static::$localizedPropertyDisplayNames ?? [] as $property => $displayNames) {\n $result[$property] = $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? $property;\n }\n\n return $result;\n }\n}\n`,\n\n 'locales': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}}\\\\Locales;\n\n/**\n * Localized display names for {{CLASS_NAME}}.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\nclass {{CLASS_NAME}}Locales\n{\n /**\n * Localized display names for the model.\n *\n * @var array<string, string>\n */\n public const DISPLAY_NAMES = [\n{{LOCALIZED_DISPLAY_NAMES}}\n ];\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n public const PROPERTY_DISPLAY_NAMES = [\n{{LOCALIZED_PROPERTY_DISPLAY_NAMES}}\n ];\n}\n`,\n\n 'omnify-support': `<?php\n\nnamespace App\\\\Support;\n\n/**\n * Omnify Support Class\n *\n * Allows Laravel packages to register their schema directories.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @example\n * // In your package's ServiceProvider:\n * use App\\\\Support\\\\Omnify;\n *\n * public function boot()\n * {\n * Omnify::addSchemaPath(__DIR__.'/../database/schemas');\n * }\n *\n * @generated by @famgia/omnify-laravel\n */\nclass Omnify\n{\n /**\n * Registered schema paths from packages.\n *\n * @var array<array{path: string, namespace: string|null}>\n */\n protected static array $schemaPaths = [];\n\n /**\n * Register a schema directory path.\n *\n * @param string $path Absolute path to schema directory\n * @param string|null $namespace Optional namespace prefix for schemas\n * @return void\n */\n public static function addSchemaPath(string $path, ?string $namespace = null): void\n {\n $realPath = realpath($path);\n\n if ($realPath === false) {\n $realPath = $path;\n }\n\n static::$schemaPaths[] = [\n 'path' => $realPath,\n 'namespace' => $namespace,\n ];\n }\n\n /**\n * Get all registered schema paths.\n *\n * @return array<array{path: string, namespace: string|null}>\n */\n public static function getSchemaPaths(): array\n {\n return static::$schemaPaths;\n }\n\n /**\n * Clear all registered schema paths.\n */\n public static function clearSchemaPaths(): void\n {\n static::$schemaPaths = [];\n }\n\n /**\n * Export schema paths to JSON file for CLI consumption.\n *\n * @param string|null $outputPath Path to write JSON file\n * @return string Path to the generated file\n */\n public static function exportPaths(?string $outputPath = null): string\n {\n $outputPath = $outputPath ?? storage_path('omnify/schema-paths.json');\n\n $dir = dirname($outputPath);\n if (!is_dir($dir)) {\n mkdir($dir, 0755, true);\n }\n\n $data = [\n 'generated_at' => date('c'),\n 'paths' => static::$schemaPaths,\n ];\n\n file_put_contents($outputPath, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));\n\n return $outputPath;\n }\n}\n`,\n\n 'omnify-command': `<?php\n\nnamespace App\\\\Console\\\\Commands;\n\nuse App\\\\Support\\\\Omnify;\nuse Illuminate\\\\Console\\\\Command;\n\n/**\n * Sync registered schema paths for Omnify CLI.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\nclass OmnifySyncCommand extends Command\n{\n protected $signature = 'omnify:sync {--output= : Custom output path}';\n\n protected $description = 'Export registered schema paths for Omnify CLI';\n\n public function handle(): int\n {\n $this->info('Syncing Omnify schema paths...');\n\n $paths = Omnify::getSchemaPaths();\n\n if (empty($paths)) {\n $this->warn('No additional schema paths registered.');\n $this->line('Tip: Packages can use Omnify::addSchemaPath()');\n } else {\n $this->line('Found ' . count($paths) . ' path(s):');\n foreach ($paths as $entry) {\n $ns = $entry['namespace'] ? \" [{$entry['namespace']}]\" : '';\n $this->line(\" • {$entry['path']}{$ns}\");\n }\n }\n\n $filePath = Omnify::exportPaths($this->option('output'));\n $this->info(\"✓ Exported to: {$filePath}\");\n\n return Command::SUCCESS;\n }\n}\n`,\n };\n\n return stubs[stubName] ?? '';\n}\n\n/**\n * Generate OmnifyServiceProvider with morph map.\n */\nfunction generateServiceProvider(\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Build morph map - only include models (not enums or hidden schemas)\n const morphMap = Object.values(schemas)\n .filter(s => s.kind !== 'enum' && s.options?.hidden !== true)\n .map(s => {\n const className = toPascalCase(s.name);\n return ` '${s.name}' => \\\\${options.modelNamespace}\\\\${className}::class,`;\n })\n .join('\\n');\n\n const content = stubContent\n .replace(/\\{\\{MORPH_MAP\\}\\}/g, morphMap);\n\n return {\n path: `${options.providersPath}/OmnifyServiceProvider.php`,\n content,\n type: 'service-provider',\n overwrite: true, // Always overwrite to keep morph map in sync\n schemaName: '__service_provider__',\n };\n}\n\n/**\n * Generate the HasLocalizedDisplayName trait.\n */\nfunction generateLocalizedDisplayNameTrait(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace);\n\n return {\n path: `${options.baseModelPath}/Traits/HasLocalizedDisplayName.php`,\n content,\n type: 'trait',\n overwrite: true, // Always overwrite trait\n schemaName: '__trait__',\n };\n}\n\n/**\n * Generate the Omnify support class for package schema registration.\n */\nfunction generateOmnifySupport(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Use modelPath as base (app/Models) and go up to app/\n const appPath = options.modelPath.replace(/\\/Models$/, '');\n return {\n path: `${appPath}/Support/Omnify.php`,\n content: stubContent,\n type: 'trait', // Use trait type for support classes\n overwrite: true, // Always overwrite\n schemaName: '__omnify_support__',\n };\n}\n\n/**\n * Generate the Omnify sync artisan command.\n */\nfunction generateOmnifyCommand(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Use modelPath as base (app/Models) and go up to app/\n const appPath = options.modelPath.replace(/\\/Models$/, '');\n return {\n path: `${appPath}/Console/Commands/OmnifySyncCommand.php`,\n content: stubContent,\n type: 'trait', // Use trait type for command classes\n overwrite: true, // Always overwrite\n schemaName: '__omnify_command__',\n };\n}\n\n/**\n * Generate the Locales class for a schema.\n */\nfunction generateLocalesClass(\n schema: LoadedSchema,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n\n // Generate localized display names\n const localizedDisplayNames = generateLocalizedDisplayNames(schema.displayName);\n const localizedPropertyDisplayNames = generatePropertyLocalizedDisplayNames(schema);\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className)\n .replace(/\\{\\{LOCALIZED_DISPLAY_NAMES\\}\\}/g, localizedDisplayNames)\n .replace(/\\{\\{LOCALIZED_PROPERTY_DISPLAY_NAMES\\}\\}/g, localizedPropertyDisplayNames);\n\n return {\n path: `${options.baseModelPath}/Locales/${className}Locales.php`,\n content,\n type: 'locales',\n overwrite: true, // Always overwrite locales\n schemaName: schema.name,\n };\n}\n\n/**\n * Generate all models for the given schemas.\n */\nexport function generateModels(\n schemas: SchemaCollection,\n options?: ModelGeneratorOptions\n): GeneratedModel[] {\n const resolved = resolveOptions(options);\n const models: GeneratedModel[] = [];\n\n // Generate shared base model\n models.push(generateBaseModel(schemas, resolved, getStubContent('base-model')));\n\n // Generate HasLocalizedDisplayName trait in Traits subfolder\n models.push(generateLocalizedDisplayNameTrait(resolved, getStubContent('has-localized-display-name')));\n\n // Generate OmnifyServiceProvider with morph map\n models.push(generateServiceProvider(schemas, resolved, getStubContent('service-provider')));\n\n // Generate Omnify support class for package schema registration\n models.push(generateOmnifySupport(resolved, getStubContent('omnify-support')));\n\n // Generate Omnify sync artisan command\n models.push(generateOmnifyCommand(resolved, getStubContent('omnify-command')));\n\n // Generate models for each schema (excluding enums and hidden schemas)\n for (const schema of Object.values(schemas)) {\n if (schema.kind === 'enum') {\n continue;\n }\n\n // Skip hidden schemas (e.g., cache, jobs, sessions)\n if (schema.options?.hidden === true) {\n continue;\n }\n\n // Generate Locales class in Locales subfolder\n models.push(generateLocalesClass(schema, resolved, getStubContent('locales')));\n\n // Generate entity base model (always overwritten)\n models.push(generateEntityBaseModel(\n schema,\n schemas,\n resolved,\n getStubContent('entity-base'),\n getStubContent('entity-base-auth')\n ));\n\n // Generate user model (created once)\n models.push(generateEntityModel(schema, resolved, getStubContent('entity')));\n }\n\n return models;\n}\n\n/**\n * Get the output path for a model.\n */\nexport function getModelPath(model: GeneratedModel): string {\n return model.path;\n}\n\n/**\n * Generate provider registration for Laravel.\n * Handles both Laravel 11+ (bootstrap/providers.php) and Laravel 10- (config/app.php).\n *\n * @param existingContent - Existing file content (null if file doesn't exist)\n * @param laravelVersion - Laravel version type\n * @param laravelRoot - Laravel root directory (e.g., \"./backend\" or \"\")\n * @returns Registration result or null if already registered\n */\nexport function generateProviderRegistration(\n existingContent: string | null,\n laravelVersion: 'laravel11+' | 'laravel10-',\n laravelRoot: string = ''\n): ProviderRegistrationResult | null {\n const providerClass = 'App\\\\Providers\\\\OmnifyServiceProvider::class';\n const providerLine = ` ${providerClass},`;\n\n // Build paths with Laravel root prefix\n const bootstrapPath = laravelRoot ? `${laravelRoot}/bootstrap/providers.php` : 'bootstrap/providers.php';\n const configPath = laravelRoot ? `${laravelRoot}/config/app.php` : 'config/app.php';\n\n // Check if already registered\n if (existingContent && existingContent.includes('OmnifyServiceProvider')) {\n return {\n path: laravelVersion === 'laravel11+' ? bootstrapPath : configPath,\n content: existingContent,\n laravelVersion,\n alreadyRegistered: true,\n };\n }\n\n if (laravelVersion === 'laravel11+') {\n // Laravel 11+ uses bootstrap/providers.php\n if (existingContent) {\n // Find the closing bracket of the array and insert before it\n const lines = existingContent.split('\\n');\n const result: string[] = [];\n let inserted = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n // Find the closing ];\n if (!inserted && line.trim() === '];') {\n // Insert before closing bracket\n result.push(providerLine);\n inserted = true;\n }\n result.push(line);\n }\n\n return {\n path: bootstrapPath,\n content: result.join('\\n'),\n laravelVersion,\n alreadyRegistered: false,\n };\n } else {\n // Create new file\n return {\n path: bootstrapPath,\n content: `<?php\n\nreturn [\n App\\\\Providers\\\\AppServiceProvider::class,\n${providerLine}\n];\n`,\n laravelVersion,\n alreadyRegistered: false,\n };\n }\n } else {\n // Laravel 10- uses config/app.php\n if (existingContent) {\n // Find 'providers' => [...] and insert OmnifyServiceProvider\n // This is more complex because config/app.php has multiple arrays\n\n // Look for the providers array closing\n // Pattern: After \"App\\Providers\\...\" look for the next line with ], and insert before\n const providersSectionRegex = /'providers'\\s*=>\\s*\\[[\\s\\S]*?\\n(\\s*)\\]/m;\n const match = existingContent.match(providersSectionRegex);\n\n if (match) {\n // Find position to insert - before the closing ]\n const providersStart = existingContent.indexOf(\"'providers'\");\n if (providersStart === -1) {\n return null; // Can't find providers section\n }\n\n // Find the closing ] of providers array\n let depth = 0;\n let foundStart = false;\n let insertPos = -1;\n\n for (let i = providersStart; i < existingContent.length; i++) {\n const char = existingContent[i];\n if (char === '[') {\n foundStart = true;\n depth++;\n } else if (char === ']') {\n depth--;\n if (foundStart && depth === 0) {\n insertPos = i;\n break;\n }\n }\n }\n\n if (insertPos !== -1) {\n // Find the last provider line before closing ]\n const beforeClose = existingContent.substring(0, insertPos);\n const lastNewline = beforeClose.lastIndexOf('\\n');\n\n // Insert after last provider, before ]\n const content =\n existingContent.substring(0, lastNewline + 1) +\n providerLine + '\\n' +\n existingContent.substring(lastNewline + 1);\n\n return {\n path: configPath,\n content,\n laravelVersion,\n alreadyRegistered: false,\n };\n }\n }\n\n return null; // Couldn't parse config/app.php\n } else {\n // Can't create config/app.php from scratch - it's too complex\n return null;\n }\n }\n}\n","/**\n * Utility functions for Laravel generator.\n */\n\n/**\n * Convert a string to snake_case.\n */\nexport function toSnakeCase(str: string): string {\n return str\n .replace(/([A-Z])/g, '_$1')\n .replace(/^_/, '')\n .toLowerCase();\n}\n\n/**\n * Convert a string to PascalCase.\n */\nexport function toPascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^(.)/, (_, c) => c.toUpperCase());\n}\n\n/**\n * Convert a string to camelCase.\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Simple pluralization (English).\n */\nexport function pluralize(word: string): string {\n if (word.endsWith('y') && !['ay', 'ey', 'iy', 'oy', 'uy'].some(v => word.endsWith(v))) {\n return word.slice(0, -1) + 'ies';\n }\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') ||\n word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n return word + 's';\n}\n","/**\n * Laravel Factory Generator\n *\n * Generates Laravel factory files for Eloquent models.\n */\n\nimport type { SchemaCollection, LoadedSchema, PropertyDefinition, CustomTypeDefinition } from '@famgia/omnify-types';\nimport { toPascalCase, toSnakeCase } from '../utils.js';\n\n/**\n * Options for factory generation.\n */\nexport interface FactoryGeneratorOptions {\n /** Model namespace */\n modelNamespace?: string;\n /** Factory output path */\n factoryPath?: string;\n /** Faker locale */\n fakerLocale?: string;\n /** Custom types registered by plugins */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Generated factory output.\n */\nexport interface GeneratedFactory {\n /** Factory class name */\n name: string;\n /** Schema name this factory is for */\n schemaName: string;\n /** Output path for the factory file */\n path: string;\n /** Generated factory content */\n content: string;\n /** Whether to overwrite if exists */\n overwrite: boolean;\n}\n\n/**\n * Resolved options with defaults applied.\n */\ninterface ResolvedOptions {\n modelNamespace: string;\n factoryPath: string;\n fakerLocale: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Resolves options with defaults.\n */\nfunction resolveOptions(options?: FactoryGeneratorOptions): ResolvedOptions {\n return {\n modelNamespace: options?.modelNamespace ?? 'App\\\\Models',\n factoryPath: options?.factoryPath ?? 'database/factories',\n fakerLocale: options?.fakerLocale ?? 'en_US',\n customTypes: options?.customTypes ?? new Map(),\n };\n}\n\n/**\n * Gets the factory stub content.\n */\nfunction getStubContent(): string {\n return `<?php\n\nnamespace Database\\\\Factories;\n\nuse {{MODEL_NAMESPACE}}\\\\{{MODEL_NAME}};\nuse Illuminate\\\\Database\\\\Eloquent\\\\Factories\\\\Factory;\n{{IMPORTS}}\n\n/**\n * @extends Factory<{{MODEL_NAME}}>\n */\nclass {{MODEL_NAME}}Factory extends Factory\n{\n protected $model = {{MODEL_NAME}}::class;\n\n /**\n * Define the model's default state.\n *\n * @return array<string, mixed>\n */\n public function definition(): array\n {\n return [\n{{ATTRIBUTES}}\n ];\n }\n}\n`;\n}\n\n/**\n * Generates fake data for Japanese compound types.\n * Returns array of field definitions or null if not a Japanese type.\n */\nfunction generateJapaneseCompoundFake(\n propertyName: string,\n property: PropertyDefinition,\n options: ResolvedOptions\n): string[] | null {\n const typeDef = options.customTypes.get(property.type);\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const snakeName = toSnakeCase(propertyName);\n const lines: string[] = [];\n const jaFaker = \"fake('ja_JP')\";\n\n switch (property.type) {\n case 'JapaneseName':\n lines.push(`'${snakeName}_lastname' => ${jaFaker}->lastName(),`);\n lines.push(`'${snakeName}_firstname' => ${jaFaker}->firstName(),`);\n lines.push(`'${snakeName}_kana_lastname' => ${jaFaker}->lastKanaName(),`);\n lines.push(`'${snakeName}_kana_firstname' => ${jaFaker}->firstKanaName(),`);\n break;\n\n case 'JapaneseAddress':\n lines.push(`'${snakeName}_postal_code' => ${jaFaker}->postcode(),`);\n lines.push(`'${snakeName}_prefecture_id' => ${jaFaker}->numberBetween(1, 47),`);\n lines.push(`'${snakeName}_address1' => ${jaFaker}->city() . ${jaFaker}->ward(),`);\n lines.push(`'${snakeName}_address2' => ${jaFaker}->streetAddress(),`);\n lines.push(`'${snakeName}_address3' => ${jaFaker}->optional()->secondaryAddress(),`);\n break;\n\n case 'JapaneseBankAccount':\n lines.push(`'${snakeName}_bank_code' => ${jaFaker}->regexify('[0-9]{4}'),`);\n lines.push(`'${snakeName}_branch_code' => ${jaFaker}->regexify('[0-9]{3}'),`);\n lines.push(`'${snakeName}_account_type' => ${jaFaker}->randomElement(['1', '2', '4']),`);\n lines.push(`'${snakeName}_account_number' => ${jaFaker}->regexify('[0-9]{7}'),`);\n lines.push(`'${snakeName}_account_holder' => ${jaFaker}->lastKanaName() . ' ' . ${jaFaker}->firstKanaName(),`);\n break;\n\n default:\n // For other compound types, generate default string fakes\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const sql = (field as any).sql;\n if (sql?.sqlType === 'TINYINT' || sql?.sqlType === 'INT' || sql?.sqlType === 'BIGINT') {\n lines.push(`'${fieldName}' => fake()->numberBetween(1, 100),`);\n } else {\n lines.push(`'${fieldName}' => fake()->words(2, true),`);\n }\n }\n break;\n }\n\n return lines;\n}\n\n/**\n * Generates fake data for Japanese non-compound types.\n */\nfunction generateJapaneseSimpleFake(\n propertyName: string,\n property: PropertyDefinition\n): string | null {\n const snakeName = toSnakeCase(propertyName);\n const jaFaker = \"fake('ja_JP')\";\n\n switch (property.type) {\n case 'JapanesePhone':\n return `'${snakeName}' => ${jaFaker}->phoneNumber(),`;\n\n case 'JapanesePostalCode':\n return `'${snakeName}' => ${jaFaker}->postcode(),`;\n\n default:\n return null;\n }\n}\n\n/**\n * Generates factory fake data for a property based on its type and name.\n */\nfunction generateFakeData(\n propertyName: string,\n property: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string | null {\n const type = property.type;\n\n // Skip system fields\n if (['deleted_at', 'created_at', 'updated_at'].includes(propertyName)) {\n return null;\n }\n\n // Skip association properties (foreign keys are handled separately)\n if (type === 'Association') {\n return null;\n }\n\n // Check for Japanese non-compound types first\n const japaneseFake = generateJapaneseSimpleFake(propertyName, property);\n if (japaneseFake) {\n return japaneseFake;\n }\n\n // Handle different property types\n switch (type) {\n case 'String':\n return generateStringFake(propertyName, property);\n\n case 'Email':\n return `'${propertyName}' => fake()->unique()->safeEmail(),`;\n\n case 'Password':\n return `'${propertyName}' => bcrypt('password'),`;\n\n case 'Int':\n case 'BigInt':\n return generateIntFake(propertyName, property);\n\n case 'Float':\n case 'Decimal':\n return `'${propertyName}' => fake()->randomFloat(2, 1, 10000),`;\n\n case 'Boolean':\n return `'${propertyName}' => fake()->boolean(),`;\n\n case 'Text':\n return `'${propertyName}' => fake()->paragraphs(3, true),`;\n\n case 'LongText':\n return `'${propertyName}' => fake()->paragraphs(5, true),`;\n\n case 'Date':\n return `'${propertyName}' => fake()->date(),`;\n\n case 'Time':\n return `'${propertyName}' => fake()->time(),`;\n\n case 'Timestamp':\n case 'DateTime':\n return `'${propertyName}' => fake()->dateTime(),`;\n\n case 'Json':\n return `'${propertyName}' => [],`;\n\n case 'Enum':\n return generateEnumFake(propertyName, property);\n\n case 'EnumRef':\n return generateEnumRefFake(propertyName, property, schemas);\n\n default:\n // Default to sentence for unknown types\n return `'${propertyName}' => fake()->sentence(),`;\n }\n}\n\n/**\n * Generates fake data for String type based on property name patterns.\n */\nfunction generateStringFake(propertyName: string, property: PropertyDefinition): string {\n // Handle special field names\n if (propertyName === 'slug') {\n return `'${propertyName}' => fake()->unique()->slug(),`;\n }\n\n if (propertyName === 'uuid' || propertyName === 'uid') {\n return `'${propertyName}' => (string) \\\\Illuminate\\\\Support\\\\Str::uuid(),`;\n }\n\n if (propertyName.includes('email')) {\n return `'${propertyName}' => fake()->unique()->safeEmail(),`;\n }\n\n if (propertyName.includes('phone')) {\n return `'${propertyName}' => fake()->phoneNumber(),`;\n }\n\n // Check image/photo/avatar before url to handle cases like 'avatar_url'\n if (propertyName.includes('image') || propertyName.includes('photo') || propertyName.includes('avatar')) {\n return `'${propertyName}' => fake()->imageUrl(),`;\n }\n\n if (propertyName.includes('url') || propertyName.includes('website')) {\n return `'${propertyName}' => fake()->url(),`;\n }\n\n if (propertyName.includes('path') || propertyName.includes('file')) {\n return `'${propertyName}' => 'uploads/' . fake()->uuid() . '.jpg',`;\n }\n\n if (propertyName === 'name' || propertyName === 'title') {\n return `'${propertyName}' => fake()->sentence(3),`;\n }\n\n if (propertyName.includes('name')) {\n return `'${propertyName}' => fake()->name(),`;\n }\n\n if (propertyName.includes('address')) {\n return `'${propertyName}' => fake()->address(),`;\n }\n\n if (propertyName.includes('city')) {\n return `'${propertyName}' => fake()->city(),`;\n }\n\n if (propertyName.includes('country')) {\n return `'${propertyName}' => fake()->country(),`;\n }\n\n if (propertyName.includes('zip') || propertyName.includes('postal')) {\n return `'${propertyName}' => fake()->postcode(),`;\n }\n\n if (propertyName.includes('color')) {\n return `'${propertyName}' => fake()->hexColor(),`;\n }\n\n if (propertyName.includes('token') || propertyName.includes('secret') || propertyName.includes('key')) {\n return `'${propertyName}' => \\\\Illuminate\\\\Support\\\\Str::random(32),`;\n }\n\n if (propertyName.includes('code')) {\n return `'${propertyName}' => fake()->unique()->regexify('[A-Z0-9]{8}'),`;\n }\n\n // Default string\n const length = (property as { length?: number }).length;\n if (length && length <= 50) {\n return `'${propertyName}' => fake()->words(3, true),`;\n }\n\n return `'${propertyName}' => fake()->sentence(),`;\n}\n\n/**\n * Generates fake data for Integer types.\n */\nfunction generateIntFake(propertyName: string, property: PropertyDefinition): string {\n if (propertyName.includes('count') || propertyName.includes('quantity')) {\n return `'${propertyName}' => fake()->numberBetween(0, 100),`;\n }\n\n if (propertyName.includes('price') || propertyName.includes('amount') || propertyName.includes('cost')) {\n return `'${propertyName}' => fake()->numberBetween(100, 10000),`;\n }\n\n if (propertyName.includes('order') || propertyName.includes('sort') || propertyName.includes('position')) {\n return `'${propertyName}' => fake()->numberBetween(1, 100),`;\n }\n\n if (propertyName.includes('age')) {\n return `'${propertyName}' => fake()->numberBetween(18, 80),`;\n }\n\n if (propertyName.includes('year')) {\n return `'${propertyName}' => fake()->year(),`;\n }\n\n return `'${propertyName}' => fake()->numberBetween(1, 1000),`;\n}\n\n/**\n * Generates fake data for inline Enum type.\n */\nfunction generateEnumFake(propertyName: string, property: PropertyDefinition): string {\n const enumValues = (property as { enum?: readonly (string | { value: string })[] }).enum;\n if (!enumValues || enumValues.length === 0) {\n return `'${propertyName}' => null,`;\n }\n\n // Extract values (handle both string and object formats)\n const values = enumValues.map(v => typeof v === 'string' ? v : v.value);\n const valuesStr = values.map(v => `'${v}'`).join(', ');\n\n return `'${propertyName}' => fake()->randomElement([${valuesStr}]),`;\n}\n\n/**\n * Generates fake data for EnumRef type.\n */\nfunction generateEnumRefFake(\n propertyName: string,\n property: PropertyDefinition,\n schemas: SchemaCollection\n): string {\n const enumName = (property as { enum?: string }).enum;\n if (!enumName) {\n return `'${propertyName}' => null,`;\n }\n\n const enumSchema = schemas[enumName];\n if (!enumSchema || enumSchema.kind !== 'enum' || !enumSchema.values) {\n return `'${propertyName}' => null,`;\n }\n\n const valuesStr = enumSchema.values.map(v => `'${v}'`).join(', ');\n return `'${propertyName}' => fake()->randomElement([${valuesStr}]),`;\n}\n\n/**\n * Generates factory data for association (foreign key).\n */\nfunction generateAssociationFake(\n propertyName: string,\n property: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n modelNamespace: string\n): { fake: string; import?: string } | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const relation = (property as { relation?: string }).relation;\n const target = (property as { target?: string }).target;\n\n // Only handle ManyToOne (belongsTo) relationships\n if (relation !== 'ManyToOne' || !target) {\n return null;\n }\n\n const foreignKey = `${toSnakeCase(propertyName)}_id`;\n const isNullable = (property as { nullable?: boolean }).nullable ?? false;\n const targetSchema = schemas[target];\n\n // Check if target schema exists\n if (!targetSchema) {\n return null;\n }\n\n // Generate the fake data\n let fake: string;\n if (isNullable) {\n fake = `'${foreignKey}' => ${target}::query()->inRandomOrder()->first()?->id,`;\n } else {\n fake = `'${foreignKey}' => ${target}::query()->inRandomOrder()->first()?->id ?? ${target}::factory()->create()->id,`;\n }\n\n // Add import if target is different from current schema\n let importStatement: string | undefined;\n if (target !== schema.name) {\n importStatement = `use ${modelNamespace}\\\\${target};`;\n }\n\n return { fake, import: importStatement };\n}\n\n/**\n * Generates a factory for a single schema.\n */\nfunction generateFactory(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedFactory | null {\n // Skip enum schemas\n if (schema.kind === 'enum') {\n return null;\n }\n\n // Skip hidden schemas (system tables like cache, jobs, sessions)\n if (schema.options?.hidden) {\n return null;\n }\n\n const modelName = toPascalCase(schema.name);\n const factoryName = `${modelName}Factory`;\n\n const attributes: string[] = [];\n const imports: string[] = [];\n\n // Process properties\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n // Handle associations (foreign keys)\n if (prop.type === 'Association') {\n const assocResult = generateAssociationFake(propName, prop, schema, schemas, options.modelNamespace);\n if (assocResult) {\n attributes.push(assocResult.fake);\n if (assocResult.import) {\n imports.push(assocResult.import);\n }\n }\n continue;\n }\n\n // Handle Japanese compound types (JapaneseName, JapaneseAddress, JapaneseBankAccount)\n const compoundFakes = generateJapaneseCompoundFake(propName, prop, options);\n if (compoundFakes) {\n attributes.push(...compoundFakes);\n continue;\n }\n\n // Handle regular properties\n const fake = generateFakeData(propName, prop, schema, schemas, options);\n if (fake) {\n attributes.push(fake);\n }\n }\n }\n\n // Build the factory content\n let content = stubContent;\n content = content.replace(/\\{\\{MODEL_NAMESPACE\\}\\}/g, options.modelNamespace);\n content = content.replace(/\\{\\{MODEL_NAME\\}\\}/g, modelName);\n\n // Format imports\n const uniqueImports = [...new Set(imports)];\n const importsStr = uniqueImports.length > 0\n ? '\\n' + uniqueImports.join('\\n')\n : '';\n content = content.replace(/\\{\\{IMPORTS\\}\\}/g, importsStr);\n\n // Format attributes with proper indentation\n const attributesStr = attributes.length > 0\n ? attributes.map(a => ` ${a}`).join('\\n')\n : '';\n content = content.replace(/\\{\\{ATTRIBUTES\\}\\}/g, attributesStr);\n\n return {\n name: factoryName,\n schemaName: schema.name,\n path: `${options.factoryPath}/${factoryName}.php`,\n content,\n overwrite: false, // Factories should not overwrite existing files\n };\n}\n\n/**\n * Generates factories for all schemas.\n */\nexport function generateFactories(\n schemas: SchemaCollection,\n options?: FactoryGeneratorOptions\n): GeneratedFactory[] {\n const resolved = resolveOptions(options);\n const stubContent = getStubContent();\n const factories: GeneratedFactory[] = [];\n\n for (const schema of Object.values(schemas)) {\n const factory = generateFactory(schema, schemas, resolved, stubContent);\n if (factory) {\n factories.push(factory);\n }\n }\n\n return factories;\n}\n\n/**\n * Gets the output path for a factory.\n */\nexport function getFactoryPath(factory: GeneratedFactory): string {\n return factory.path;\n}\n","/**\n * @famgia/omnify-laravel - Plugin\n *\n * Plugin for generating Laravel migration files and Eloquent models from Omnify schemas.\n *\n * @example Basic usage (Laravel at project root)\n * ```typescript\n * import { defineConfig } from '@famgia/omnify';\n * import laravel from '@famgia/omnify-laravel/plugin';\n *\n * export default defineConfig({\n * plugins: [laravel()], // Uses all defaults\n * });\n * ```\n *\n * @example Monorepo (Laravel in ./backend/)\n * ```typescript\n * import { defineConfig } from '@famgia/omnify';\n * import laravel from '@famgia/omnify-laravel/plugin';\n *\n * export default defineConfig({\n * plugins: [\n * laravel({\n * base: './backend/', // All paths relative to this\n * generateRequests: true,\n * generateResources: true,\n * }),\n * ],\n * });\n * ```\n */\n\nimport { readFileSync, existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { OmnifyPlugin, GeneratorOutput, GeneratorContext, PluginConfigSchema, SchemaChange } from '@famgia/omnify-types';\nimport { generateMigrations, getMigrationPath, generateMigrationsFromChanges, type MigrationOptions } from './migration/index.js';\nimport { generateModels, getModelPath, generateProviderRegistration, type ModelGeneratorOptions } from './model/index.js';\nimport { generateFactories, getFactoryPath, type FactoryGeneratorOptions } from './factory/index.js';\nimport { generateRequests, getRequestPath, type RequestGeneratorOptions } from './request/index.js';\nimport { generateResources, getResourcePath, type ResourceGeneratorOptions } from './resource/index.js';\nimport { generateAIGuides, shouldGenerateAIGuides } from './ai-guides/index.js';\n\n/**\n * Infer Laravel root directory from providersPath.\n * E.g., \"./backend/app/Providers\" → \"./backend\"\n * E.g., \"app/Providers\" → \"\"\n */\nfunction inferLaravelRoot(providersPath: string): string {\n // Remove app/Providers suffix to get Laravel root\n const normalized = providersPath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.*)\\/app\\/Providers\\/?$/i);\n if (match && match[1]) {\n return match[1];\n }\n // Check for OmnifyBase pattern: ./backend/app/Providers/OmnifyBase\n const baseMatch = normalized.match(/^(.*)\\/app\\/Providers\\/OmnifyBase\\/?$/i);\n if (baseMatch && baseMatch[1]) {\n return baseMatch[1];\n }\n return '';\n}\n\n/**\n * Scans a directory for existing migration files and returns tables that already have CREATE migrations.\n */\nfunction getExistingMigrationTables(migrationsDir: string): Set<string> {\n const existingTables = new Set<string>();\n\n if (!existsSync(migrationsDir)) {\n return existingTables;\n }\n\n try {\n const files = readdirSync(migrationsDir);\n // Match pattern: YYYY_MM_DD_HHMMSS_create_<table>_table.php\n const createMigrationPattern = /^\\d{4}_\\d{2}_\\d{2}_\\d{6}_create_(.+)_table\\.php$/;\n\n for (const file of files) {\n const match = file.match(createMigrationPattern);\n if (match) {\n existingTables.add(match[1]); // table name\n }\n }\n } catch {\n // Ignore errors reading directory\n }\n\n return existingTables;\n}\n\n/**\n * Configuration schema for Laravel plugin UI settings\n */\nconst LARAVEL_CONFIG_SCHEMA: PluginConfigSchema = {\n fields: [\n {\n key: 'base',\n type: 'path',\n label: 'Laravel Base Path',\n description: 'Base directory for Laravel project (e.g., \"./backend/\" for monorepo). All other paths are relative to this.',\n default: '',\n group: 'output',\n },\n {\n key: 'migrationsPath',\n type: 'path',\n label: 'Migrations Path',\n description: 'Directory for Laravel migration files (relative to base)',\n default: 'database/migrations/omnify',\n group: 'output',\n },\n {\n key: 'modelsPath',\n type: 'path',\n label: 'Models Path',\n description: 'Directory for user-editable model files (relative to base)',\n default: 'app/Models',\n group: 'output',\n },\n {\n key: 'baseModelsPath',\n type: 'path',\n label: 'Base Models Path',\n description: 'Directory for auto-generated base model files',\n default: 'app/Models/OmnifyBase',\n group: 'output',\n },\n {\n key: 'providersPath',\n type: 'path',\n label: 'Providers Path',\n description: 'Directory for Laravel service provider files',\n default: 'app/Providers',\n group: 'output',\n },\n {\n key: 'generateModels',\n type: 'boolean',\n label: 'Generate Models',\n description: 'Generate Eloquent model classes',\n default: true,\n group: 'options',\n },\n {\n key: 'factoriesPath',\n type: 'path',\n label: 'Factories Path',\n description: 'Directory for Laravel factory files',\n default: 'database/factories',\n group: 'output',\n },\n {\n key: 'generateFactories',\n type: 'boolean',\n label: 'Generate Factories',\n description: 'Generate Laravel factory classes for testing',\n default: true,\n group: 'options',\n },\n {\n key: 'connection',\n type: 'string',\n label: 'Database Connection',\n description: 'Laravel database connection name (optional)',\n placeholder: 'mysql',\n group: 'options',\n },\n {\n key: 'requestsPath',\n type: 'path',\n label: 'Requests Path',\n description: 'Directory for user-editable FormRequest files',\n default: 'app/Http/Requests',\n group: 'output',\n },\n {\n key: 'baseRequestsPath',\n type: 'path',\n label: 'Base Requests Path',\n description: 'Directory for auto-generated base FormRequest files',\n default: 'app/Http/Requests/OmnifyBase',\n group: 'output',\n },\n {\n key: 'generateRequests',\n type: 'boolean',\n label: 'Generate Requests',\n description: 'Generate Laravel FormRequest classes for validation',\n default: false,\n group: 'options',\n },\n {\n key: 'resourcesPath',\n type: 'path',\n label: 'Resources Path',\n description: 'Directory for user-editable API Resource files',\n default: 'app/Http/Resources',\n group: 'output',\n },\n {\n key: 'baseResourcesPath',\n type: 'path',\n label: 'Base Resources Path',\n description: 'Directory for auto-generated base API Resource files',\n default: 'app/Http/Resources/OmnifyBase',\n group: 'output',\n },\n {\n key: 'generateResources',\n type: 'boolean',\n label: 'Generate Resources',\n description: 'Generate Laravel API Resource classes',\n default: false,\n group: 'options',\n },\n ],\n};\n\n/**\n * Options for the Laravel plugin.\n */\nexport interface LaravelPluginOptions {\n /**\n * Base directory for Laravel project (relative to project root).\n * All other paths will be relative to this base.\n * \n * @default '' (project root)\n * @example './backend/' for monorepo with Laravel in backend folder\n */\n base?: string;\n\n /**\n * Path for Laravel migration files (relative to base).\n * @default 'database/migrations/omnify'\n */\n migrationsPath?: string;\n\n /**\n * Path for user-editable model files (relative to base).\n * @default 'app/Models'\n */\n modelsPath?: string;\n\n /**\n * Path for auto-generated base model files (relative to base).\n * @default 'app/Models/OmnifyBase'\n */\n baseModelsPath?: string;\n\n /**\n * Path for Laravel service provider files (relative to base).\n * @default 'app/Providers'\n */\n providersPath?: string;\n\n /**\n * Model namespace.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Base model namespace.\n * @default 'App\\\\Models\\\\OmnifyBase'\n */\n baseModelNamespace?: string;\n\n /**\n * Whether to generate Eloquent models.\n * @default true\n */\n generateModels?: boolean;\n\n /**\n * Path for Laravel factory files.\n * @default 'database/factories'\n */\n factoriesPath?: string;\n\n /**\n * Whether to generate Laravel factories.\n * @default true\n */\n generateFactories?: boolean;\n\n /**\n * Faker locale for factory data.\n * @default 'en_US'\n */\n fakerLocale?: string;\n\n /**\n * Database connection name for migrations.\n */\n connection?: string;\n\n /**\n * Custom timestamp for migration file names (mainly for testing).\n */\n timestamp?: string;\n\n /**\n * Path for user-editable FormRequest files.\n * @default 'app/Http/Requests'\n */\n requestsPath?: string;\n\n /**\n * Path for auto-generated base FormRequest files.\n * @default 'app/Http/Requests/OmnifyBase'\n */\n baseRequestsPath?: string;\n\n /**\n * Request namespace.\n * @default 'App\\\\Http\\\\Requests'\n */\n requestNamespace?: string;\n\n /**\n * Base request namespace.\n * @default 'App\\\\Http\\\\Requests\\\\OmnifyBase'\n */\n baseRequestNamespace?: string;\n\n /**\n * Whether to generate Laravel FormRequest classes.\n * @default true\n */\n generateRequests?: boolean;\n\n /**\n * Path for user-editable API Resource files.\n * @default 'app/Http/Resources'\n */\n resourcesPath?: string;\n\n /**\n * Path for auto-generated base API Resource files.\n * @default 'app/Http/Resources/OmnifyBase'\n */\n baseResourcesPath?: string;\n\n /**\n * Resource namespace.\n * @default 'App\\\\Http\\\\Resources'\n */\n resourceNamespace?: string;\n\n /**\n * Base resource namespace.\n * @default 'App\\\\Http\\\\Resources\\\\OmnifyBase'\n */\n baseResourceNamespace?: string;\n\n /**\n * Whether to generate Laravel API Resource classes.\n * @default true\n */\n generateResources?: boolean;\n}\n\n/**\n * Resolved options with defaults applied.\n */\ninterface ResolvedOptions {\n migrationsPath: string;\n modelsPath: string;\n baseModelsPath: string;\n providersPath: string;\n modelNamespace: string;\n baseModelNamespace: string;\n generateModels: boolean;\n factoriesPath: string;\n generateFactories: boolean;\n fakerLocale: string;\n connection: string | undefined;\n timestamp: string | undefined;\n requestsPath: string;\n baseRequestsPath: string;\n requestNamespace: string;\n baseRequestNamespace: string;\n generateRequests: boolean;\n resourcesPath: string;\n baseResourcesPath: string;\n resourceNamespace: string;\n baseResourceNamespace: string;\n generateResources: boolean;\n}\n\n/**\n * Resolves options with defaults.\n */\n/**\n * Joins base path with relative path, normalizing slashes.\n */\nfunction joinPath(base: string, relativePath: string): string {\n if (!base) return relativePath;\n // Normalize: remove trailing slash from base, ensure no double slashes\n const normalizedBase = base.replace(/\\/+$/, '');\n return `${normalizedBase}/${relativePath}`;\n}\n\nfunction resolveOptions(options?: LaravelPluginOptions): ResolvedOptions {\n const base = options?.base ?? '';\n\n return {\n migrationsPath: options?.migrationsPath ?? joinPath(base, 'database/migrations/omnify'),\n modelsPath: options?.modelsPath ?? joinPath(base, 'app/Models'),\n baseModelsPath: options?.baseModelsPath ?? joinPath(base, 'app/Models/OmnifyBase'),\n providersPath: options?.providersPath ?? joinPath(base, 'app/Providers'),\n modelNamespace: options?.modelNamespace ?? 'App\\\\Models',\n baseModelNamespace: options?.baseModelNamespace ?? 'App\\\\Models\\\\OmnifyBase',\n generateModels: options?.generateModels ?? true,\n factoriesPath: options?.factoriesPath ?? joinPath(base, 'database/factories'),\n generateFactories: options?.generateFactories ?? true,\n fakerLocale: options?.fakerLocale ?? 'en_US',\n connection: options?.connection,\n timestamp: options?.timestamp,\n requestsPath: options?.requestsPath ?? joinPath(base, 'app/Http/Requests'),\n baseRequestsPath: options?.baseRequestsPath ?? joinPath(base, 'app/Http/Requests/OmnifyBase'),\n requestNamespace: options?.requestNamespace ?? 'App\\\\Http\\\\Requests',\n baseRequestNamespace: options?.baseRequestNamespace ?? 'App\\\\Http\\\\Requests\\\\OmnifyBase',\n generateRequests: options?.generateRequests ?? true,\n resourcesPath: options?.resourcesPath ?? joinPath(base, 'app/Http/Resources'),\n baseResourcesPath: options?.baseResourcesPath ?? joinPath(base, 'app/Http/Resources/OmnifyBase'),\n resourceNamespace: options?.resourceNamespace ?? 'App\\\\Http\\\\Resources',\n baseResourceNamespace: options?.baseResourceNamespace ?? 'App\\\\Http\\\\Resources\\\\OmnifyBase',\n generateResources: options?.generateResources ?? true,\n };\n}\n\n/**\n * Creates the Laravel plugin with the specified options.\n *\n * @param options - Plugin configuration options\n * @returns OmnifyPlugin configured for Laravel migrations and models\n */\nexport default function laravelPlugin(options?: LaravelPluginOptions): OmnifyPlugin {\n const resolved = resolveOptions(options);\n\n // Build generators array\n const migrationGenerator = {\n name: 'laravel-migrations',\n description: 'Generate Laravel migration files',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const migrationOptions: MigrationOptions = {\n connection: resolved.connection,\n timestamp: resolved.timestamp,\n customTypes: ctx.customTypes,\n };\n\n const outputs: GeneratorOutput[] = [];\n const migrationsDir = join(ctx.cwd, resolved.migrationsPath);\n const existingTables = getExistingMigrationTables(migrationsDir);\n\n // If we have change information (including empty array), use it for smarter migration generation\n // undefined = no change info → fallback to generating all\n // empty array = no changes detected → no migrations needed\n if (ctx.changes !== undefined) {\n // Empty changes array = no changes, no migrations needed\n if (ctx.changes.length === 0) {\n return outputs;\n }\n\n // Generate CREATE migrations only for added schemas\n const addedSchemaNames = new Set(\n ctx.changes\n .filter((c) => c.changeType === 'added')\n .map((c) => c.schemaName)\n );\n\n if (addedSchemaNames.size > 0) {\n const addedSchemas = Object.fromEntries(\n Object.entries(ctx.schemas).filter(([name]) => addedSchemaNames.has(name))\n );\n\n const createMigrations = generateMigrations(addedSchemas, migrationOptions);\n\n for (const migration of createMigrations) {\n const tableName = migration.tables[0];\n // Skip if table already has a create migration\n if (existingTables.has(tableName)) {\n ctx.logger.debug(`Skipping CREATE for ${tableName} (already exists)`);\n continue;\n }\n\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName,\n migrationType: 'create',\n },\n });\n }\n }\n\n // Generate ALTER/DROP migrations for modified/removed schemas\n const alterChanges = ctx.changes.filter(\n (c) => c.changeType === 'modified' || c.changeType === 'removed'\n );\n\n if (alterChanges.length > 0) {\n // Convert SchemaChange to the format expected by alter-generator\n const alterMigrations = generateMigrationsFromChanges(\n alterChanges as unknown as import('@famgia/omnify-atlas').SchemaChange[],\n migrationOptions\n );\n\n for (const migration of alterMigrations) {\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName: migration.tables[0],\n migrationType: migration.type,\n },\n });\n }\n }\n } else {\n // No change info - generate CREATE migrations for all schemas\n // but skip tables that already have migrations (deduplication)\n const migrations = generateMigrations(ctx.schemas, migrationOptions);\n\n for (const migration of migrations) {\n const tableName = migration.tables[0];\n if (migration.type === 'create' && existingTables.has(tableName)) {\n ctx.logger.debug(`Skipping migration for ${tableName} (already exists)`);\n continue;\n }\n\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName,\n migrationType: migration.type,\n },\n });\n }\n }\n\n return outputs;\n },\n };\n\n const modelGenerator = {\n name: 'laravel-models',\n description: 'Generate Eloquent model classes',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const modelOptions: ModelGeneratorOptions = {\n modelNamespace: resolved.modelNamespace,\n baseModelNamespace: resolved.baseModelNamespace,\n modelPath: resolved.modelsPath,\n baseModelPath: resolved.baseModelsPath,\n providersPath: resolved.providersPath,\n customTypes: ctx.customTypes,\n };\n\n const models = generateModels(ctx.schemas, modelOptions);\n const outputs: GeneratorOutput[] = models.map((model) => ({\n path: getModelPath(model),\n content: model.content,\n type: 'model' as const,\n // Skip writing user models if they already exist\n skipIfExists: !model.overwrite,\n metadata: {\n modelType: model.type,\n schemaName: model.schemaName,\n },\n }));\n\n // Generate provider registration\n // Check for Laravel 11+ (bootstrap/providers.php) or Laravel 10- (config/app.php)\n // Infer Laravel root from providersPath (e.g., \"./backend/app/Providers\" → \"./backend\")\n const laravelRoot = inferLaravelRoot(resolved.providersPath);\n const bootstrapProvidersRelPath = laravelRoot ? `${laravelRoot}/bootstrap/providers.php` : 'bootstrap/providers.php';\n const configAppRelPath = laravelRoot ? `${laravelRoot}/config/app.php` : 'config/app.php';\n const bootstrapProvidersPath = join(ctx.cwd, bootstrapProvidersRelPath);\n const configAppPath = join(ctx.cwd, configAppRelPath);\n\n let existingContent: string | null = null;\n let laravelVersion: 'laravel11+' | 'laravel10-';\n\n if (existsSync(bootstrapProvidersPath)) {\n // Laravel 11+ with bootstrap/providers.php\n laravelVersion = 'laravel11+';\n try {\n existingContent = readFileSync(bootstrapProvidersPath, 'utf-8');\n } catch {\n existingContent = null;\n }\n } else if (existsSync(configAppPath)) {\n // Check if config/app.php has a 'providers' array (Laravel 10-)\n // or is Laravel 11+ format (no providers array)\n try {\n const configContent = readFileSync(configAppPath, 'utf-8');\n if (/'providers'\\s*=>\\s*\\[/.test(configContent)) {\n // Laravel 10- with providers array in config/app.php\n laravelVersion = 'laravel10-';\n existingContent = configContent;\n } else {\n // Laravel 11+ format (config/app.php exists but no providers array)\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n } catch {\n // Assume Laravel 11+ if can't read config\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n } else {\n // Assume Laravel 11+ for new projects\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n\n const registration = generateProviderRegistration(existingContent, laravelVersion, laravelRoot);\n\n if (registration && !registration.alreadyRegistered) {\n outputs.push({\n path: registration.path,\n content: registration.content,\n type: 'other' as const,\n skipIfExists: false, // We want to modify the file\n metadata: {\n registrationType: 'provider-registration',\n laravelVersion: registration.laravelVersion,\n },\n });\n ctx.logger.info(`OmnifyServiceProvider will be registered in ${registration.path}`);\n } else if (registration?.alreadyRegistered) {\n ctx.logger.info('OmnifyServiceProvider is already registered');\n }\n\n return outputs;\n },\n };\n\n const factoryGenerator = {\n name: 'laravel-factories',\n description: 'Generate Laravel factory classes for testing',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const factoryOptions: FactoryGeneratorOptions = {\n modelNamespace: resolved.modelNamespace,\n factoryPath: resolved.factoriesPath,\n fakerLocale: resolved.fakerLocale,\n customTypes: ctx.customTypes,\n };\n\n const factories = generateFactories(ctx.schemas, factoryOptions);\n\n return factories.map((factory) => ({\n path: getFactoryPath(factory),\n content: factory.content,\n type: 'factory' as const,\n // Skip writing factories if they already exist (allow customization)\n skipIfExists: !factory.overwrite,\n metadata: {\n factoryName: factory.name,\n schemaName: factory.schemaName,\n },\n }));\n },\n };\n\n const requestGenerator = {\n name: 'laravel-requests',\n description: 'Generate Laravel FormRequest classes for validation',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const requestOptions: RequestGeneratorOptions = {\n requestNamespace: resolved.requestNamespace,\n baseRequestNamespace: resolved.baseRequestNamespace,\n requestPath: resolved.requestsPath,\n baseRequestPath: resolved.baseRequestsPath,\n modelNamespace: resolved.modelNamespace,\n customTypes: ctx.customTypes,\n };\n\n const requests = generateRequests(ctx.schemas, requestOptions);\n\n return requests.map((request) => ({\n path: getRequestPath(request),\n content: request.content,\n type: 'other' as const,\n // Skip writing user requests if they already exist\n skipIfExists: !request.overwrite,\n metadata: {\n requestType: request.type,\n schemaName: request.schemaName,\n module: request.module,\n },\n }));\n },\n };\n\n const resourceGenerator = {\n name: 'laravel-resources',\n description: 'Generate Laravel API Resource classes',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const resourceOptions: ResourceGeneratorOptions = {\n resourceNamespace: resolved.resourceNamespace,\n baseResourceNamespace: resolved.baseResourceNamespace,\n resourcePath: resolved.resourcesPath,\n baseResourcePath: resolved.baseResourcesPath,\n customTypes: ctx.customTypes,\n };\n\n const resources = generateResources(ctx.schemas, resourceOptions);\n\n return resources.map((resource) => ({\n path: getResourcePath(resource),\n content: resource.content,\n type: 'other' as const,\n // Skip writing user resources if they already exist\n skipIfExists: !resource.overwrite,\n metadata: {\n resourceType: resource.type,\n schemaName: resource.schemaName,\n module: resource.module,\n },\n }));\n },\n };\n\n const aiGuidesGenerator = {\n name: 'laravel-ai-guides',\n description: 'Generate AI assistant guides (Claude, Cursor) for Laravel development',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n // Only generate if guides don't exist\n if (!shouldGenerateAIGuides(ctx.cwd)) {\n ctx.logger.debug('AI guides already exist, skipping');\n return [];\n }\n\n const result = generateAIGuides(ctx.cwd, {\n modelsPath: resolved.modelsPath,\n migrationsPath: resolved.migrationsPath,\n laravelBasePath: 'app',\n });\n\n const claudeTotal = result.claudeGuides + result.claudeRules + result.claudeChecklists + result.claudeWorkflows + result.claudeAgents + result.claudeOmnify;\n ctx.logger.info(`Generated ${claudeTotal} Claude files, ${result.cursorRules} Cursor rules`);\n\n // Return empty outputs since files are written directly by generateAIGuides\n // This is because the files go to .claude/ and .cursor/ which are outside normal output\n return [];\n },\n };\n\n // Build generators array based on options\n const generators = [migrationGenerator];\n if (resolved.generateModels) {\n generators.push(modelGenerator);\n }\n if (resolved.generateFactories) {\n generators.push(factoryGenerator);\n }\n if (resolved.generateRequests) {\n generators.push(requestGenerator);\n }\n if (resolved.generateResources) {\n generators.push(resourceGenerator);\n }\n\n // Always add AI guides generator\n generators.push(aiGuidesGenerator);\n\n return {\n name: '@famgia/omnify-laravel',\n version: '0.0.14',\n configSchema: LARAVEL_CONFIG_SCHEMA,\n generators,\n };\n}\n\n// Named export for flexibility\nexport { laravelPlugin };\n","/**\n * Laravel FormRequest Generator\n *\n * Generates Laravel FormRequest classes from Omnify schemas.\n * Creates base requests (auto-generated) and user requests (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition, AssociationDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { pluralize, toSnakeCase, toPascalCase } from '../utils.js';\n\n/**\n * Options for request generation.\n */\nexport interface RequestGeneratorOptions {\n /**\n * Base request namespace.\n * @default 'App\\\\Http\\\\Requests\\\\OmnifyBase'\n */\n baseRequestNamespace?: string;\n\n /**\n * User request namespace.\n * @default 'App\\\\Http\\\\Requests'\n */\n requestNamespace?: string;\n\n /**\n * Output path for base requests.\n * @default 'app/Http/Requests/OmnifyBase'\n */\n baseRequestPath?: string;\n\n /**\n * Output path for user requests.\n * @default 'app/Http/Requests'\n */\n requestPath?: string;\n\n /**\n * Model namespace for exists rules.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Custom types registered by plugins.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n\n /**\n * Locale for displayName (used in attributes).\n * @default 'en'\n */\n locale?: string;\n}\n\n/**\n * Generated request output.\n */\nexport interface GeneratedRequest {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Request type */\n type: 'store-base' | 'update-base' | 'store' | 'update';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n /** Module name (from schema path or empty) */\n module: string;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseRequestNamespace: string;\n requestNamespace: string;\n baseRequestPath: string;\n requestPath: string;\n modelNamespace: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n locale: string;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseRequestNamespace: 'App\\\\Http\\\\Requests\\\\OmnifyBase',\n requestNamespace: 'App\\\\Http\\\\Requests',\n baseRequestPath: 'app/Http/Requests/OmnifyBase',\n requestPath: 'app/Http/Requests',\n modelNamespace: 'App\\\\Models',\n customTypes: new Map(),\n locale: 'en',\n};\n\n/**\n * Fields to skip when generating validation rules.\n */\nconst SKIP_FIELDS = new Set([\n 'id',\n 'created_at',\n 'updated_at',\n 'deleted_at',\n 'remember_token',\n 'email_verified_at',\n]);\n\n/**\n * OpenAPI property definition for requests.\n */\ninterface RequestOpenApiProperty {\n property: string;\n type: string;\n format?: string;\n maxLength?: number;\n minLength?: number;\n nullable?: boolean;\n enum?: string[];\n example?: string | number | boolean;\n}\n\n/**\n * Get example value based on field name pattern.\n */\nfunction getExampleValue(fieldName: string, type: string): string | number | boolean | undefined {\n // Japanese name patterns\n if (fieldName.endsWith('_lastname') && !fieldName.includes('kana')) {\n return '田中';\n }\n if (fieldName.endsWith('_firstname') && !fieldName.includes('kana')) {\n return '太郎';\n }\n if (fieldName.includes('kana_lastname') || fieldName.endsWith('_kana_lastname')) {\n return 'タナカ';\n }\n if (fieldName.includes('kana_firstname') || fieldName.endsWith('_kana_firstname')) {\n return 'タロウ';\n }\n\n // Email\n if (fieldName.includes('email')) {\n return 'user@example.com';\n }\n\n // Password\n if (fieldName.includes('password')) {\n return 'password123';\n }\n\n // URL\n if (fieldName.includes('url') || fieldName.includes('website')) {\n return 'https://example.com';\n }\n\n // ID fields\n if (fieldName.endsWith('_id')) {\n return 1;\n }\n\n // DateTime fields\n if (fieldName.endsWith('_at')) {\n return '2024-01-01T00:00:00Z';\n }\n\n // Boolean\n if (type === 'boolean') {\n return true;\n }\n\n // Integer\n if (type === 'integer') {\n return 1;\n }\n\n return undefined;\n}\n\n/**\n * Map validation type to OpenAPI type.\n */\nfunction mapValidationToOpenApiType(rules: string[], fieldName: string): { type: string; format?: string } {\n // Check field name patterns first\n if (fieldName.includes('email')) {\n return { type: 'string', format: 'email' };\n }\n if (fieldName.includes('password')) {\n return { type: 'string', format: 'password' };\n }\n if (fieldName.includes('url') || fieldName.includes('website')) {\n return { type: 'string', format: 'uri' };\n }\n\n // Check validation rules\n for (const rule of rules) {\n if (rule === \"'integer'\") {\n return { type: 'integer' };\n }\n if (rule === \"'boolean'\") {\n return { type: 'boolean' };\n }\n if (rule === \"'numeric'\") {\n return { type: 'number' };\n }\n if (rule === \"'array'\") {\n return { type: 'array' };\n }\n if (rule === \"'email'\") {\n return { type: 'string', format: 'email' };\n }\n if (rule === \"'url'\") {\n return { type: 'string', format: 'uri' };\n }\n if (rule === \"'date'\") {\n // Check if it looks like datetime\n if (fieldName.endsWith('_at')) {\n return { type: 'string', format: 'date-time' };\n }\n return { type: 'string', format: 'date' };\n }\n }\n\n return { type: 'string' };\n}\n\n/**\n * Extract constraints from validation rules.\n */\nfunction extractConstraints(rules: string[]): { maxLength?: number; minLength?: number; nullable?: boolean; enum?: string[] } {\n const constraints: { maxLength?: number; minLength?: number; nullable?: boolean; enum?: string[] } = {};\n\n for (const rule of rules) {\n // max:N\n const maxMatch = rule.match(/'max:(\\d+)'/);\n if (maxMatch) {\n constraints.maxLength = parseInt(maxMatch[1], 10);\n }\n\n // min:N (for strings)\n const minMatch = rule.match(/'min:(\\d+)'/);\n if (minMatch) {\n constraints.minLength = parseInt(minMatch[1], 10);\n }\n\n // nullable\n if (rule === \"'nullable'\") {\n constraints.nullable = true;\n }\n\n // Rule::in([...])\n const inMatch = rule.match(/Rule::in\\(\\[([^\\]]+)\\]\\)/);\n if (inMatch) {\n const values = inMatch[1].split(',').map(v => v.trim().replace(/^'|'$/g, ''));\n constraints.enum = values;\n }\n }\n\n return constraints;\n}\n\n/**\n * Format OpenAPI property for request as PHP attribute.\n */\nfunction formatRequestOpenApiProperty(prop: RequestOpenApiProperty, indent: string): string {\n const parts: string[] = [`property: '${prop.property}'`, `type: '${prop.type}'`];\n\n if (prop.format) {\n parts.push(`format: '${prop.format}'`);\n }\n if (prop.maxLength) {\n parts.push(`maxLength: ${prop.maxLength}`);\n }\n if (prop.minLength) {\n parts.push(`minLength: ${prop.minLength}`);\n }\n if (prop.nullable) {\n parts.push(`nullable: true`);\n }\n if (prop.enum) {\n const enumStr = prop.enum.map(v => `'${v}'`).join(', ');\n parts.push(`enum: [${enumStr}]`);\n }\n if (prop.example !== undefined) {\n if (typeof prop.example === 'string') {\n parts.push(`example: '${escapePhpString(prop.example)}'`);\n } else {\n parts.push(`example: ${prop.example}`);\n }\n }\n\n return `${indent}new OA\\\\Property(${parts.join(', ')})`;\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: RequestGeneratorOptions): ResolvedOptions {\n return {\n baseRequestNamespace: options?.baseRequestNamespace ?? DEFAULT_OPTIONS.baseRequestNamespace,\n requestNamespace: options?.requestNamespace ?? DEFAULT_OPTIONS.requestNamespace,\n baseRequestPath: options?.baseRequestPath ?? DEFAULT_OPTIONS.baseRequestPath,\n requestPath: options?.requestPath ?? DEFAULT_OPTIONS.requestPath,\n modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,\n customTypes: options?.customTypes ?? new Map(),\n locale: options?.locale ?? DEFAULT_OPTIONS.locale,\n };\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Get display name from LocalizedString.\n */\nfunction getDisplayName(displayName: LocalizedString | undefined, locale: string, fallback: string): string {\n if (!displayName) return fallback;\n if (typeof displayName === 'string') return displayName;\n if (isLocaleMap(displayName)) {\n return displayName[locale] ?? displayName['en'] ?? fallback;\n }\n return fallback;\n}\n\n/**\n * Get module name from schema (based on schema path or options).\n */\nfunction getModuleName(schema: LoadedSchema): string {\n // Use schema.module if available, otherwise derive from schema path or use empty string\n // For now, we'll use a simple heuristic - can be enhanced later\n if ((schema as any).module) {\n return (schema as any).module;\n }\n // Default: no module (files go directly in Requests folder)\n return '';\n}\n\n/**\n * Generate validation rules for a property (Store - required by default).\n */\nfunction generateStoreRules(\n propName: string,\n propDef: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const rules: string[] = [];\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n\n // Check if nullable\n const isNullable = prop.nullable === true;\n\n // Required rule (unless nullable)\n if (!isNullable) {\n rules.push(\"'required'\");\n } else {\n rules.push(\"'nullable'\");\n }\n\n // Type-specific rules\n switch (propDef.type) {\n case 'String':\n case 'Email':\n case 'Password':\n rules.push(\"'string'\");\n const length = prop.length ?? 255;\n rules.push(`'max:${length}'`);\n if (propDef.type === 'Email') {\n rules.push(\"'email'\");\n }\n break;\n\n case 'Text':\n case 'MediumText':\n case 'LongText':\n rules.push(\"'string'\");\n break;\n\n case 'TinyInt':\n case 'Int':\n case 'BigInt':\n rules.push(\"'integer'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Float':\n case 'Decimal':\n rules.push(\"'numeric'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Boolean':\n rules.push(\"'boolean'\");\n break;\n\n case 'Date':\n rules.push(\"'date'\");\n break;\n\n case 'DateTime':\n case 'Timestamp':\n rules.push(\"'date'\");\n break;\n\n case 'Json':\n rules.push(\"'array'\");\n break;\n\n case 'Enum':\n case 'EnumRef':\n rules.push(\"'string'\");\n if (prop.enum && Array.isArray(prop.enum)) {\n const values = prop.enum.map((v: string) => `'${v}'`).join(', ');\n rules.push(`Rule::in([${values}])`);\n }\n break;\n\n case 'Association':\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (assoc.target) {\n const targetSchema = schemas[assoc.target];\n const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));\n rules.push(\"'integer'\");\n rules.push(`'exists:${targetTable},id'`);\n }\n }\n break;\n\n default:\n // Handle custom types (non-compound)\n const customType = options.customTypes.get(propDef.type);\n if (customType && !customType.compound) {\n // Japanese custom types\n if (propDef.type === 'JapanesePhone') {\n rules.push(\"'string'\");\n rules.push(\"'max:15'\");\n // Japanese phone format: 090-1234-5678 or 03-1234-5678\n rules.push(\"'regex:/^\\\\d{2,4}-\\\\d{2,4}-\\\\d{4}$/'\");\n } else if (propDef.type === 'JapanesePostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else {\n // Default: use SQL type info from custom type\n const sqlType = customType.sql?.sqlType ?? 'VARCHAR';\n const sqlLength = customType.sql?.length ?? 255;\n if (sqlType === 'VARCHAR' || sqlType === 'TEXT') {\n rules.push(\"'string'\");\n if (sqlType === 'VARCHAR') {\n rules.push(`'max:${sqlLength}'`);\n }\n } else if (sqlType === 'INT' || sqlType === 'TINYINT' || sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n } else if (sqlType === 'DECIMAL' || sqlType === 'FLOAT') {\n rules.push(\"'numeric'\");\n }\n }\n }\n break;\n }\n\n // Unique constraint\n if (prop.unique === true) {\n rules.push(`'unique:${tableName}'`);\n }\n\n return rules;\n}\n\n/**\n * Generate validation rules for a property (Update - sometimes by default).\n */\nfunction generateUpdateRules(\n propName: string,\n propDef: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const rules: string[] = [];\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n const modelVar = toSnakeCase(schema.name);\n\n // Use 'sometimes' for partial updates\n rules.push(\"'sometimes'\");\n\n // Type-specific rules (same as store, but without required)\n switch (propDef.type) {\n case 'String':\n case 'Email':\n case 'Password':\n rules.push(\"'string'\");\n const length = prop.length ?? 255;\n rules.push(`'max:${length}'`);\n if (propDef.type === 'Email') {\n rules.push(\"'email'\");\n }\n break;\n\n case 'Text':\n case 'MediumText':\n case 'LongText':\n rules.push(\"'string'\");\n break;\n\n case 'TinyInt':\n case 'Int':\n case 'BigInt':\n rules.push(\"'integer'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Float':\n case 'Decimal':\n rules.push(\"'numeric'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Boolean':\n rules.push(\"'boolean'\");\n break;\n\n case 'Date':\n rules.push(\"'date'\");\n break;\n\n case 'DateTime':\n case 'Timestamp':\n rules.push(\"'date'\");\n break;\n\n case 'Json':\n rules.push(\"'array'\");\n break;\n\n case 'Enum':\n case 'EnumRef':\n rules.push(\"'string'\");\n if (prop.enum && Array.isArray(prop.enum)) {\n const values = prop.enum.map((v: string) => `'${v}'`).join(', ');\n rules.push(`Rule::in([${values}])`);\n }\n break;\n\n case 'Association':\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (assoc.target) {\n const targetSchema = schemas[assoc.target];\n const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));\n rules.push(\"'integer'\");\n rules.push(`'exists:${targetTable},id'`);\n }\n }\n break;\n\n default:\n // Handle custom types (non-compound)\n const customType = options.customTypes.get(propDef.type);\n if (customType && !customType.compound) {\n // Japanese custom types\n if (propDef.type === 'JapanesePhone') {\n rules.push(\"'string'\");\n rules.push(\"'max:15'\");\n // Japanese phone format: 090-1234-5678 or 03-1234-5678\n rules.push(\"'regex:/^\\\\d{2,4}-\\\\d{2,4}-\\\\d{4}$/'\");\n } else if (propDef.type === 'JapanesePostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else {\n // Default: use SQL type info from custom type\n const sqlType = customType.sql?.sqlType ?? 'VARCHAR';\n const sqlLength = customType.sql?.length ?? 255;\n if (sqlType === 'VARCHAR' || sqlType === 'TEXT') {\n rules.push(\"'string'\");\n if (sqlType === 'VARCHAR') {\n rules.push(`'max:${sqlLength}'`);\n }\n } else if (sqlType === 'INT' || sqlType === 'TINYINT' || sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n } else if (sqlType === 'DECIMAL' || sqlType === 'FLOAT') {\n rules.push(\"'numeric'\");\n }\n }\n }\n break;\n }\n\n // Unique constraint with ignore for updates\n if (prop.unique === true) {\n rules.push(`Rule::unique('${tableName}')->ignore($this->route('${modelVar}'))`);\n }\n\n return rules;\n}\n\n/**\n * Get validation rules for a specific compound field type.\n */\nfunction getCompoundFieldRules(\n typeName: string,\n suffix: string,\n field: any,\n fieldOverride: any\n): string[] {\n const rules: string[] = [];\n const sql = field.sql;\n const length = fieldOverride?.length ?? sql?.length ?? 255;\n\n // Handle different compound types with specific validation\n switch (typeName) {\n case 'JapaneseName':\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n // Kana fields could have katakana validation\n if (suffix === 'KanaLastname' || suffix === 'KanaFirstname') {\n // Katakana regex: only katakana and common punctuation\n rules.push(\"'regex:/^[\\\\x{30A0}-\\\\x{30FF}\\\\x{3000}-\\\\x{303F}\\\\x{FF00}-\\\\x{FF9F}\\\\s]+$/u'\");\n }\n break;\n\n case 'JapaneseAddress':\n if (suffix === 'PostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else if (suffix === 'PrefectureId') {\n rules.push(\"'integer'\");\n rules.push(\"'between:1,47'\");\n } else {\n // Address1, Address2, Address3\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n }\n break;\n\n case 'JapaneseBankAccount':\n if (suffix === 'BankCode') {\n rules.push(\"'string'\");\n rules.push(\"'size:4'\");\n rules.push(\"'regex:/^\\\\d{4}$/'\");\n } else if (suffix === 'BranchCode') {\n rules.push(\"'string'\");\n rules.push(\"'size:3'\");\n rules.push(\"'regex:/^\\\\d{3}$/'\");\n } else if (suffix === 'AccountType') {\n rules.push(\"'string'\");\n rules.push(\"Rule::in(['1', '2', '4'])\"); // 普通/当座/貯蓄\n } else if (suffix === 'AccountNumber') {\n rules.push(\"'string'\");\n rules.push(\"'max:7'\");\n rules.push(\"'regex:/^\\\\d{1,7}$/'\");\n } else if (suffix === 'AccountHolder') {\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n // Katakana validation for account holder name\n rules.push(\"'regex:/^[\\\\x{30A0}-\\\\x{30FF}\\\\x{3000}-\\\\x{303F}\\\\x{FF00}-\\\\x{FF9F}\\\\s]+$/u'\");\n }\n break;\n\n default:\n // Default handling for unknown compound types\n if (sql?.sqlType === 'TINYINT' || sql?.sqlType === 'INT' || sql?.sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n if (sql?.unsigned) {\n rules.push(\"'min:0'\");\n }\n } else {\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n }\n break;\n }\n\n return rules;\n}\n\n/**\n * Expand compound type fields.\n */\nfunction expandCompoundTypeFields(\n propName: string,\n propDef: PropertyDefinition,\n options: ResolvedOptions\n): { fieldName: string; rules: string[]; needsRuleImport: boolean }[] {\n const typeDef = options.customTypes.get(propDef.type);\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return [];\n }\n\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const isNullable = prop.nullable === true;\n const fields: { fieldName: string; rules: string[]; needsRuleImport: boolean }[] = [];\n\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const fieldOverride = prop.fields?.[field.suffix];\n\n // Field-level nullable can override property-level\n // Also check if the field itself is defined as nullable in the type definition\n const fieldDefNullable = (field as any).sql?.nullable ?? false;\n const fieldNullable = fieldOverride?.nullable ?? fieldDefNullable ?? isNullable;\n\n const rules: string[] = [];\n if (!fieldNullable) {\n rules.push(\"'required'\");\n } else {\n rules.push(\"'nullable'\");\n }\n\n // Get type-specific validation rules\n const typeRules = getCompoundFieldRules(propDef.type, field.suffix, field, fieldOverride);\n rules.push(...typeRules);\n\n const needsRuleImport = rules.some(r => r.includes('Rule::'));\n fields.push({ fieldName, rules, needsRuleImport });\n }\n\n return fields;\n}\n\n/**\n * Generate Store Request Base class.\n */\nfunction generateStoreRequestBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const rulesLines: string[] = [];\n const attributeLines: string[] = [];\n const fieldList: string[] = [];\n let needsRuleImport = false;\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip association relations that don't have FK (OneToMany, ManyToMany, etc.)\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n // For ManyToOne/OneToOne, use the FK field name\n const fkName = `${snakeName}_id`;\n const rules = generateStoreRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${fkName}' => [${rules.join(', ')}],`);\n fieldList.push(fkName);\n\n // Attribute for FK\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${fkName}' => '${escapePhpString(displayName)}',`);\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n if (field.needsRuleImport) needsRuleImport = true;\n rulesLines.push(` '${field.fieldName}' => [${field.rules.join(', ')}],`);\n fieldList.push(field.fieldName);\n attributeLines.push(` '${field.fieldName}' => '${escapePhpString(field.fieldName)}',`);\n }\n continue;\n }\n\n // Regular field\n const rules = generateStoreRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${snakeName}' => [${rules.join(', ')}],`);\n fieldList.push(snakeName);\n\n // Attribute\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${snakeName}' => '${escapePhpString(displayName)}',`);\n }\n\n const ruleImport = needsRuleImport ? '\\nuse Illuminate\\\\Validation\\\\Rule;' : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Foundation\\\\Http\\\\FormRequest;${ruleImport}\n\nabstract class ${className}StoreRequestBase extends FormRequest\n{\n /**\n * Validation rules generated from Omnify schema.\n *\n * Generated fields: ${fieldList.join(', ')}\n *\n * @return array<string, array<int, mixed>>\n */\n protected function schemaRules(): array\n {\n return [\n${rulesLines.join('\\n')}\n ];\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n protected function schemaAttributes(): array\n {\n return [\n${attributeLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseRequestPath}${modulePath}/${className}StoreRequestBase.php`,\n content,\n type: 'store-base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Update Request Base class.\n */\nfunction generateUpdateRequestBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const rulesLines: string[] = [];\n const attributeLines: string[] = [];\n let needsRuleImport = false;\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip association relations that don't have FK\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n const fkName = `${snakeName}_id`;\n const rules = generateUpdateRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::') || r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${fkName}' => [${rules.join(', ')}],`);\n\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${fkName}' => '${escapePhpString(displayName)}',`);\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n if (field.needsRuleImport) needsRuleImport = true;\n // For update, replace 'required' with 'sometimes'\n const updateRules = field.rules.map(r => r === \"'required'\" ? \"'sometimes'\" : r);\n rulesLines.push(` '${field.fieldName}' => [${updateRules.join(', ')}],`);\n attributeLines.push(` '${field.fieldName}' => '${escapePhpString(field.fieldName)}',`);\n }\n continue;\n }\n\n // Regular field\n const rules = generateUpdateRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${snakeName}' => [${rules.join(', ')}],`);\n\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${snakeName}' => '${escapePhpString(displayName)}',`);\n }\n\n const ruleImport = needsRuleImport ? '\\nuse Illuminate\\\\Validation\\\\Rule;' : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Foundation\\\\Http\\\\FormRequest;${ruleImport}\n\nabstract class ${className}UpdateRequestBase extends FormRequest\n{\n /**\n * Validation rules generated from Omnify schema.\n * All fields use 'sometimes' for partial updates.\n *\n * @return array<string, array<int, mixed>>\n */\n protected function schemaRules(): array\n {\n return [\n${rulesLines.join('\\n')}\n ];\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n protected function schemaAttributes(): array\n {\n return [\n${attributeLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseRequestPath}${modulePath}/${className}UpdateRequestBase.php`,\n content,\n type: 'update-base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate OpenAPI properties for a request based on schema.\n */\nfunction generateRequestOpenApiProperties(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n isStore: boolean\n): { properties: RequestOpenApiProperty[]; requiredFields: string[] } {\n const properties: RequestOpenApiProperty[] = [];\n const requiredFields: string[] = [];\n const schemaProps = schema.properties ?? {};\n\n for (const [propName, propDef] of Object.entries(schemaProps)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip associations that don't have FK\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n // For FK fields\n const fkName = `${snakeName}_id`;\n const rules = isStore\n ? generateStoreRules(propName, propDef, schema, schemas, options)\n : generateUpdateRules(propName, propDef, schema, schemas, options);\n const openApiType = mapValidationToOpenApiType(rules, fkName);\n const constraints = extractConstraints(rules);\n const example = getExampleValue(fkName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: fkName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and not nullable\n if (isStore && !(propDef as any).nullable) {\n requiredFields.push(fkName);\n }\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n const openApiType = mapValidationToOpenApiType(field.rules, field.fieldName);\n const constraints = extractConstraints(field.rules);\n const example = getExampleValue(field.fieldName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: field.fieldName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and has 'required' rule\n if (isStore && field.rules.includes(\"'required'\")) {\n requiredFields.push(field.fieldName);\n }\n }\n continue;\n }\n\n // Regular field\n const rules = isStore\n ? generateStoreRules(propName, propDef, schema, schemas, options)\n : generateUpdateRules(propName, propDef, schema, schemas, options);\n const openApiType = mapValidationToOpenApiType(rules, snakeName);\n const constraints = extractConstraints(rules);\n const example = getExampleValue(snakeName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: snakeName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and has 'required' rule\n if (isStore && rules.includes(\"'required'\")) {\n requiredFields.push(snakeName);\n }\n }\n\n return { properties, requiredFields };\n}\n\n/**\n * Generate Store Request (user-editable).\n */\nfunction generateStoreRequest(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.requestNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties\n const { properties, requiredFields } = generateRequestOpenApiProperties(schema, schemas, options, true);\n const propsIndent = ' ';\n const openApiPropsFormatted = properties\n .map(prop => formatRequestOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n // Format required array\n const requiredArray = requiredFields.length > 0\n ? `\\n required: [${requiredFields.map(f => `'${f}'`).join(', ')}],`\n : '';\n\n const content = `<?php\n\n/**\n * ${className} Store Request\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}StoreRequestBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}StoreRequest',${requiredArray}\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}StoreRequest extends ${className}StoreRequestBase\n{\n /**\n * Determine if the user is authorized to make this request.\n */\n public function authorize(): bool\n {\n return true;\n }\n\n /**\n * Get the validation rules that apply to the request.\n *\n * @return array<string, array<int, mixed>>\n */\n public function rules(): array\n {\n return array_merge($this->schemaRules(), [\n // Custom/override rules here\n ]);\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n public function attributes(): array\n {\n return array_merge($this->schemaAttributes(), [\n // Custom attributes here\n ]);\n }\n\n /**\n * Get custom messages for validator errors.\n *\n * @return array<string, string>\n */\n public function messages(): array\n {\n return [\n // Custom messages here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.requestPath}${modulePath}/${className}StoreRequest.php`,\n content,\n type: 'store',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Update Request (user-editable).\n */\nfunction generateUpdateRequest(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.requestNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties (no required array for update - partial updates allowed)\n const { properties } = generateRequestOpenApiProperties(schema, schemas, options, false);\n const propsIndent = ' ';\n const openApiPropsFormatted = properties\n .map(prop => formatRequestOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n const content = `<?php\n\n/**\n * ${className} Update Request\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}UpdateRequestBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}UpdateRequest',\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}UpdateRequest extends ${className}UpdateRequestBase\n{\n /**\n * Determine if the user is authorized to make this request.\n */\n public function authorize(): bool\n {\n return true;\n }\n\n /**\n * Get the validation rules that apply to the request.\n *\n * @return array<string, array<int, mixed>>\n */\n public function rules(): array\n {\n return array_merge($this->schemaRules(), [\n // Custom/override rules here\n ]);\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n public function attributes(): array\n {\n return array_merge($this->schemaAttributes(), [\n // Custom attributes here\n ]);\n }\n\n /**\n * Get custom messages for validator errors.\n *\n * @return array<string, string>\n */\n public function messages(): array\n {\n return [\n // Custom messages here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.requestPath}${modulePath}/${className}UpdateRequest.php`,\n content,\n type: 'update',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate all FormRequest classes for the given schemas.\n */\nexport function generateRequests(\n schemas: SchemaCollection,\n options?: RequestGeneratorOptions\n): GeneratedRequest[] {\n const resolved = resolveOptions(options);\n const requests: GeneratedRequest[] = [];\n\n for (const schema of Object.values(schemas)) {\n // Skip enums\n if (schema.kind === 'enum') continue;\n\n // Skip hidden schemas\n if (schema.options?.hidden === true) continue;\n\n // Generate base requests (always overwritten)\n requests.push(generateStoreRequestBase(schema, schemas, resolved));\n requests.push(generateUpdateRequestBase(schema, schemas, resolved));\n\n // Generate user requests (created once)\n requests.push(generateStoreRequest(schema, schemas, resolved));\n requests.push(generateUpdateRequest(schema, schemas, resolved));\n }\n\n return requests;\n}\n\n/**\n * Get the output path for a request.\n */\nexport function getRequestPath(request: GeneratedRequest): string {\n return request.path;\n}\n","/**\n * Laravel Resource Generator\n *\n * Generates Laravel API Resource classes from Omnify schemas.\n * Creates base resources (auto-generated) and user resources (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition, AssociationDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { toSnakeCase, toPascalCase, toCamelCase } from '../utils.js';\n\n/**\n * Options for resource generation.\n */\nexport interface ResourceGeneratorOptions {\n /**\n * Base resource namespace.\n * @default 'App\\\\Http\\\\Resources\\\\OmnifyBase'\n */\n baseResourceNamespace?: string;\n\n /**\n * User resource namespace.\n * @default 'App\\\\Http\\\\Resources'\n */\n resourceNamespace?: string;\n\n /**\n * Output path for base resources.\n * @default 'app/Http/Resources/OmnifyBase'\n */\n baseResourcePath?: string;\n\n /**\n * Output path for user resources.\n * @default 'app/Http/Resources'\n */\n resourcePath?: string;\n\n /**\n * Custom types registered by plugins.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n\n /**\n * Locale for displayName.\n * @default 'en'\n */\n locale?: string;\n}\n\n/**\n * Generated resource output.\n */\nexport interface GeneratedResource {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Resource type */\n type: 'base' | 'user';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n /** Module name (from schema path or empty) */\n module: string;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseResourceNamespace: string;\n resourceNamespace: string;\n baseResourcePath: string;\n resourcePath: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n locale: string;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseResourceNamespace: 'App\\\\Http\\\\Resources\\\\OmnifyBase',\n resourceNamespace: 'App\\\\Http\\\\Resources',\n baseResourcePath: 'app/Http/Resources/OmnifyBase',\n resourcePath: 'app/Http/Resources',\n customTypes: new Map(),\n locale: 'en',\n};\n\n/**\n * Fields to skip when generating resource output.\n */\nconst SKIP_FIELDS = new Set([\n 'password',\n 'remember_token',\n]);\n\n/**\n * OpenAPI property definition.\n */\ninterface OpenApiProperty {\n property: string;\n type: string;\n format?: string;\n maxLength?: number;\n nullable?: boolean;\n example?: string | number | boolean;\n}\n\n/**\n * Map TypeScript type to OpenAPI type and format.\n */\nfunction mapTsTypeToOpenApi(tsType: string, fieldName: string): { type: string; format?: string } {\n // Check for special field name patterns\n if (fieldName.includes('email')) {\n return { type: 'string', format: 'email' };\n }\n\n switch (tsType) {\n case 'string':\n return { type: 'string' };\n case 'number':\n return { type: 'number' };\n case 'boolean':\n return { type: 'boolean' };\n default:\n return { type: 'string' };\n }\n}\n\n/**\n * Map Omnify type to OpenAPI type and format.\n */\nfunction getOpenApiType(propDef: PropertyDefinition, fieldName: string): { type: string; format?: string } {\n // Handle date/time types first (before field name checks)\n switch (propDef.type) {\n case 'Date':\n return { type: 'string', format: 'date' };\n case 'DateTime':\n case 'Timestamp':\n return { type: 'string', format: 'date-time' };\n }\n\n // Check for special field name patterns\n if (fieldName.includes('email') && !fieldName.endsWith('_at')) {\n return { type: 'string', format: 'email' };\n }\n if (fieldName.includes('password')) {\n return { type: 'string', format: 'password' };\n }\n\n switch (propDef.type) {\n case 'String':\n case 'Text':\n case 'LongText':\n return { type: 'string' };\n case 'Int':\n case 'BigInt':\n return { type: 'integer' };\n case 'Float':\n case 'Decimal':\n return { type: 'number' };\n case 'Boolean':\n return { type: 'boolean' };\n case 'Email':\n return { type: 'string', format: 'email' };\n case 'UUID':\n return { type: 'string', format: 'uuid' };\n case 'JSON':\n return { type: 'object' };\n default:\n return { type: 'string' };\n }\n}\n\n/**\n * Generate OpenAPI properties for a schema.\n */\nfunction generateOpenApiProperties(\n schema: LoadedSchema,\n options: ResolvedOptions\n): OpenApiProperty[] {\n const properties: OpenApiProperty[] = [];\n const schemaProps = schema.properties ?? {};\n\n // Always include id first\n if (schema.options?.id !== false) {\n properties.push({\n property: 'id',\n type: 'integer',\n example: 1,\n });\n }\n\n // Process schema properties\n for (const [propName, propDef] of Object.entries(schemaProps)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip hidden fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n if ((propDef as { hidden?: boolean }).hidden === true) continue;\n\n // Skip associations (they're complex nested objects)\n if (propDef.type === 'Association') continue;\n\n // Handle compound types\n const typeDef = options.customTypes.get(propDef.type);\n if (typeDef?.compound && typeDef.expand) {\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n // Get type from typescript definition or default to string\n const tsType = field.typescript?.type ?? 'string';\n const openApiType = mapTsTypeToOpenApi(tsType, fieldName);\n const prop: OpenApiProperty = {\n property: fieldName,\n ...openApiType,\n };\n // Get maxLength from SQL definition if available\n const sqlDef = field.sql as { length?: number } | undefined;\n if (sqlDef?.length) {\n prop.maxLength = sqlDef.length;\n }\n properties.push(prop);\n }\n // Add accessors\n if (typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n properties.push({\n property: accessorName,\n type: 'string',\n });\n }\n }\n continue;\n }\n\n // Regular field\n const openApiType = getOpenApiType(propDef, snakeName);\n const prop: OpenApiProperty = {\n property: snakeName,\n ...openApiType,\n };\n\n // Add maxLength from length property\n const length = (propDef as { length?: number }).length;\n if (length) {\n prop.maxLength = length;\n }\n\n // Add nullable\n if ((propDef as { nullable?: boolean }).nullable) {\n prop.nullable = true;\n }\n\n properties.push(prop);\n }\n\n // Add timestamps\n if (schema.options?.timestamps !== false) {\n properties.push({\n property: 'created_at',\n type: 'string',\n format: 'date-time',\n });\n properties.push({\n property: 'updated_at',\n type: 'string',\n format: 'date-time',\n });\n }\n\n // Add soft delete timestamp\n if (schema.options?.softDelete) {\n properties.push({\n property: 'deleted_at',\n type: 'string',\n format: 'date-time',\n nullable: true,\n });\n }\n\n return properties;\n}\n\n/**\n * Format OpenAPI property as PHP attribute.\n */\nfunction formatOpenApiProperty(prop: OpenApiProperty, indent: string): string {\n const parts: string[] = [`property: '${prop.property}'`, `type: '${prop.type}'`];\n\n if (prop.format) {\n parts.push(`format: '${prop.format}'`);\n }\n if (prop.maxLength) {\n parts.push(`maxLength: ${prop.maxLength}`);\n }\n if (prop.nullable) {\n parts.push(`nullable: true`);\n }\n if (prop.example !== undefined) {\n if (typeof prop.example === 'string') {\n parts.push(`example: '${prop.example}'`);\n } else {\n parts.push(`example: ${prop.example}`);\n }\n }\n\n return `${indent}new OA\\\\Property(${parts.join(', ')})`;\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: ResourceGeneratorOptions): ResolvedOptions {\n return {\n baseResourceNamespace: options?.baseResourceNamespace ?? DEFAULT_OPTIONS.baseResourceNamespace,\n resourceNamespace: options?.resourceNamespace ?? DEFAULT_OPTIONS.resourceNamespace,\n baseResourcePath: options?.baseResourcePath ?? DEFAULT_OPTIONS.baseResourcePath,\n resourcePath: options?.resourcePath ?? DEFAULT_OPTIONS.resourcePath,\n customTypes: options?.customTypes ?? new Map(),\n locale: options?.locale ?? DEFAULT_OPTIONS.locale,\n };\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Get module name from schema.\n */\nfunction getModuleName(schema: LoadedSchema): string {\n if ((schema as any).module) {\n return (schema as any).module;\n }\n return '';\n}\n\n/**\n * Get the PHP output expression for a field based on its type.\n * For date/time fields, always use ?-> for safe null handling.\n */\nfunction getFieldExpression(fieldName: string, propDef: PropertyDefinition): string {\n switch (propDef.type) {\n case 'Date':\n return `$this->${fieldName}?->toDateString()`;\n case 'DateTime':\n case 'Timestamp':\n return `$this->${fieldName}?->toISOString()`;\n default:\n return `$this->${fieldName}`;\n }\n}\n\n/**\n * Get resource field output for a property.\n */\nfunction getPropertyOutput(\n propName: string,\n propDef: PropertyDefinition,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const snakeName = toSnakeCase(propName);\n const lines: string[] = [];\n\n // Skip hidden fields\n if (SKIP_FIELDS.has(snakeName)) {\n return lines;\n }\n\n // Handle associations\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n const targetClass = assoc.target ? toPascalCase(assoc.target) : '';\n\n switch (assoc.relation) {\n case 'ManyToOne':\n case 'OneToOne':\n // Include FK and optionally loaded relation\n lines.push(` '${snakeName}_id' => $this->${snakeName}_id,`);\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => new ${targetClass}Resource($this->${toCamelCase(propName)})),`);\n break;\n case 'OneToMany':\n case 'ManyToMany':\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => ${targetClass}Resource::collection($this->${toCamelCase(propName)})),`);\n break;\n case 'MorphTo':\n lines.push(` '${snakeName}_type' => $this->${snakeName}_type,`);\n lines.push(` '${snakeName}_id' => $this->${snakeName}_id,`);\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}'),`);\n break;\n case 'MorphOne':\n case 'MorphMany':\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => ${targetClass}Resource::collection($this->${toCamelCase(propName)})),`);\n break;\n }\n return lines;\n }\n\n // Handle compound types\n const typeDef = options.customTypes.get(propDef.type);\n if (typeDef?.compound && typeDef.expand) {\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n lines.push(` '${fieldName}' => $this->${fieldName},`);\n }\n // Add accessor if exists\n if (typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n lines.push(` '${accessorName}' => $this->${accessorName},`);\n }\n }\n return lines;\n }\n\n // Regular fields - apply date/time formatting\n const expression = getFieldExpression(snakeName, propDef);\n lines.push(` '${snakeName}' => ${expression},`);\n return lines;\n}\n\n/**\n * Generate Resource Base class.\n */\nfunction generateResourceBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedResource {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseResourceNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const outputLines: string[] = [];\n const imports: Set<string> = new Set();\n\n // Always include id\n if (schema.options?.id !== false) {\n outputLines.push(` 'id' => $this->id,`);\n }\n\n // Process properties\n for (const [propName, propDef] of Object.entries(properties)) {\n const lines = getPropertyOutput(propName, propDef, schemas, options);\n outputLines.push(...lines);\n\n // Collect imports for related resources\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n const targetModule = getModuleName(schemas[assoc.target] ?? schema);\n const targetModuleNs = targetModule ? `\\\\${targetModule}` : '';\n imports.add(`use ${options.resourceNamespace}${targetModuleNs}\\\\${toPascalCase(assoc.target)}Resource;`);\n }\n }\n }\n\n // Add timestamps\n if (schema.options?.timestamps !== false) {\n outputLines.push(` 'created_at' => $this->created_at?->toISOString(),`);\n outputLines.push(` 'updated_at' => $this->updated_at?->toISOString(),`);\n }\n\n // Add soft delete\n if (schema.options?.softDelete) {\n outputLines.push(` 'deleted_at' => $this->deleted_at?->toISOString(),`);\n }\n\n const importLines = Array.from(imports).sort().join('\\n');\n const importBlock = importLines ? `\\n${importLines}` : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Http\\\\Request;\nuse Illuminate\\\\Http\\\\Resources\\\\Json\\\\JsonResource;${importBlock}\n\nclass ${className}ResourceBase extends JsonResource\n{\n /**\n * Transform the resource into an array.\n *\n * @return array<string, mixed>\n */\n protected function schemaArray(Request $request): array\n {\n return [\n${outputLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseResourcePath}${modulePath}/${className}ResourceBase.php`,\n content,\n type: 'base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Resource (user-editable).\n */\nfunction generateResource(\n schema: LoadedSchema,\n options: ResolvedOptions\n): GeneratedResource {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.resourceNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseResourceNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties\n const openApiProps = generateOpenApiProperties(schema, options);\n const propsIndent = ' ';\n const openApiPropsFormatted = openApiProps\n .map(prop => formatOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n // Get description from displayName or use default\n const description = schema.displayName\n ? (typeof schema.displayName === 'string' ? schema.displayName : schema.displayName['en'] ?? schema.name)\n : `${schema.name} resource`;\n\n const content = `<?php\n\n/**\n * ${className} Resource\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Http\\\\Request;\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}ResourceBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}',\n description: '${escapePhpString(description)}',\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}Resource extends ${className}ResourceBase\n{\n /**\n * Transform the resource into an array.\n *\n * @return array<string, mixed>\n */\n public function toArray(Request $request): array\n {\n return array_merge($this->schemaArray($request), [\n // Custom fields here\n ]);\n }\n\n /**\n * Get additional data that should be returned with the resource array.\n *\n * @return array<string, mixed>\n */\n public function with(Request $request): array\n {\n return [\n // Additional metadata here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.resourcePath}${modulePath}/${className}Resource.php`,\n content,\n type: 'user',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate all Resource classes for the given schemas.\n */\nexport function generateResources(\n schemas: SchemaCollection,\n options?: ResourceGeneratorOptions\n): GeneratedResource[] {\n const resolved = resolveOptions(options);\n const resources: GeneratedResource[] = [];\n\n for (const schema of Object.values(schemas)) {\n // Skip enums\n if (schema.kind === 'enum') continue;\n\n // Skip hidden schemas\n if (schema.options?.hidden === true) continue;\n\n // Generate base resource (always overwritten)\n resources.push(generateResourceBase(schema, schemas, resolved));\n\n // Generate user resource (created once)\n resources.push(generateResource(schema, resolved));\n }\n\n return resources;\n}\n\n/**\n * Get the output path for a resource.\n */\nexport function getResourcePath(resource: GeneratedResource): string {\n return resource.path;\n}\n","/**\n * AI Guides Generator\n *\n * Generates AI assistant guides (Claude, Cursor) for Laravel projects.\n * Simply copies .stub files, removes .stub extension, and replaces placeholders.\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { resolve, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Options for AI guides generation\n */\nexport interface AIGuidesOptions {\n /**\n * Laravel models path from config (e.g., 'app/Models')\n * Used to extract the base path for glob replacement\n */\n modelsPath?: string;\n\n /**\n * Laravel migrations path from config\n */\n migrationsPath?: string;\n\n /**\n * Base path for Laravel files (default: extracted from modelsPath or 'app')\n * Used for placeholder replacement in Cursor rules\n */\n laravelBasePath?: string;\n\n /**\n * TypeScript/React base path (e.g., 'resources/ts' or 'frontend/src')\n * Used for placeholder replacement in Cursor rules\n */\n typescriptBasePath?: string;\n}\n\n/**\n * Result of AI guides generation\n */\nexport interface AIGuidesResult {\n claudeGuides: number;\n claudeRules: number;\n claudeChecklists: number;\n claudeWorkflows: number;\n claudeAgents: number;\n claudeOmnify: number;\n cursorRules: number;\n files: string[];\n}\n\n/**\n * Get the stubs directory path\n */\nfunction getStubsDir(): string {\n // Try dev path first: packages/laravel-generator/stubs/ai-guides\n const devPath = resolve(__dirname, '../../stubs/ai-guides');\n if (existsSync(devPath)) {\n return devPath;\n }\n\n // Try dist path (when installed as package)\n const distPath = resolve(__dirname, '../stubs/ai-guides');\n if (existsSync(distPath)) {\n return distPath;\n }\n\n throw new Error('AI guides stubs not found');\n}\n\n/**\n * Extract Laravel app path from modelsPath\n * e.g., 'app/Models' -> 'app'\n * e.g., 'backend/app/Models' -> 'backend/app'\n */\nfunction extractLaravelBasePath(modelsPath?: string): string {\n if (!modelsPath) return 'app';\n\n // Remove 'Models' or 'Models/...' suffix\n const normalized = modelsPath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.+?)\\/Models(?:\\/.*)?$/);\n if (match && match[1]) {\n return match[1];\n }\n\n // Fallback: get directory of modelsPath\n const parts = normalized.split('/').filter(Boolean);\n if (parts.length > 1) {\n return parts.slice(0, -1).join('/');\n }\n\n return 'app';\n}\n\n/**\n * Extract Laravel project root from basePath\n * e.g., 'app' -> '' (standard Laravel)\n * e.g., 'backend/app' -> 'backend' (monorepo)\n */\nfunction extractLaravelRoot(basePath: string): string {\n // basePath is like 'app' or 'backend/app'\n // We want '' or 'backend'\n const normalized = basePath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.+?)\\/app$/);\n if (match && match[1]) {\n return match[1];\n }\n return ''; // Standard Laravel, no prefix\n}\n\n/**\n * Replace placeholders in stub content\n * - {{LARAVEL_BASE}} -> app folder path (e.g., 'app' or 'backend/app')\n * - {{LARAVEL_ROOT}} -> project root (e.g., '' or 'backend/')\n * - {{TYPESCRIPT_BASE}} -> TypeScript base path (e.g., 'resources/ts' or 'frontend/src')\n */\nfunction replacePlaceholders(content: string, basePath: string, typescriptPath?: string): string {\n const root = extractLaravelRoot(basePath);\n let result = content.replace(/\\{\\{LARAVEL_BASE\\}\\}/g, basePath);\n\n // Replace {{LARAVEL_ROOT}} with root path (with trailing slash if not empty)\n if (root) {\n result = result.replace(/\\{\\{LARAVEL_ROOT\\}\\}/g, root + '/');\n } else {\n result = result.replace(/\\{\\{LARAVEL_ROOT\\}\\}/g, '');\n }\n\n // Replace {{TYPESCRIPT_BASE}} with TypeScript path\n const tsPath = typescriptPath || 'resources/ts';\n result = result.replace(/\\{\\{TYPESCRIPT_BASE\\}\\}/g, tsPath);\n\n return result;\n}\n\n/**\n * Copy .stub files to destination, removing .stub extension and replacing placeholders\n */\nfunction copyStubs(\n srcDir: string,\n destDir: string,\n transform?: (content: string) => string\n): string[] {\n const writtenFiles: string[] = [];\n\n if (!existsSync(srcDir)) {\n return writtenFiles;\n }\n\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n\n const entries = readdirSync(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(srcDir, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively copy subdirectories\n const subDestDir = join(destDir, entry.name);\n const subFiles = copyStubs(srcPath, subDestDir, transform);\n writtenFiles.push(...subFiles);\n } else if (entry.isFile() && entry.name.endsWith('.stub')) {\n // Remove .stub extension\n const destName = entry.name.slice(0, -5);\n const destPath = join(destDir, destName);\n\n let content = readFileSync(srcPath, 'utf-8');\n\n if (transform) {\n content = transform(content);\n }\n\n writeFileSync(destPath, content);\n writtenFiles.push(destPath);\n }\n }\n\n return writtenFiles;\n}\n\n/**\n * Generate AI guides for Claude and Cursor\n */\nexport function generateAIGuides(\n rootDir: string,\n options: AIGuidesOptions = {}\n): AIGuidesResult {\n const stubsDir = getStubsDir();\n const basePath = options.laravelBasePath || extractLaravelBasePath(options.modelsPath);\n const tsPath = options.typescriptBasePath || 'resources/ts';\n\n const result: AIGuidesResult = {\n claudeGuides: 0,\n claudeRules: 0,\n claudeChecklists: 0,\n claudeWorkflows: 0,\n claudeAgents: 0,\n claudeOmnify: 0,\n cursorRules: 0,\n files: [],\n };\n\n // All Claude files go under .claude/omnify/\n\n // 0. Copy README.md to .claude/omnify/\n const readmeSrcPath = join(stubsDir, 'README.md.stub');\n if (existsSync(readmeSrcPath)) {\n const readmeDestDir = resolve(rootDir, '.claude/omnify');\n if (!existsSync(readmeDestDir)) {\n mkdirSync(readmeDestDir, { recursive: true });\n }\n const content = readFileSync(readmeSrcPath, 'utf-8');\n writeFileSync(resolve(readmeDestDir, 'README.md'), content);\n result.files.push(resolve(readmeDestDir, 'README.md'));\n }\n\n // 1. Copy Laravel guides to .claude/omnify/guides/laravel/\n const claudeSrcDir = join(stubsDir, 'laravel');\n const claudeDestDir = resolve(rootDir, '.claude/omnify/guides/laravel');\n\n if (existsSync(claudeSrcDir)) {\n const files = copyStubs(claudeSrcDir, claudeDestDir);\n result.claudeGuides = files.length;\n result.files.push(...files);\n }\n\n // 1b. Copy React guides to .claude/omnify/guides/react/\n const reactSrcDir = join(stubsDir, 'react');\n const reactDestDir = resolve(rootDir, '.claude/omnify/guides/react');\n\n if (existsSync(reactSrcDir)) {\n const files = copyStubs(reactSrcDir, reactDestDir);\n result.claudeGuides += files.length;\n result.files.push(...files);\n }\n\n // 2. Copy rules to .claude/rules/omnify/ (Claude Code official location)\n // These are path-specific rules with `paths:` frontmatter\n const claudeRulesSrcDir = join(stubsDir, 'claude-rules');\n const claudeRulesDestDir = resolve(rootDir, '.claude/rules/omnify');\n\n if (existsSync(claudeRulesSrcDir)) {\n const files = copyStubs(claudeRulesSrcDir, claudeRulesDestDir, (content) =>\n replacePlaceholders(content, basePath, tsPath)\n );\n result.claudeRules = files.length;\n result.files.push(...files);\n }\n\n // 3. Copy checklists to .claude/omnify/checklists/\n const claudeChecklistsSrcDir = join(stubsDir, 'claude-checklists');\n const claudeChecklistsDestDir = resolve(rootDir, '.claude/omnify/checklists');\n\n if (existsSync(claudeChecklistsSrcDir)) {\n const files = copyStubs(claudeChecklistsSrcDir, claudeChecklistsDestDir);\n result.claudeChecklists = files.length;\n result.files.push(...files);\n }\n\n // 4. Copy workflows to .claude/omnify/workflows/\n const claudeWorkflowsSrcDir = join(stubsDir, 'claude-workflows');\n const claudeWorkflowsDestDir = resolve(rootDir, '.claude/omnify/workflows');\n\n if (existsSync(claudeWorkflowsSrcDir)) {\n const files = copyStubs(claudeWorkflowsSrcDir, claudeWorkflowsDestDir);\n result.claudeWorkflows = files.length;\n result.files.push(...files);\n }\n\n // 5. Copy agents to .claude/omnify/agents/\n const claudeAgentsSrcDir = join(stubsDir, 'claude-agents');\n const claudeAgentsDestDir = resolve(rootDir, '.claude/omnify/agents');\n\n if (existsSync(claudeAgentsSrcDir)) {\n const files = copyStubs(claudeAgentsSrcDir, claudeAgentsDestDir);\n result.claudeAgents = files.length;\n result.files.push(...files);\n }\n\n // 6. Copy omnify docs to .claude/omnify/guides/omnify/\n const claudeOmnifySrcDir = join(stubsDir, 'claude-omnify');\n const claudeOmnifyDestDir = resolve(rootDir, '.claude/omnify/guides/omnify');\n\n if (existsSync(claudeOmnifySrcDir)) {\n const files = copyStubs(claudeOmnifySrcDir, claudeOmnifyDestDir);\n result.claudeOmnify = files.length;\n result.files.push(...files);\n }\n\n // 7. Copy Cursor rules to .cursor/rules/omnify/\n const cursorSrcDir = join(stubsDir, 'cursor');\n const cursorDestDir = resolve(rootDir, '.cursor/rules/omnify');\n\n if (existsSync(cursorSrcDir)) {\n const files = copyStubs(cursorSrcDir, cursorDestDir, (content) =>\n replacePlaceholders(content, basePath, tsPath)\n );\n result.cursorRules = files.length;\n result.files.push(...files);\n }\n\n // Clean up root-level duplicates (from postinstall) that are now in guides/omnify/\n cleanupRootLevelDuplicates(rootDir);\n\n return result;\n}\n\n/**\n * Remove root-level files that are now properly located in guides/omnify/\n * This cleans up duplicates from postinstall that existed before generate was run\n */\nfunction cleanupRootLevelDuplicates(rootDir: string): void {\n const claudeOmnify = resolve(rootDir, '.claude/omnify');\n const guidesOmnify = resolve(rootDir, '.claude/omnify/guides/omnify');\n\n if (!existsSync(guidesOmnify)) return;\n\n // Files that should only be in guides/omnify/, not at root\n const filesToCleanup = [\n 'schema-guide.md',\n 'config-guide.md',\n 'typescript-guide.md',\n 'laravel-guide.md',\n 'antdesign-guide.md',\n 'react-form-guide.md',\n 'japan-guide.md',\n ];\n\n for (const file of filesToCleanup) {\n const rootFile = resolve(claudeOmnify, file);\n const guidesFile = resolve(guidesOmnify, file);\n\n // Only remove if both exist (duplicate)\n if (existsSync(rootFile) && existsSync(guidesFile)) {\n try {\n unlinkSync(rootFile);\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * Check if AI guides need to be generated\n */\nexport function shouldGenerateAIGuides(rootDir: string): boolean {\n const claudeDir = resolve(rootDir, '.claude/omnify/guides/laravel');\n const cursorDir = resolve(rootDir, '.cursor/rules/omnify');\n\n if (!existsSync(claudeDir) || !existsSync(cursorDir)) {\n return true;\n }\n\n try {\n const claudeFiles = readdirSync(claudeDir);\n const cursorFiles = readdirSync(cursorDir);\n const hasLaravelRules = cursorFiles.some((f) => f.startsWith('laravel'));\n\n return claudeFiles.length === 0 || !hasLaravelRules;\n } catch {\n return true;\n }\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkGpB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA6BV,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmDpB,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["isNullable","columnMethod","TYPE_METHOD_MAP","generateTimestamp","import_omnify_types","hasAutoId","properties","typeDef","isCompoundType","resolveOptions","getStubContent","isNullable","import_node_fs","import_node_path","import_omnify_types","DEFAULT_OPTIONS","escapePhpString","resolveOptions","isNullable","module","rules","displayName","openApiType","constraints","example","prop","import_omnify_types","DEFAULT_OPTIONS","SKIP_FIELDS","openApiType","prop","resolveOptions","escapePhpString","getModuleName","module","resolveOptions"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/migration/schema-builder.ts","../src/migration/generator.ts","../src/migration/alter-generator.ts","../src/model/generator.ts","../src/utils.ts","../src/factory/generator.ts","../src/plugin.ts","../src/request/generator.ts","../src/resource/generator.ts","../src/ai-guides/generator.ts"],"sourcesContent":["/**\n * @famgia/omnify-laravel\n *\n * Laravel migration generator for Omnify schemas.\n */\n\n// Migration generation\nexport {\n // Types\n type MigrationFile,\n type MigrationOptions,\n type ColumnMethod,\n type ColumnModifier,\n type ForeignKeyDefinition,\n type IndexDefinition,\n type TableBlueprint,\n type MigrationOperation,\n type MigrationDefinition,\n type PivotFieldInfo,\n type PivotTableInfo,\n type MorphToManyPivotInfo,\n // Schema builder\n toColumnName,\n toTableName,\n propertyToColumnMethod,\n generatePrimaryKeyColumn,\n generateTimestampColumns,\n generateSoftDeleteColumn,\n generateForeignKey,\n schemaToBlueprint,\n formatColumnMethod,\n formatForeignKey,\n formatIndex,\n generatePivotTableName,\n extractManyToManyRelations,\n generatePivotTableBlueprint,\n extractMorphToManyRelations,\n generateMorphToManyPivotBlueprint,\n // Generator\n generateMigrations,\n generateMigrationFromSchema,\n generateDropMigrationForTable,\n formatMigrationFile,\n getMigrationPath,\n // ALTER migration generator\n generateAlterMigration,\n generateDropTableMigration,\n generateMigrationsFromChanges,\n} from './migration/index.js';\n\n// Model generation\nexport {\n generateModels,\n getModelPath,\n generateProviderRegistration,\n type GeneratedModel,\n type ModelGeneratorOptions,\n type ProviderRegistrationResult,\n} from './model/index.js';\n\n// Factory generation\nexport {\n generateFactories,\n getFactoryPath,\n type FactoryGeneratorOptions,\n type GeneratedFactory,\n} from './factory/index.js';\n\n// Plugin\nexport {\n default as laravelPlugin,\n type LaravelPluginOptions,\n} from './plugin.js';\n\n// AI Guides generation\nexport {\n generateAIGuides,\n shouldGenerateAIGuides,\n type AIGuidesOptions,\n type AIGuidesResult,\n} from './ai-guides/index.js';\n","/**\n * @famgia/omnify-laravel - Schema Builder Converter\n *\n * Converts SQL types and operations to Laravel Schema Builder methods.\n */\n\nimport type { PropertyDefinition, LoadedSchema, SchemaCollection, CustomTypeDefinition, LocalizedString, LocaleResolutionOptions } from '@famgia/omnify-types';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport type {\n ColumnMethod,\n ColumnModifier,\n ForeignKeyDefinition,\n IndexDefinition,\n TableBlueprint,\n} from './types.js';\n\n/**\n * Maps Omnify property types to Laravel column methods.\n */\nconst TYPE_METHOD_MAP: Record<string, string> = {\n String: 'string',\n TinyInt: 'tinyInteger',\n Int: 'integer',\n BigInt: 'bigInteger',\n Float: 'double',\n Decimal: 'decimal',\n Boolean: 'boolean',\n Text: 'text',\n MediumText: 'mediumText',\n LongText: 'longText',\n Date: 'date',\n Time: 'time',\n DateTime: 'dateTime',\n Timestamp: 'timestamp',\n Json: 'json',\n Email: 'string',\n Password: 'string',\n Enum: 'enum',\n EnumRef: 'string', // EnumRef stores the enum value as string (lookup via schema)\n // Note: File type is now polymorphic - no column generated, uses files table\n};\n\n/**\n * Maps primary key types to Laravel methods.\n * Laravel 8+ uses id() for BigInt auto-increment primary keys.\n */\nconst PK_METHOD_MAP: Record<string, string> = {\n Int: 'increments',\n BigInt: 'id',\n Uuid: 'uuid',\n String: 'string',\n};\n\n/**\n * Gets the ID type from schema options.\n */\nfunction getIdType(schema: LoadedSchema): 'Int' | 'BigInt' | 'Uuid' | 'String' {\n return (schema.options?.idType ?? 'BigInt') as 'Int' | 'BigInt' | 'Uuid' | 'String';\n}\n\n/**\n * Checks if the schema should have an auto-generated ID column.\n * Returns false if options.id is explicitly set to false.\n */\nfunction hasAutoId(schema: LoadedSchema): boolean {\n return schema.options?.id !== false;\n}\n\n/**\n * Converts a property name to snake_case column name.\n */\nexport function toColumnName(propertyName: string): string {\n return propertyName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n}\n\n/**\n * Converts schema name to snake_case plural table name.\n */\nexport function toTableName(schemaName: string): string {\n const snakeCase = schemaName\n .replace(/([A-Z])/g, '_$1')\n .toLowerCase()\n .replace(/^_/, '');\n\n // Simple pluralization\n if (snakeCase.endsWith('y')) {\n return snakeCase.slice(0, -1) + 'ies';\n } else if (\n snakeCase.endsWith('s') ||\n snakeCase.endsWith('x') ||\n snakeCase.endsWith('ch') ||\n snakeCase.endsWith('sh')\n ) {\n return snakeCase + 'es';\n } else {\n return snakeCase + 's';\n }\n}\n\n/**\n * Options for property to column conversion.\n */\nexport interface PropertyToColumnOptions {\n /** Locale resolution options for displayName */\n locale?: LocaleResolutionOptions;\n}\n\n/**\n * Converts a property to Laravel column method.\n */\nexport function propertyToColumnMethod(\n propertyName: string,\n property: PropertyDefinition,\n options: PropertyToColumnOptions = {}\n): ColumnMethod | null {\n // Skip associations - they're handled separately\n if (property.type === 'Association') {\n return null;\n }\n\n // Skip File type - uses polymorphic relation to files table\n if (property.type === 'File') {\n return null;\n }\n\n const columnName = toColumnName(propertyName);\n const method = TYPE_METHOD_MAP[property.type] ?? 'string';\n const args: (string | number | boolean)[] = [columnName];\n const modifiers: ColumnModifier[] = [];\n\n // Handle length for string types\n const propWithLength = property as { length?: number };\n if (method === 'string' && propWithLength.length) {\n args.push(propWithLength.length);\n } else if (property.type === 'EnumRef') {\n // Default length for EnumRef columns (store enum value, typically short codes)\n args.push(50);\n }\n\n // Handle precision and scale for decimal types\n if (property.type === 'Decimal') {\n const decimalProp = property as { precision?: number; scale?: number };\n const precision = decimalProp.precision ?? 8;\n const scale = decimalProp.scale ?? 2;\n args.push(precision, scale);\n }\n\n // Handle enum values\n if (property.type === 'Enum') {\n const enumProp = property as { enum?: readonly string[] };\n if (enumProp.enum && enumProp.enum.length > 0) {\n args.push(enumProp.enum as unknown as string);\n }\n }\n\n // Add modifiers\n const baseProp = property as {\n nullable?: boolean;\n unique?: boolean;\n default?: unknown;\n unsigned?: boolean;\n primary?: boolean;\n };\n\n // Add primary key modifier (for custom primary keys with id: false)\n if (baseProp.primary) {\n modifiers.push({ method: 'primary' });\n }\n\n if (baseProp.nullable) {\n modifiers.push({ method: 'nullable' });\n }\n\n if (baseProp.unique) {\n modifiers.push({ method: 'unique' });\n }\n\n if (baseProp.default !== undefined && baseProp.default !== null) {\n // Keep native types for proper PHP rendering (boolean false vs string 'false')\n modifiers.push({ method: 'default', args: [baseProp.default as string | number | boolean] });\n }\n\n if (baseProp.unsigned && (method === 'tinyInteger' || method === 'integer' || method === 'bigInteger')) {\n modifiers.push({ method: 'unsigned' });\n }\n\n // Timestamp modifiers: useCurrent and useCurrentOnUpdate\n if (method === 'timestamp') {\n const timestampProp = property as { useCurrent?: boolean; useCurrentOnUpdate?: boolean };\n if (timestampProp.useCurrent) {\n modifiers.push({ method: 'useCurrent' });\n }\n if (timestampProp.useCurrentOnUpdate) {\n modifiers.push({ method: 'useCurrentOnUpdate' });\n }\n }\n\n // Add comment from displayName if available (resolve LocalizedString to string)\n const rawDisplayName = (property as { displayName?: LocalizedString }).displayName;\n if (rawDisplayName) {\n const displayName = resolveLocalizedString(rawDisplayName, options.locale);\n if (displayName) {\n modifiers.push({ method: 'comment', args: [displayName] });\n }\n }\n\n return {\n name: columnName,\n method,\n args,\n modifiers,\n };\n}\n\n/**\n * Generates primary key column method.\n */\nexport function generatePrimaryKeyColumn(\n pkType: 'Int' | 'BigInt' | 'Uuid' | 'String' = 'BigInt'\n): ColumnMethod {\n const method = PK_METHOD_MAP[pkType] ?? 'id';\n\n if (pkType === 'Uuid') {\n return {\n name: 'id',\n method: 'uuid',\n args: ['id'],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n if (pkType === 'String') {\n return {\n name: 'id',\n method: 'string',\n args: ['id', 255],\n modifiers: [{ method: 'primary' }],\n };\n }\n\n // For Int/BigInt, use increments/id which auto-creates primary key\n // $table->id() needs no args, $table->increments('id') needs column name\n return {\n name: 'id',\n method,\n args: method === 'id' ? [] : ['id'],\n modifiers: [],\n };\n}\n\n/**\n * Generates timestamp columns.\n */\nexport function generateTimestampColumns(): ColumnMethod[] {\n return [\n {\n name: 'created_at',\n method: 'timestamp',\n args: ['created_at'],\n modifiers: [{ method: 'nullable' }],\n },\n {\n name: 'updated_at',\n method: 'timestamp',\n args: ['updated_at'],\n modifiers: [{ method: 'nullable' }],\n },\n ];\n}\n\n/**\n * Generates soft delete column.\n */\nexport function generateSoftDeleteColumn(): ColumnMethod {\n return {\n name: 'deleted_at',\n method: 'timestamp',\n args: ['deleted_at'],\n modifiers: [{ method: 'nullable' }],\n };\n}\n\n/**\n * Polymorphic column result with type enum and id column.\n */\nexport interface PolymorphicColumnsResult {\n typeColumn: ColumnMethod;\n idColumn: ColumnMethod;\n indexes: IndexDefinition[];\n}\n\n/**\n * Generates polymorphic columns for MorphTo relations.\n * Creates {name}_type (ENUM) and {name}_id columns.\n */\nexport function generatePolymorphicColumns(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection\n): PolymorphicColumnsResult | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const assocProp = property as {\n relation?: string;\n targets?: readonly string[];\n nullable?: boolean;\n };\n\n // Only handle MorphTo - it creates the type and id columns\n if (assocProp.relation !== 'MorphTo') {\n return null;\n }\n\n // Check if nullable is explicitly set (default: true for MorphTo)\n const isNullable = assocProp.nullable !== false;\n\n const targets = assocProp.targets;\n if (!targets || targets.length === 0) {\n return null;\n }\n\n const columnBaseName = toColumnName(propertyName);\n const typeColumnName = `${columnBaseName}_type`;\n const idColumnName = `${columnBaseName}_id`;\n\n // Generate ENUM type column with target schema names as values\n const typeColumn: ColumnMethod = {\n name: typeColumnName,\n method: 'enum',\n args: [typeColumnName, targets as unknown as string],\n modifiers: isNullable ? [{ method: 'nullable' }] : [],\n };\n\n // For polymorphic id, we need to determine the largest ID type among targets\n // Default to unsignedBigInteger for maximum compatibility\n let idMethod = 'unsignedBigInteger';\n\n // Check if any target uses UUID or String - those take precedence\n for (const targetName of targets) {\n const targetSchema = allSchemas[targetName];\n if (targetSchema) {\n const targetIdType = (targetSchema.options?.idType ?? 'BigInt') as string;\n if (targetIdType === 'Uuid') {\n idMethod = 'uuid';\n break; // UUID takes highest precedence\n } else if (targetIdType === 'String') {\n idMethod = 'string';\n // Don't break - UUID still takes precedence\n }\n }\n }\n\n const idColumn: ColumnMethod = {\n name: idColumnName,\n method: idMethod,\n args: idMethod === 'string' ? [idColumnName, 255] : [idColumnName],\n modifiers: isNullable ? [{ method: 'nullable' }] : [],\n };\n\n // Create composite index for faster polymorphic lookups\n const indexes: IndexDefinition[] = [\n {\n columns: [typeColumnName, idColumnName],\n unique: false,\n },\n ];\n\n return { typeColumn, idColumn, indexes };\n}\n\n/**\n * Generates foreign key column and constraint from association.\n */\nexport function generateForeignKey(\n propertyName: string,\n property: PropertyDefinition,\n allSchemas: SchemaCollection,\n options: PropertyToColumnOptions = {}\n): { column: ColumnMethod; foreignKey: ForeignKeyDefinition; index: IndexDefinition } | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n onDelete?: string;\n onUpdate?: string;\n mappedBy?: string;\n owningSide?: boolean;\n nullable?: boolean;\n default?: string | number;\n displayName?: LocalizedString;\n };\n\n // Only create FK column for ManyToOne and OneToOne (owning side)\n if (assocProp.relation !== 'ManyToOne' && assocProp.relation !== 'OneToOne') {\n return null;\n }\n\n // Skip inverse side (mappedBy means this is the inverse side)\n if (assocProp.mappedBy) {\n return null;\n }\n\n const columnName = toColumnName(propertyName) + '_id';\n const targetSchema = assocProp.target ? allSchemas[assocProp.target] : undefined;\n const targetTable = assocProp.target ? toTableName(assocProp.target) : 'unknown';\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine column method based on target PK type\n let method = 'unsignedBigInteger';\n if (targetPkType === 'Int') {\n method = 'unsignedInteger';\n } else if (targetPkType === 'Uuid') {\n method = 'uuid';\n } else if (targetPkType === 'String') {\n method = 'string';\n }\n\n // Build modifiers for the column\n const modifiers: ColumnModifier[] = [];\n\n // Add nullable only if explicitly set to true (consistent with other property types)\n if (assocProp.nullable === true) {\n modifiers.push({ method: 'nullable' });\n }\n\n // Add default if specified\n if (assocProp.default !== undefined && assocProp.default !== null) {\n modifiers.push({ method: 'default', args: [assocProp.default] });\n }\n\n // Add comment from displayName if available (resolve LocalizedString to string)\n if (assocProp.displayName) {\n const displayName = resolveLocalizedString(assocProp.displayName, options.locale);\n if (displayName) {\n modifiers.push({ method: 'comment', args: [displayName] });\n }\n }\n\n const column: ColumnMethod = {\n name: columnName,\n method,\n args: [columnName],\n modifiers,\n };\n\n const foreignKey: ForeignKeyDefinition = {\n columns: [columnName],\n references: 'id',\n on: [targetTable],\n onDelete: assocProp.onDelete ?? 'restrict',\n onUpdate: assocProp.onUpdate ?? 'cascade',\n };\n\n // Don't specify index name - let Laravel auto-generate unique names\n const index: IndexDefinition = {\n columns: [columnName],\n unique: false,\n };\n\n return { column, foreignKey, index };\n}\n\n/**\n * Expands compound type properties into multiple columns.\n * Returns the expanded properties or null if not a compound type.\n */\nfunction expandCompoundType(\n propName: string,\n property: PropertyDefinition,\n customTypes: ReadonlyMap<string, CustomTypeDefinition>,\n options: PropertyToColumnOptions = {}\n): { name: string; property: PropertyDefinition }[] | null {\n const typeDef = customTypes.get(property.type);\n\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const expanded: { name: string; property: PropertyDefinition }[] = [];\n const baseProp = property as unknown as Record<string, unknown>;\n\n for (const field of typeDef.expand) {\n // Generate column name: propName + suffix (converted to snake_case)\n const suffixSnake = toColumnName(field.suffix);\n const columnName = `${propName}_${suffixSnake}`;\n\n // Build property definition\n const expandedProp: Record<string, unknown> = {\n type: 'String', // Default type, will be overridden by sql definition\n };\n\n // Check for per-field overrides from schema's `fields` property\n const fieldOverrides = baseProp.fields as Record<string, { nullable?: boolean; hidden?: boolean; fillable?: boolean; length?: number }> | undefined;\n const fieldOverride = fieldOverrides?.[field.suffix];\n\n // Handle enumRef field - reference to enum schema\n const fieldWithEnumRef = field as { enumRef?: string };\n if (fieldWithEnumRef.enumRef) {\n expandedProp.type = 'EnumRef';\n expandedProp.enum = fieldWithEnumRef.enumRef;\n // Inherit nullable from parent property, or use per-field override\n if (fieldOverride?.nullable !== undefined) {\n expandedProp.nullable = fieldOverride.nullable;\n } else if (baseProp.nullable !== undefined) {\n expandedProp.nullable = baseProp.nullable;\n }\n }\n // Map SQL type to Omnify type\n else if (field.sql) {\n const sqlType = field.sql.sqlType.toUpperCase();\n if (sqlType === 'VARCHAR' || sqlType === 'CHAR' || sqlType === 'STRING') {\n expandedProp.type = 'String';\n // Use field override length if provided, otherwise use default from type definition\n if (fieldOverride?.length) {\n expandedProp.length = fieldOverride.length;\n } else if (field.sql.length) {\n expandedProp.length = field.sql.length;\n }\n } else if (sqlType === 'TINYINT') {\n expandedProp.type = 'TinyInt';\n } else if (sqlType === 'INT' || sqlType === 'INTEGER') {\n expandedProp.type = 'Int';\n } else if (sqlType === 'BIGINT') {\n expandedProp.type = 'BigInt';\n } else if (sqlType === 'TEXT') {\n expandedProp.type = 'Text';\n } else if (sqlType === 'BOOLEAN' || sqlType === 'BOOL') {\n expandedProp.type = 'Boolean';\n } else if (sqlType === 'DECIMAL') {\n expandedProp.type = 'Decimal';\n if (field.sql.precision) expandedProp.precision = field.sql.precision;\n if (field.sql.scale) expandedProp.scale = field.sql.scale;\n } else if (sqlType === 'DATE') {\n expandedProp.type = 'Date';\n } else if (sqlType === 'TIMESTAMP' || sqlType === 'DATETIME') {\n expandedProp.type = 'Timestamp';\n }\n\n // Handle unsigned flag for integer types\n if (field.sql.unsigned) {\n expandedProp.unsigned = true;\n }\n\n // Handle default value\n if (field.sql.default !== undefined) {\n expandedProp.default = field.sql.default;\n }\n\n // Handle nullable: priority is per-field override > field.sql.nullable > parent property\n if (field.sql.nullable !== undefined) {\n expandedProp.nullable = field.sql.nullable;\n } else if (baseProp.nullable !== undefined) {\n expandedProp.nullable = baseProp.nullable;\n }\n // Per-field nullable override takes highest priority\n if (fieldOverride?.nullable !== undefined) {\n expandedProp.nullable = fieldOverride.nullable;\n }\n }\n\n // Copy displayName if parent has it (with suffix context)\n // Resolve LocalizedString to string before appending suffix\n if (baseProp.displayName) {\n const resolvedDisplayName = resolveLocalizedString(\n baseProp.displayName as LocalizedString,\n options.locale\n );\n if (resolvedDisplayName) {\n expandedProp.displayName = `${resolvedDisplayName} (${field.suffix})`;\n }\n }\n\n expanded.push({\n name: columnName,\n property: expandedProp as unknown as PropertyDefinition,\n });\n }\n\n return expanded;\n}\n\n/**\n * Options for schema to blueprint conversion.\n */\nexport interface SchemaToBlueprintOptions {\n /** Custom types from plugins (for compound type expansion) */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n /** Locale resolution options for displayName */\n locale?: LocaleResolutionOptions;\n}\n\n/**\n * Generates table blueprint from schema.\n */\nexport function schemaToBlueprint(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: SchemaToBlueprintOptions = {}\n): TableBlueprint {\n const { customTypes = new Map(), locale } = options;\n const columnOptions: PropertyToColumnOptions = { locale };\n // Use options.tableName if specified, otherwise derive from schema name\n const tableName = schema.options?.tableName ?? toTableName(schema.name);\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Primary key (only if id is not disabled)\n if (hasAutoId(schema)) {\n const pkType = getIdType(schema);\n columns.push(generatePrimaryKeyColumn(pkType));\n }\n\n // Process properties\n if (schema.properties) {\n for (const [propName, property] of Object.entries(schema.properties)) {\n // Check for compound type expansion first\n const expandedProps = expandCompoundType(propName, property, customTypes, columnOptions);\n if (expandedProps) {\n // Compound type - process each expanded property\n for (const { name: expandedName, property: expandedProp } of expandedProps) {\n const columnMethod = propertyToColumnMethod(expandedName, expandedProp, columnOptions);\n if (columnMethod) {\n columns.push(columnMethod);\n }\n }\n continue; // Skip normal processing for compound types\n }\n\n // Handle regular columns\n const columnMethod = propertyToColumnMethod(propName, property, columnOptions);\n if (columnMethod) {\n columns.push(columnMethod);\n }\n\n // Handle foreign keys (standard associations)\n const fkResult = generateForeignKey(propName, property, allSchemas, columnOptions);\n if (fkResult) {\n columns.push(fkResult.column);\n foreignKeys.push(fkResult.foreignKey);\n indexes.push(fkResult.index);\n }\n\n // Handle polymorphic columns (MorphTo)\n const polyResult = generatePolymorphicColumns(propName, property, allSchemas);\n if (polyResult) {\n columns.push(polyResult.typeColumn);\n columns.push(polyResult.idColumn);\n indexes.push(...polyResult.indexes);\n }\n }\n }\n\n // Timestamps\n if (schema.options?.timestamps !== false) {\n columns.push(...generateTimestampColumns());\n }\n\n // Soft delete\n if (schema.options?.softDelete) {\n columns.push(generateSoftDeleteColumn());\n }\n\n // Custom indexes\n if (schema.options?.indexes) {\n // Helper to convert property name to column name, considering Association type\n const propToColName = (propName: string): string => {\n const colName = toColumnName(propName);\n const prop = schema.properties?.[propName];\n if (prop?.type === 'Association') {\n const assoc = prop as { relation?: string; mappedBy?: string };\n // Only add _id for owning side (ManyToOne, OneToOne without mappedBy)\n if (\n (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') &&\n !assoc.mappedBy\n ) {\n return colName + '_id';\n }\n }\n return colName;\n };\n\n for (const index of schema.options.indexes) {\n // Handle both shorthand (string) and full object format\n if (typeof index === 'string') {\n // Shorthand: just column name\n indexes.push({\n columns: [propToColName(index)],\n unique: false,\n });\n } else {\n // Full object format\n indexes.push({\n name: index.name,\n columns: index.columns.map(propToColName),\n unique: index.unique ?? false,\n });\n }\n }\n }\n\n // Unique constraints\n if (schema.options?.unique) {\n // Helper to convert property name to column name, considering Association type\n const propToColName = (propName: string): string => {\n const colName = toColumnName(propName);\n const prop = schema.properties?.[propName];\n if (prop?.type === 'Association') {\n const assoc = prop as { relation?: string; mappedBy?: string };\n if (\n (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') &&\n !assoc.mappedBy\n ) {\n return colName + '_id';\n }\n }\n return colName;\n };\n\n const uniqueConstraints = Array.isArray(schema.options.unique[0])\n ? (schema.options.unique as readonly (readonly string[])[])\n : [schema.options.unique as readonly string[]];\n\n for (const constraint of uniqueConstraints) {\n indexes.push({\n columns: constraint.map(propToColName),\n unique: true,\n });\n }\n }\n\n // Deduplicate indexes by columns (keep first occurrence)\n const seenIndexes = new Set<string>();\n const uniqueIndexes = indexes.filter(idx => {\n const key = idx.columns.join(',') + (idx.unique ? ':unique' : '');\n if (seenIndexes.has(key)) {\n return false;\n }\n seenIndexes.add(key);\n return true;\n });\n\n // Determine primary key column(s)\n let primaryKey: string[] | undefined;\n if (hasAutoId(schema)) {\n primaryKey = ['id'];\n } else if (schema.properties) {\n // Find properties marked with primary: true\n const pkColumns: string[] = [];\n for (const [propName, property] of Object.entries(schema.properties)) {\n if ((property as { primary?: boolean }).primary) {\n pkColumns.push(toColumnName(propName));\n }\n }\n if (pkColumns.length > 0) {\n primaryKey = pkColumns;\n }\n }\n\n return {\n tableName,\n columns,\n primaryKey,\n foreignKeys,\n indexes: uniqueIndexes,\n };\n}\n\n/**\n * Formats a column method to PHP code.\n */\nexport function formatColumnMethod(column: ColumnMethod): string {\n const args = column.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n if (Array.isArray(arg)) {\n return `[${(arg as string[]).map(v => `'${v}'`).join(', ')}]`;\n }\n return String(arg);\n }).join(', ');\n\n let code = `$table->${column.method}(${args})`;\n\n for (const modifier of column.modifiers) {\n if (modifier.args && modifier.args.length > 0) {\n const modArgs = modifier.args.map(arg => {\n if (typeof arg === 'string') {\n return `'${arg}'`;\n }\n if (typeof arg === 'boolean') {\n return arg ? 'true' : 'false';\n }\n if (typeof arg === 'number') {\n return String(arg);\n }\n return String(arg);\n }).join(', ');\n code += `->${modifier.method}(${modArgs})`;\n } else {\n code += `->${modifier.method}()`;\n }\n }\n\n return code + ';';\n}\n\n/**\n * Formats a foreign key to PHP code.\n */\nexport function formatForeignKey(fk: ForeignKeyDefinition): string {\n const column = fk.columns[0];\n const table = fk.on[0];\n let code = `$table->foreign('${column}')->references('${fk.references}')->on('${table}')`;\n\n if (fk.onDelete) {\n code += `->onDelete('${fk.onDelete}')`;\n }\n if (fk.onUpdate) {\n code += `->onUpdate('${fk.onUpdate}')`;\n }\n\n return code + ';';\n}\n\n/**\n * Formats an index to PHP code.\n */\nexport function formatIndex(index: IndexDefinition): string {\n const columns = index.columns.length === 1\n ? `'${index.columns[0]}'`\n : `[${index.columns.map(c => `'${c}'`).join(', ')}]`;\n\n const method = index.unique ? 'unique' : 'index';\n const name = index.name ? `, '${index.name}'` : '';\n\n return `$table->${method}(${columns}${name});`;\n}\n\n/**\n * Pivot field definition (simplified from PropertyDefinition for pivot tables).\n */\nexport interface PivotFieldInfo {\n /** Field name in snake_case */\n name: string;\n /** Property type (String, Int, Boolean, Timestamp, etc.) */\n type: string;\n /** Whether the field can be null */\n nullable?: boolean;\n /** Default value for the field */\n default?: unknown;\n /** String length (for String type) */\n length?: number;\n /** Whether the field is unsigned (for numeric types) */\n unsigned?: boolean;\n}\n\n/**\n * Pivot table information for ManyToMany relationships.\n */\nexport interface PivotTableInfo {\n tableName: string;\n sourceTable: string;\n targetTable: string;\n sourceColumn: string;\n targetColumn: string;\n sourcePkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n targetPkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n onDelete: string | undefined;\n onUpdate: string | undefined;\n /** Additional fields on the pivot table */\n pivotFields?: PivotFieldInfo[];\n}\n\n/**\n * Polymorphic pivot table information for MorphToMany relationships.\n */\nexport interface MorphToManyPivotInfo {\n tableName: string;\n /** The fixed target schema that uses MorphToMany */\n targetTable: string;\n targetColumn: string;\n targetPkType: 'Int' | 'BigInt' | 'Uuid' | 'String';\n /** Base name for polymorphic columns (creates {name}_type and {name}_id) */\n morphName: string;\n /** Schema names that can be morphed to */\n morphTargets: readonly string[];\n onDelete: string | undefined;\n onUpdate: string | undefined;\n}\n\n/**\n * Generates pivot table name for ManyToMany relationship.\n * Uses alphabetical ordering for consistency.\n */\nexport function generatePivotTableName(\n sourceTable: string,\n targetTable: string,\n customName?: string\n): string {\n if (customName) {\n return customName;\n }\n\n // Sort alphabetically for consistent naming\n const tables = [sourceTable, targetTable].sort();\n // Remove trailing 's' and join with underscore\n const singular1 = tables[0]!.replace(/ies$/, 'y').replace(/s$/, '');\n const singular2 = tables[1]!.replace(/ies$/, 'y').replace(/s$/, '');\n return `${singular1}_${singular2}`;\n}\n\n/**\n * Extracts ManyToMany relationships from a schema.\n */\nexport function extractManyToManyRelations(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): PivotTableInfo[] {\n const pivotTables: PivotTableInfo[] = [];\n\n if (!schema.properties) {\n return pivotTables;\n }\n\n const sourceTable = toTableName(schema.name);\n const sourcePkType = getIdType(schema);\n\n for (const [, property] of Object.entries(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n joinTable?: string;\n onDelete?: string;\n onUpdate?: string;\n owning?: boolean;\n mappedBy?: string;\n pivotFields?: Record<string, {\n type: string;\n nullable?: boolean;\n default?: unknown;\n length?: number;\n unsigned?: boolean;\n }>;\n };\n\n // Only handle ManyToMany on the owning side (or if not specified, use alphabetical order)\n if (assocProp.relation !== 'ManyToMany') {\n continue;\n }\n\n // Skip inverse side (mappedBy means this is the inverse side)\n if (assocProp.mappedBy) {\n continue;\n }\n\n const targetName = assocProp.target;\n if (!targetName) {\n continue;\n }\n\n const targetSchema = allSchemas[targetName];\n const targetTable = toTableName(targetName);\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine if this side owns the relationship\n // Priority: 1) explicit owning flag, 2) pivotFields presence, 3) inverse side check, 4) alphabetical\n let isOwningSide: boolean;\n\n if (assocProp.owning !== undefined) {\n // Explicit owning flag takes highest priority\n isOwningSide = assocProp.owning;\n } else if (assocProp.pivotFields && Object.keys(assocProp.pivotFields).length > 0) {\n // If this side defines pivotFields, it's the owning side\n isOwningSide = true;\n } else {\n // Check if target schema has an inverse relationship with mappedBy pointing to this schema\n // If so, this side should be the owner\n let targetHasMappedByToThisSide = false;\n if (targetSchema?.properties) {\n for (const [, targetProp] of Object.entries(targetSchema.properties)) {\n if (targetProp.type !== 'Association') continue;\n const targetAssoc = targetProp as { relation?: string; target?: string; mappedBy?: string };\n if (\n targetAssoc.relation === 'ManyToMany' &&\n targetAssoc.target === schema.name &&\n targetAssoc.mappedBy\n ) {\n targetHasMappedByToThisSide = true;\n break;\n }\n }\n }\n\n if (targetHasMappedByToThisSide) {\n // Target has mappedBy pointing to this schema, so this is the owning side\n isOwningSide = true;\n } else {\n // Fall back to alphabetical ordering\n isOwningSide = schema.name < targetName;\n }\n }\n\n if (!isOwningSide) {\n continue; // Skip non-owning side to avoid duplicate pivot tables\n }\n\n const pivotTableName = generatePivotTableName(sourceTable, targetTable, assocProp.joinTable);\n\n // Column names: singular form of table name + _id\n const sourceColumn = sourceTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n const targetColumn = targetTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n\n // Extract pivot fields\n const pivotFields: PivotFieldInfo[] = [];\n if (assocProp.pivotFields) {\n for (const [fieldName, fieldDef] of Object.entries(assocProp.pivotFields)) {\n pivotFields.push({\n name: toColumnName(fieldName),\n type: fieldDef.type,\n nullable: fieldDef.nullable,\n default: fieldDef.default,\n length: fieldDef.length,\n unsigned: fieldDef.unsigned,\n });\n }\n }\n\n pivotTables.push({\n tableName: pivotTableName,\n sourceTable,\n targetTable,\n sourceColumn,\n targetColumn,\n sourcePkType,\n targetPkType,\n onDelete: assocProp.onDelete,\n onUpdate: assocProp.onUpdate,\n pivotFields: pivotFields.length > 0 ? pivotFields : undefined,\n });\n }\n\n return pivotTables;\n}\n\n/**\n * Converts a pivot field definition to a column method.\n */\nfunction pivotFieldToColumn(field: PivotFieldInfo): ColumnMethod {\n const method = TYPE_METHOD_MAP[field.type] ?? 'string';\n const args: (string | number | boolean)[] = [field.name];\n const modifiers: ColumnModifier[] = [];\n\n // Handle length for string types\n if (method === 'string' && field.length) {\n args.push(field.length);\n }\n\n // Handle nullable\n if (field.nullable) {\n modifiers.push({ method: 'nullable' });\n }\n\n // Handle default value\n if (field.default !== undefined && field.default !== null) {\n modifiers.push({ method: 'default', args: [field.default as string | number | boolean] });\n }\n\n // Handle unsigned for numeric types\n if (field.unsigned && (method === 'tinyInteger' || method === 'integer' || method === 'bigInteger')) {\n modifiers.push({ method: 'unsigned' });\n }\n\n return {\n name: field.name,\n method,\n args,\n modifiers,\n };\n}\n\n/**\n * Generates blueprint for a pivot table.\n */\nexport function generatePivotTableBlueprint(pivot: PivotTableInfo): TableBlueprint {\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n // Determine column methods based on PK types\n const getMethodForPkType = (pkType: string): string => {\n switch (pkType) {\n case 'Int': return 'unsignedInteger';\n case 'Uuid': return 'uuid';\n case 'String': return 'string';\n default: return 'unsignedBigInteger';\n }\n };\n\n // Source column\n columns.push({\n name: pivot.sourceColumn,\n method: getMethodForPkType(pivot.sourcePkType),\n args: [pivot.sourceColumn],\n modifiers: [],\n });\n\n // Target column\n columns.push({\n name: pivot.targetColumn,\n method: getMethodForPkType(pivot.targetPkType),\n args: [pivot.targetColumn],\n modifiers: [],\n });\n\n // Pivot fields (additional columns on the pivot table)\n if (pivot.pivotFields && pivot.pivotFields.length > 0) {\n for (const field of pivot.pivotFields) {\n columns.push(pivotFieldToColumn(field));\n }\n }\n\n // Timestamps for pivot table (Laravel's withTimestamps())\n columns.push(...generateTimestampColumns());\n\n // Foreign keys\n foreignKeys.push({\n columns: [pivot.sourceColumn],\n references: 'id',\n on: [pivot.sourceTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n foreignKeys.push({\n columns: [pivot.targetColumn],\n references: 'id',\n on: [pivot.targetTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n // Composite primary key / unique constraint\n indexes.push({\n columns: [pivot.sourceColumn, pivot.targetColumn],\n unique: true,\n });\n\n // Individual indexes for faster lookups (no name - let Laravel auto-generate)\n indexes.push({\n columns: [pivot.sourceColumn],\n unique: false,\n });\n\n indexes.push({\n columns: [pivot.targetColumn],\n unique: false,\n });\n\n return {\n tableName: pivot.tableName,\n columns,\n primaryKey: [pivot.sourceColumn, pivot.targetColumn],\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Extracts MorphToMany relationships from a schema.\n * MorphToMany creates a pivot table with polymorphic type/id columns.\n */\nexport function extractMorphToManyRelations(\n schema: LoadedSchema,\n allSchemas: SchemaCollection\n): MorphToManyPivotInfo[] {\n const morphPivotTables: MorphToManyPivotInfo[] = [];\n\n if (!schema.properties) {\n return morphPivotTables;\n }\n\n for (const [propName, property] of Object.entries(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n joinTable?: string;\n onDelete?: string;\n onUpdate?: string;\n owning?: boolean;\n };\n\n if (assocProp.relation !== 'MorphToMany') {\n continue;\n }\n\n const targetName = assocProp.target;\n if (!targetName) {\n continue;\n }\n\n const targetSchema = allSchemas[targetName];\n const targetTable = toTableName(targetName);\n const targetPkType = targetSchema ? getIdType(targetSchema) : 'BigInt';\n\n // Determine if this side owns the relationship\n const isOwningSide = assocProp.owning ?? (schema.name < targetName);\n\n if (!isOwningSide) {\n continue;\n }\n\n // Find all schemas that have MorphedByMany pointing to this target\n // to determine the morphTargets for the ENUM\n const morphTargets: string[] = [];\n\n // The source schema itself is a morph target\n morphTargets.push(schema.name);\n\n // Look for other schemas with MorphToMany to the same target\n for (const [otherName, otherSchema] of Object.entries(allSchemas)) {\n if (otherName === schema.name) continue;\n if (!otherSchema.properties) continue;\n\n for (const otherProp of Object.values(otherSchema.properties)) {\n if (otherProp.type !== 'Association') continue;\n const otherAssoc = otherProp as { relation?: string; target?: string };\n if (otherAssoc.relation === 'MorphToMany' && otherAssoc.target === targetName) {\n if (!morphTargets.includes(otherName)) {\n morphTargets.push(otherName);\n }\n }\n }\n }\n\n // Default table name: taggables (for Tag target), commentables, etc.\n const defaultTableName = targetTable.replace(/s$/, '') + 'ables';\n const tableName = assocProp.joinTable ?? defaultTableName;\n\n // Column name for the target side (e.g., tag_id for Tag)\n const targetColumn = targetTable.replace(/ies$/, 'y').replace(/s$/, '') + '_id';\n\n // MorphName is typically the property name or a convention like 'taggable'\n const morphName = propName.replace(/s$/, '') + 'able';\n\n morphPivotTables.push({\n tableName,\n targetTable,\n targetColumn,\n targetPkType,\n morphName,\n morphTargets,\n onDelete: assocProp.onDelete,\n onUpdate: assocProp.onUpdate,\n });\n }\n\n return morphPivotTables;\n}\n\n/**\n * Generates blueprint for a polymorphic pivot table (MorphToMany).\n */\nexport function generateMorphToManyPivotBlueprint(pivot: MorphToManyPivotInfo): TableBlueprint {\n const columns: ColumnMethod[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n const indexes: IndexDefinition[] = [];\n\n const getMethodForPkType = (pkType: string): string => {\n switch (pkType) {\n case 'Int': return 'unsignedInteger';\n case 'Uuid': return 'uuid';\n case 'String': return 'string';\n default: return 'unsignedBigInteger';\n }\n };\n\n // Target column (e.g., tag_id)\n columns.push({\n name: pivot.targetColumn,\n method: getMethodForPkType(pivot.targetPkType),\n args: [pivot.targetColumn],\n modifiers: [],\n });\n\n // Polymorphic type column as ENUM\n const typeColumnName = `${pivot.morphName}_type`;\n columns.push({\n name: typeColumnName,\n method: 'enum',\n args: [typeColumnName, pivot.morphTargets as unknown as string],\n modifiers: [],\n });\n\n // Polymorphic ID column\n const idColumnName = `${pivot.morphName}_id`;\n columns.push({\n name: idColumnName,\n method: 'unsignedBigInteger', // Default to BigInt for polymorphic IDs\n args: [idColumnName],\n modifiers: [],\n });\n\n // Foreign key for target\n foreignKeys.push({\n columns: [pivot.targetColumn],\n references: 'id',\n on: [pivot.targetTable],\n onDelete: pivot.onDelete ?? 'cascade',\n onUpdate: pivot.onUpdate ?? 'cascade',\n });\n\n // Unique constraint for polymorphic pivot (target + morphable)\n indexes.push({\n columns: [pivot.targetColumn, typeColumnName, idColumnName],\n unique: true,\n });\n\n // Index for faster polymorphic lookups\n indexes.push({\n columns: [typeColumnName, idColumnName],\n unique: false,\n });\n\n // Index for target lookups\n indexes.push({\n columns: [pivot.targetColumn],\n unique: false,\n });\n\n return {\n tableName: pivot.tableName,\n columns,\n primaryKey: [pivot.targetColumn, typeColumnName, idColumnName],\n foreignKeys,\n indexes,\n };\n}\n\n// Note: File schema functions (hasFileProperties, schemasHaveFileProperties, generateFilesTableBlueprint)\n// have been moved to @famgia/omnify-core's schema/loader.ts\n// The File table is now managed as a proper schema (File.yaml) instead of being auto-generated in code.\n","/**\n * @famgia/omnify-laravel - Migration Generator\n *\n * Generates Laravel migration files from schemas.\n */\n\nimport type { LoadedSchema, SchemaCollection } from '@famgia/omnify-types';\nimport type {\n MigrationFile,\n MigrationOptions,\n TableBlueprint,\n} from './types.js';\nimport {\n schemaToBlueprint,\n formatColumnMethod,\n formatForeignKey,\n formatIndex,\n extractManyToManyRelations,\n generatePivotTableBlueprint,\n} from './schema-builder.js';\n\n/**\n * Generates timestamp prefix for migration file name.\n */\nfunction generateTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;\n}\n\n/**\n * Converts table name to Laravel migration class name.\n */\nfunction toClassName(tableName: string, type: 'create' | 'alter' | 'drop'): string {\n const pascalCase = tableName\n .split('_')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n\n switch (type) {\n case 'create':\n return `Create${pascalCase}Table`;\n case 'alter':\n return `Alter${pascalCase}Table`;\n case 'drop':\n return `Drop${pascalCase}Table`;\n }\n}\n\n/**\n * Generates file name for migration.\n */\nfunction generateFileName(\n tableName: string,\n type: 'create' | 'alter' | 'drop',\n timestamp?: string\n): string {\n const ts = timestamp ?? generateTimestamp();\n const action = type === 'create' ? 'create' : type === 'drop' ? 'drop' : 'update';\n return `${ts}_${action}_${tableName}_table.php`;\n}\n\n/**\n * Renders the up method body for a create table operation.\n */\nfunction renderCreateTableUp(blueprint: TableBlueprint): string {\n const lines: string[] = [];\n\n // Column definitions\n for (const column of blueprint.columns) {\n lines.push(` ${formatColumnMethod(column)}`);\n }\n\n // Foreign keys (separate for Laravel best practices)\n // Note: Foreign keys should be in a separate migration or at the end\n // We'll include them in the same migration for simplicity\n\n return lines.join('\\n');\n}\n\n/**\n * Renders foreign key constraints (usually added after all columns).\n */\nfunction renderForeignKeys(blueprint: TableBlueprint): string {\n if (blueprint.foreignKeys.length === 0) {\n return '';\n }\n\n const lines = blueprint.foreignKeys.map(fk => ` ${formatForeignKey(fk)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Renders indexes.\n */\nfunction renderIndexes(blueprint: TableBlueprint): string {\n // Filter out indexes that are already handled (primary key, unique columns)\n const customIndexes = blueprint.indexes.filter(idx => {\n // Skip single-column unique indexes (handled by column modifier)\n if (idx.unique && idx.columns.length === 1) {\n return false;\n }\n return true;\n });\n\n if (customIndexes.length === 0) {\n return '';\n }\n\n const lines = customIndexes.map(idx => ` ${formatIndex(idx)}`);\n return '\\n' + lines.join('\\n');\n}\n\n/**\n * Generates a create table migration.\n */\nfunction generateCreateMigration(\n blueprint: TableBlueprint,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(blueprint.tableName, 'create');\n const fileName = generateFileName(blueprint.tableName, 'create', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const upContent = renderCreateTableUp(blueprint);\n const foreignKeyContent = renderForeignKeys(blueprint);\n const indexContent = renderIndexes(blueprint);\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * To modify the schema, edit the corresponding YAML file in schemas/\n * and run: npx omnify generate\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::create('${blueprint.tableName}', function (Blueprint $table) {\n${upContent}${foreignKeyContent}${indexContent}\n });\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n Schema::dropIfExists('${blueprint.tableName}');\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [blueprint.tableName],\n type: 'create',\n };\n}\n\n/**\n * Generates a drop table migration.\n */\nfunction generateDropMigration(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n const className = toClassName(tableName, 'drop');\n const fileName = generateFileName(tableName, 'drop', options.timestamp);\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::dropIfExists('${tableName}');\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n // Cannot recreate table without schema information\n // This is a one-way migration\n }\n};\n`;\n\n return {\n fileName,\n className,\n content,\n tables: [tableName],\n type: 'drop',\n };\n}\n\n/**\n * Extracts FK dependencies from a schema.\n * Returns array of schema names that this schema depends on.\n */\nfunction extractDependencies(schema: LoadedSchema): string[] {\n const deps: string[] = [];\n\n if (!schema.properties) {\n return deps;\n }\n\n for (const property of Object.values(schema.properties)) {\n if (property.type !== 'Association') {\n continue;\n }\n\n const assocProp = property as {\n relation?: string;\n target?: string;\n mappedBy?: string;\n };\n\n // ManyToOne and OneToOne (owning side) create FK columns\n if (\n (assocProp.relation === 'ManyToOne' || assocProp.relation === 'OneToOne') &&\n !assocProp.mappedBy &&\n assocProp.target\n ) {\n deps.push(assocProp.target);\n }\n }\n\n return deps;\n}\n\n/**\n * Topological sort of schemas based on FK dependencies.\n * Returns schemas in order where dependencies come before dependents.\n */\nfunction topologicalSort(schemas: SchemaCollection): LoadedSchema[] {\n const schemaList = Object.values(schemas).filter(s => s.kind !== 'enum');\n const sorted: LoadedSchema[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>(); // For cycle detection\n\n function visit(schema: LoadedSchema): void {\n if (visited.has(schema.name)) {\n return;\n }\n\n if (visiting.has(schema.name)) {\n // Circular dependency - just continue (FK can be nullable)\n return;\n }\n\n visiting.add(schema.name);\n\n // Visit dependencies first\n const deps = extractDependencies(schema);\n for (const depName of deps) {\n const depSchema = schemas[depName];\n if (depSchema && depSchema.kind !== 'enum') {\n visit(depSchema);\n }\n }\n\n visiting.delete(schema.name);\n visited.add(schema.name);\n sorted.push(schema);\n }\n\n // Visit all schemas\n for (const schema of schemaList) {\n visit(schema);\n }\n\n return sorted;\n}\n\n/**\n * Generates migrations for all schemas.\n */\nexport function generateMigrations(\n schemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile[] {\n const migrations: MigrationFile[] = [];\n const pivotTablesGenerated = new Set<string>();\n let timestampOffset = 0;\n\n // Note: File table (for polymorphic file storage) is now managed as a proper schema (File.yaml)\n // It will be processed like any other schema in the topological sort below.\n // Use ensureFileSchema() from @famgia/omnify-core to auto-generate File.yaml when needed.\n\n // Sort schemas by FK dependencies (topological sort)\n const sortedSchemas = topologicalSort(schemas);\n\n // Generate main table migrations in dependency order\n for (const schema of sortedSchemas) {\n // Generate timestamp with offset to ensure unique filenames\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = schemaToBlueprint(schema, schemas, {\n customTypes: options.customTypes,\n locale: options.locale,\n });\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n\n // Third pass: generate pivot table migrations for ManyToMany (always last)\n for (const schema of sortedSchemas) {\n const pivotTables = extractManyToManyRelations(schema, schemas);\n\n for (const pivot of pivotTables) {\n // Skip if already generated\n if (pivotTablesGenerated.has(pivot.tableName)) {\n continue;\n }\n pivotTablesGenerated.add(pivot.tableName);\n\n const timestamp = options.timestamp ?? generateTimestamp();\n const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);\n timestampOffset++;\n\n const blueprint = generatePivotTableBlueprint(pivot);\n const migration = generateCreateMigration(blueprint, {\n ...options,\n timestamp: offsetTimestamp,\n });\n migrations.push(migration);\n }\n }\n\n return migrations;\n}\n\n/**\n * Increments a timestamp by seconds.\n */\nfunction incrementTimestamp(timestamp: string, seconds: number): string {\n if (seconds === 0) return timestamp;\n\n // Parse timestamp: YYYY_MM_DD_HHMMSS\n const parts = timestamp.split('_');\n if (parts.length < 4) {\n // Invalid format, return original\n return timestamp;\n }\n\n const yearPart = parts[0] ?? '2024';\n const monthPart = parts[1] ?? '01';\n const dayPart = parts[2] ?? '01';\n const timePart = parts[3] ?? '000000';\n\n const year = parseInt(yearPart, 10);\n const month = parseInt(monthPart, 10) - 1;\n const day = parseInt(dayPart, 10);\n const hours = parseInt(timePart.substring(0, 2), 10);\n const minutes = parseInt(timePart.substring(2, 4), 10);\n const secs = parseInt(timePart.substring(4, 6), 10);\n\n const date = new Date(year, month, day, hours, minutes, secs + seconds);\n\n const newYear = date.getFullYear();\n const newMonth = String(date.getMonth() + 1).padStart(2, '0');\n const newDay = String(date.getDate()).padStart(2, '0');\n const newHours = String(date.getHours()).padStart(2, '0');\n const newMinutes = String(date.getMinutes()).padStart(2, '0');\n const newSecs = String(date.getSeconds()).padStart(2, '0');\n\n return `${newYear}_${newMonth}_${newDay}_${newHours}${newMinutes}${newSecs}`;\n}\n\n/**\n * Generates migration from a single schema.\n */\nexport function generateMigrationFromSchema(\n schema: LoadedSchema,\n allSchemas: SchemaCollection,\n options: MigrationOptions = {}\n): MigrationFile {\n const blueprint = schemaToBlueprint(schema, allSchemas);\n return generateCreateMigration(blueprint, options);\n}\n\n/**\n * Generates drop migration for a table.\n */\nexport function generateDropMigrationForTable(\n tableName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n return generateDropMigration(tableName, options);\n}\n\n/**\n * Formats migration content for writing to file.\n */\nexport function formatMigrationFile(migration: MigrationFile): string {\n return migration.content;\n}\n\n/**\n * Gets the output path for a migration file.\n */\nexport function getMigrationPath(\n migration: MigrationFile,\n outputDir: string = 'database/migrations'\n): string {\n return `${outputDir}/${migration.fileName}`;\n}\n","/**\n * @famgia/omnify-laravel - ALTER Migration Generator\n *\n * Generates Laravel migration files for ALTER table operations.\n */\n\nimport type { SchemaChange, PropertySnapshot } from '@famgia/omnify-atlas';\nimport type { MigrationFile, MigrationOptions } from './types.js';\nimport { toTableName, toColumnName } from './schema-builder.js';\n\n/**\n * Maps Omnify property types to Laravel column methods.\n */\nconst TYPE_METHOD_MAP: Record<string, string> = {\n String: 'string',\n TinyInt: 'tinyInteger',\n Int: 'integer',\n BigInt: 'bigInteger',\n Float: 'double',\n Decimal: 'decimal',\n Boolean: 'boolean',\n Text: 'text',\n MediumText: 'mediumText',\n LongText: 'longText',\n Date: 'date',\n Time: 'time',\n DateTime: 'dateTime',\n Timestamp: 'timestamp',\n Json: 'json',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'json',\n Enum: 'enum',\n Select: 'string',\n Lookup: 'unsignedBigInteger',\n};\n\n/**\n * Generates timestamp prefix for migration file name.\n */\nfunction generateTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}_${month}_${day}_${hours}${minutes}${seconds}`;\n}\n\n/**\n * Formats a column addition.\n */\nfunction formatAddColumn(columnName: string, prop: PropertySnapshot): string {\n const snakeColumn = toColumnName(columnName);\n const method = TYPE_METHOD_MAP[prop.type] ?? 'string';\n\n let code: string;\n\n // Handle decimal with precision and scale\n if (prop.type === 'Decimal') {\n const precision = prop.precision ?? 8;\n const scale = prop.scale ?? 2;\n code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;\n } else {\n code = `$table->${method}('${snakeColumn}')`;\n }\n\n // Add modifiers\n if (prop.nullable) code += '->nullable()';\n if (prop.unique) code += '->unique()';\n if (prop.default !== undefined) {\n const defaultValue = typeof prop.default === 'string'\n ? `'${prop.default}'`\n : JSON.stringify(prop.default);\n code += `->default(${defaultValue})`;\n }\n\n return code + ';';\n}\n\n/**\n * Formats a column removal.\n */\nfunction formatDropColumn(columnName: string): string {\n const snakeColumn = toColumnName(columnName);\n return `$table->dropColumn('${snakeColumn}');`;\n}\n\n/**\n * Formats a column rename.\n * Note: Requires doctrine/dbal package in Laravel.\n */\nfunction formatRenameColumn(oldName: string, newName: string): string {\n const oldSnake = toColumnName(oldName);\n const newSnake = toColumnName(newName);\n return `$table->renameColumn('${oldSnake}', '${newSnake}');`;\n}\n\n/**\n * Formats a column modification.\n * Note: Requires doctrine/dbal package in Laravel.\n */\nfunction formatModifyColumn(\n columnName: string,\n _prevProp: PropertySnapshot,\n currProp: PropertySnapshot\n): string {\n const snakeColumn = toColumnName(columnName);\n const method = TYPE_METHOD_MAP[currProp.type] ?? 'string';\n\n let code: string;\n\n // Handle decimal with precision and scale\n if (currProp.type === 'Decimal') {\n const precision = currProp.precision ?? 8;\n const scale = currProp.scale ?? 2;\n code = `$table->${method}('${snakeColumn}', ${precision}, ${scale})`;\n } else {\n code = `$table->${method}('${snakeColumn}')`;\n }\n\n // Add modifiers\n if (currProp.nullable) code += '->nullable()';\n if (currProp.unique) code += '->unique()';\n if (currProp.default !== undefined) {\n const defaultValue = typeof currProp.default === 'string'\n ? `'${currProp.default}'`\n : JSON.stringify(currProp.default);\n code += `->default(${defaultValue})`;\n }\n\n return code + '->change();';\n}\n\n/**\n * Formats an index addition.\n */\nfunction formatAddIndex(columns: readonly string[], unique: boolean): string {\n const snakeColumns = columns.map(toColumnName);\n const method = unique ? 'unique' : 'index';\n const colsArg = snakeColumns.length === 1\n ? `'${snakeColumns[0]}'`\n : `[${snakeColumns.map(c => `'${c}'`).join(', ')}]`;\n\n return `$table->${method}(${colsArg});`;\n}\n\n/**\n * Formats an index removal.\n */\nfunction formatDropIndex(tableName: string, columns: readonly string[], unique: boolean): string {\n const snakeColumns = columns.map(toColumnName);\n const method = unique ? 'dropUnique' : 'dropIndex';\n\n // Laravel generates index names as: {table}_{columns}_{type}\n const suffix = unique ? 'unique' : 'index';\n const indexName = `${tableName}_${snakeColumns.join('_')}_${suffix}`;\n\n return `$table->${method}('${indexName}');`;\n}\n\n/**\n * Generates ALTER migration content for a schema change.\n */\nfunction generateAlterMigrationContent(\n tableName: string,\n change: SchemaChange,\n options: MigrationOptions = {}\n): string {\n const upLines: string[] = [];\n const downLines: string[] = [];\n\n // Column changes\n if (change.columnChanges) {\n for (const col of change.columnChanges) {\n if (col.changeType === 'added' && col.currentDef) {\n upLines.push(` ${formatAddColumn(col.column, col.currentDef)}`);\n downLines.push(` ${formatDropColumn(col.column)}`);\n } else if (col.changeType === 'removed' && col.previousDef) {\n upLines.push(` ${formatDropColumn(col.column)}`);\n downLines.push(` ${formatAddColumn(col.column, col.previousDef)}`);\n } else if (col.changeType === 'modified' && col.previousDef && col.currentDef) {\n upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);\n downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);\n } else if (col.changeType === 'renamed' && col.previousColumn) {\n // Rename column\n upLines.push(` ${formatRenameColumn(col.previousColumn, col.column)}`);\n downLines.push(` ${formatRenameColumn(col.column, col.previousColumn)}`);\n\n // If there are also property modifications, apply them after rename\n if (col.modifications && col.modifications.length > 0 && col.previousDef && col.currentDef) {\n upLines.push(` ${formatModifyColumn(col.column, col.previousDef, col.currentDef)}`);\n downLines.push(` ${formatModifyColumn(col.column, col.currentDef, col.previousDef)}`);\n }\n }\n }\n }\n\n // Index changes\n if (change.indexChanges) {\n for (const idx of change.indexChanges) {\n if (idx.changeType === 'added') {\n upLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);\n downLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);\n } else {\n upLines.push(` ${formatDropIndex(tableName, idx.index.columns, idx.index.unique)}`);\n downLines.push(` ${formatAddIndex(idx.index.columns, idx.index.unique)}`);\n }\n }\n }\n\n // Option changes (timestamps, softDelete)\n if (change.optionChanges) {\n if (change.optionChanges.timestamps) {\n const { from, to } = change.optionChanges.timestamps;\n if (to && !from) {\n upLines.push(` $table->timestamps();`);\n downLines.push(` $table->dropTimestamps();`);\n } else if (from && !to) {\n upLines.push(` $table->dropTimestamps();`);\n downLines.push(` $table->timestamps();`);\n }\n }\n\n if (change.optionChanges.softDelete) {\n const { from, to } = change.optionChanges.softDelete;\n if (to && !from) {\n upLines.push(` $table->softDeletes();`);\n downLines.push(` $table->dropSoftDeletes();`);\n } else if (from && !to) {\n upLines.push(` $table->dropSoftDeletes();`);\n downLines.push(` $table->softDeletes();`);\n }\n }\n }\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n return `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * To modify the schema, edit the corresponding YAML file in schemas/\n * and run: npx omnify generate\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::table('${tableName}', function (Blueprint $table) {\n${upLines.join('\\n')}\n });\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n Schema::table('${tableName}', function (Blueprint $table) {\n${downLines.join('\\n')}\n });\n }\n};\n`;\n}\n\n/**\n * Generates ALTER migration for a modified schema.\n */\nexport function generateAlterMigration(\n change: SchemaChange,\n options: MigrationOptions = {}\n): MigrationFile | null {\n if (change.changeType !== 'modified') {\n return null;\n }\n\n // Check if there are actual changes to migrate\n const hasChanges =\n (change.columnChanges && change.columnChanges.length > 0) ||\n (change.indexChanges && change.indexChanges.length > 0) ||\n (change.optionChanges &&\n (change.optionChanges.timestamps ||\n change.optionChanges.softDelete));\n\n if (!hasChanges) {\n return null;\n }\n\n const tableName = toTableName(change.schemaName);\n const timestamp = options.timestamp ?? generateTimestamp();\n const fileName = `${timestamp}_update_${tableName}_table.php`;\n\n const content = generateAlterMigrationContent(tableName, change, options);\n\n return {\n fileName,\n className: `Update${change.schemaName}Table`,\n content,\n tables: [tableName],\n type: 'alter',\n };\n}\n\n/**\n * Generates DROP migration for a removed schema.\n */\nexport function generateDropTableMigration(\n schemaName: string,\n options: MigrationOptions = {}\n): MigrationFile {\n const tableName = toTableName(schemaName);\n const timestamp = options.timestamp ?? generateTimestamp();\n const fileName = `${timestamp}_drop_${tableName}_table.php`;\n\n const connection = options.connection\n ? `\\n protected $connection = '${options.connection}';\\n`\n : '';\n\n const content = `<?php\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Migrations\\\\Migration;\nuse Illuminate\\\\Database\\\\Schema\\\\Blueprint;\nuse Illuminate\\\\Support\\\\Facades\\\\Schema;\n\nreturn new class extends Migration\n{${connection}\n /**\n * Run the migrations.\n */\n public function up(): void\n {\n Schema::dropIfExists('${tableName}');\n }\n\n /**\n * Reverse the migrations.\n */\n public function down(): void\n {\n // Cannot recreate table without full schema\n // Consider restoring from backup if needed\n }\n};\n`;\n\n return {\n fileName,\n className: `Drop${schemaName}Table`,\n content,\n tables: [tableName],\n type: 'drop',\n };\n}\n\n/**\n * Generates migrations for all schema changes.\n */\nexport function generateMigrationsFromChanges(\n changes: readonly SchemaChange[],\n options: MigrationOptions = {}\n): MigrationFile[] {\n const migrations: MigrationFile[] = [];\n let timestampOffset = 0;\n\n const getNextTimestamp = () => {\n const ts = options.timestamp ?? generateTimestamp();\n const offset = timestampOffset++;\n if (offset === 0) return ts;\n\n // Increment seconds\n const parts = ts.split('_');\n if (parts.length >= 4) {\n const timePart = parts[3] ?? '000000';\n const secs = parseInt(timePart.substring(4, 6), 10) + offset;\n const newSecs = String(secs % 60).padStart(2, '0');\n parts[3] = timePart.substring(0, 4) + newSecs;\n return parts.join('_');\n }\n return ts;\n };\n\n for (const change of changes) {\n if (change.changeType === 'modified') {\n const migration = generateAlterMigration(change, {\n ...options,\n timestamp: getNextTimestamp(),\n });\n if (migration) {\n migrations.push(migration);\n }\n } else if (change.changeType === 'removed') {\n migrations.push(\n generateDropTableMigration(change.schemaName, {\n ...options,\n timestamp: getNextTimestamp(),\n })\n );\n }\n // 'added' changes are handled by the regular CREATE migration generator\n }\n\n return migrations;\n}\n","/**\n * Laravel Model Generator\n *\n * Generates Eloquent model classes from Omnify schemas.\n * Creates base models (auto-generated) and user models (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, AssociationDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { pluralize, toSnakeCase, toPascalCase, toCamelCase } from '../utils.js';\n\n/**\n * Options for model generation.\n */\nexport interface ModelGeneratorOptions {\n /**\n * Base model namespace.\n * @default 'App\\\\Models\\\\OmnifyBase'\n */\n baseModelNamespace?: string;\n\n /**\n * User model namespace.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Base model class name.\n * @default 'BaseModel'\n */\n baseModelClassName?: string;\n\n /**\n * Output path for base models.\n * @default 'app/Models/OmnifyBase'\n */\n baseModelPath?: string;\n\n /**\n * Output path for user models.\n * @default 'app/Models'\n */\n modelPath?: string;\n\n /**\n * Output path for service provider files.\n * @default 'app/Providers'\n */\n providersPath?: string;\n\n /**\n * Custom types registered by plugins.\n * Used to expand compound types in fillable array.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Generated model output.\n */\nexport interface GeneratedModel {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Model type */\n type: 'base-model' | 'entity-base' | 'entity' | 'service-provider' | 'provider-registration' | 'trait' | 'locales';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n}\n\n/**\n * Provider registration result.\n */\nexport interface ProviderRegistrationResult {\n /** Path to the provider registration file */\n path: string;\n /** Modified content */\n content: string;\n /** Laravel version type */\n laravelVersion: 'laravel11+' | 'laravel10-';\n /** Whether registration was already present */\n alreadyRegistered: boolean;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseModelNamespace: string;\n modelNamespace: string;\n baseModelClassName: string;\n baseModelPath: string;\n modelPath: string;\n providersPath: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseModelNamespace: 'App\\\\Models\\\\OmnifyBase',\n modelNamespace: 'App\\\\Models',\n baseModelClassName: 'BaseModel',\n baseModelPath: 'app/Models/OmnifyBase',\n modelPath: 'app/Models',\n providersPath: 'app/Providers',\n customTypes: new Map(),\n};\n\n/**\n * Generate PHP array entries for localized display names.\n * Converts LocalizedString to PHP array format.\n */\nfunction generateLocalizedDisplayNames(displayName: LocalizedString | undefined, indent: string = ' '): string {\n if (displayName === undefined) {\n return '';\n }\n\n if (typeof displayName === 'string') {\n // Single string - use 'en' as default locale\n return `${indent}'en' => '${escapePhpString(displayName)}',`;\n }\n\n if (isLocaleMap(displayName)) {\n const entries = Object.entries(displayName)\n .map(([locale, value]) => `${indent}'${locale}' => '${escapePhpString(value)}',`)\n .join('\\n');\n return entries;\n }\n\n return '';\n}\n\n/**\n * Generate PHP array entries for property localized display names.\n */\nfunction generatePropertyLocalizedDisplayNames(\n schema: LoadedSchema,\n indent: string = ' '\n): string {\n const properties = schema.properties ?? {};\n const entries: string[] = [];\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n const displayName = (propDef as { displayName?: LocalizedString }).displayName;\n\n if (displayName === undefined) {\n continue;\n }\n\n const innerIndent = indent + ' ';\n\n if (typeof displayName === 'string') {\n entries.push(`${indent}'${snakeName}' => [\\n${innerIndent}'en' => '${escapePhpString(displayName)}',\\n${indent}],`);\n } else if (isLocaleMap(displayName)) {\n const localeEntries = Object.entries(displayName)\n .map(([locale, value]) => `${innerIndent}'${locale}' => '${escapePhpString(value)}',`)\n .join('\\n');\n entries.push(`${indent}'${snakeName}' => [\\n${localeEntries}\\n${indent}],`);\n }\n }\n\n return entries.join('\\n');\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: ModelGeneratorOptions): ResolvedOptions {\n return {\n baseModelNamespace: options?.baseModelNamespace ?? DEFAULT_OPTIONS.baseModelNamespace,\n modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,\n baseModelClassName: options?.baseModelClassName ?? DEFAULT_OPTIONS.baseModelClassName,\n baseModelPath: options?.baseModelPath ?? DEFAULT_OPTIONS.baseModelPath,\n modelPath: options?.modelPath ?? DEFAULT_OPTIONS.modelPath,\n providersPath: options?.providersPath ?? DEFAULT_OPTIONS.providersPath,\n customTypes: options?.customTypes ?? new Map(),\n };\n}\n\n/**\n * Get PHP type for casting.\n */\nfunction getCastType(propDef: PropertyDefinition): string | null {\n switch (propDef.type) {\n case 'Boolean':\n return 'boolean';\n case 'Int':\n case 'BigInt':\n return 'integer';\n case 'Float':\n return 'float';\n case 'Decimal':\n return 'decimal:' + ((propDef as any).scale ?? 2);\n case 'Json':\n return 'array';\n case 'Date':\n return 'date';\n case 'DateTime':\n case 'Timestamp':\n return 'datetime';\n case 'Password':\n return 'hashed';\n default:\n return null;\n }\n}\n\n/**\n * Check if a property definition is nullable.\n * For associations, check the 'nullable' field if it exists as an extension.\n */\nfunction isNullable(propDef: PropertyDefinition): boolean {\n // BasePropertyDefinition has nullable, AssociationDefinition does not\n // But some schemas may define nullable on associations as an extension\n return 'nullable' in propDef && propDef.nullable === true;\n}\n\n/**\n * Get PHP doc type for a property.\n */\nfunction getPhpDocType(propDef: PropertyDefinition, schemas: SchemaCollection): string {\n const nullable = isNullable(propDef);\n\n switch (propDef.type) {\n case 'String':\n case 'Text':\n case 'LongText':\n case 'Email':\n case 'Password':\n return 'string' + (nullable ? '|null' : '');\n case 'Int':\n case 'BigInt':\n return 'int' + (nullable ? '|null' : '');\n case 'Float':\n case 'Decimal':\n return 'float' + (nullable ? '|null' : '');\n case 'Boolean':\n return 'bool' + (nullable ? '|null' : '');\n case 'Date':\n case 'DateTime':\n case 'Time':\n case 'Timestamp':\n return '\\\\Carbon\\\\Carbon' + (nullable ? '|null' : '');\n case 'Json':\n return 'array' + (nullable ? '|null' : '');\n case 'Enum':\n case 'EnumRef':\n return 'string' + (nullable ? '|null' : '');\n case 'Association': {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n const className = toPascalCase(assoc.target);\n switch (assoc.relation) {\n case 'OneToMany':\n case 'ManyToMany':\n case 'MorphMany':\n case 'MorphToMany':\n case 'MorphedByMany':\n return `\\\\Illuminate\\\\Database\\\\Eloquent\\\\Collection<${className}>`;\n default:\n // ManyToOne, OneToOne - typically nullable unless owning\n return className + '|null';\n }\n }\n return 'mixed';\n }\n default:\n return 'mixed';\n }\n}\n\n/**\n * Expand compound type property into field names.\n * Returns array of field names (snake_case) or null if not a compound type.\n */\nfunction expandCompoundTypeFields(\n propName: string,\n propType: string,\n customTypes: ReadonlyMap<string, CustomTypeDefinition>\n): string[] | null {\n const typeDef = customTypes.get(propType);\n\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const snakeName = toSnakeCase(propName);\n const fields: string[] = [];\n\n for (const field of typeDef.expand) {\n // Convert suffix to snake_case and combine with property name\n const suffixSnake = toSnakeCase(field.suffix);\n fields.push(`${snakeName}_${suffixSnake}`);\n }\n\n return fields;\n}\n\n/**\n * Generate the shared BaseModel class.\n */\nfunction generateBaseModel(\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Build model map\n const modelMap = Object.values(schemas)\n .filter(s => s.kind !== 'enum')\n .map(s => {\n const className = toPascalCase(s.name);\n return ` '${s.name}' => \\\\${options.modelNamespace}\\\\${className}::class,`;\n })\n .join('\\n');\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{BASE_MODEL_CLASS\\}\\}/g, options.baseModelClassName)\n .replace(/\\{\\{MODEL_MAP\\}\\}/g, modelMap);\n\n return {\n path: `${options.baseModelPath}/${options.baseModelClassName}.php`,\n content,\n type: 'base-model',\n overwrite: true,\n schemaName: '__base__',\n };\n}\n\n/**\n * Generate entity base model (auto-generated).\n */\nfunction generateEntityBaseModel(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string,\n authStubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n const isAuth = schema.options?.authenticatable ?? false;\n\n // Determine primary key\n // Check if id is disabled and we need to find a custom primary key\n const hasAutoId = schema.options?.id !== false;\n let primaryKey = 'id';\n let isStringKey = false;\n let isUuid = false;\n let isNonIncrementing = false;\n\n if (hasAutoId) {\n // Standard auto-incrementing or UUID id\n const idType = schema.options?.idType ?? 'BigInt';\n isUuid = idType === 'Uuid';\n isStringKey = idType === 'Uuid' || idType === 'String';\n isNonIncrementing = isUuid;\n } else {\n // Custom primary key - find the property with primary: true\n const properties = schema.properties ?? {};\n for (const [propName, propDef] of Object.entries(properties)) {\n if ((propDef as { primary?: boolean }).primary === true) {\n primaryKey = toSnakeCase(propName);\n // Determine if it's a string-type key\n const propType = propDef.type;\n isStringKey = propType === 'String' || propType === 'Text' || propType === 'Email';\n isNonIncrementing = true; // Custom primary keys are not auto-incrementing\n break;\n }\n }\n }\n\n // Build imports, traits, fillable, hidden, casts, relations\n const imports: string[] = [];\n const traits: string[] = [];\n const fillable: string[] = [];\n const hidden: string[] = [];\n const appends: string[] = [];\n const casts: string[] = [];\n const relations: string[] = [];\n const docProperties: string[] = [];\n\n // Add soft delete\n if (schema.options?.softDelete) {\n imports.push('use Illuminate\\\\Database\\\\Eloquent\\\\SoftDeletes;');\n traits.push(' use SoftDeletes;');\n }\n\n // Process properties\n const properties = schema.properties ?? {};\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Check if this is a compound type (defer docProperties to expanded fields)\n const typeDef = options.customTypes.get(propDef.type);\n const isCompoundType = typeDef?.compound && typeDef.expand;\n\n // Add to doc comments (skip for compound types - they'll be added per field)\n if (!isCompoundType) {\n const phpType = getPhpDocType(propDef, schemas);\n docProperties.push(` * @property ${phpType} $${snakeName}`);\n }\n\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n imports.push(`use ${options.modelNamespace}\\\\${toPascalCase(assoc.target)};`);\n }\n relations.push(generateRelation(propName, assoc, schema, schemas, options));\n\n // Add foreign key to fillable for belongsTo relations\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (!assoc.mappedBy) {\n const fkName = toSnakeCase(propName) + '_id';\n fillable.push(` '${fkName}',`);\n docProperties.push(` * @property int|null $${fkName}`);\n }\n }\n } else if (propDef.type === 'Password') {\n // Check if fillable: false is set\n const propWithFillable = propDef as { fillable?: boolean };\n if (propWithFillable.fillable !== false) {\n fillable.push(` '${snakeName}',`);\n }\n hidden.push(` '${snakeName}',`);\n const cast = getCastType(propDef);\n if (cast) {\n casts.push(` '${snakeName}' => '${cast}',`);\n }\n } else if (propDef.type === 'File') {\n // File properties don't add to fillable (polymorphic)\n const relMethod = generateFileRelation(propName, propDef as any);\n relations.push(relMethod);\n } else {\n // Check for fillable property (default: true)\n const propWithOptions = propDef as { fillable?: boolean; hidden?: boolean; fields?: Record<string, { nullable?: boolean; hidden?: boolean; fillable?: boolean }> };\n const isFillable = propWithOptions.fillable !== false;\n const isHidden = propWithOptions.hidden === true;\n\n // Check if this is a compound type that should be expanded\n const typeDef = options.customTypes.get(propDef.type);\n const isCompoundType = typeDef?.compound && typeDef.expand;\n\n if (isCompoundType && typeDef.expand) {\n // Compound type - process each expanded field with per-field overrides\n const fieldOverrides = propWithOptions.fields ?? {};\n const basePropWithNullable = propDef as { nullable?: boolean };\n\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const override = fieldOverrides[field.suffix];\n\n // Determine nullable for PHP type\n const fieldNullable = override?.nullable ?? basePropWithNullable.nullable ?? false;\n const phpType = field.typescript?.type === 'number' ? 'int' : 'string';\n const nullSuffix = fieldNullable ? '|null' : '';\n docProperties.push(` * @property ${phpType}${nullSuffix} $${fieldName}`);\n\n // Determine fillable: use field override if set, otherwise use property-level setting\n const fieldFillable = override?.fillable !== undefined ? override.fillable : isFillable;\n if (fieldFillable) {\n fillable.push(` '${fieldName}',`);\n }\n\n // Determine hidden: use field override if set, otherwise use property-level setting\n const fieldHidden = override?.hidden !== undefined ? override.hidden : isHidden;\n if (fieldHidden) {\n hidden.push(` '${fieldName}',`);\n }\n }\n } else {\n // Regular property\n if (isFillable) {\n fillable.push(` '${snakeName}',`);\n }\n\n const cast = getCastType(propDef);\n if (cast) {\n casts.push(` '${snakeName}' => '${cast}',`);\n }\n\n // Check for hidden: true property (for non-Password types)\n if (isHidden) {\n hidden.push(` '${snakeName}',`);\n }\n }\n\n // Check for compound type accessors (reuse typeDef from above)\n if (typeDef?.compound && typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n // Generate accessor name with property prefix\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n appends.push(` '${accessorName}',`);\n\n // Generate accessor method\n const methodName = toPascalCase(accessorName);\n const separator = accessor.separator ?? ' ';\n\n // Build field references\n const fieldRefs = accessor.fields.map(field => {\n const fieldName = `${snakeName}_${toSnakeCase(field)}`;\n return `$this->${fieldName}`;\n });\n\n // Generate accessor method with null filtering for optional fields\n const accessorMethod = ` /**\n * Get the ${accessor.name.replace(/_/g, ' ')} attribute.\n */\n public function get${methodName}Attribute(): ?string\n {\n $parts = array_filter([${fieldRefs.join(', ')}], fn($v) => $v !== null && $v !== '');\n return count($parts) > 0 ? implode('${separator}', $parts) : null;\n }`;\n relations.push(accessorMethod);\n }\n }\n }\n }\n\n // Build doc comment\n const docComment = `/**\n * ${className}BaseModel\n *\n${docProperties.join('\\n')}\n */`;\n\n // Choose stub based on authenticatable\n const stub = isAuth ? authStubContent : stubContent;\n\n // Build key type and incrementing\n const keyType = isStringKey ? ` /**\n * The \"type\" of the primary key ID.\n */\n protected $keyType = 'string';\n\n` : '';\n\n const incrementing = isNonIncrementing ? ` /**\n * Indicates if the IDs are auto-incrementing.\n */\n public $incrementing = false;\n\n` : '';\n\n // Add UUID trait if needed\n if (isUuid) {\n imports.push('use Illuminate\\\\Database\\\\Eloquent\\\\Concerns\\\\HasUuids;');\n traits.push(' use HasUuids;');\n }\n\n const content = stub\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{BASE_MODEL_CLASS\\}\\}/g, options.baseModelClassName)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className)\n .replace(/\\{\\{TABLE_NAME\\}\\}/g, tableName)\n .replace(/\\{\\{PRIMARY_KEY\\}\\}/g, primaryKey)\n .replace(/\\{\\{KEY_TYPE\\}\\}/g, keyType)\n .replace(/\\{\\{INCREMENTING\\}\\}/g, incrementing)\n .replace(/\\{\\{TIMESTAMPS\\}\\}/g, schema.options?.timestamps !== false ? 'true' : 'false')\n .replace(/\\{\\{IMPORTS\\}\\}/g, [...new Set(imports)].sort().join('\\n'))\n .replace(/\\{\\{TRAITS\\}\\}/g, traits.join('\\n'))\n .replace(/\\{\\{DOC_COMMENT\\}\\}/g, docComment)\n .replace(/\\{\\{FILLABLE\\}\\}/g, fillable.join('\\n'))\n .replace(/\\{\\{HIDDEN\\}\\}/g, hidden.join('\\n'))\n .replace(/\\{\\{APPENDS\\}\\}/g, appends.join('\\n'))\n .replace(/\\{\\{CASTS\\}\\}/g, casts.join('\\n'))\n .replace(/\\{\\{RELATIONS\\}\\}/g, relations.join('\\n\\n'));\n\n return {\n path: `${options.baseModelPath}/${className}BaseModel.php`,\n content,\n type: 'entity-base',\n overwrite: true,\n schemaName: schema.name,\n };\n}\n\n/**\n * Find the inverse ManyToOne relationship on target schema that points back to current schema.\n */\nfunction findInverseRelation(\n currentSchemaName: string,\n targetSchemaName: string,\n schemas: SchemaCollection\n): string | null {\n const targetSchema = schemas[targetSchemaName];\n if (!targetSchema || !targetSchema.properties) {\n return null;\n }\n\n for (const [propName, propDef] of Object.entries(targetSchema.properties)) {\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' && assoc.target === currentSchemaName) {\n return propName;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Generate relation method.\n */\nfunction generateRelation(\n propName: string,\n assoc: AssociationDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string {\n const methodName = toCamelCase(propName);\n const targetClass = assoc.target ? toPascalCase(assoc.target) : '';\n const fkName = toSnakeCase(propName) + '_id';\n\n switch (assoc.relation) {\n case 'ManyToOne':\n return ` /**\n * Get the ${propName} that owns this model.\n */\n public function ${methodName}(): BelongsTo\n {\n return $this->belongsTo(${targetClass}::class, '${fkName}');\n }`;\n\n case 'OneToOne':\n if (assoc.mappedBy) {\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): HasOne\n {\n return $this->hasOne(${targetClass}::class, '${toSnakeCase(assoc.mappedBy)}_id');\n }`;\n }\n return ` /**\n * Get the ${propName} that owns this model.\n */\n public function ${methodName}(): BelongsTo\n {\n return $this->belongsTo(${targetClass}::class, '${fkName}');\n }`;\n\n case 'OneToMany': {\n // Find the inverse ManyToOne relationship on target to determine correct FK\n let foreignKey: string;\n if (assoc.inversedBy) {\n // If inversedBy is specified, use it\n foreignKey = toSnakeCase(assoc.inversedBy) + '_id';\n } else if (assoc.target) {\n // Look up the inverse relationship on the target schema\n const inverseRelation = findInverseRelation(schema.name, assoc.target, schemas);\n if (inverseRelation) {\n foreignKey = toSnakeCase(inverseRelation) + '_id';\n } else {\n // Fallback: use the current schema name as snake_case + _id\n foreignKey = toSnakeCase(schema.name) + '_id';\n }\n } else {\n foreignKey = toSnakeCase(propName) + '_id';\n }\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): HasMany\n {\n return $this->hasMany(${targetClass}::class, '${foreignKey}');\n }`;\n }\n\n case 'ManyToMany': {\n const pivotTable = assoc.joinTable ?? `${toSnakeCase(propName)}_pivot`;\n\n // Generate withPivot() for pivot fields\n // First check this side's pivotFields, then check the inverse side if mappedBy is specified\n let pivotFieldNames: string[] = [];\n\n if (assoc.pivotFields && Object.keys(assoc.pivotFields).length > 0) {\n // This is the owning side with pivotFields defined\n pivotFieldNames = Object.keys(assoc.pivotFields).map(f => toSnakeCase(f));\n } else if (assoc.mappedBy && assoc.target) {\n // This is the inverse side - look up pivotFields from the owning side\n const targetSchema = schemas[assoc.target];\n if (targetSchema?.properties) {\n const owningProp = targetSchema.properties[assoc.mappedBy];\n if (owningProp?.type === 'Association') {\n const owningAssoc = owningProp as AssociationDefinition;\n if (owningAssoc.pivotFields && Object.keys(owningAssoc.pivotFields).length > 0) {\n pivotFieldNames = Object.keys(owningAssoc.pivotFields).map(f => toSnakeCase(f));\n }\n }\n }\n }\n\n const pivotFieldsCode = pivotFieldNames.length > 0\n ? pivotFieldNames.map(f => `'${f}'`).join(', ')\n : null;\n\n const withPivotLine = pivotFieldsCode\n ? `\\n ->withPivot(${pivotFieldsCode})`\n : '';\n\n return ` /**\n * The ${propName} that belong to this model.\n */\n public function ${methodName}(): BelongsToMany\n {\n return $this->belongsToMany(${targetClass}::class, '${pivotTable}')${withPivotLine}\n ->withTimestamps();\n }`;\n }\n\n case 'MorphTo':\n return ` /**\n * Get the parent ${propName} model.\n */\n public function ${methodName}(): MorphTo\n {\n return $this->morphTo('${methodName}');\n }`;\n\n case 'MorphOne':\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): MorphOne\n {\n return $this->morphOne(${targetClass}::class, '${assoc.morphName ?? propName}');\n }`;\n\n case 'MorphMany':\n return ` /**\n * Get the ${propName} for this model.\n */\n public function ${methodName}(): MorphMany\n {\n return $this->morphMany(${targetClass}::class, '${assoc.morphName ?? propName}');\n }`;\n\n default:\n return ` // TODO: Implement ${assoc.relation} relation for ${propName}`;\n }\n}\n\n/**\n * Generate file relation method.\n */\nfunction generateFileRelation(propName: string, propDef: { multiple?: boolean }): string {\n const methodName = toCamelCase(propName);\n const relationType = propDef.multiple ? 'MorphMany' : 'MorphOne';\n const relationMethod = propDef.multiple ? 'morphMany' : 'morphOne';\n\n return ` /**\n * Get the ${propName} file(s) for this model.\n */\n public function ${methodName}(): ${relationType}\n {\n return $this->${relationMethod}(FileUpload::class, 'uploadable')\n ->where('attribute_name', '${propName}');\n }`;\n}\n\n/**\n * Generate user model (created once, not overwritten).\n */\nfunction generateEntityModel(\n schema: LoadedSchema,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{MODEL_NAMESPACE\\}\\}/g, options.modelNamespace)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className);\n\n return {\n path: `${options.modelPath}/${className}.php`,\n content,\n type: 'entity',\n overwrite: false, // Never overwrite user models\n schemaName: schema.name,\n };\n}\n\n/**\n * Read stub file content.\n */\nfunction getStubContent(stubName: string): string {\n // Stubs are embedded as strings since this runs in Node.js\n const stubs: Record<string, string> = {\n 'base-model': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * Base model class for all Omnify-generated models.\n * Contains model mapping for polymorphic relations.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Eloquent\\\\Model;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation;\n\nabstract class {{BASE_MODEL_CLASS}} extends Model\n{\n /**\n * Model class map for polymorphic relations.\n */\n protected static array $modelMap = [\n{{MODEL_MAP}}\n ];\n\n /**\n * Boot the model and register morph map.\n */\n protected static function boot(): void\n {\n parent::boot();\n\n // Register morph map for polymorphic relations\n Relation::enforceMorphMap(static::$modelMap);\n }\n\n /**\n * Get the model class for a given morph type.\n */\n public static function getModelClass(string $morphType): ?string\n {\n return static::$modelMap[$morphType] ?? null;\n }\n}\n`,\n\n 'entity-base': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Collection as EloquentCollection;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Traits\\\\HasLocalizedDisplayName;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Locales\\\\{{CLASS_NAME}}Locales;\n{{IMPORTS}}\n\n{{DOC_COMMENT}}\nclass {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}\n{\n use HasLocalizedDisplayName;\n{{TRAITS}}\n /**\n * The table associated with the model.\n */\n protected $table = '{{TABLE_NAME}}';\n\n /**\n * The primary key for the model.\n */\n protected $primaryKey = '{{PRIMARY_KEY}}';\n\n{{KEY_TYPE}}\n{{INCREMENTING}}\n /**\n * Indicates if the model should be timestamped.\n */\n public $timestamps = {{TIMESTAMPS}};\n\n /**\n * Localized display names for this model.\n *\n * @var array<string, string>\n */\n protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;\n\n /**\n * The attributes that are mass assignable.\n */\n protected $fillable = [\n{{FILLABLE}}\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n */\n protected $hidden = [\n{{HIDDEN}}\n ];\n\n /**\n * The accessors to append to the model's array form.\n */\n protected $appends = [\n{{APPENDS}}\n ];\n\n /**\n * Get the attributes that should be cast.\n */\n protected function casts(): array\n {\n return [\n{{CASTS}}\n ];\n }\n\n{{RELATIONS}}\n}\n`,\n\n 'entity-base-auth': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}};\n\n/**\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\n\nuse Illuminate\\\\Foundation\\\\Auth\\\\User as Authenticatable;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\BelongsToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphTo;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphOne;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\MorphToMany;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Collection as EloquentCollection;\nuse Illuminate\\\\Notifications\\\\Notifiable;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Traits\\\\HasLocalizedDisplayName;\nuse {{BASE_MODEL_NAMESPACE}}\\\\Locales\\\\{{CLASS_NAME}}Locales;\n{{IMPORTS}}\n\n{{DOC_COMMENT}}\nclass {{CLASS_NAME}}BaseModel extends Authenticatable\n{\n use Notifiable;\n use HasLocalizedDisplayName;\n{{TRAITS}}\n /**\n * The table associated with the model.\n */\n protected $table = '{{TABLE_NAME}}';\n\n /**\n * The primary key for the model.\n */\n protected $primaryKey = '{{PRIMARY_KEY}}';\n\n{{KEY_TYPE}}\n{{INCREMENTING}}\n /**\n * Indicates if the model should be timestamped.\n */\n public $timestamps = {{TIMESTAMPS}};\n\n /**\n * Localized display names for this model.\n *\n * @var array<string, string>\n */\n protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;\n\n /**\n * The attributes that are mass assignable.\n */\n protected $fillable = [\n{{FILLABLE}}\n ];\n\n /**\n * The attributes that should be hidden for serialization.\n */\n protected $hidden = [\n{{HIDDEN}}\n ];\n\n /**\n * The accessors to append to the model's array form.\n */\n protected $appends = [\n{{APPENDS}}\n ];\n\n /**\n * Get the attributes that should be cast.\n */\n protected function casts(): array\n {\n return [\n{{CASTS}}\n ];\n }\n\n{{RELATIONS}}\n}\n`,\n\n 'entity': `<?php\n\nnamespace {{MODEL_NAMESPACE}};\n\nuse {{BASE_MODEL_NAMESPACE}}\\\\{{CLASS_NAME}}BaseModel;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Factories\\\\HasFactory;\n\n/**\n * {{CLASS_NAME}} Model\n *\n * This file is generated once and can be customized.\n * Add your custom methods and logic here.\n */\nclass {{CLASS_NAME}} extends {{CLASS_NAME}}BaseModel\n{\n use HasFactory;\n\n /**\n * Create a new model instance.\n */\n public function __construct(array $attributes = [])\n {\n parent::__construct($attributes);\n }\n\n // Add your custom methods here\n}\n`,\n\n 'service-provider': `<?php\n\nnamespace App\\\\Providers;\n\nuse App\\\\Support\\\\Omnify;\nuse Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation;\nuse Illuminate\\\\Support\\\\ServiceProvider;\n\n/**\n * Omnify Service Provider\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * - Loads Omnify migrations from database/migrations/omnify\n * - Registers morph map for polymorphic relationships\n * - Exports schema paths for CLI consumption\n *\n * @generated by @famgia/omnify-laravel\n */\nclass OmnifyServiceProvider extends ServiceProvider\n{\n /**\n * Register any application services.\n */\n public function register(): void\n {\n //\n }\n\n /**\n * Bootstrap any application services.\n */\n public function boot(): void\n {\n // Load Omnify migrations from custom directory\n $this->loadMigrationsFrom(database_path('migrations/omnify'));\n\n // Register morph map for polymorphic relationships\n Relation::enforceMorphMap([\n{{MORPH_MAP}}\n ]);\n\n // Export registered schema paths for CLI (only when running artisan commands)\n if ($this->app->runningInConsole()) {\n Omnify::exportPaths();\n }\n }\n}\n`,\n\n 'has-localized-display-name': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}}\\\\Traits;\n\n/**\n * Trait for localized display names.\n * Uses Laravel's app()->getLocale() for locale resolution.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\ntrait HasLocalizedDisplayName\n{\n /**\n * Get the localized display name for this model.\n *\n * @param string|null $locale Locale code (defaults to app locale)\n * @return string\n */\n public static function displayName(?string $locale = null): string\n {\n $locale = $locale ?? app()->getLocale();\n $displayNames = static::$localizedDisplayNames ?? [];\n\n return $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? class_basename(static::class);\n }\n\n /**\n * Get all localized display names for this model.\n *\n * @return array<string, string>\n */\n public static function allDisplayNames(): array\n {\n return static::$localizedDisplayNames ?? [];\n }\n\n /**\n * Get the localized display name for a property.\n *\n * @param string $property Property name\n * @param string|null $locale Locale code (defaults to app locale)\n * @return string\n */\n public static function propertyDisplayName(string $property, ?string $locale = null): string\n {\n $locale = $locale ?? app()->getLocale();\n $displayNames = static::$localizedPropertyDisplayNames[$property] ?? [];\n\n return $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? $property;\n }\n\n /**\n * Get all localized display names for a property.\n *\n * @param string $property Property name\n * @return array<string, string>\n */\n public static function allPropertyDisplayNames(string $property): array\n {\n return static::$localizedPropertyDisplayNames[$property] ?? [];\n }\n\n /**\n * Get all property display names for a given locale.\n *\n * @param string|null $locale Locale code (defaults to app locale)\n * @return array<string, string>\n */\n public static function allPropertyDisplayNamesForLocale(?string $locale = null): array\n {\n $locale = $locale ?? app()->getLocale();\n $result = [];\n\n foreach (static::$localizedPropertyDisplayNames ?? [] as $property => $displayNames) {\n $result[$property] = $displayNames[$locale]\n ?? $displayNames[config('app.fallback_locale', 'en')]\n ?? $displayNames[array_key_first($displayNames) ?? 'en']\n ?? $property;\n }\n\n return $result;\n }\n}\n`,\n\n 'locales': `<?php\n\nnamespace {{BASE_MODEL_NAMESPACE}}\\\\Locales;\n\n/**\n * Localized display names for {{CLASS_NAME}}.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\nclass {{CLASS_NAME}}Locales\n{\n /**\n * Localized display names for the model.\n *\n * @var array<string, string>\n */\n public const DISPLAY_NAMES = [\n{{LOCALIZED_DISPLAY_NAMES}}\n ];\n\n /**\n * Localized display names for properties.\n *\n * @var array<string, array<string, string>>\n */\n public const PROPERTY_DISPLAY_NAMES = [\n{{LOCALIZED_PROPERTY_DISPLAY_NAMES}}\n ];\n}\n`,\n\n 'omnify-support': `<?php\n\nnamespace App\\\\Support;\n\n/**\n * Omnify Support Class\n *\n * Allows Laravel packages to register their schema directories.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @example\n * // In your package's ServiceProvider:\n * use App\\\\Support\\\\Omnify;\n *\n * public function boot()\n * {\n * Omnify::addSchemaPath(__DIR__.'/../database/schemas');\n * }\n *\n * @generated by @famgia/omnify-laravel\n */\nclass Omnify\n{\n /**\n * Registered schema paths from packages.\n *\n * @var array<array{path: string, namespace: string|null}>\n */\n protected static array $schemaPaths = [];\n\n /**\n * Register a schema directory path.\n *\n * @param string $path Absolute path to schema directory\n * @param string|null $namespace Optional namespace prefix for schemas\n * @return void\n */\n public static function addSchemaPath(string $path, ?string $namespace = null): void\n {\n $realPath = realpath($path);\n\n if ($realPath === false) {\n $realPath = $path;\n }\n\n static::$schemaPaths[] = [\n 'path' => $realPath,\n 'namespace' => $namespace,\n ];\n }\n\n /**\n * Get all registered schema paths.\n *\n * @return array<array{path: string, namespace: string|null}>\n */\n public static function getSchemaPaths(): array\n {\n return static::$schemaPaths;\n }\n\n /**\n * Clear all registered schema paths.\n */\n public static function clearSchemaPaths(): void\n {\n static::$schemaPaths = [];\n }\n\n /**\n * Export schema paths to JSON file for CLI consumption.\n *\n * @param string|null $outputPath Path to write JSON file\n * @return string Path to the generated file\n */\n public static function exportPaths(?string $outputPath = null): string\n {\n $outputPath = $outputPath ?? storage_path('omnify/schema-paths.json');\n\n $dir = dirname($outputPath);\n if (!is_dir($dir)) {\n mkdir($dir, 0755, true);\n }\n\n $data = [\n 'generated_at' => date('c'),\n 'paths' => static::$schemaPaths,\n ];\n\n file_put_contents($outputPath, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));\n\n return $outputPath;\n }\n}\n`,\n\n 'omnify-command': `<?php\n\nnamespace App\\\\Console\\\\Commands;\n\nuse App\\\\Support\\\\Omnify;\nuse Illuminate\\\\Console\\\\Command;\n\n/**\n * Sync registered schema paths for Omnify CLI.\n *\n * DO NOT EDIT - This file is auto-generated by Omnify.\n * Any changes will be overwritten on next generation.\n *\n * @generated by @famgia/omnify-laravel\n */\nclass OmnifySyncCommand extends Command\n{\n protected $signature = 'omnify:sync {--output= : Custom output path}';\n\n protected $description = 'Export registered schema paths for Omnify CLI';\n\n public function handle(): int\n {\n $this->info('Syncing Omnify schema paths...');\n\n $paths = Omnify::getSchemaPaths();\n\n if (empty($paths)) {\n $this->warn('No additional schema paths registered.');\n $this->line('Tip: Packages can use Omnify::addSchemaPath()');\n } else {\n $this->line('Found ' . count($paths) . ' path(s):');\n foreach ($paths as $entry) {\n $ns = $entry['namespace'] ? \" [{$entry['namespace']}]\" : '';\n $this->line(\" • {$entry['path']}{$ns}\");\n }\n }\n\n $filePath = Omnify::exportPaths($this->option('output'));\n $this->info(\"✓ Exported to: {$filePath}\");\n\n return Command::SUCCESS;\n }\n}\n`,\n };\n\n return stubs[stubName] ?? '';\n}\n\n/**\n * Generate OmnifyServiceProvider with morph map.\n */\nfunction generateServiceProvider(\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Build morph map - only include models (not enums or hidden schemas)\n const morphMap = Object.values(schemas)\n .filter(s => s.kind !== 'enum' && s.options?.hidden !== true)\n .map(s => {\n const className = toPascalCase(s.name);\n return ` '${s.name}' => \\\\${options.modelNamespace}\\\\${className}::class,`;\n })\n .join('\\n');\n\n const content = stubContent\n .replace(/\\{\\{MORPH_MAP\\}\\}/g, morphMap);\n\n return {\n path: `${options.providersPath}/OmnifyServiceProvider.php`,\n content,\n type: 'service-provider',\n overwrite: true, // Always overwrite to keep morph map in sync\n schemaName: '__service_provider__',\n };\n}\n\n/**\n * Generate the HasLocalizedDisplayName trait.\n */\nfunction generateLocalizedDisplayNameTrait(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace);\n\n return {\n path: `${options.baseModelPath}/Traits/HasLocalizedDisplayName.php`,\n content,\n type: 'trait',\n overwrite: true, // Always overwrite trait\n schemaName: '__trait__',\n };\n}\n\n/**\n * Generate the Omnify support class for package schema registration.\n */\nfunction generateOmnifySupport(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Use modelPath as base (app/Models) and go up to app/\n const appPath = options.modelPath.replace(/\\/Models$/, '');\n return {\n path: `${appPath}/Support/Omnify.php`,\n content: stubContent,\n type: 'trait', // Use trait type for support classes\n overwrite: true, // Always overwrite\n schemaName: '__omnify_support__',\n };\n}\n\n/**\n * Generate the Omnify sync artisan command.\n */\nfunction generateOmnifyCommand(\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n // Use modelPath as base (app/Models) and go up to app/\n const appPath = options.modelPath.replace(/\\/Models$/, '');\n return {\n path: `${appPath}/Console/Commands/OmnifySyncCommand.php`,\n content: stubContent,\n type: 'trait', // Use trait type for command classes\n overwrite: true, // Always overwrite\n schemaName: '__omnify_command__',\n };\n}\n\n/**\n * Generate the Locales class for a schema.\n */\nfunction generateLocalesClass(\n schema: LoadedSchema,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedModel {\n const className = toPascalCase(schema.name);\n\n // Generate localized display names\n const localizedDisplayNames = generateLocalizedDisplayNames(schema.displayName);\n const localizedPropertyDisplayNames = generatePropertyLocalizedDisplayNames(schema);\n\n const content = stubContent\n .replace(/\\{\\{BASE_MODEL_NAMESPACE\\}\\}/g, options.baseModelNamespace)\n .replace(/\\{\\{CLASS_NAME\\}\\}/g, className)\n .replace(/\\{\\{LOCALIZED_DISPLAY_NAMES\\}\\}/g, localizedDisplayNames)\n .replace(/\\{\\{LOCALIZED_PROPERTY_DISPLAY_NAMES\\}\\}/g, localizedPropertyDisplayNames);\n\n return {\n path: `${options.baseModelPath}/Locales/${className}Locales.php`,\n content,\n type: 'locales',\n overwrite: true, // Always overwrite locales\n schemaName: schema.name,\n };\n}\n\n/**\n * Generate all models for the given schemas.\n */\nexport function generateModels(\n schemas: SchemaCollection,\n options?: ModelGeneratorOptions\n): GeneratedModel[] {\n const resolved = resolveOptions(options);\n const models: GeneratedModel[] = [];\n\n // Generate shared base model\n models.push(generateBaseModel(schemas, resolved, getStubContent('base-model')));\n\n // Generate HasLocalizedDisplayName trait in Traits subfolder\n models.push(generateLocalizedDisplayNameTrait(resolved, getStubContent('has-localized-display-name')));\n\n // Generate OmnifyServiceProvider with morph map\n models.push(generateServiceProvider(schemas, resolved, getStubContent('service-provider')));\n\n // Generate Omnify support class for package schema registration\n models.push(generateOmnifySupport(resolved, getStubContent('omnify-support')));\n\n // Generate Omnify sync artisan command\n models.push(generateOmnifyCommand(resolved, getStubContent('omnify-command')));\n\n // Generate models for each schema (excluding enums and hidden schemas)\n for (const schema of Object.values(schemas)) {\n if (schema.kind === 'enum') {\n continue;\n }\n\n // Skip hidden schemas (e.g., cache, jobs, sessions)\n if (schema.options?.hidden === true) {\n continue;\n }\n\n // Generate Locales class in Locales subfolder\n models.push(generateLocalesClass(schema, resolved, getStubContent('locales')));\n\n // Generate entity base model (always overwritten)\n models.push(generateEntityBaseModel(\n schema,\n schemas,\n resolved,\n getStubContent('entity-base'),\n getStubContent('entity-base-auth')\n ));\n\n // Generate user model (created once)\n models.push(generateEntityModel(schema, resolved, getStubContent('entity')));\n }\n\n return models;\n}\n\n/**\n * Get the output path for a model.\n */\nexport function getModelPath(model: GeneratedModel): string {\n return model.path;\n}\n\n/**\n * Generate provider registration for Laravel.\n * Handles both Laravel 11+ (bootstrap/providers.php) and Laravel 10- (config/app.php).\n *\n * @param existingContent - Existing file content (null if file doesn't exist)\n * @param laravelVersion - Laravel version type\n * @param laravelRoot - Laravel root directory (e.g., \"./backend\" or \"\")\n * @returns Registration result or null if already registered\n */\nexport function generateProviderRegistration(\n existingContent: string | null,\n laravelVersion: 'laravel11+' | 'laravel10-',\n laravelRoot: string = ''\n): ProviderRegistrationResult | null {\n const providerClass = 'App\\\\Providers\\\\OmnifyServiceProvider::class';\n const providerLine = ` ${providerClass},`;\n\n // Build paths with Laravel root prefix\n const bootstrapPath = laravelRoot ? `${laravelRoot}/bootstrap/providers.php` : 'bootstrap/providers.php';\n const configPath = laravelRoot ? `${laravelRoot}/config/app.php` : 'config/app.php';\n\n // Check if already registered\n if (existingContent && existingContent.includes('OmnifyServiceProvider')) {\n return {\n path: laravelVersion === 'laravel11+' ? bootstrapPath : configPath,\n content: existingContent,\n laravelVersion,\n alreadyRegistered: true,\n };\n }\n\n if (laravelVersion === 'laravel11+') {\n // Laravel 11+ uses bootstrap/providers.php\n if (existingContent) {\n // Find the closing bracket of the array and insert before it\n const lines = existingContent.split('\\n');\n const result: string[] = [];\n let inserted = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n // Find the closing ];\n if (!inserted && line.trim() === '];') {\n // Insert before closing bracket\n result.push(providerLine);\n inserted = true;\n }\n result.push(line);\n }\n\n return {\n path: bootstrapPath,\n content: result.join('\\n'),\n laravelVersion,\n alreadyRegistered: false,\n };\n } else {\n // Create new file\n return {\n path: bootstrapPath,\n content: `<?php\n\nreturn [\n App\\\\Providers\\\\AppServiceProvider::class,\n${providerLine}\n];\n`,\n laravelVersion,\n alreadyRegistered: false,\n };\n }\n } else {\n // Laravel 10- uses config/app.php\n if (existingContent) {\n // Find 'providers' => [...] and insert OmnifyServiceProvider\n // This is more complex because config/app.php has multiple arrays\n\n // Look for the providers array closing\n // Pattern: After \"App\\Providers\\...\" look for the next line with ], and insert before\n const providersSectionRegex = /'providers'\\s*=>\\s*\\[[\\s\\S]*?\\n(\\s*)\\]/m;\n const match = existingContent.match(providersSectionRegex);\n\n if (match) {\n // Find position to insert - before the closing ]\n const providersStart = existingContent.indexOf(\"'providers'\");\n if (providersStart === -1) {\n return null; // Can't find providers section\n }\n\n // Find the closing ] of providers array\n let depth = 0;\n let foundStart = false;\n let insertPos = -1;\n\n for (let i = providersStart; i < existingContent.length; i++) {\n const char = existingContent[i];\n if (char === '[') {\n foundStart = true;\n depth++;\n } else if (char === ']') {\n depth--;\n if (foundStart && depth === 0) {\n insertPos = i;\n break;\n }\n }\n }\n\n if (insertPos !== -1) {\n // Find the last provider line before closing ]\n const beforeClose = existingContent.substring(0, insertPos);\n const lastNewline = beforeClose.lastIndexOf('\\n');\n\n // Insert after last provider, before ]\n const content =\n existingContent.substring(0, lastNewline + 1) +\n providerLine + '\\n' +\n existingContent.substring(lastNewline + 1);\n\n return {\n path: configPath,\n content,\n laravelVersion,\n alreadyRegistered: false,\n };\n }\n }\n\n return null; // Couldn't parse config/app.php\n } else {\n // Can't create config/app.php from scratch - it's too complex\n return null;\n }\n }\n}\n","/**\n * Utility functions for Laravel generator.\n */\n\n/**\n * Convert a string to snake_case.\n */\nexport function toSnakeCase(str: string): string {\n return str\n .replace(/([A-Z])/g, '_$1')\n .replace(/^_/, '')\n .toLowerCase();\n}\n\n/**\n * Convert a string to PascalCase.\n */\nexport function toPascalCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n .replace(/^(.)/, (_, c) => c.toUpperCase());\n}\n\n/**\n * Convert a string to camelCase.\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Simple pluralization (English).\n */\nexport function pluralize(word: string): string {\n if (word.endsWith('y') && !['ay', 'ey', 'iy', 'oy', 'uy'].some(v => word.endsWith(v))) {\n return word.slice(0, -1) + 'ies';\n }\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') ||\n word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n return word + 's';\n}\n","/**\n * Laravel Factory Generator\n *\n * Generates Laravel factory files for Eloquent models.\n */\n\nimport type { SchemaCollection, LoadedSchema, PropertyDefinition, CustomTypeDefinition } from '@famgia/omnify-types';\nimport { toPascalCase, toSnakeCase } from '../utils.js';\n\n/**\n * Options for factory generation.\n */\nexport interface FactoryGeneratorOptions {\n /** Model namespace */\n modelNamespace?: string;\n /** Factory output path */\n factoryPath?: string;\n /** Faker locale */\n fakerLocale?: string;\n /** Custom types registered by plugins */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Generated factory output.\n */\nexport interface GeneratedFactory {\n /** Factory class name */\n name: string;\n /** Schema name this factory is for */\n schemaName: string;\n /** Output path for the factory file */\n path: string;\n /** Generated factory content */\n content: string;\n /** Whether to overwrite if exists */\n overwrite: boolean;\n}\n\n/**\n * Resolved options with defaults applied.\n */\ninterface ResolvedOptions {\n modelNamespace: string;\n factoryPath: string;\n fakerLocale: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n}\n\n/**\n * Resolves options with defaults.\n */\nfunction resolveOptions(options?: FactoryGeneratorOptions): ResolvedOptions {\n return {\n modelNamespace: options?.modelNamespace ?? 'App\\\\Models',\n factoryPath: options?.factoryPath ?? 'database/factories',\n fakerLocale: options?.fakerLocale ?? 'en_US',\n customTypes: options?.customTypes ?? new Map(),\n };\n}\n\n/**\n * Gets the factory stub content.\n */\nfunction getStubContent(): string {\n return `<?php\n\nnamespace Database\\\\Factories;\n\nuse {{MODEL_NAMESPACE}}\\\\{{MODEL_NAME}};\nuse Illuminate\\\\Database\\\\Eloquent\\\\Factories\\\\Factory;\n{{IMPORTS}}\n\n/**\n * @extends Factory<{{MODEL_NAME}}>\n */\nclass {{MODEL_NAME}}Factory extends Factory\n{\n protected $model = {{MODEL_NAME}}::class;\n\n /**\n * Define the model's default state.\n *\n * @return array<string, mixed>\n */\n public function definition(): array\n {\n return [\n{{ATTRIBUTES}}\n ];\n }\n}\n`;\n}\n\n/**\n * Generates fake data for Japanese compound types.\n * Returns array of field definitions or null if not a Japanese type.\n */\nfunction generateJapaneseCompoundFake(\n propertyName: string,\n property: PropertyDefinition,\n options: ResolvedOptions\n): string[] | null {\n const typeDef = options.customTypes.get(property.type);\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return null;\n }\n\n const snakeName = toSnakeCase(propertyName);\n const lines: string[] = [];\n const jaFaker = \"fake('ja_JP')\";\n\n switch (property.type) {\n case 'JapaneseName':\n lines.push(`'${snakeName}_lastname' => ${jaFaker}->lastName(),`);\n lines.push(`'${snakeName}_firstname' => ${jaFaker}->firstName(),`);\n lines.push(`'${snakeName}_kana_lastname' => ${jaFaker}->lastKanaName(),`);\n lines.push(`'${snakeName}_kana_firstname' => ${jaFaker}->firstKanaName(),`);\n break;\n\n case 'JapaneseAddress':\n lines.push(`'${snakeName}_postal_code' => ${jaFaker}->postcode(),`);\n lines.push(`'${snakeName}_prefecture_id' => ${jaFaker}->numberBetween(1, 47),`);\n lines.push(`'${snakeName}_address1' => ${jaFaker}->city() . ${jaFaker}->ward(),`);\n lines.push(`'${snakeName}_address2' => ${jaFaker}->streetAddress(),`);\n lines.push(`'${snakeName}_address3' => ${jaFaker}->optional()->secondaryAddress(),`);\n break;\n\n case 'JapaneseBankAccount':\n lines.push(`'${snakeName}_bank_code' => ${jaFaker}->regexify('[0-9]{4}'),`);\n lines.push(`'${snakeName}_branch_code' => ${jaFaker}->regexify('[0-9]{3}'),`);\n lines.push(`'${snakeName}_account_type' => ${jaFaker}->randomElement(['1', '2', '4']),`);\n lines.push(`'${snakeName}_account_number' => ${jaFaker}->regexify('[0-9]{7}'),`);\n lines.push(`'${snakeName}_account_holder' => ${jaFaker}->lastKanaName() . ' ' . ${jaFaker}->firstKanaName(),`);\n break;\n\n default:\n // For other compound types, generate default string fakes\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const sql = (field as any).sql;\n if (sql?.sqlType === 'TINYINT' || sql?.sqlType === 'INT' || sql?.sqlType === 'BIGINT') {\n lines.push(`'${fieldName}' => fake()->numberBetween(1, 100),`);\n } else {\n lines.push(`'${fieldName}' => fake()->words(2, true),`);\n }\n }\n break;\n }\n\n return lines;\n}\n\n/**\n * Generates fake data for Japanese non-compound types.\n */\nfunction generateJapaneseSimpleFake(\n propertyName: string,\n property: PropertyDefinition\n): string | null {\n const snakeName = toSnakeCase(propertyName);\n const jaFaker = \"fake('ja_JP')\";\n\n switch (property.type) {\n case 'JapanesePhone':\n return `'${snakeName}' => ${jaFaker}->phoneNumber(),`;\n\n case 'JapanesePostalCode':\n return `'${snakeName}' => ${jaFaker}->postcode(),`;\n\n default:\n return null;\n }\n}\n\n/**\n * Generates factory fake data for a property based on its type and name.\n */\nfunction generateFakeData(\n propertyName: string,\n property: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string | null {\n const type = property.type;\n\n // Skip system fields\n if (['deleted_at', 'created_at', 'updated_at'].includes(propertyName)) {\n return null;\n }\n\n // Skip association properties (foreign keys are handled separately)\n if (type === 'Association') {\n return null;\n }\n\n // Check for Japanese non-compound types first\n const japaneseFake = generateJapaneseSimpleFake(propertyName, property);\n if (japaneseFake) {\n return japaneseFake;\n }\n\n // Handle different property types\n switch (type) {\n case 'String':\n return generateStringFake(propertyName, property);\n\n case 'Email':\n return `'${propertyName}' => fake()->unique()->safeEmail(),`;\n\n case 'Password':\n return `'${propertyName}' => bcrypt('password'),`;\n\n case 'Int':\n case 'BigInt':\n return generateIntFake(propertyName, property);\n\n case 'Float':\n case 'Decimal':\n return `'${propertyName}' => fake()->randomFloat(2, 1, 10000),`;\n\n case 'Boolean':\n return `'${propertyName}' => fake()->boolean(),`;\n\n case 'Text':\n return `'${propertyName}' => fake()->paragraphs(3, true),`;\n\n case 'LongText':\n return `'${propertyName}' => fake()->paragraphs(5, true),`;\n\n case 'Date':\n return `'${propertyName}' => fake()->date(),`;\n\n case 'Time':\n return `'${propertyName}' => fake()->time(),`;\n\n case 'Timestamp':\n case 'DateTime':\n return `'${propertyName}' => fake()->dateTime(),`;\n\n case 'Json':\n return `'${propertyName}' => [],`;\n\n case 'Enum':\n return generateEnumFake(propertyName, property);\n\n case 'EnumRef':\n return generateEnumRefFake(propertyName, property, schemas);\n\n default:\n // Default to sentence for unknown types\n return `'${propertyName}' => fake()->sentence(),`;\n }\n}\n\n/**\n * Generates fake data for String type based on property name patterns.\n */\nfunction generateStringFake(propertyName: string, property: PropertyDefinition): string {\n // Handle special field names\n if (propertyName === 'slug') {\n return `'${propertyName}' => fake()->unique()->slug(),`;\n }\n\n if (propertyName === 'uuid' || propertyName === 'uid') {\n return `'${propertyName}' => (string) \\\\Illuminate\\\\Support\\\\Str::uuid(),`;\n }\n\n if (propertyName.includes('email')) {\n return `'${propertyName}' => fake()->unique()->safeEmail(),`;\n }\n\n if (propertyName.includes('phone')) {\n return `'${propertyName}' => fake()->phoneNumber(),`;\n }\n\n // Check image/photo/avatar before url to handle cases like 'avatar_url'\n if (propertyName.includes('image') || propertyName.includes('photo') || propertyName.includes('avatar')) {\n return `'${propertyName}' => fake()->imageUrl(),`;\n }\n\n if (propertyName.includes('url') || propertyName.includes('website')) {\n return `'${propertyName}' => fake()->url(),`;\n }\n\n if (propertyName.includes('path') || propertyName.includes('file')) {\n return `'${propertyName}' => 'uploads/' . fake()->uuid() . '.jpg',`;\n }\n\n if (propertyName === 'name' || propertyName === 'title') {\n return `'${propertyName}' => fake()->sentence(3),`;\n }\n\n if (propertyName.includes('name')) {\n return `'${propertyName}' => fake()->name(),`;\n }\n\n if (propertyName.includes('address')) {\n return `'${propertyName}' => fake()->address(),`;\n }\n\n if (propertyName.includes('city')) {\n return `'${propertyName}' => fake()->city(),`;\n }\n\n if (propertyName.includes('country')) {\n return `'${propertyName}' => fake()->country(),`;\n }\n\n if (propertyName.includes('zip') || propertyName.includes('postal')) {\n return `'${propertyName}' => fake()->postcode(),`;\n }\n\n if (propertyName.includes('color')) {\n return `'${propertyName}' => fake()->hexColor(),`;\n }\n\n if (propertyName.includes('token') || propertyName.includes('secret') || propertyName.includes('key')) {\n return `'${propertyName}' => \\\\Illuminate\\\\Support\\\\Str::random(32),`;\n }\n\n if (propertyName.includes('code')) {\n return `'${propertyName}' => fake()->unique()->regexify('[A-Z0-9]{8}'),`;\n }\n\n // Default string\n const length = (property as { length?: number }).length;\n if (length && length <= 50) {\n return `'${propertyName}' => fake()->words(3, true),`;\n }\n\n return `'${propertyName}' => fake()->sentence(),`;\n}\n\n/**\n * Generates fake data for Integer types.\n */\nfunction generateIntFake(propertyName: string, property: PropertyDefinition): string {\n if (propertyName.includes('count') || propertyName.includes('quantity')) {\n return `'${propertyName}' => fake()->numberBetween(0, 100),`;\n }\n\n if (propertyName.includes('price') || propertyName.includes('amount') || propertyName.includes('cost')) {\n return `'${propertyName}' => fake()->numberBetween(100, 10000),`;\n }\n\n if (propertyName.includes('order') || propertyName.includes('sort') || propertyName.includes('position')) {\n return `'${propertyName}' => fake()->numberBetween(1, 100),`;\n }\n\n if (propertyName.includes('age')) {\n return `'${propertyName}' => fake()->numberBetween(18, 80),`;\n }\n\n if (propertyName.includes('year')) {\n return `'${propertyName}' => fake()->year(),`;\n }\n\n return `'${propertyName}' => fake()->numberBetween(1, 1000),`;\n}\n\n/**\n * Generates fake data for inline Enum type.\n */\nfunction generateEnumFake(propertyName: string, property: PropertyDefinition): string {\n const enumValues = (property as { enum?: readonly (string | { value: string })[] }).enum;\n if (!enumValues || enumValues.length === 0) {\n return `'${propertyName}' => null,`;\n }\n\n // Extract values (handle both string and object formats)\n const values = enumValues.map(v => typeof v === 'string' ? v : v.value);\n const valuesStr = values.map(v => `'${v}'`).join(', ');\n\n return `'${propertyName}' => fake()->randomElement([${valuesStr}]),`;\n}\n\n/**\n * Generates fake data for EnumRef type.\n */\nfunction generateEnumRefFake(\n propertyName: string,\n property: PropertyDefinition,\n schemas: SchemaCollection\n): string {\n const enumName = (property as { enum?: string }).enum;\n if (!enumName) {\n return `'${propertyName}' => null,`;\n }\n\n const enumSchema = schemas[enumName];\n if (!enumSchema || enumSchema.kind !== 'enum' || !enumSchema.values) {\n return `'${propertyName}' => null,`;\n }\n\n const valuesStr = enumSchema.values.map(v => `'${v}'`).join(', ');\n return `'${propertyName}' => fake()->randomElement([${valuesStr}]),`;\n}\n\n/**\n * Generates factory data for association (foreign key).\n */\nfunction generateAssociationFake(\n propertyName: string,\n property: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n modelNamespace: string\n): { fake: string; import?: string } | null {\n if (property.type !== 'Association') {\n return null;\n }\n\n const relation = (property as { relation?: string }).relation;\n const target = (property as { target?: string }).target;\n\n // Only handle ManyToOne (belongsTo) relationships\n if (relation !== 'ManyToOne' || !target) {\n return null;\n }\n\n const foreignKey = `${toSnakeCase(propertyName)}_id`;\n const isNullable = (property as { nullable?: boolean }).nullable ?? false;\n const targetSchema = schemas[target];\n\n // Check if target schema exists\n if (!targetSchema) {\n return null;\n }\n\n // Generate the fake data\n let fake: string;\n if (isNullable) {\n fake = `'${foreignKey}' => ${target}::query()->inRandomOrder()->first()?->id,`;\n } else {\n fake = `'${foreignKey}' => ${target}::query()->inRandomOrder()->first()?->id ?? ${target}::factory()->create()->id,`;\n }\n\n // Add import if target is different from current schema\n let importStatement: string | undefined;\n if (target !== schema.name) {\n importStatement = `use ${modelNamespace}\\\\${target};`;\n }\n\n return { fake, import: importStatement };\n}\n\n/**\n * Generates a factory for a single schema.\n */\nfunction generateFactory(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n stubContent: string\n): GeneratedFactory | null {\n // Skip enum schemas\n if (schema.kind === 'enum') {\n return null;\n }\n\n // Skip hidden schemas (system tables like cache, jobs, sessions)\n if (schema.options?.hidden) {\n return null;\n }\n\n const modelName = toPascalCase(schema.name);\n const factoryName = `${modelName}Factory`;\n\n const attributes: string[] = [];\n const imports: string[] = [];\n\n // Process properties\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n // Handle associations (foreign keys)\n if (prop.type === 'Association') {\n const assocResult = generateAssociationFake(propName, prop, schema, schemas, options.modelNamespace);\n if (assocResult) {\n attributes.push(assocResult.fake);\n if (assocResult.import) {\n imports.push(assocResult.import);\n }\n }\n continue;\n }\n\n // Handle Japanese compound types (JapaneseName, JapaneseAddress, JapaneseBankAccount)\n const compoundFakes = generateJapaneseCompoundFake(propName, prop, options);\n if (compoundFakes) {\n attributes.push(...compoundFakes);\n continue;\n }\n\n // Handle regular properties\n const fake = generateFakeData(propName, prop, schema, schemas, options);\n if (fake) {\n attributes.push(fake);\n }\n }\n }\n\n // Build the factory content\n let content = stubContent;\n content = content.replace(/\\{\\{MODEL_NAMESPACE\\}\\}/g, options.modelNamespace);\n content = content.replace(/\\{\\{MODEL_NAME\\}\\}/g, modelName);\n\n // Format imports\n const uniqueImports = [...new Set(imports)];\n const importsStr = uniqueImports.length > 0\n ? '\\n' + uniqueImports.join('\\n')\n : '';\n content = content.replace(/\\{\\{IMPORTS\\}\\}/g, importsStr);\n\n // Format attributes with proper indentation\n const attributesStr = attributes.length > 0\n ? attributes.map(a => ` ${a}`).join('\\n')\n : '';\n content = content.replace(/\\{\\{ATTRIBUTES\\}\\}/g, attributesStr);\n\n return {\n name: factoryName,\n schemaName: schema.name,\n path: `${options.factoryPath}/${factoryName}.php`,\n content,\n overwrite: false, // Factories should not overwrite existing files\n };\n}\n\n/**\n * Generates factories for all schemas.\n */\nexport function generateFactories(\n schemas: SchemaCollection,\n options?: FactoryGeneratorOptions\n): GeneratedFactory[] {\n const resolved = resolveOptions(options);\n const stubContent = getStubContent();\n const factories: GeneratedFactory[] = [];\n\n for (const schema of Object.values(schemas)) {\n const factory = generateFactory(schema, schemas, resolved, stubContent);\n if (factory) {\n factories.push(factory);\n }\n }\n\n return factories;\n}\n\n/**\n * Gets the output path for a factory.\n */\nexport function getFactoryPath(factory: GeneratedFactory): string {\n return factory.path;\n}\n","/**\n * @famgia/omnify-laravel - Plugin\n *\n * Plugin for generating Laravel migration files and Eloquent models from Omnify schemas.\n *\n * @example Basic usage (Laravel at project root)\n * ```typescript\n * import { defineConfig } from '@famgia/omnify';\n * import laravel from '@famgia/omnify-laravel/plugin';\n *\n * export default defineConfig({\n * plugins: [laravel()], // Uses all defaults\n * });\n * ```\n *\n * @example Monorepo (Laravel in ./backend/)\n * ```typescript\n * import { defineConfig } from '@famgia/omnify';\n * import laravel from '@famgia/omnify-laravel/plugin';\n *\n * export default defineConfig({\n * plugins: [\n * laravel({\n * base: './backend/', // All paths relative to this\n * generateRequests: true,\n * generateResources: true,\n * }),\n * ],\n * });\n * ```\n */\n\nimport { readFileSync, existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { OmnifyPlugin, GeneratorOutput, GeneratorContext, PluginConfigSchema, SchemaChange } from '@famgia/omnify-types';\nimport { generateMigrations, getMigrationPath, generateMigrationsFromChanges, type MigrationOptions } from './migration/index.js';\nimport { generateModels, getModelPath, generateProviderRegistration, type ModelGeneratorOptions } from './model/index.js';\nimport { generateFactories, getFactoryPath, type FactoryGeneratorOptions } from './factory/index.js';\nimport { generateRequests, getRequestPath, type RequestGeneratorOptions } from './request/index.js';\nimport { generateResources, getResourcePath, type ResourceGeneratorOptions } from './resource/index.js';\nimport { generateAIGuides, shouldGenerateAIGuides } from './ai-guides/index.js';\n\n/**\n * Infer Laravel root directory from providersPath.\n * E.g., \"./backend/app/Providers\" → \"./backend\"\n * E.g., \"app/Providers\" → \"\"\n */\nfunction inferLaravelRoot(providersPath: string): string {\n // Remove app/Providers suffix to get Laravel root\n const normalized = providersPath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.*)\\/app\\/Providers\\/?$/i);\n if (match && match[1]) {\n return match[1];\n }\n // Check for OmnifyBase pattern: ./backend/app/Providers/OmnifyBase\n const baseMatch = normalized.match(/^(.*)\\/app\\/Providers\\/OmnifyBase\\/?$/i);\n if (baseMatch && baseMatch[1]) {\n return baseMatch[1];\n }\n return '';\n}\n\n/**\n * Scans a directory for existing migration files and returns tables that already have CREATE migrations.\n */\nfunction getExistingMigrationTables(migrationsDir: string): Set<string> {\n const existingTables = new Set<string>();\n\n if (!existsSync(migrationsDir)) {\n return existingTables;\n }\n\n try {\n const files = readdirSync(migrationsDir);\n // Match pattern: YYYY_MM_DD_HHMMSS_create_<table>_table.php\n const createMigrationPattern = /^\\d{4}_\\d{2}_\\d{2}_\\d{6}_create_(.+)_table\\.php$/;\n\n for (const file of files) {\n const match = file.match(createMigrationPattern);\n if (match) {\n existingTables.add(match[1]); // table name\n }\n }\n } catch {\n // Ignore errors reading directory\n }\n\n return existingTables;\n}\n\n/**\n * Configuration schema for Laravel plugin UI settings\n */\nconst LARAVEL_CONFIG_SCHEMA: PluginConfigSchema = {\n fields: [\n {\n key: 'base',\n type: 'path',\n label: 'Laravel Base Path',\n description: 'Base directory for Laravel project (e.g., \"./backend/\" for monorepo). All other paths are relative to this.',\n default: '',\n group: 'output',\n },\n {\n key: 'migrationsPath',\n type: 'path',\n label: 'Migrations Path',\n description: 'Directory for Laravel migration files (relative to base)',\n default: 'database/migrations/omnify',\n group: 'output',\n },\n {\n key: 'modelsPath',\n type: 'path',\n label: 'Models Path',\n description: 'Directory for user-editable model files (relative to base)',\n default: 'app/Models',\n group: 'output',\n },\n {\n key: 'baseModelsPath',\n type: 'path',\n label: 'Base Models Path',\n description: 'Directory for auto-generated base model files',\n default: 'app/Models/OmnifyBase',\n group: 'output',\n },\n {\n key: 'providersPath',\n type: 'path',\n label: 'Providers Path',\n description: 'Directory for Laravel service provider files',\n default: 'app/Providers',\n group: 'output',\n },\n {\n key: 'generateModels',\n type: 'boolean',\n label: 'Generate Models',\n description: 'Generate Eloquent model classes',\n default: true,\n group: 'options',\n },\n {\n key: 'factoriesPath',\n type: 'path',\n label: 'Factories Path',\n description: 'Directory for Laravel factory files',\n default: 'database/factories',\n group: 'output',\n },\n {\n key: 'generateFactories',\n type: 'boolean',\n label: 'Generate Factories',\n description: 'Generate Laravel factory classes for testing',\n default: true,\n group: 'options',\n },\n {\n key: 'connection',\n type: 'string',\n label: 'Database Connection',\n description: 'Laravel database connection name (optional)',\n placeholder: 'mysql',\n group: 'options',\n },\n {\n key: 'requestsPath',\n type: 'path',\n label: 'Requests Path',\n description: 'Directory for user-editable FormRequest files',\n default: 'app/Http/Requests',\n group: 'output',\n },\n {\n key: 'baseRequestsPath',\n type: 'path',\n label: 'Base Requests Path',\n description: 'Directory for auto-generated base FormRequest files',\n default: 'app/Http/Requests/OmnifyBase',\n group: 'output',\n },\n {\n key: 'generateRequests',\n type: 'boolean',\n label: 'Generate Requests',\n description: 'Generate Laravel FormRequest classes for validation',\n default: false,\n group: 'options',\n },\n {\n key: 'resourcesPath',\n type: 'path',\n label: 'Resources Path',\n description: 'Directory for user-editable API Resource files',\n default: 'app/Http/Resources',\n group: 'output',\n },\n {\n key: 'baseResourcesPath',\n type: 'path',\n label: 'Base Resources Path',\n description: 'Directory for auto-generated base API Resource files',\n default: 'app/Http/Resources/OmnifyBase',\n group: 'output',\n },\n {\n key: 'generateResources',\n type: 'boolean',\n label: 'Generate Resources',\n description: 'Generate Laravel API Resource classes',\n default: false,\n group: 'options',\n },\n ],\n};\n\n/**\n * Options for the Laravel plugin.\n */\nexport interface LaravelPluginOptions {\n /**\n * Base directory for Laravel project (relative to project root).\n * All other paths will be relative to this base.\n * \n * @default '' (project root)\n * @example './backend/' for monorepo with Laravel in backend folder\n */\n base?: string;\n\n /**\n * Path for Laravel migration files (relative to base).\n * @default 'database/migrations/omnify'\n */\n migrationsPath?: string;\n\n /**\n * Path for user-editable model files (relative to base).\n * @default 'app/Models'\n */\n modelsPath?: string;\n\n /**\n * Path for auto-generated base model files (relative to base).\n * @default 'app/Models/OmnifyBase'\n */\n baseModelsPath?: string;\n\n /**\n * Path for Laravel service provider files (relative to base).\n * @default 'app/Providers'\n */\n providersPath?: string;\n\n /**\n * Model namespace.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Base model namespace.\n * @default 'App\\\\Models\\\\OmnifyBase'\n */\n baseModelNamespace?: string;\n\n /**\n * Whether to generate Eloquent models.\n * @default true\n */\n generateModels?: boolean;\n\n /**\n * Path for Laravel factory files.\n * @default 'database/factories'\n */\n factoriesPath?: string;\n\n /**\n * Whether to generate Laravel factories.\n * @default true\n */\n generateFactories?: boolean;\n\n /**\n * Faker locale for factory data.\n * @default 'en_US'\n */\n fakerLocale?: string;\n\n /**\n * Database connection name for migrations.\n */\n connection?: string;\n\n /**\n * Custom timestamp for migration file names (mainly for testing).\n */\n timestamp?: string;\n\n /**\n * Path for user-editable FormRequest files.\n * @default 'app/Http/Requests'\n */\n requestsPath?: string;\n\n /**\n * Path for auto-generated base FormRequest files.\n * @default 'app/Http/Requests/OmnifyBase'\n */\n baseRequestsPath?: string;\n\n /**\n * Request namespace.\n * @default 'App\\\\Http\\\\Requests'\n */\n requestNamespace?: string;\n\n /**\n * Base request namespace.\n * @default 'App\\\\Http\\\\Requests\\\\OmnifyBase'\n */\n baseRequestNamespace?: string;\n\n /**\n * Whether to generate Laravel FormRequest classes.\n * @default true\n */\n generateRequests?: boolean;\n\n /**\n * Path for user-editable API Resource files.\n * @default 'app/Http/Resources'\n */\n resourcesPath?: string;\n\n /**\n * Path for auto-generated base API Resource files.\n * @default 'app/Http/Resources/OmnifyBase'\n */\n baseResourcesPath?: string;\n\n /**\n * Resource namespace.\n * @default 'App\\\\Http\\\\Resources'\n */\n resourceNamespace?: string;\n\n /**\n * Base resource namespace.\n * @default 'App\\\\Http\\\\Resources\\\\OmnifyBase'\n */\n baseResourceNamespace?: string;\n\n /**\n * Whether to generate Laravel API Resource classes.\n * @default true\n */\n generateResources?: boolean;\n}\n\n/**\n * Resolved options with defaults applied.\n */\ninterface ResolvedOptions {\n migrationsPath: string;\n modelsPath: string;\n baseModelsPath: string;\n providersPath: string;\n modelNamespace: string;\n baseModelNamespace: string;\n generateModels: boolean;\n factoriesPath: string;\n generateFactories: boolean;\n fakerLocale: string;\n connection: string | undefined;\n timestamp: string | undefined;\n requestsPath: string;\n baseRequestsPath: string;\n requestNamespace: string;\n baseRequestNamespace: string;\n generateRequests: boolean;\n resourcesPath: string;\n baseResourcesPath: string;\n resourceNamespace: string;\n baseResourceNamespace: string;\n generateResources: boolean;\n}\n\n/**\n * Resolves options with defaults.\n */\n/**\n * Joins base path with relative path, normalizing slashes.\n */\nfunction joinPath(base: string, relativePath: string): string {\n if (!base) return relativePath;\n // Normalize: remove trailing slash from base, ensure no double slashes\n const normalizedBase = base.replace(/\\/+$/, '');\n return `${normalizedBase}/${relativePath}`;\n}\n\nfunction resolveOptions(options?: LaravelPluginOptions): ResolvedOptions {\n const base = options?.base ?? '';\n\n return {\n migrationsPath: options?.migrationsPath ?? joinPath(base, 'database/migrations/omnify'),\n modelsPath: options?.modelsPath ?? joinPath(base, 'app/Models'),\n baseModelsPath: options?.baseModelsPath ?? joinPath(base, 'app/Models/OmnifyBase'),\n providersPath: options?.providersPath ?? joinPath(base, 'app/Providers'),\n modelNamespace: options?.modelNamespace ?? 'App\\\\Models',\n baseModelNamespace: options?.baseModelNamespace ?? 'App\\\\Models\\\\OmnifyBase',\n generateModels: options?.generateModels ?? true,\n factoriesPath: options?.factoriesPath ?? joinPath(base, 'database/factories'),\n generateFactories: options?.generateFactories ?? true,\n fakerLocale: options?.fakerLocale ?? 'en_US',\n connection: options?.connection,\n timestamp: options?.timestamp,\n requestsPath: options?.requestsPath ?? joinPath(base, 'app/Http/Requests'),\n baseRequestsPath: options?.baseRequestsPath ?? joinPath(base, 'app/Http/Requests/OmnifyBase'),\n requestNamespace: options?.requestNamespace ?? 'App\\\\Http\\\\Requests',\n baseRequestNamespace: options?.baseRequestNamespace ?? 'App\\\\Http\\\\Requests\\\\OmnifyBase',\n generateRequests: options?.generateRequests ?? true,\n resourcesPath: options?.resourcesPath ?? joinPath(base, 'app/Http/Resources'),\n baseResourcesPath: options?.baseResourcesPath ?? joinPath(base, 'app/Http/Resources/OmnifyBase'),\n resourceNamespace: options?.resourceNamespace ?? 'App\\\\Http\\\\Resources',\n baseResourceNamespace: options?.baseResourceNamespace ?? 'App\\\\Http\\\\Resources\\\\OmnifyBase',\n generateResources: options?.generateResources ?? true,\n };\n}\n\n/**\n * Creates the Laravel plugin with the specified options.\n *\n * @param options - Plugin configuration options\n * @returns OmnifyPlugin configured for Laravel migrations and models\n */\nexport default function laravelPlugin(options?: LaravelPluginOptions): OmnifyPlugin {\n const resolved = resolveOptions(options);\n\n // Build generators array\n const migrationGenerator = {\n name: 'laravel-migrations',\n description: 'Generate Laravel migration files',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const migrationOptions: MigrationOptions = {\n connection: resolved.connection,\n timestamp: resolved.timestamp,\n customTypes: ctx.customTypes,\n };\n\n const outputs: GeneratorOutput[] = [];\n const migrationsDir = join(ctx.cwd, resolved.migrationsPath);\n const existingTables = getExistingMigrationTables(migrationsDir);\n\n // If we have change information (including empty array), use it for smarter migration generation\n // undefined = no change info → fallback to generating all\n // empty array = no changes detected → no migrations needed\n if (ctx.changes !== undefined) {\n // Empty changes array = no changes, no migrations needed\n if (ctx.changes.length === 0) {\n return outputs;\n }\n\n // Generate CREATE migrations only for added schemas\n const addedSchemaNames = new Set(\n ctx.changes\n .filter((c) => c.changeType === 'added')\n .map((c) => c.schemaName)\n );\n\n if (addedSchemaNames.size > 0) {\n const addedSchemas = Object.fromEntries(\n Object.entries(ctx.schemas).filter(([name]) => addedSchemaNames.has(name))\n );\n\n const createMigrations = generateMigrations(addedSchemas, migrationOptions);\n\n for (const migration of createMigrations) {\n const tableName = migration.tables[0];\n // Skip if table already has a create migration\n if (existingTables.has(tableName)) {\n ctx.logger.debug(`Skipping CREATE for ${tableName} (already exists)`);\n continue;\n }\n\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName,\n migrationType: 'create',\n },\n });\n }\n }\n\n // Generate ALTER/DROP migrations for modified/removed schemas\n const alterChanges = ctx.changes.filter(\n (c) => c.changeType === 'modified' || c.changeType === 'removed'\n );\n\n if (alterChanges.length > 0) {\n // Convert SchemaChange to the format expected by alter-generator\n const alterMigrations = generateMigrationsFromChanges(\n alterChanges as unknown as import('@famgia/omnify-atlas').SchemaChange[],\n migrationOptions\n );\n\n for (const migration of alterMigrations) {\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName: migration.tables[0],\n migrationType: migration.type,\n },\n });\n }\n }\n } else {\n // No change info - generate CREATE migrations for all schemas\n // but skip tables that already have migrations (deduplication)\n const migrations = generateMigrations(ctx.schemas, migrationOptions);\n\n for (const migration of migrations) {\n const tableName = migration.tables[0];\n if (migration.type === 'create' && existingTables.has(tableName)) {\n ctx.logger.debug(`Skipping migration for ${tableName} (already exists)`);\n continue;\n }\n\n outputs.push({\n path: getMigrationPath(migration, resolved.migrationsPath),\n content: migration.content,\n type: 'migration' as const,\n metadata: {\n tableName,\n migrationType: migration.type,\n },\n });\n }\n }\n\n return outputs;\n },\n };\n\n const modelGenerator = {\n name: 'laravel-models',\n description: 'Generate Eloquent model classes',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const modelOptions: ModelGeneratorOptions = {\n modelNamespace: resolved.modelNamespace,\n baseModelNamespace: resolved.baseModelNamespace,\n modelPath: resolved.modelsPath,\n baseModelPath: resolved.baseModelsPath,\n providersPath: resolved.providersPath,\n customTypes: ctx.customTypes,\n };\n\n const models = generateModels(ctx.schemas, modelOptions);\n const outputs: GeneratorOutput[] = models.map((model) => ({\n path: getModelPath(model),\n content: model.content,\n type: 'model' as const,\n // Skip writing user models if they already exist\n skipIfExists: !model.overwrite,\n metadata: {\n modelType: model.type,\n schemaName: model.schemaName,\n },\n }));\n\n // Generate provider registration\n // Check for Laravel 11+ (bootstrap/providers.php) or Laravel 10- (config/app.php)\n // Infer Laravel root from providersPath (e.g., \"./backend/app/Providers\" → \"./backend\")\n const laravelRoot = inferLaravelRoot(resolved.providersPath);\n const bootstrapProvidersRelPath = laravelRoot ? `${laravelRoot}/bootstrap/providers.php` : 'bootstrap/providers.php';\n const configAppRelPath = laravelRoot ? `${laravelRoot}/config/app.php` : 'config/app.php';\n const bootstrapProvidersPath = join(ctx.cwd, bootstrapProvidersRelPath);\n const configAppPath = join(ctx.cwd, configAppRelPath);\n\n let existingContent: string | null = null;\n let laravelVersion: 'laravel11+' | 'laravel10-';\n\n if (existsSync(bootstrapProvidersPath)) {\n // Laravel 11+ with bootstrap/providers.php\n laravelVersion = 'laravel11+';\n try {\n existingContent = readFileSync(bootstrapProvidersPath, 'utf-8');\n } catch {\n existingContent = null;\n }\n } else if (existsSync(configAppPath)) {\n // Check if config/app.php has a 'providers' array (Laravel 10-)\n // or is Laravel 11+ format (no providers array)\n try {\n const configContent = readFileSync(configAppPath, 'utf-8');\n if (/'providers'\\s*=>\\s*\\[/.test(configContent)) {\n // Laravel 10- with providers array in config/app.php\n laravelVersion = 'laravel10-';\n existingContent = configContent;\n } else {\n // Laravel 11+ format (config/app.php exists but no providers array)\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n } catch {\n // Assume Laravel 11+ if can't read config\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n } else {\n // Assume Laravel 11+ for new projects\n laravelVersion = 'laravel11+';\n existingContent = null;\n }\n\n const registration = generateProviderRegistration(existingContent, laravelVersion, laravelRoot);\n\n if (registration && !registration.alreadyRegistered) {\n outputs.push({\n path: registration.path,\n content: registration.content,\n type: 'other' as const,\n skipIfExists: false, // We want to modify the file\n metadata: {\n registrationType: 'provider-registration',\n laravelVersion: registration.laravelVersion,\n },\n });\n ctx.logger.info(`OmnifyServiceProvider will be registered in ${registration.path}`);\n } else if (registration?.alreadyRegistered) {\n ctx.logger.info('OmnifyServiceProvider is already registered');\n }\n\n return outputs;\n },\n };\n\n const factoryGenerator = {\n name: 'laravel-factories',\n description: 'Generate Laravel factory classes for testing',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const factoryOptions: FactoryGeneratorOptions = {\n modelNamespace: resolved.modelNamespace,\n factoryPath: resolved.factoriesPath,\n fakerLocale: resolved.fakerLocale,\n customTypes: ctx.customTypes,\n };\n\n const factories = generateFactories(ctx.schemas, factoryOptions);\n\n return factories.map((factory) => ({\n path: getFactoryPath(factory),\n content: factory.content,\n type: 'factory' as const,\n // Skip writing factories if they already exist (allow customization)\n skipIfExists: !factory.overwrite,\n metadata: {\n factoryName: factory.name,\n schemaName: factory.schemaName,\n },\n }));\n },\n };\n\n const requestGenerator = {\n name: 'laravel-requests',\n description: 'Generate Laravel FormRequest classes for validation',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const requestOptions: RequestGeneratorOptions = {\n requestNamespace: resolved.requestNamespace,\n baseRequestNamespace: resolved.baseRequestNamespace,\n requestPath: resolved.requestsPath,\n baseRequestPath: resolved.baseRequestsPath,\n modelNamespace: resolved.modelNamespace,\n customTypes: ctx.customTypes,\n };\n\n const requests = generateRequests(ctx.schemas, requestOptions);\n\n return requests.map((request) => ({\n path: getRequestPath(request),\n content: request.content,\n type: 'other' as const,\n // Skip writing user requests if they already exist\n skipIfExists: !request.overwrite,\n metadata: {\n requestType: request.type,\n schemaName: request.schemaName,\n module: request.module,\n },\n }));\n },\n };\n\n const resourceGenerator = {\n name: 'laravel-resources',\n description: 'Generate Laravel API Resource classes',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n const resourceOptions: ResourceGeneratorOptions = {\n resourceNamespace: resolved.resourceNamespace,\n baseResourceNamespace: resolved.baseResourceNamespace,\n resourcePath: resolved.resourcesPath,\n baseResourcePath: resolved.baseResourcesPath,\n customTypes: ctx.customTypes,\n };\n\n const resources = generateResources(ctx.schemas, resourceOptions);\n\n return resources.map((resource) => ({\n path: getResourcePath(resource),\n content: resource.content,\n type: 'other' as const,\n // Skip writing user resources if they already exist\n skipIfExists: !resource.overwrite,\n metadata: {\n resourceType: resource.type,\n schemaName: resource.schemaName,\n module: resource.module,\n },\n }));\n },\n };\n\n const aiGuidesGenerator = {\n name: 'laravel-ai-guides',\n description: 'Generate AI assistant guides (Claude, Cursor) for Laravel development',\n\n generate: async (ctx: GeneratorContext): Promise<GeneratorOutput[]> => {\n // Only generate if guides don't exist\n if (!shouldGenerateAIGuides(ctx.cwd)) {\n ctx.logger.debug('AI guides already exist, skipping');\n return [];\n }\n\n const result = generateAIGuides(ctx.cwd, {\n modelsPath: resolved.modelsPath,\n migrationsPath: resolved.migrationsPath,\n laravelBasePath: 'app',\n });\n\n const claudeTotal = result.claudeGuides + result.claudeRules + result.claudeChecklists + result.claudeWorkflows + result.claudeAgents + result.claudeOmnify;\n ctx.logger.info(`Generated ${claudeTotal} Claude files, ${result.cursorRules} Cursor rules`);\n\n // Return empty outputs since files are written directly by generateAIGuides\n // This is because the files go to .claude/ and .cursor/ which are outside normal output\n return [];\n },\n };\n\n // Build generators array based on options\n const generators = [migrationGenerator];\n if (resolved.generateModels) {\n generators.push(modelGenerator);\n }\n if (resolved.generateFactories) {\n generators.push(factoryGenerator);\n }\n if (resolved.generateRequests) {\n generators.push(requestGenerator);\n }\n if (resolved.generateResources) {\n generators.push(resourceGenerator);\n }\n\n // Always add AI guides generator\n generators.push(aiGuidesGenerator);\n\n return {\n name: '@famgia/omnify-laravel',\n version: '0.0.14',\n configSchema: LARAVEL_CONFIG_SCHEMA,\n generators,\n };\n}\n\n// Named export for flexibility\nexport { laravelPlugin };\n","/**\n * Laravel FormRequest Generator\n *\n * Generates Laravel FormRequest classes from Omnify schemas.\n * Creates base requests (auto-generated) and user requests (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition, AssociationDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { pluralize, toSnakeCase, toPascalCase } from '../utils.js';\n\n/**\n * Options for request generation.\n */\nexport interface RequestGeneratorOptions {\n /**\n * Base request namespace.\n * @default 'App\\\\Http\\\\Requests\\\\OmnifyBase'\n */\n baseRequestNamespace?: string;\n\n /**\n * User request namespace.\n * @default 'App\\\\Http\\\\Requests'\n */\n requestNamespace?: string;\n\n /**\n * Output path for base requests.\n * @default 'app/Http/Requests/OmnifyBase'\n */\n baseRequestPath?: string;\n\n /**\n * Output path for user requests.\n * @default 'app/Http/Requests'\n */\n requestPath?: string;\n\n /**\n * Model namespace for exists rules.\n * @default 'App\\\\Models'\n */\n modelNamespace?: string;\n\n /**\n * Custom types registered by plugins.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n\n /**\n * Locale for displayName (used in attributes).\n * @default 'en'\n */\n locale?: string;\n}\n\n/**\n * Generated request output.\n */\nexport interface GeneratedRequest {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Request type */\n type: 'store-base' | 'update-base' | 'store' | 'update';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n /** Module name (from schema path or empty) */\n module: string;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseRequestNamespace: string;\n requestNamespace: string;\n baseRequestPath: string;\n requestPath: string;\n modelNamespace: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n locale: string;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseRequestNamespace: 'App\\\\Http\\\\Requests\\\\OmnifyBase',\n requestNamespace: 'App\\\\Http\\\\Requests',\n baseRequestPath: 'app/Http/Requests/OmnifyBase',\n requestPath: 'app/Http/Requests',\n modelNamespace: 'App\\\\Models',\n customTypes: new Map(),\n locale: 'en',\n};\n\n/**\n * Fields to skip when generating validation rules.\n */\nconst SKIP_FIELDS = new Set([\n 'id',\n 'created_at',\n 'updated_at',\n 'deleted_at',\n 'remember_token',\n 'email_verified_at',\n]);\n\n/**\n * OpenAPI property definition for requests.\n */\ninterface RequestOpenApiProperty {\n property: string;\n type: string;\n format?: string;\n maxLength?: number;\n minLength?: number;\n nullable?: boolean;\n enum?: string[];\n example?: string | number | boolean;\n}\n\n/**\n * Get example value based on field name pattern.\n */\nfunction getExampleValue(fieldName: string, type: string): string | number | boolean | undefined {\n // Japanese name patterns\n if (fieldName.endsWith('_lastname') && !fieldName.includes('kana')) {\n return '田中';\n }\n if (fieldName.endsWith('_firstname') && !fieldName.includes('kana')) {\n return '太郎';\n }\n if (fieldName.includes('kana_lastname') || fieldName.endsWith('_kana_lastname')) {\n return 'タナカ';\n }\n if (fieldName.includes('kana_firstname') || fieldName.endsWith('_kana_firstname')) {\n return 'タロウ';\n }\n\n // Email\n if (fieldName.includes('email')) {\n return 'user@example.com';\n }\n\n // Password\n if (fieldName.includes('password')) {\n return 'password123';\n }\n\n // URL\n if (fieldName.includes('url') || fieldName.includes('website')) {\n return 'https://example.com';\n }\n\n // ID fields\n if (fieldName.endsWith('_id')) {\n return 1;\n }\n\n // DateTime fields\n if (fieldName.endsWith('_at')) {\n return '2024-01-01T00:00:00Z';\n }\n\n // Boolean\n if (type === 'boolean') {\n return true;\n }\n\n // Integer\n if (type === 'integer') {\n return 1;\n }\n\n return undefined;\n}\n\n/**\n * Map validation type to OpenAPI type.\n */\nfunction mapValidationToOpenApiType(rules: string[], fieldName: string): { type: string; format?: string } {\n // Check field name patterns first\n if (fieldName.includes('email')) {\n return { type: 'string', format: 'email' };\n }\n if (fieldName.includes('password')) {\n return { type: 'string', format: 'password' };\n }\n if (fieldName.includes('url') || fieldName.includes('website')) {\n return { type: 'string', format: 'uri' };\n }\n\n // Check validation rules\n for (const rule of rules) {\n if (rule === \"'integer'\") {\n return { type: 'integer' };\n }\n if (rule === \"'boolean'\") {\n return { type: 'boolean' };\n }\n if (rule === \"'numeric'\") {\n return { type: 'number' };\n }\n if (rule === \"'array'\") {\n return { type: 'array' };\n }\n if (rule === \"'email'\") {\n return { type: 'string', format: 'email' };\n }\n if (rule === \"'url'\") {\n return { type: 'string', format: 'uri' };\n }\n if (rule === \"'date'\") {\n // Check if it looks like datetime\n if (fieldName.endsWith('_at')) {\n return { type: 'string', format: 'date-time' };\n }\n return { type: 'string', format: 'date' };\n }\n }\n\n return { type: 'string' };\n}\n\n/**\n * Extract constraints from validation rules.\n */\nfunction extractConstraints(rules: string[]): { maxLength?: number; minLength?: number; nullable?: boolean; enum?: string[] } {\n const constraints: { maxLength?: number; minLength?: number; nullable?: boolean; enum?: string[] } = {};\n\n for (const rule of rules) {\n // max:N\n const maxMatch = rule.match(/'max:(\\d+)'/);\n if (maxMatch) {\n constraints.maxLength = parseInt(maxMatch[1], 10);\n }\n\n // min:N (for strings)\n const minMatch = rule.match(/'min:(\\d+)'/);\n if (minMatch) {\n constraints.minLength = parseInt(minMatch[1], 10);\n }\n\n // nullable\n if (rule === \"'nullable'\") {\n constraints.nullable = true;\n }\n\n // Rule::in([...])\n const inMatch = rule.match(/Rule::in\\(\\[([^\\]]+)\\]\\)/);\n if (inMatch) {\n const values = inMatch[1].split(',').map(v => v.trim().replace(/^'|'$/g, ''));\n constraints.enum = values;\n }\n }\n\n return constraints;\n}\n\n/**\n * Format OpenAPI property for request as PHP attribute.\n */\nfunction formatRequestOpenApiProperty(prop: RequestOpenApiProperty, indent: string): string {\n const parts: string[] = [`property: '${prop.property}'`, `type: '${prop.type}'`];\n\n if (prop.format) {\n parts.push(`format: '${prop.format}'`);\n }\n if (prop.maxLength) {\n parts.push(`maxLength: ${prop.maxLength}`);\n }\n if (prop.minLength) {\n parts.push(`minLength: ${prop.minLength}`);\n }\n if (prop.nullable) {\n parts.push(`nullable: true`);\n }\n if (prop.enum) {\n const enumStr = prop.enum.map(v => `'${v}'`).join(', ');\n parts.push(`enum: [${enumStr}]`);\n }\n if (prop.example !== undefined) {\n if (typeof prop.example === 'string') {\n parts.push(`example: '${escapePhpString(prop.example)}'`);\n } else {\n parts.push(`example: ${prop.example}`);\n }\n }\n\n return `${indent}new OA\\\\Property(${parts.join(', ')})`;\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: RequestGeneratorOptions): ResolvedOptions {\n return {\n baseRequestNamespace: options?.baseRequestNamespace ?? DEFAULT_OPTIONS.baseRequestNamespace,\n requestNamespace: options?.requestNamespace ?? DEFAULT_OPTIONS.requestNamespace,\n baseRequestPath: options?.baseRequestPath ?? DEFAULT_OPTIONS.baseRequestPath,\n requestPath: options?.requestPath ?? DEFAULT_OPTIONS.requestPath,\n modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,\n customTypes: options?.customTypes ?? new Map(),\n locale: options?.locale ?? DEFAULT_OPTIONS.locale,\n };\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Get display name from LocalizedString.\n */\nfunction getDisplayName(displayName: LocalizedString | undefined, locale: string, fallback: string): string {\n if (!displayName) return fallback;\n if (typeof displayName === 'string') return displayName;\n if (isLocaleMap(displayName)) {\n return displayName[locale] ?? displayName['en'] ?? fallback;\n }\n return fallback;\n}\n\n/**\n * Get module name from schema (based on schema path or options).\n */\nfunction getModuleName(schema: LoadedSchema): string {\n // Use schema.module if available, otherwise derive from schema path or use empty string\n // For now, we'll use a simple heuristic - can be enhanced later\n if ((schema as any).module) {\n return (schema as any).module;\n }\n // Default: no module (files go directly in Requests folder)\n return '';\n}\n\n/**\n * Generate validation rules for a property (Store - required by default).\n */\nfunction generateStoreRules(\n propName: string,\n propDef: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const rules: string[] = [];\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n\n // Check if nullable\n const isNullable = prop.nullable === true;\n\n // Required rule (unless nullable)\n if (!isNullable) {\n rules.push(\"'required'\");\n } else {\n rules.push(\"'nullable'\");\n }\n\n // Type-specific rules\n switch (propDef.type) {\n case 'String':\n case 'Email':\n case 'Password':\n rules.push(\"'string'\");\n const length = prop.length ?? 255;\n rules.push(`'max:${length}'`);\n if (propDef.type === 'Email') {\n rules.push(\"'email'\");\n }\n break;\n\n case 'Text':\n case 'MediumText':\n case 'LongText':\n rules.push(\"'string'\");\n break;\n\n case 'TinyInt':\n case 'Int':\n case 'BigInt':\n rules.push(\"'integer'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Float':\n case 'Decimal':\n rules.push(\"'numeric'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Boolean':\n rules.push(\"'boolean'\");\n break;\n\n case 'Date':\n rules.push(\"'date'\");\n break;\n\n case 'DateTime':\n case 'Timestamp':\n rules.push(\"'date'\");\n break;\n\n case 'Json':\n rules.push(\"'array'\");\n break;\n\n case 'Enum':\n case 'EnumRef':\n rules.push(\"'string'\");\n if (prop.enum && Array.isArray(prop.enum)) {\n const values = prop.enum.map((v: string) => `'${v}'`).join(', ');\n rules.push(`Rule::in([${values}])`);\n }\n break;\n\n case 'Association':\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (assoc.target) {\n const targetSchema = schemas[assoc.target];\n const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));\n rules.push(\"'integer'\");\n rules.push(`'exists:${targetTable},id'`);\n }\n }\n break;\n\n default:\n // Handle custom types (non-compound)\n const customType = options.customTypes.get(propDef.type);\n if (customType && !customType.compound) {\n // Japanese custom types\n if (propDef.type === 'JapanesePhone') {\n rules.push(\"'string'\");\n rules.push(\"'max:15'\");\n // Japanese phone format: 090-1234-5678 or 03-1234-5678\n rules.push(\"'regex:/^\\\\d{2,4}-\\\\d{2,4}-\\\\d{4}$/'\");\n } else if (propDef.type === 'JapanesePostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else {\n // Default: use SQL type info from custom type\n const sqlType = customType.sql?.sqlType ?? 'VARCHAR';\n const sqlLength = customType.sql?.length ?? 255;\n if (sqlType === 'VARCHAR' || sqlType === 'TEXT') {\n rules.push(\"'string'\");\n if (sqlType === 'VARCHAR') {\n rules.push(`'max:${sqlLength}'`);\n }\n } else if (sqlType === 'INT' || sqlType === 'TINYINT' || sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n } else if (sqlType === 'DECIMAL' || sqlType === 'FLOAT') {\n rules.push(\"'numeric'\");\n }\n }\n }\n break;\n }\n\n // Unique constraint\n if (prop.unique === true) {\n rules.push(`'unique:${tableName}'`);\n }\n\n return rules;\n}\n\n/**\n * Generate validation rules for a property (Update - sometimes by default).\n */\nfunction generateUpdateRules(\n propName: string,\n propDef: PropertyDefinition,\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const rules: string[] = [];\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));\n const modelVar = toSnakeCase(schema.name);\n\n // Use 'sometimes' for partial updates\n rules.push(\"'sometimes'\");\n\n // Type-specific rules (same as store, but without required)\n switch (propDef.type) {\n case 'String':\n case 'Email':\n case 'Password':\n rules.push(\"'string'\");\n const length = prop.length ?? 255;\n rules.push(`'max:${length}'`);\n if (propDef.type === 'Email') {\n rules.push(\"'email'\");\n }\n break;\n\n case 'Text':\n case 'MediumText':\n case 'LongText':\n rules.push(\"'string'\");\n break;\n\n case 'TinyInt':\n case 'Int':\n case 'BigInt':\n rules.push(\"'integer'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Float':\n case 'Decimal':\n rules.push(\"'numeric'\");\n if (prop.min !== undefined) {\n rules.push(`'min:${prop.min}'`);\n }\n if (prop.max !== undefined) {\n rules.push(`'max:${prop.max}'`);\n }\n break;\n\n case 'Boolean':\n rules.push(\"'boolean'\");\n break;\n\n case 'Date':\n rules.push(\"'date'\");\n break;\n\n case 'DateTime':\n case 'Timestamp':\n rules.push(\"'date'\");\n break;\n\n case 'Json':\n rules.push(\"'array'\");\n break;\n\n case 'Enum':\n case 'EnumRef':\n rules.push(\"'string'\");\n if (prop.enum && Array.isArray(prop.enum)) {\n const values = prop.enum.map((v: string) => `'${v}'`).join(', ');\n rules.push(`Rule::in([${values}])`);\n }\n break;\n\n case 'Association':\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation === 'ManyToOne' || assoc.relation === 'OneToOne') {\n if (assoc.target) {\n const targetSchema = schemas[assoc.target];\n const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));\n rules.push(\"'integer'\");\n rules.push(`'exists:${targetTable},id'`);\n }\n }\n break;\n\n default:\n // Handle custom types (non-compound)\n const customType = options.customTypes.get(propDef.type);\n if (customType && !customType.compound) {\n // Japanese custom types\n if (propDef.type === 'JapanesePhone') {\n rules.push(\"'string'\");\n rules.push(\"'max:15'\");\n // Japanese phone format: 090-1234-5678 or 03-1234-5678\n rules.push(\"'regex:/^\\\\d{2,4}-\\\\d{2,4}-\\\\d{4}$/'\");\n } else if (propDef.type === 'JapanesePostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else {\n // Default: use SQL type info from custom type\n const sqlType = customType.sql?.sqlType ?? 'VARCHAR';\n const sqlLength = customType.sql?.length ?? 255;\n if (sqlType === 'VARCHAR' || sqlType === 'TEXT') {\n rules.push(\"'string'\");\n if (sqlType === 'VARCHAR') {\n rules.push(`'max:${sqlLength}'`);\n }\n } else if (sqlType === 'INT' || sqlType === 'TINYINT' || sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n } else if (sqlType === 'DECIMAL' || sqlType === 'FLOAT') {\n rules.push(\"'numeric'\");\n }\n }\n }\n break;\n }\n\n // Unique constraint with ignore for updates\n if (prop.unique === true) {\n rules.push(`Rule::unique('${tableName}')->ignore($this->route('${modelVar}'))`);\n }\n\n return rules;\n}\n\n/**\n * Get validation rules for a specific compound field type.\n */\nfunction getCompoundFieldRules(\n typeName: string,\n suffix: string,\n field: any,\n fieldOverride: any\n): string[] {\n const rules: string[] = [];\n const sql = field.sql;\n const length = fieldOverride?.length ?? sql?.length ?? 255;\n\n // Handle different compound types with specific validation\n switch (typeName) {\n case 'JapaneseName':\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n // Kana fields could have katakana validation\n if (suffix === 'KanaLastname' || suffix === 'KanaFirstname') {\n // Katakana regex: only katakana and common punctuation\n rules.push(\"'regex:/^[\\\\x{30A0}-\\\\x{30FF}\\\\x{3000}-\\\\x{303F}\\\\x{FF00}-\\\\x{FF9F}\\\\s]+$/u'\");\n }\n break;\n\n case 'JapaneseAddress':\n if (suffix === 'PostalCode') {\n rules.push(\"'string'\");\n rules.push(\"'max:8'\");\n // Postal code format: 123-4567\n rules.push(\"'regex:/^\\\\d{3}-\\\\d{4}$/'\");\n } else if (suffix === 'PrefectureId') {\n rules.push(\"'integer'\");\n rules.push(\"'between:1,47'\");\n } else {\n // Address1, Address2, Address3\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n }\n break;\n\n case 'JapaneseBankAccount':\n if (suffix === 'BankCode') {\n rules.push(\"'string'\");\n rules.push(\"'size:4'\");\n rules.push(\"'regex:/^\\\\d{4}$/'\");\n } else if (suffix === 'BranchCode') {\n rules.push(\"'string'\");\n rules.push(\"'size:3'\");\n rules.push(\"'regex:/^\\\\d{3}$/'\");\n } else if (suffix === 'AccountType') {\n rules.push(\"'string'\");\n rules.push(\"Rule::in(['1', '2', '4'])\"); // 普通/当座/貯蓄\n } else if (suffix === 'AccountNumber') {\n rules.push(\"'string'\");\n rules.push(\"'max:7'\");\n rules.push(\"'regex:/^\\\\d{1,7}$/'\");\n } else if (suffix === 'AccountHolder') {\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n // Katakana validation for account holder name\n rules.push(\"'regex:/^[\\\\x{30A0}-\\\\x{30FF}\\\\x{3000}-\\\\x{303F}\\\\x{FF00}-\\\\x{FF9F}\\\\s]+$/u'\");\n }\n break;\n\n default:\n // Default handling for unknown compound types\n if (sql?.sqlType === 'TINYINT' || sql?.sqlType === 'INT' || sql?.sqlType === 'BIGINT') {\n rules.push(\"'integer'\");\n if (sql?.unsigned) {\n rules.push(\"'min:0'\");\n }\n } else {\n rules.push(\"'string'\");\n rules.push(`'max:${length}'`);\n }\n break;\n }\n\n return rules;\n}\n\n/**\n * Expand compound type fields.\n */\nfunction expandCompoundTypeFields(\n propName: string,\n propDef: PropertyDefinition,\n options: ResolvedOptions\n): { fieldName: string; rules: string[]; needsRuleImport: boolean }[] {\n const typeDef = options.customTypes.get(propDef.type);\n if (!typeDef || !typeDef.compound || !typeDef.expand) {\n return [];\n }\n\n const snakeName = toSnakeCase(propName);\n const prop = propDef as any;\n const isNullable = prop.nullable === true;\n const fields: { fieldName: string; rules: string[]; needsRuleImport: boolean }[] = [];\n\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n const fieldOverride = prop.fields?.[field.suffix];\n\n // Field-level nullable can override property-level\n // Also check if the field itself is defined as nullable in the type definition\n const fieldDefNullable = (field as any).sql?.nullable ?? false;\n const fieldNullable = fieldOverride?.nullable ?? fieldDefNullable ?? isNullable;\n\n const rules: string[] = [];\n if (!fieldNullable) {\n rules.push(\"'required'\");\n } else {\n rules.push(\"'nullable'\");\n }\n\n // Get type-specific validation rules\n const typeRules = getCompoundFieldRules(propDef.type, field.suffix, field, fieldOverride);\n rules.push(...typeRules);\n\n const needsRuleImport = rules.some(r => r.includes('Rule::'));\n fields.push({ fieldName, rules, needsRuleImport });\n }\n\n return fields;\n}\n\n/**\n * Generate Store Request Base class.\n */\nfunction generateStoreRequestBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const rulesLines: string[] = [];\n const attributeLines: string[] = [];\n const fieldList: string[] = [];\n let needsRuleImport = false;\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip association relations that don't have FK (OneToMany, ManyToMany, etc.)\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n // For ManyToOne/OneToOne, use the FK field name\n const fkName = `${snakeName}_id`;\n const rules = generateStoreRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${fkName}' => [${rules.join(', ')}],`);\n fieldList.push(fkName);\n\n // Attribute for FK\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${fkName}' => '${escapePhpString(displayName)}',`);\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n if (field.needsRuleImport) needsRuleImport = true;\n rulesLines.push(` '${field.fieldName}' => [${field.rules.join(', ')}],`);\n fieldList.push(field.fieldName);\n attributeLines.push(` '${field.fieldName}' => '${escapePhpString(field.fieldName)}',`);\n }\n continue;\n }\n\n // Regular field\n const rules = generateStoreRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${snakeName}' => [${rules.join(', ')}],`);\n fieldList.push(snakeName);\n\n // Attribute\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${snakeName}' => '${escapePhpString(displayName)}',`);\n }\n\n const ruleImport = needsRuleImport ? '\\nuse Illuminate\\\\Validation\\\\Rule;' : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Foundation\\\\Http\\\\FormRequest;${ruleImport}\n\nabstract class ${className}StoreRequestBase extends FormRequest\n{\n /**\n * Validation rules generated from Omnify schema.\n *\n * Generated fields: ${fieldList.join(', ')}\n *\n * @return array<string, array<int, mixed>>\n */\n protected function schemaRules(): array\n {\n return [\n${rulesLines.join('\\n')}\n ];\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n protected function schemaAttributes(): array\n {\n return [\n${attributeLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseRequestPath}${modulePath}/${className}StoreRequestBase.php`,\n content,\n type: 'store-base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Update Request Base class.\n */\nfunction generateUpdateRequestBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const rulesLines: string[] = [];\n const attributeLines: string[] = [];\n let needsRuleImport = false;\n\n for (const [propName, propDef] of Object.entries(properties)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip association relations that don't have FK\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n const fkName = `${snakeName}_id`;\n const rules = generateUpdateRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::') || r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${fkName}' => [${rules.join(', ')}],`);\n\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${fkName}' => '${escapePhpString(displayName)}',`);\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n if (field.needsRuleImport) needsRuleImport = true;\n // For update, replace 'required' with 'sometimes'\n const updateRules = field.rules.map(r => r === \"'required'\" ? \"'sometimes'\" : r);\n rulesLines.push(` '${field.fieldName}' => [${updateRules.join(', ')}],`);\n attributeLines.push(` '${field.fieldName}' => '${escapePhpString(field.fieldName)}',`);\n }\n continue;\n }\n\n // Regular field\n const rules = generateUpdateRules(propName, propDef, schema, schemas, options);\n if (rules.some(r => r.includes('Rule::'))) needsRuleImport = true;\n rulesLines.push(` '${snakeName}' => [${rules.join(', ')}],`);\n\n const displayName = getDisplayName((propDef as any).displayName, options.locale, propName);\n attributeLines.push(` '${snakeName}' => '${escapePhpString(displayName)}',`);\n }\n\n const ruleImport = needsRuleImport ? '\\nuse Illuminate\\\\Validation\\\\Rule;' : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Foundation\\\\Http\\\\FormRequest;${ruleImport}\n\nabstract class ${className}UpdateRequestBase extends FormRequest\n{\n /**\n * Validation rules generated from Omnify schema.\n * All fields use 'sometimes' for partial updates.\n *\n * @return array<string, array<int, mixed>>\n */\n protected function schemaRules(): array\n {\n return [\n${rulesLines.join('\\n')}\n ];\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n protected function schemaAttributes(): array\n {\n return [\n${attributeLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseRequestPath}${modulePath}/${className}UpdateRequestBase.php`,\n content,\n type: 'update-base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate OpenAPI properties for a request based on schema.\n */\nfunction generateRequestOpenApiProperties(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions,\n isStore: boolean\n): { properties: RequestOpenApiProperty[]; requiredFields: string[] } {\n const properties: RequestOpenApiProperty[] = [];\n const requiredFields: string[] = [];\n const schemaProps = schema.properties ?? {};\n\n for (const [propName, propDef] of Object.entries(schemaProps)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip system fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n\n // Skip associations that don't have FK\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.relation !== 'ManyToOne' && assoc.relation !== 'OneToOne') {\n continue;\n }\n // For FK fields\n const fkName = `${snakeName}_id`;\n const rules = isStore\n ? generateStoreRules(propName, propDef, schema, schemas, options)\n : generateUpdateRules(propName, propDef, schema, schemas, options);\n const openApiType = mapValidationToOpenApiType(rules, fkName);\n const constraints = extractConstraints(rules);\n const example = getExampleValue(fkName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: fkName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and not nullable\n if (isStore && !(propDef as any).nullable) {\n requiredFields.push(fkName);\n }\n continue;\n }\n\n // Check for compound types\n const expandedFields = expandCompoundTypeFields(propName, propDef, options);\n if (expandedFields.length > 0) {\n for (const field of expandedFields) {\n const openApiType = mapValidationToOpenApiType(field.rules, field.fieldName);\n const constraints = extractConstraints(field.rules);\n const example = getExampleValue(field.fieldName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: field.fieldName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and has 'required' rule\n if (isStore && field.rules.includes(\"'required'\")) {\n requiredFields.push(field.fieldName);\n }\n }\n continue;\n }\n\n // Regular field\n const rules = isStore\n ? generateStoreRules(propName, propDef, schema, schemas, options)\n : generateUpdateRules(propName, propDef, schema, schemas, options);\n const openApiType = mapValidationToOpenApiType(rules, snakeName);\n const constraints = extractConstraints(rules);\n const example = getExampleValue(snakeName, openApiType.type);\n\n const prop: RequestOpenApiProperty = {\n property: snakeName,\n ...openApiType,\n ...constraints,\n };\n if (example !== undefined) prop.example = example;\n properties.push(prop);\n\n // Required if store and has 'required' rule\n if (isStore && rules.includes(\"'required'\")) {\n requiredFields.push(snakeName);\n }\n }\n\n return { properties, requiredFields };\n}\n\n/**\n * Generate Store Request (user-editable).\n */\nfunction generateStoreRequest(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.requestNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties\n const { properties, requiredFields } = generateRequestOpenApiProperties(schema, schemas, options, true);\n const propsIndent = ' ';\n const openApiPropsFormatted = properties\n .map(prop => formatRequestOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n // Format required array\n const requiredArray = requiredFields.length > 0\n ? `\\n required: [${requiredFields.map(f => `'${f}'`).join(', ')}],`\n : '';\n\n const content = `<?php\n\n/**\n * ${className} Store Request\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}StoreRequestBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}StoreRequest',${requiredArray}\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}StoreRequest extends ${className}StoreRequestBase\n{\n /**\n * Determine if the user is authorized to make this request.\n */\n public function authorize(): bool\n {\n return true;\n }\n\n /**\n * Get the validation rules that apply to the request.\n *\n * @return array<string, array<int, mixed>>\n */\n public function rules(): array\n {\n return array_merge($this->schemaRules(), [\n // Custom/override rules here\n ]);\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n public function attributes(): array\n {\n return array_merge($this->schemaAttributes(), [\n // Custom attributes here\n ]);\n }\n\n /**\n * Get custom messages for validator errors.\n *\n * @return array<string, string>\n */\n public function messages(): array\n {\n return [\n // Custom messages here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.requestPath}${modulePath}/${className}StoreRequest.php`,\n content,\n type: 'store',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Update Request (user-editable).\n */\nfunction generateUpdateRequest(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedRequest {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.requestNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties (no required array for update - partial updates allowed)\n const { properties } = generateRequestOpenApiProperties(schema, schemas, options, false);\n const propsIndent = ' ';\n const openApiPropsFormatted = properties\n .map(prop => formatRequestOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n const content = `<?php\n\n/**\n * ${className} Update Request\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}UpdateRequestBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}UpdateRequest',\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}UpdateRequest extends ${className}UpdateRequestBase\n{\n /**\n * Determine if the user is authorized to make this request.\n */\n public function authorize(): bool\n {\n return true;\n }\n\n /**\n * Get the validation rules that apply to the request.\n *\n * @return array<string, array<int, mixed>>\n */\n public function rules(): array\n {\n return array_merge($this->schemaRules(), [\n // Custom/override rules here\n ]);\n }\n\n /**\n * Get custom attributes for validator errors.\n *\n * @return array<string, string>\n */\n public function attributes(): array\n {\n return array_merge($this->schemaAttributes(), [\n // Custom attributes here\n ]);\n }\n\n /**\n * Get custom messages for validator errors.\n *\n * @return array<string, string>\n */\n public function messages(): array\n {\n return [\n // Custom messages here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.requestPath}${modulePath}/${className}UpdateRequest.php`,\n content,\n type: 'update',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate all FormRequest classes for the given schemas.\n */\nexport function generateRequests(\n schemas: SchemaCollection,\n options?: RequestGeneratorOptions\n): GeneratedRequest[] {\n const resolved = resolveOptions(options);\n const requests: GeneratedRequest[] = [];\n\n for (const schema of Object.values(schemas)) {\n // Skip enums\n if (schema.kind === 'enum') continue;\n\n // Skip hidden schemas\n if (schema.options?.hidden === true) continue;\n\n // Generate base requests (always overwritten)\n requests.push(generateStoreRequestBase(schema, schemas, resolved));\n requests.push(generateUpdateRequestBase(schema, schemas, resolved));\n\n // Generate user requests (created once)\n requests.push(generateStoreRequest(schema, schemas, resolved));\n requests.push(generateUpdateRequest(schema, schemas, resolved));\n }\n\n return requests;\n}\n\n/**\n * Get the output path for a request.\n */\nexport function getRequestPath(request: GeneratedRequest): string {\n return request.path;\n}\n","/**\n * Laravel Resource Generator\n *\n * Generates Laravel API Resource classes from Omnify schemas.\n * Creates base resources (auto-generated) and user resources (created once).\n */\n\nimport type { LoadedSchema, PropertyDefinition, SchemaCollection, LocalizedString, CustomTypeDefinition, AssociationDefinition } from '@famgia/omnify-types';\nimport { isLocaleMap } from '@famgia/omnify-types';\nimport { toSnakeCase, toPascalCase, toCamelCase } from '../utils.js';\n\n/**\n * Options for resource generation.\n */\nexport interface ResourceGeneratorOptions {\n /**\n * Base resource namespace.\n * @default 'App\\\\Http\\\\Resources\\\\OmnifyBase'\n */\n baseResourceNamespace?: string;\n\n /**\n * User resource namespace.\n * @default 'App\\\\Http\\\\Resources'\n */\n resourceNamespace?: string;\n\n /**\n * Output path for base resources.\n * @default 'app/Http/Resources/OmnifyBase'\n */\n baseResourcePath?: string;\n\n /**\n * Output path for user resources.\n * @default 'app/Http/Resources'\n */\n resourcePath?: string;\n\n /**\n * Custom types registered by plugins.\n */\n customTypes?: ReadonlyMap<string, CustomTypeDefinition>;\n\n /**\n * Locale for displayName.\n * @default 'en'\n */\n locale?: string;\n}\n\n/**\n * Generated resource output.\n */\nexport interface GeneratedResource {\n /** File path relative to project root */\n path: string;\n /** PHP content */\n content: string;\n /** Resource type */\n type: 'base' | 'user';\n /** Whether to overwrite existing file */\n overwrite: boolean;\n /** Schema name */\n schemaName: string;\n /** Module name (from schema path or empty) */\n module: string;\n}\n\n/**\n * Resolved options with defaults.\n */\ninterface ResolvedOptions {\n baseResourceNamespace: string;\n resourceNamespace: string;\n baseResourcePath: string;\n resourcePath: string;\n customTypes: ReadonlyMap<string, CustomTypeDefinition>;\n locale: string;\n}\n\n/**\n * Default options.\n */\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n baseResourceNamespace: 'App\\\\Http\\\\Resources\\\\OmnifyBase',\n resourceNamespace: 'App\\\\Http\\\\Resources',\n baseResourcePath: 'app/Http/Resources/OmnifyBase',\n resourcePath: 'app/Http/Resources',\n customTypes: new Map(),\n locale: 'en',\n};\n\n/**\n * Fields to skip when generating resource output.\n */\nconst SKIP_FIELDS = new Set([\n 'password',\n 'remember_token',\n]);\n\n/**\n * OpenAPI property definition.\n */\ninterface OpenApiProperty {\n property: string;\n type: string;\n format?: string;\n maxLength?: number;\n nullable?: boolean;\n example?: string | number | boolean;\n}\n\n/**\n * Map TypeScript type to OpenAPI type and format.\n */\nfunction mapTsTypeToOpenApi(tsType: string, fieldName: string): { type: string; format?: string } {\n // Check for special field name patterns\n if (fieldName.includes('email')) {\n return { type: 'string', format: 'email' };\n }\n\n switch (tsType) {\n case 'string':\n return { type: 'string' };\n case 'number':\n return { type: 'number' };\n case 'boolean':\n return { type: 'boolean' };\n default:\n return { type: 'string' };\n }\n}\n\n/**\n * Map Omnify type to OpenAPI type and format.\n */\nfunction getOpenApiType(propDef: PropertyDefinition, fieldName: string): { type: string; format?: string } {\n // Handle date/time types first (before field name checks)\n switch (propDef.type) {\n case 'Date':\n return { type: 'string', format: 'date' };\n case 'DateTime':\n case 'Timestamp':\n return { type: 'string', format: 'date-time' };\n }\n\n // Check for special field name patterns\n if (fieldName.includes('email') && !fieldName.endsWith('_at')) {\n return { type: 'string', format: 'email' };\n }\n if (fieldName.includes('password')) {\n return { type: 'string', format: 'password' };\n }\n\n switch (propDef.type) {\n case 'String':\n case 'Text':\n case 'LongText':\n return { type: 'string' };\n case 'Int':\n case 'BigInt':\n return { type: 'integer' };\n case 'Float':\n case 'Decimal':\n return { type: 'number' };\n case 'Boolean':\n return { type: 'boolean' };\n case 'Email':\n return { type: 'string', format: 'email' };\n case 'UUID':\n return { type: 'string', format: 'uuid' };\n case 'JSON':\n return { type: 'object' };\n default:\n return { type: 'string' };\n }\n}\n\n/**\n * Generate OpenAPI properties for a schema.\n */\nfunction generateOpenApiProperties(\n schema: LoadedSchema,\n options: ResolvedOptions\n): OpenApiProperty[] {\n const properties: OpenApiProperty[] = [];\n const schemaProps = schema.properties ?? {};\n\n // Always include id first\n if (schema.options?.id !== false) {\n properties.push({\n property: 'id',\n type: 'integer',\n example: 1,\n });\n }\n\n // Process schema properties\n for (const [propName, propDef] of Object.entries(schemaProps)) {\n const snakeName = toSnakeCase(propName);\n\n // Skip hidden fields\n if (SKIP_FIELDS.has(snakeName)) continue;\n if ((propDef as { hidden?: boolean }).hidden === true) continue;\n\n // Skip associations (they're complex nested objects)\n if (propDef.type === 'Association') continue;\n\n // Handle compound types\n const typeDef = options.customTypes.get(propDef.type);\n if (typeDef?.compound && typeDef.expand) {\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n // Get type from typescript definition or default to string\n const tsType = field.typescript?.type ?? 'string';\n const openApiType = mapTsTypeToOpenApi(tsType, fieldName);\n const prop: OpenApiProperty = {\n property: fieldName,\n ...openApiType,\n };\n // Get maxLength from SQL definition if available\n const sqlDef = field.sql as { length?: number } | undefined;\n if (sqlDef?.length) {\n prop.maxLength = sqlDef.length;\n }\n properties.push(prop);\n }\n // Add accessors\n if (typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n properties.push({\n property: accessorName,\n type: 'string',\n });\n }\n }\n continue;\n }\n\n // Regular field\n const openApiType = getOpenApiType(propDef, snakeName);\n const prop: OpenApiProperty = {\n property: snakeName,\n ...openApiType,\n };\n\n // Add maxLength from length property\n const length = (propDef as { length?: number }).length;\n if (length) {\n prop.maxLength = length;\n }\n\n // Add nullable\n if ((propDef as { nullable?: boolean }).nullable) {\n prop.nullable = true;\n }\n\n properties.push(prop);\n }\n\n // Add timestamps\n if (schema.options?.timestamps !== false) {\n properties.push({\n property: 'created_at',\n type: 'string',\n format: 'date-time',\n });\n properties.push({\n property: 'updated_at',\n type: 'string',\n format: 'date-time',\n });\n }\n\n // Add soft delete timestamp\n if (schema.options?.softDelete) {\n properties.push({\n property: 'deleted_at',\n type: 'string',\n format: 'date-time',\n nullable: true,\n });\n }\n\n return properties;\n}\n\n/**\n * Format OpenAPI property as PHP attribute.\n */\nfunction formatOpenApiProperty(prop: OpenApiProperty, indent: string): string {\n const parts: string[] = [`property: '${prop.property}'`, `type: '${prop.type}'`];\n\n if (prop.format) {\n parts.push(`format: '${prop.format}'`);\n }\n if (prop.maxLength) {\n parts.push(`maxLength: ${prop.maxLength}`);\n }\n if (prop.nullable) {\n parts.push(`nullable: true`);\n }\n if (prop.example !== undefined) {\n if (typeof prop.example === 'string') {\n parts.push(`example: '${prop.example}'`);\n } else {\n parts.push(`example: ${prop.example}`);\n }\n }\n\n return `${indent}new OA\\\\Property(${parts.join(', ')})`;\n}\n\n/**\n * Resolve options with defaults.\n */\nfunction resolveOptions(options?: ResourceGeneratorOptions): ResolvedOptions {\n return {\n baseResourceNamespace: options?.baseResourceNamespace ?? DEFAULT_OPTIONS.baseResourceNamespace,\n resourceNamespace: options?.resourceNamespace ?? DEFAULT_OPTIONS.resourceNamespace,\n baseResourcePath: options?.baseResourcePath ?? DEFAULT_OPTIONS.baseResourcePath,\n resourcePath: options?.resourcePath ?? DEFAULT_OPTIONS.resourcePath,\n customTypes: options?.customTypes ?? new Map(),\n locale: options?.locale ?? DEFAULT_OPTIONS.locale,\n };\n}\n\n/**\n * Escape string for PHP single-quoted string.\n */\nfunction escapePhpString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Get module name from schema.\n */\nfunction getModuleName(schema: LoadedSchema): string {\n if ((schema as any).module) {\n return (schema as any).module;\n }\n return '';\n}\n\n/**\n * Get the PHP output expression for a field based on its type.\n * For date/time fields, always use ?-> for safe null handling.\n */\nfunction getFieldExpression(fieldName: string, propDef: PropertyDefinition): string {\n switch (propDef.type) {\n case 'Date':\n return `$this->${fieldName}?->toDateString()`;\n case 'DateTime':\n case 'Timestamp':\n return `$this->${fieldName}?->toISOString()`;\n default:\n return `$this->${fieldName}`;\n }\n}\n\n/**\n * Get resource field output for a property.\n */\nfunction getPropertyOutput(\n propName: string,\n propDef: PropertyDefinition,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): string[] {\n const snakeName = toSnakeCase(propName);\n const lines: string[] = [];\n\n // Skip hidden fields\n if (SKIP_FIELDS.has(snakeName)) {\n return lines;\n }\n\n // Handle associations\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n const targetClass = assoc.target ? toPascalCase(assoc.target) : '';\n\n switch (assoc.relation) {\n case 'ManyToOne':\n case 'OneToOne':\n // Include FK and optionally loaded relation\n lines.push(` '${snakeName}_id' => $this->${snakeName}_id,`);\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => new ${targetClass}Resource($this->${toCamelCase(propName)})),`);\n break;\n case 'OneToMany':\n case 'ManyToMany':\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => ${targetClass}Resource::collection($this->${toCamelCase(propName)})),`);\n break;\n case 'MorphTo':\n lines.push(` '${snakeName}_type' => $this->${snakeName}_type,`);\n lines.push(` '${snakeName}_id' => $this->${snakeName}_id,`);\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}'),`);\n break;\n case 'MorphOne':\n case 'MorphMany':\n lines.push(` '${snakeName}' => $this->whenLoaded('${toCamelCase(propName)}', fn() => ${targetClass}Resource::collection($this->${toCamelCase(propName)})),`);\n break;\n }\n return lines;\n }\n\n // Handle compound types\n const typeDef = options.customTypes.get(propDef.type);\n if (typeDef?.compound && typeDef.expand) {\n for (const field of typeDef.expand) {\n const suffixSnake = toSnakeCase(field.suffix);\n const fieldName = `${snakeName}_${suffixSnake}`;\n lines.push(` '${fieldName}' => $this->${fieldName},`);\n }\n // Add accessor if exists\n if (typeDef.accessors) {\n for (const accessor of typeDef.accessors) {\n const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;\n lines.push(` '${accessorName}' => $this->${accessorName},`);\n }\n }\n return lines;\n }\n\n // Regular fields - apply date/time formatting\n const expression = getFieldExpression(snakeName, propDef);\n lines.push(` '${snakeName}' => ${expression},`);\n return lines;\n}\n\n/**\n * Generate Resource Base class.\n */\nfunction generateResourceBase(\n schema: LoadedSchema,\n schemas: SchemaCollection,\n options: ResolvedOptions\n): GeneratedResource {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.baseResourceNamespace}${namespaceModule}`;\n\n const properties = schema.properties ?? {};\n const outputLines: string[] = [];\n const imports: Set<string> = new Set();\n\n // Always include id\n if (schema.options?.id !== false) {\n outputLines.push(` 'id' => $this->id,`);\n }\n\n // Process properties\n for (const [propName, propDef] of Object.entries(properties)) {\n const lines = getPropertyOutput(propName, propDef, schemas, options);\n outputLines.push(...lines);\n\n // Collect imports for related resources\n if (propDef.type === 'Association') {\n const assoc = propDef as AssociationDefinition;\n if (assoc.target) {\n const targetModule = getModuleName(schemas[assoc.target] ?? schema);\n const targetModuleNs = targetModule ? `\\\\${targetModule}` : '';\n imports.add(`use ${options.resourceNamespace}${targetModuleNs}\\\\${toPascalCase(assoc.target)}Resource;`);\n }\n }\n }\n\n // Add timestamps\n if (schema.options?.timestamps !== false) {\n outputLines.push(` 'created_at' => $this->created_at?->toISOString(),`);\n outputLines.push(` 'updated_at' => $this->updated_at?->toISOString(),`);\n }\n\n // Add soft delete\n if (schema.options?.softDelete) {\n outputLines.push(` 'deleted_at' => $this->deleted_at?->toISOString(),`);\n }\n\n const importLines = Array.from(imports).sort().join('\\n');\n const importBlock = importLines ? `\\n${importLines}` : '';\n\n const content = `<?php\n\n/**\n * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!\n *\n * This file is generated from Omnify schema: ${schema.name}\n * Re-run \\`npx omnify generate\\` to update.\n *\n * @generated\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Http\\\\Request;\nuse Illuminate\\\\Http\\\\Resources\\\\Json\\\\JsonResource;${importBlock}\n\nclass ${className}ResourceBase extends JsonResource\n{\n /**\n * Transform the resource into an array.\n *\n * @return array<string, mixed>\n */\n protected function schemaArray(Request $request): array\n {\n return [\n${outputLines.join('\\n')}\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.baseResourcePath}${modulePath}/${className}ResourceBase.php`,\n content,\n type: 'base',\n overwrite: true,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate Resource (user-editable).\n */\nfunction generateResource(\n schema: LoadedSchema,\n options: ResolvedOptions\n): GeneratedResource {\n const className = toPascalCase(schema.name);\n const module = getModuleName(schema);\n const namespaceModule = module ? `\\\\${module}` : '';\n const namespace = `${options.resourceNamespace}${namespaceModule}`;\n const baseNamespace = `${options.baseResourceNamespace}${namespaceModule}`;\n\n // Generate OpenAPI properties\n const openApiProps = generateOpenApiProperties(schema, options);\n const propsIndent = ' ';\n const openApiPropsFormatted = openApiProps\n .map(prop => formatOpenApiProperty(prop, propsIndent))\n .join(',\\n');\n\n // Get description from displayName or use default\n const description = schema.displayName\n ? (typeof schema.displayName === 'string' ? schema.displayName : schema.displayName['en'] ?? schema.name)\n : `${schema.name} resource`;\n\n const content = `<?php\n\n/**\n * ${className} Resource\n *\n * SAFE TO EDIT - This file is never overwritten by Omnify.\n */\n\nnamespace ${namespace};\n\nuse Illuminate\\\\Http\\\\Request;\nuse OpenApi\\\\Attributes as OA;\nuse ${baseNamespace}\\\\${className}ResourceBase;\n\n#[OA\\\\Schema(\n schema: '${schema.name}',\n description: '${escapePhpString(description)}',\n properties: [\n${openApiPropsFormatted},\n ]\n)]\nclass ${className}Resource extends ${className}ResourceBase\n{\n /**\n * Transform the resource into an array.\n *\n * @return array<string, mixed>\n */\n public function toArray(Request $request): array\n {\n return array_merge($this->schemaArray($request), [\n // Custom fields here\n ]);\n }\n\n /**\n * Get additional data that should be returned with the resource array.\n *\n * @return array<string, mixed>\n */\n public function with(Request $request): array\n {\n return [\n // Additional metadata here\n ];\n }\n}\n`;\n\n const modulePath = module ? `/${module}` : '';\n return {\n path: `${options.resourcePath}${modulePath}/${className}Resource.php`,\n content,\n type: 'user',\n overwrite: false,\n schemaName: schema.name,\n module,\n };\n}\n\n/**\n * Generate all Resource classes for the given schemas.\n */\nexport function generateResources(\n schemas: SchemaCollection,\n options?: ResourceGeneratorOptions\n): GeneratedResource[] {\n const resolved = resolveOptions(options);\n const resources: GeneratedResource[] = [];\n\n for (const schema of Object.values(schemas)) {\n // Skip enums\n if (schema.kind === 'enum') continue;\n\n // Skip hidden schemas\n if (schema.options?.hidden === true) continue;\n\n // Generate base resource (always overwritten)\n resources.push(generateResourceBase(schema, schemas, resolved));\n\n // Generate user resource (created once)\n resources.push(generateResource(schema, resolved));\n }\n\n return resources;\n}\n\n/**\n * Get the output path for a resource.\n */\nexport function getResourcePath(resource: GeneratedResource): string {\n return resource.path;\n}\n","/**\n * AI Guides Generator\n *\n * Generates AI assistant guides (Claude, Cursor) for Laravel projects.\n * Simply copies .stub files, removes .stub extension, and replaces placeholders.\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { resolve, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Options for AI guides generation\n */\nexport interface AIGuidesOptions {\n /**\n * Laravel models path from config (e.g., 'app/Models')\n * Used to extract the base path for glob replacement\n */\n modelsPath?: string;\n\n /**\n * Laravel migrations path from config\n */\n migrationsPath?: string;\n\n /**\n * Base path for Laravel files (default: extracted from modelsPath or 'app')\n * Used for placeholder replacement in Cursor rules\n */\n laravelBasePath?: string;\n\n /**\n * TypeScript/React base path (e.g., 'resources/ts' or 'frontend/src')\n * Used for placeholder replacement in Cursor rules\n */\n typescriptBasePath?: string;\n}\n\n/**\n * Result of AI guides generation\n */\nexport interface AIGuidesResult {\n claudeGuides: number;\n claudeRules: number;\n claudeChecklists: number;\n claudeWorkflows: number;\n claudeAgents: number;\n claudeOmnify: number;\n cursorRules: number;\n files: string[];\n}\n\n/**\n * Get the stubs directory path\n */\nfunction getStubsDir(): string {\n // Try dev path first: packages/laravel-generator/stubs/ai-guides\n const devPath = resolve(__dirname, '../../stubs/ai-guides');\n if (existsSync(devPath)) {\n return devPath;\n }\n\n // Try dist path (when installed as package)\n const distPath = resolve(__dirname, '../stubs/ai-guides');\n if (existsSync(distPath)) {\n return distPath;\n }\n\n throw new Error('AI guides stubs not found');\n}\n\n/**\n * Extract Laravel app path from modelsPath\n * e.g., 'app/Models' -> 'app'\n * e.g., 'backend/app/Models' -> 'backend/app'\n */\nfunction extractLaravelBasePath(modelsPath?: string): string {\n if (!modelsPath) return 'app';\n\n // Remove 'Models' or 'Models/...' suffix\n const normalized = modelsPath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.+?)\\/Models(?:\\/.*)?$/);\n if (match && match[1]) {\n return match[1];\n }\n\n // Fallback: get directory of modelsPath\n const parts = normalized.split('/').filter(Boolean);\n if (parts.length > 1) {\n return parts.slice(0, -1).join('/');\n }\n\n return 'app';\n}\n\n/**\n * Extract Laravel project root from basePath\n * e.g., 'app' -> '' (standard Laravel)\n * e.g., 'backend/app' -> 'backend' (monorepo)\n */\nfunction extractLaravelRoot(basePath: string): string {\n // basePath is like 'app' or 'backend/app'\n // We want '' or 'backend'\n const normalized = basePath.replace(/\\\\/g, '/');\n const match = normalized.match(/^(.+?)\\/app$/);\n if (match && match[1]) {\n return match[1];\n }\n return ''; // Standard Laravel, no prefix\n}\n\n/**\n * Replace placeholders in stub content\n * - {{LARAVEL_BASE}} -> app folder path (e.g., 'app' or 'backend/app')\n * - {{LARAVEL_ROOT}} -> project root (e.g., '' or 'backend/')\n * - {{TYPESCRIPT_BASE}} -> TypeScript base path (e.g., 'resources/ts' or 'frontend/src')\n */\nfunction replacePlaceholders(content: string, basePath: string, typescriptPath?: string): string {\n const root = extractLaravelRoot(basePath);\n let result = content.replace(/\\{\\{LARAVEL_BASE\\}\\}/g, basePath);\n\n // Replace {{LARAVEL_ROOT}} with root path (with trailing slash if not empty)\n if (root) {\n result = result.replace(/\\{\\{LARAVEL_ROOT\\}\\}/g, root + '/');\n } else {\n result = result.replace(/\\{\\{LARAVEL_ROOT\\}\\}/g, '');\n }\n\n // Replace {{TYPESCRIPT_BASE}} with TypeScript path\n const tsPath = typescriptPath || 'resources/ts';\n result = result.replace(/\\{\\{TYPESCRIPT_BASE\\}\\}/g, tsPath);\n\n return result;\n}\n\n/**\n * Copy .stub files to destination, removing .stub extension and replacing placeholders\n */\nfunction copyStubs(\n srcDir: string,\n destDir: string,\n transform?: (content: string) => string\n): string[] {\n const writtenFiles: string[] = [];\n\n if (!existsSync(srcDir)) {\n return writtenFiles;\n }\n\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n\n const entries = readdirSync(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(srcDir, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively copy subdirectories\n const subDestDir = join(destDir, entry.name);\n const subFiles = copyStubs(srcPath, subDestDir, transform);\n writtenFiles.push(...subFiles);\n } else if (entry.isFile() && entry.name.endsWith('.stub')) {\n // Remove .stub extension\n const destName = entry.name.slice(0, -5);\n const destPath = join(destDir, destName);\n\n let content = readFileSync(srcPath, 'utf-8');\n\n if (transform) {\n content = transform(content);\n }\n\n writeFileSync(destPath, content);\n writtenFiles.push(destPath);\n }\n }\n\n return writtenFiles;\n}\n\n/**\n * Generate AI guides for Claude and Cursor\n */\nexport function generateAIGuides(\n rootDir: string,\n options: AIGuidesOptions = {}\n): AIGuidesResult {\n const stubsDir = getStubsDir();\n const basePath = options.laravelBasePath || extractLaravelBasePath(options.modelsPath);\n const tsPath = options.typescriptBasePath || 'resources/ts';\n\n const result: AIGuidesResult = {\n claudeGuides: 0,\n claudeRules: 0,\n claudeChecklists: 0,\n claudeWorkflows: 0,\n claudeAgents: 0,\n claudeOmnify: 0,\n cursorRules: 0,\n files: [],\n };\n\n // All Claude files go under .claude/omnify/\n\n // 0. Copy README.md to .claude/omnify/\n const readmeSrcPath = join(stubsDir, 'README.md.stub');\n if (existsSync(readmeSrcPath)) {\n const readmeDestDir = resolve(rootDir, '.claude/omnify');\n if (!existsSync(readmeDestDir)) {\n mkdirSync(readmeDestDir, { recursive: true });\n }\n const content = readFileSync(readmeSrcPath, 'utf-8');\n writeFileSync(resolve(readmeDestDir, 'README.md'), content);\n result.files.push(resolve(readmeDestDir, 'README.md'));\n }\n\n // 1. Copy Laravel guides to .claude/omnify/guides/laravel/\n const claudeSrcDir = join(stubsDir, 'laravel');\n const claudeDestDir = resolve(rootDir, '.claude/omnify/guides/laravel');\n\n if (existsSync(claudeSrcDir)) {\n const files = copyStubs(claudeSrcDir, claudeDestDir);\n result.claudeGuides = files.length;\n result.files.push(...files);\n }\n\n // 1b. Copy React guides to .claude/omnify/guides/react/\n const reactSrcDir = join(stubsDir, 'react');\n const reactDestDir = resolve(rootDir, '.claude/omnify/guides/react');\n\n if (existsSync(reactSrcDir)) {\n const files = copyStubs(reactSrcDir, reactDestDir);\n result.claudeGuides += files.length;\n result.files.push(...files);\n }\n\n // 2. Copy rules to .claude/rules/omnify/ (Claude Code official location)\n // These are path-specific rules with `paths:` frontmatter\n const claudeRulesSrcDir = join(stubsDir, 'claude-rules');\n const claudeRulesDestDir = resolve(rootDir, '.claude/rules/omnify');\n\n if (existsSync(claudeRulesSrcDir)) {\n const files = copyStubs(claudeRulesSrcDir, claudeRulesDestDir, (content) =>\n replacePlaceholders(content, basePath, tsPath)\n );\n result.claudeRules = files.length;\n result.files.push(...files);\n }\n\n // 3. Copy checklists to .claude/omnify/checklists/\n const claudeChecklistsSrcDir = join(stubsDir, 'claude-checklists');\n const claudeChecklistsDestDir = resolve(rootDir, '.claude/omnify/checklists');\n\n if (existsSync(claudeChecklistsSrcDir)) {\n const files = copyStubs(claudeChecklistsSrcDir, claudeChecklistsDestDir);\n result.claudeChecklists = files.length;\n result.files.push(...files);\n }\n\n // 4. Copy workflows to .claude/omnify/workflows/\n const claudeWorkflowsSrcDir = join(stubsDir, 'claude-workflows');\n const claudeWorkflowsDestDir = resolve(rootDir, '.claude/omnify/workflows');\n\n if (existsSync(claudeWorkflowsSrcDir)) {\n const files = copyStubs(claudeWorkflowsSrcDir, claudeWorkflowsDestDir);\n result.claudeWorkflows = files.length;\n result.files.push(...files);\n }\n\n // 5. Copy agents to .claude/omnify/agents/\n const claudeAgentsSrcDir = join(stubsDir, 'claude-agents');\n const claudeAgentsDestDir = resolve(rootDir, '.claude/omnify/agents');\n\n if (existsSync(claudeAgentsSrcDir)) {\n const files = copyStubs(claudeAgentsSrcDir, claudeAgentsDestDir);\n result.claudeAgents = files.length;\n result.files.push(...files);\n }\n\n // 6. Copy omnify docs to .claude/omnify/guides/omnify/\n const claudeOmnifySrcDir = join(stubsDir, 'claude-omnify');\n const claudeOmnifyDestDir = resolve(rootDir, '.claude/omnify/guides/omnify');\n\n if (existsSync(claudeOmnifySrcDir)) {\n const files = copyStubs(claudeOmnifySrcDir, claudeOmnifyDestDir);\n result.claudeOmnify = files.length;\n result.files.push(...files);\n }\n\n // 7. Copy Cursor rules to .cursor/rules/omnify/\n const cursorSrcDir = join(stubsDir, 'cursor');\n const cursorDestDir = resolve(rootDir, '.cursor/rules/omnify');\n\n if (existsSync(cursorSrcDir)) {\n const files = copyStubs(cursorSrcDir, cursorDestDir, (content) =>\n replacePlaceholders(content, basePath, tsPath)\n );\n result.cursorRules = files.length;\n result.files.push(...files);\n }\n\n // Clean up root-level duplicates (from postinstall) that are now in guides/omnify/\n cleanupRootLevelDuplicates(rootDir);\n\n return result;\n}\n\n/**\n * Remove root-level files that are now properly located in guides/omnify/\n * This cleans up duplicates from postinstall that existed before generate was run\n */\nfunction cleanupRootLevelDuplicates(rootDir: string): void {\n const claudeOmnify = resolve(rootDir, '.claude/omnify');\n const guidesOmnify = resolve(rootDir, '.claude/omnify/guides/omnify');\n\n if (!existsSync(guidesOmnify)) return;\n\n // Files that should only be in guides/omnify/, not at root\n const filesToCleanup = [\n 'schema-guide.md',\n 'config-guide.md',\n 'typescript-guide.md',\n 'laravel-guide.md',\n 'antdesign-guide.md',\n 'react-form-guide.md',\n 'japan-guide.md',\n ];\n\n for (const file of filesToCleanup) {\n const rootFile = resolve(claudeOmnify, file);\n const guidesFile = resolve(guidesOmnify, file);\n\n // Only remove if both exist (duplicate)\n if (existsSync(rootFile) && existsSync(guidesFile)) {\n try {\n unlinkSync(rootFile);\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * Check if AI guides need to be generated\n */\nexport function shouldGenerateAIGuides(rootDir: string): boolean {\n const claudeDir = resolve(rootDir, '.claude/omnify/guides/laravel');\n const cursorDir = resolve(rootDir, '.cursor/rules/omnify');\n\n if (!existsSync(claudeDir) || !existsSync(cursorDir)) {\n return true;\n }\n\n try {\n const claudeFiles = readdirSync(claudeDir);\n const cursorFiles = readdirSync(cursorDir);\n const hasLaravelRules = cursorFiles.some((f) => f.startsWith('laravel'));\n\n return claudeFiles.length === 0 || !hasLaravelRules;\n } catch {\n return true;\n }\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkGpB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA6BV,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmDpB,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["isNullable","columnMethod","TYPE_METHOD_MAP","generateTimestamp","import_omnify_types","hasAutoId","properties","typeDef","isCompoundType","resolveOptions","getStubContent","isNullable","import_node_fs","import_node_path","import_omnify_types","DEFAULT_OPTIONS","escapePhpString","resolveOptions","isNullable","module","rules","displayName","openApiType","constraints","example","prop","import_omnify_types","DEFAULT_OPTIONS","SKIP_FIELDS","openApiType","prop","resolveOptions","escapePhpString","getModuleName","module","resolveOptions"]}
|