@famgia/omnify-laravel 0.0.13 → 0.0.14

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.
@@ -266,11 +266,18 @@ function schemaToBlueprint(schema, allSchemas) {
266
266
  }
267
267
  if (schema.options?.indexes) {
268
268
  for (const index of schema.options.indexes) {
269
- indexes.push({
270
- name: index.name,
271
- columns: index.columns.map(toColumnName),
272
- unique: index.unique ?? false
273
- });
269
+ if (typeof index === "string") {
270
+ indexes.push({
271
+ columns: [toColumnName(index)],
272
+ unique: false
273
+ });
274
+ } else {
275
+ indexes.push({
276
+ name: index.name,
277
+ columns: index.columns.map(toColumnName),
278
+ unique: index.unique ?? false
279
+ });
280
+ }
274
281
  }
275
282
  }
276
283
  if (schema.options?.unique) {
@@ -988,6 +995,579 @@ function generateMigrationsFromChanges(changes, options = {}) {
988
995
  return migrations;
989
996
  }
990
997
 
998
+ // src/utils.ts
999
+ function toSnakeCase(str) {
1000
+ return str.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
1001
+ }
1002
+ function toPascalCase(str) {
1003
+ return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, (_, c) => c.toUpperCase());
1004
+ }
1005
+ function toCamelCase(str) {
1006
+ const pascal = toPascalCase(str);
1007
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
1008
+ }
1009
+ function pluralize(word) {
1010
+ if (word.endsWith("y") && !["ay", "ey", "iy", "oy", "uy"].some((v) => word.endsWith(v))) {
1011
+ return word.slice(0, -1) + "ies";
1012
+ }
1013
+ if (word.endsWith("s") || word.endsWith("x") || word.endsWith("z") || word.endsWith("ch") || word.endsWith("sh")) {
1014
+ return word + "es";
1015
+ }
1016
+ return word + "s";
1017
+ }
1018
+
1019
+ // src/model/generator.ts
1020
+ var DEFAULT_OPTIONS = {
1021
+ baseModelNamespace: "App\\Models\\OmnifyBase",
1022
+ modelNamespace: "App\\Models",
1023
+ baseModelClassName: "BaseModel",
1024
+ baseModelPath: "app/Models/OmnifyBase",
1025
+ modelPath: "app/Models"
1026
+ };
1027
+ function resolveOptions(options) {
1028
+ return {
1029
+ baseModelNamespace: options?.baseModelNamespace ?? DEFAULT_OPTIONS.baseModelNamespace,
1030
+ modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,
1031
+ baseModelClassName: options?.baseModelClassName ?? DEFAULT_OPTIONS.baseModelClassName,
1032
+ baseModelPath: options?.baseModelPath ?? DEFAULT_OPTIONS.baseModelPath,
1033
+ modelPath: options?.modelPath ?? DEFAULT_OPTIONS.modelPath
1034
+ };
1035
+ }
1036
+ function getCastType(propDef) {
1037
+ switch (propDef.type) {
1038
+ case "Boolean":
1039
+ return "boolean";
1040
+ case "Int":
1041
+ case "BigInt":
1042
+ return "integer";
1043
+ case "Float":
1044
+ return "float";
1045
+ case "Decimal":
1046
+ return "decimal:" + (propDef.scale ?? 2);
1047
+ case "Json":
1048
+ return "array";
1049
+ case "Date":
1050
+ return "date";
1051
+ case "Timestamp":
1052
+ return "datetime";
1053
+ case "Password":
1054
+ return "hashed";
1055
+ default:
1056
+ return null;
1057
+ }
1058
+ }
1059
+ function isNullable(propDef) {
1060
+ return "nullable" in propDef && propDef.nullable === true;
1061
+ }
1062
+ function getPhpDocType(propDef, schemas) {
1063
+ const nullable = isNullable(propDef);
1064
+ switch (propDef.type) {
1065
+ case "String":
1066
+ case "Text":
1067
+ case "LongText":
1068
+ case "Email":
1069
+ case "Password":
1070
+ return "string" + (nullable ? "|null" : "");
1071
+ case "Int":
1072
+ case "BigInt":
1073
+ return "int" + (nullable ? "|null" : "");
1074
+ case "Float":
1075
+ case "Decimal":
1076
+ return "float" + (nullable ? "|null" : "");
1077
+ case "Boolean":
1078
+ return "bool" + (nullable ? "|null" : "");
1079
+ case "Date":
1080
+ case "Time":
1081
+ case "Timestamp":
1082
+ return "\\Carbon\\Carbon" + (nullable ? "|null" : "");
1083
+ case "Json":
1084
+ return "array" + (nullable ? "|null" : "");
1085
+ case "Enum":
1086
+ case "EnumRef":
1087
+ return "string" + (nullable ? "|null" : "");
1088
+ case "Association": {
1089
+ const assoc = propDef;
1090
+ if (assoc.target) {
1091
+ const className = toPascalCase(assoc.target);
1092
+ switch (assoc.relation) {
1093
+ case "OneToMany":
1094
+ case "ManyToMany":
1095
+ case "MorphMany":
1096
+ case "MorphToMany":
1097
+ case "MorphedByMany":
1098
+ return `\\Illuminate\\Database\\Eloquent\\Collection<${className}>`;
1099
+ default:
1100
+ return className + "|null";
1101
+ }
1102
+ }
1103
+ return "mixed";
1104
+ }
1105
+ default:
1106
+ return "mixed";
1107
+ }
1108
+ }
1109
+ function generateBaseModel(schemas, options, stubContent) {
1110
+ const modelMap = Object.values(schemas).filter((s) => s.kind !== "enum").map((s) => {
1111
+ const className = toPascalCase(s.name);
1112
+ return ` '${s.name}' => \\${options.modelNamespace}\\${className}::class,`;
1113
+ }).join("\n");
1114
+ const content = stubContent.replace(/\{\{BASE_MODEL_NAMESPACE\}\}/g, options.baseModelNamespace).replace(/\{\{BASE_MODEL_CLASS\}\}/g, options.baseModelClassName).replace(/\{\{MODEL_MAP\}\}/g, modelMap);
1115
+ return {
1116
+ path: `${options.baseModelPath}/${options.baseModelClassName}.php`,
1117
+ content,
1118
+ type: "base-model",
1119
+ overwrite: true,
1120
+ schemaName: "__base__"
1121
+ };
1122
+ }
1123
+ function generateEntityBaseModel(schema, schemas, options, stubContent, authStubContent) {
1124
+ const className = toPascalCase(schema.name);
1125
+ const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));
1126
+ const isAuth = schema.options?.authenticatable ?? false;
1127
+ const primaryKey = "id";
1128
+ const idType = schema.options?.idType ?? "BigInt";
1129
+ const isUuid = idType === "Uuid";
1130
+ const isStringKey = idType === "Uuid" || idType === "String";
1131
+ const imports = [];
1132
+ const traits = [];
1133
+ const fillable = [];
1134
+ const hidden = [];
1135
+ const appends = [];
1136
+ const casts = [];
1137
+ const relations = [];
1138
+ const docProperties = [];
1139
+ if (schema.options?.softDelete) {
1140
+ imports.push("use Illuminate\\Database\\Eloquent\\SoftDeletes;");
1141
+ traits.push(" use SoftDeletes;");
1142
+ }
1143
+ const properties = schema.properties ?? {};
1144
+ for (const [propName, propDef] of Object.entries(properties)) {
1145
+ const snakeName = toSnakeCase(propName);
1146
+ const phpType = getPhpDocType(propDef, schemas);
1147
+ docProperties.push(` * @property ${phpType} $${snakeName}`);
1148
+ if (propDef.type === "Association") {
1149
+ const assoc = propDef;
1150
+ if (assoc.target) {
1151
+ imports.push(`use ${options.modelNamespace}\\${toPascalCase(assoc.target)};`);
1152
+ }
1153
+ relations.push(generateRelation(propName, assoc, options));
1154
+ if (assoc.relation === "ManyToOne" || assoc.relation === "OneToOne") {
1155
+ if (!assoc.mappedBy) {
1156
+ const fkName = toSnakeCase(propName) + "_id";
1157
+ fillable.push(` '${fkName}',`);
1158
+ docProperties.push(` * @property int|null $${fkName}`);
1159
+ }
1160
+ }
1161
+ } else if (propDef.type === "Password") {
1162
+ fillable.push(` '${snakeName}',`);
1163
+ hidden.push(` '${snakeName}',`);
1164
+ const cast = getCastType(propDef);
1165
+ if (cast) {
1166
+ casts.push(` '${snakeName}' => '${cast}',`);
1167
+ }
1168
+ } else if (propDef.type === "File") {
1169
+ const relMethod = generateFileRelation(propName, propDef);
1170
+ relations.push(relMethod);
1171
+ } else {
1172
+ fillable.push(` '${snakeName}',`);
1173
+ const cast = getCastType(propDef);
1174
+ if (cast) {
1175
+ casts.push(` '${snakeName}' => '${cast}',`);
1176
+ }
1177
+ }
1178
+ }
1179
+ const docComment = `/**
1180
+ * ${className}BaseModel
1181
+ *
1182
+ ${docProperties.join("\n")}
1183
+ */`;
1184
+ const stub = isAuth ? authStubContent : stubContent;
1185
+ const keyType = isStringKey ? ` /**
1186
+ * The "type" of the primary key ID.
1187
+ */
1188
+ protected $keyType = 'string';
1189
+
1190
+ ` : "";
1191
+ const incrementing = isUuid ? ` /**
1192
+ * Indicates if the IDs are auto-incrementing.
1193
+ */
1194
+ public $incrementing = false;
1195
+
1196
+ ` : "";
1197
+ if (isUuid) {
1198
+ imports.push("use Illuminate\\Database\\Eloquent\\Concerns\\HasUuids;");
1199
+ traits.push(" use HasUuids;");
1200
+ }
1201
+ const content = stub.replace(/\{\{BASE_MODEL_NAMESPACE\}\}/g, options.baseModelNamespace).replace(/\{\{BASE_MODEL_CLASS\}\}/g, options.baseModelClassName).replace(/\{\{CLASS_NAME\}\}/g, className).replace(/\{\{TABLE_NAME\}\}/g, tableName).replace(/\{\{PRIMARY_KEY\}\}/g, primaryKey).replace(/\{\{KEY_TYPE\}\}/g, keyType).replace(/\{\{INCREMENTING\}\}/g, incrementing).replace(/\{\{TIMESTAMPS\}\}/g, schema.options?.timestamps !== false ? "true" : "false").replace(/\{\{IMPORTS\}\}/g, [...new Set(imports)].sort().join("\n")).replace(/\{\{TRAITS\}\}/g, traits.join("\n")).replace(/\{\{DOC_COMMENT\}\}/g, docComment).replace(/\{\{FILLABLE\}\}/g, fillable.join("\n")).replace(/\{\{HIDDEN\}\}/g, hidden.join("\n")).replace(/\{\{APPENDS\}\}/g, appends.join("\n")).replace(/\{\{CASTS\}\}/g, casts.join("\n")).replace(/\{\{RELATIONS\}\}/g, relations.join("\n\n"));
1202
+ return {
1203
+ path: `${options.baseModelPath}/${className}BaseModel.php`,
1204
+ content,
1205
+ type: "entity-base",
1206
+ overwrite: true,
1207
+ schemaName: schema.name
1208
+ };
1209
+ }
1210
+ function generateRelation(propName, assoc, options) {
1211
+ const methodName = toCamelCase(propName);
1212
+ const targetClass = assoc.target ? toPascalCase(assoc.target) : "";
1213
+ const fkName = toSnakeCase(propName) + "_id";
1214
+ switch (assoc.relation) {
1215
+ case "ManyToOne":
1216
+ return ` /**
1217
+ * Get the ${propName} that owns this model.
1218
+ */
1219
+ public function ${methodName}(): BelongsTo
1220
+ {
1221
+ return $this->belongsTo(${targetClass}::class, '${fkName}');
1222
+ }`;
1223
+ case "OneToOne":
1224
+ if (assoc.mappedBy) {
1225
+ return ` /**
1226
+ * Get the ${propName} for this model.
1227
+ */
1228
+ public function ${methodName}(): HasOne
1229
+ {
1230
+ return $this->hasOne(${targetClass}::class, '${toSnakeCase(assoc.mappedBy)}_id');
1231
+ }`;
1232
+ }
1233
+ return ` /**
1234
+ * Get the ${propName} that owns this model.
1235
+ */
1236
+ public function ${methodName}(): BelongsTo
1237
+ {
1238
+ return $this->belongsTo(${targetClass}::class, '${fkName}');
1239
+ }`;
1240
+ case "OneToMany":
1241
+ return ` /**
1242
+ * Get the ${propName} for this model.
1243
+ */
1244
+ public function ${methodName}(): HasMany
1245
+ {
1246
+ return $this->hasMany(${targetClass}::class, '${toSnakeCase(assoc.inversedBy ?? propName)}_id');
1247
+ }`;
1248
+ case "ManyToMany": {
1249
+ const pivotTable = assoc.joinTable ?? `${toSnakeCase(propName)}_pivot`;
1250
+ return ` /**
1251
+ * The ${propName} that belong to this model.
1252
+ */
1253
+ public function ${methodName}(): BelongsToMany
1254
+ {
1255
+ return $this->belongsToMany(${targetClass}::class, '${pivotTable}')
1256
+ ->withTimestamps();
1257
+ }`;
1258
+ }
1259
+ case "MorphTo":
1260
+ return ` /**
1261
+ * Get the parent ${propName} model.
1262
+ */
1263
+ public function ${methodName}(): MorphTo
1264
+ {
1265
+ return $this->morphTo('${methodName}');
1266
+ }`;
1267
+ case "MorphOne":
1268
+ return ` /**
1269
+ * Get the ${propName} for this model.
1270
+ */
1271
+ public function ${methodName}(): MorphOne
1272
+ {
1273
+ return $this->morphOne(${targetClass}::class, '${assoc.morphName ?? propName}');
1274
+ }`;
1275
+ case "MorphMany":
1276
+ return ` /**
1277
+ * Get the ${propName} for this model.
1278
+ */
1279
+ public function ${methodName}(): MorphMany
1280
+ {
1281
+ return $this->morphMany(${targetClass}::class, '${assoc.morphName ?? propName}');
1282
+ }`;
1283
+ default:
1284
+ return ` // TODO: Implement ${assoc.relation} relation for ${propName}`;
1285
+ }
1286
+ }
1287
+ function generateFileRelation(propName, propDef) {
1288
+ const methodName = toCamelCase(propName);
1289
+ const relationType = propDef.multiple ? "MorphMany" : "MorphOne";
1290
+ const relationMethod = propDef.multiple ? "morphMany" : "morphOne";
1291
+ return ` /**
1292
+ * Get the ${propName} file(s) for this model.
1293
+ */
1294
+ public function ${methodName}(): ${relationType}
1295
+ {
1296
+ return $this->${relationMethod}(FileUpload::class, 'uploadable')
1297
+ ->where('attribute_name', '${propName}');
1298
+ }`;
1299
+ }
1300
+ function generateEntityModel(schema, options, stubContent) {
1301
+ const className = toPascalCase(schema.name);
1302
+ const content = stubContent.replace(/\{\{BASE_MODEL_NAMESPACE\}\}/g, options.baseModelNamespace).replace(/\{\{MODEL_NAMESPACE\}\}/g, options.modelNamespace).replace(/\{\{CLASS_NAME\}\}/g, className);
1303
+ return {
1304
+ path: `${options.modelPath}/${className}.php`,
1305
+ content,
1306
+ type: "entity",
1307
+ overwrite: false,
1308
+ // Never overwrite user models
1309
+ schemaName: schema.name
1310
+ };
1311
+ }
1312
+ function getStubContent(stubName) {
1313
+ const stubs = {
1314
+ "base-model": `<?php
1315
+
1316
+ namespace {{BASE_MODEL_NAMESPACE}};
1317
+
1318
+ /**
1319
+ * Base model class for all Omnify-generated models.
1320
+ * Contains model mapping for polymorphic relations.
1321
+ *
1322
+ * DO NOT EDIT - This file is auto-generated by Omnify.
1323
+ * Any changes will be overwritten on next generation.
1324
+ *
1325
+ * @generated by @famgia/omnify-laravel
1326
+ */
1327
+
1328
+ use Illuminate\\Database\\Eloquent\\Model;
1329
+ use Illuminate\\Database\\Eloquent\\Relations\\Relation;
1330
+
1331
+ abstract class {{BASE_MODEL_CLASS}} extends Model
1332
+ {
1333
+ /**
1334
+ * Model class map for polymorphic relations.
1335
+ */
1336
+ protected static array $modelMap = [
1337
+ {{MODEL_MAP}}
1338
+ ];
1339
+
1340
+ /**
1341
+ * Boot the model and register morph map.
1342
+ */
1343
+ protected static function boot(): void
1344
+ {
1345
+ parent::boot();
1346
+
1347
+ // Register morph map for polymorphic relations
1348
+ Relation::enforceMorphMap(static::$modelMap);
1349
+ }
1350
+
1351
+ /**
1352
+ * Get the model class for a given morph type.
1353
+ */
1354
+ public static function getModelClass(string $morphType): ?string
1355
+ {
1356
+ return static::$modelMap[$morphType] ?? null;
1357
+ }
1358
+ }
1359
+ `,
1360
+ "entity-base": `<?php
1361
+
1362
+ namespace {{BASE_MODEL_NAMESPACE}};
1363
+
1364
+ /**
1365
+ * DO NOT EDIT - This file is auto-generated by Omnify.
1366
+ * Any changes will be overwritten on next generation.
1367
+ *
1368
+ * @generated by @famgia/omnify-laravel
1369
+ */
1370
+
1371
+ use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;
1372
+ use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
1373
+ use Illuminate\\Database\\Eloquent\\Relations\\HasOne;
1374
+ use Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;
1375
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphTo;
1376
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphOne;
1377
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
1378
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
1379
+ use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
1380
+ {{IMPORTS}}
1381
+
1382
+ {{DOC_COMMENT}}
1383
+ class {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}
1384
+ {
1385
+ {{TRAITS}}
1386
+ /**
1387
+ * The table associated with the model.
1388
+ */
1389
+ protected $table = '{{TABLE_NAME}}';
1390
+
1391
+ /**
1392
+ * The primary key for the model.
1393
+ */
1394
+ protected $primaryKey = '{{PRIMARY_KEY}}';
1395
+
1396
+ {{KEY_TYPE}}
1397
+ {{INCREMENTING}}
1398
+ /**
1399
+ * Indicates if the model should be timestamped.
1400
+ */
1401
+ public $timestamps = {{TIMESTAMPS}};
1402
+
1403
+ /**
1404
+ * The attributes that are mass assignable.
1405
+ */
1406
+ protected $fillable = [
1407
+ {{FILLABLE}}
1408
+ ];
1409
+
1410
+ /**
1411
+ * The attributes that should be hidden for serialization.
1412
+ */
1413
+ protected $hidden = [
1414
+ {{HIDDEN}}
1415
+ ];
1416
+
1417
+ /**
1418
+ * The accessors to append to the model's array form.
1419
+ */
1420
+ protected $appends = [
1421
+ {{APPENDS}}
1422
+ ];
1423
+
1424
+ /**
1425
+ * Get the attributes that should be cast.
1426
+ */
1427
+ protected function casts(): array
1428
+ {
1429
+ return [
1430
+ {{CASTS}}
1431
+ ];
1432
+ }
1433
+
1434
+ {{RELATIONS}}
1435
+ }
1436
+ `,
1437
+ "entity-base-auth": `<?php
1438
+
1439
+ namespace {{BASE_MODEL_NAMESPACE}};
1440
+
1441
+ /**
1442
+ * DO NOT EDIT - This file is auto-generated by Omnify.
1443
+ * Any changes will be overwritten on next generation.
1444
+ *
1445
+ * @generated by @famgia/omnify-laravel
1446
+ */
1447
+
1448
+ use Illuminate\\Foundation\\Auth\\User as Authenticatable;
1449
+ use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;
1450
+ use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
1451
+ use Illuminate\\Database\\Eloquent\\Relations\\HasOne;
1452
+ use Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;
1453
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphTo;
1454
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphOne;
1455
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
1456
+ use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
1457
+ use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
1458
+ use Illuminate\\Notifications\\Notifiable;
1459
+ {{IMPORTS}}
1460
+
1461
+ {{DOC_COMMENT}}
1462
+ class {{CLASS_NAME}}BaseModel extends Authenticatable
1463
+ {
1464
+ use Notifiable;
1465
+ {{TRAITS}}
1466
+ /**
1467
+ * The table associated with the model.
1468
+ */
1469
+ protected $table = '{{TABLE_NAME}}';
1470
+
1471
+ /**
1472
+ * The primary key for the model.
1473
+ */
1474
+ protected $primaryKey = '{{PRIMARY_KEY}}';
1475
+
1476
+ {{KEY_TYPE}}
1477
+ {{INCREMENTING}}
1478
+ /**
1479
+ * Indicates if the model should be timestamped.
1480
+ */
1481
+ public $timestamps = {{TIMESTAMPS}};
1482
+
1483
+ /**
1484
+ * The attributes that are mass assignable.
1485
+ */
1486
+ protected $fillable = [
1487
+ {{FILLABLE}}
1488
+ ];
1489
+
1490
+ /**
1491
+ * The attributes that should be hidden for serialization.
1492
+ */
1493
+ protected $hidden = [
1494
+ {{HIDDEN}}
1495
+ ];
1496
+
1497
+ /**
1498
+ * The accessors to append to the model's array form.
1499
+ */
1500
+ protected $appends = [
1501
+ {{APPENDS}}
1502
+ ];
1503
+
1504
+ /**
1505
+ * Get the attributes that should be cast.
1506
+ */
1507
+ protected function casts(): array
1508
+ {
1509
+ return [
1510
+ {{CASTS}}
1511
+ ];
1512
+ }
1513
+
1514
+ {{RELATIONS}}
1515
+ }
1516
+ `,
1517
+ "entity": `<?php
1518
+
1519
+ namespace {{MODEL_NAMESPACE}};
1520
+
1521
+ use {{BASE_MODEL_NAMESPACE}}\\{{CLASS_NAME}}BaseModel;
1522
+ use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
1523
+
1524
+ /**
1525
+ * {{CLASS_NAME}} Model
1526
+ *
1527
+ * This file is generated once and can be customized.
1528
+ * Add your custom methods and logic here.
1529
+ */
1530
+ class {{CLASS_NAME}} extends {{CLASS_NAME}}BaseModel
1531
+ {
1532
+ use HasFactory;
1533
+
1534
+ /**
1535
+ * Create a new model instance.
1536
+ */
1537
+ public function __construct(array $attributes = [])
1538
+ {
1539
+ parent::__construct($attributes);
1540
+ }
1541
+
1542
+ // Add your custom methods here
1543
+ }
1544
+ `
1545
+ };
1546
+ return stubs[stubName] ?? "";
1547
+ }
1548
+ function generateModels(schemas, options) {
1549
+ const resolved = resolveOptions(options);
1550
+ const models = [];
1551
+ models.push(generateBaseModel(schemas, resolved, getStubContent("base-model")));
1552
+ for (const schema of Object.values(schemas)) {
1553
+ if (schema.kind === "enum") {
1554
+ continue;
1555
+ }
1556
+ models.push(generateEntityBaseModel(
1557
+ schema,
1558
+ schemas,
1559
+ resolved,
1560
+ getStubContent("entity-base"),
1561
+ getStubContent("entity-base-auth")
1562
+ ));
1563
+ models.push(generateEntityModel(schema, resolved, getStubContent("entity")));
1564
+ }
1565
+ return models;
1566
+ }
1567
+ function getModelPath(model) {
1568
+ return model.path;
1569
+ }
1570
+
991
1571
  // src/plugin.ts
992
1572
  var LARAVEL_CONFIG_SCHEMA = {
993
1573
  fields: [
@@ -999,6 +1579,30 @@ var LARAVEL_CONFIG_SCHEMA = {
999
1579
  default: "database/migrations",
1000
1580
  group: "output"
1001
1581
  },
1582
+ {
1583
+ key: "modelsPath",
1584
+ type: "path",
1585
+ label: "Models Path",
1586
+ description: "Directory for user-editable model files",
1587
+ default: "app/Models",
1588
+ group: "output"
1589
+ },
1590
+ {
1591
+ key: "baseModelsPath",
1592
+ type: "path",
1593
+ label: "Base Models Path",
1594
+ description: "Directory for auto-generated base model files",
1595
+ default: "app/Models/OmnifyBase",
1596
+ group: "output"
1597
+ },
1598
+ {
1599
+ key: "generateModels",
1600
+ type: "boolean",
1601
+ label: "Generate Models",
1602
+ description: "Generate Eloquent model classes",
1603
+ default: true,
1604
+ group: "options"
1605
+ },
1002
1606
  {
1003
1607
  key: "connection",
1004
1608
  type: "string",
@@ -1009,41 +1613,69 @@ var LARAVEL_CONFIG_SCHEMA = {
1009
1613
  }
1010
1614
  ]
1011
1615
  };
1012
- function resolveOptions(options) {
1616
+ function resolveOptions2(options) {
1013
1617
  return {
1014
1618
  migrationsPath: options?.migrationsPath ?? "database/migrations",
1619
+ modelsPath: options?.modelsPath ?? "app/Models",
1620
+ baseModelsPath: options?.baseModelsPath ?? "app/Models/OmnifyBase",
1621
+ modelNamespace: options?.modelNamespace ?? "App\\Models",
1622
+ baseModelNamespace: options?.baseModelNamespace ?? "App\\Models\\OmnifyBase",
1623
+ generateModels: options?.generateModels ?? true,
1015
1624
  connection: options?.connection,
1016
1625
  timestamp: options?.timestamp
1017
1626
  };
1018
1627
  }
1019
1628
  function laravelPlugin(options) {
1020
- const resolved = resolveOptions(options);
1629
+ const resolved = resolveOptions2(options);
1630
+ const migrationGenerator = {
1631
+ name: "laravel-migrations",
1632
+ description: "Generate Laravel migration files",
1633
+ generate: async (ctx) => {
1634
+ const migrationOptions = {
1635
+ connection: resolved.connection,
1636
+ timestamp: resolved.timestamp
1637
+ };
1638
+ const migrations = generateMigrations(ctx.schemas, migrationOptions);
1639
+ return migrations.map((migration) => ({
1640
+ path: getMigrationPath(migration, resolved.migrationsPath),
1641
+ content: migration.content,
1642
+ type: "migration",
1643
+ metadata: {
1644
+ tableName: migration.tables[0],
1645
+ migrationType: migration.type
1646
+ }
1647
+ }));
1648
+ }
1649
+ };
1650
+ const modelGenerator = {
1651
+ name: "laravel-models",
1652
+ description: "Generate Eloquent model classes",
1653
+ generate: async (ctx) => {
1654
+ const modelOptions = {
1655
+ modelNamespace: resolved.modelNamespace,
1656
+ baseModelNamespace: resolved.baseModelNamespace,
1657
+ modelPath: resolved.modelsPath,
1658
+ baseModelPath: resolved.baseModelsPath
1659
+ };
1660
+ const models = generateModels(ctx.schemas, modelOptions);
1661
+ return models.map((model) => ({
1662
+ path: getModelPath(model),
1663
+ content: model.content,
1664
+ type: "model",
1665
+ // Skip writing user models if they already exist
1666
+ skipIfExists: !model.overwrite,
1667
+ metadata: {
1668
+ modelType: model.type,
1669
+ schemaName: model.schemaName
1670
+ }
1671
+ }));
1672
+ }
1673
+ };
1021
1674
  return {
1022
1675
  name: "@famgia/omnify-laravel",
1023
- version: "0.0.13",
1676
+ version: "0.0.14",
1024
1677
  configSchema: LARAVEL_CONFIG_SCHEMA,
1025
- generators: [
1026
- {
1027
- name: "laravel-migrations",
1028
- description: "Generate Laravel migration files",
1029
- generate: async (ctx) => {
1030
- const migrationOptions = {
1031
- connection: resolved.connection,
1032
- timestamp: resolved.timestamp
1033
- };
1034
- const migrations = generateMigrations(ctx.schemas, migrationOptions);
1035
- return migrations.map((migration) => ({
1036
- path: getMigrationPath(migration, resolved.migrationsPath),
1037
- content: migration.content,
1038
- type: "migration",
1039
- metadata: {
1040
- tableName: migration.tables[0],
1041
- migrationType: migration.type
1042
- }
1043
- }));
1044
- }
1045
- }
1046
- ]
1678
+ generators: resolved.generateModels ? [migrationGenerator, modelGenerator] : [migrationGenerator]
1047
1679
  };
1048
1680
  }
1049
1681
 
@@ -1069,4 +1701,4 @@ export {
1069
1701
  generateMigrationsFromChanges,
1070
1702
  laravelPlugin
1071
1703
  };
1072
- //# sourceMappingURL=chunk-G4UAJVC2.js.map
1704
+ //# sourceMappingURL=chunk-UVF7W2J2.js.map