@famgia/omnify-laravel 0.0.29 → 0.0.31

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/index.cjs CHANGED
@@ -47,8 +47,10 @@ __export(index_exports, {
47
47
  module.exports = __toCommonJS(index_exports);
48
48
 
49
49
  // src/migration/schema-builder.ts
50
+ var import_omnify_types = require("@famgia/omnify-types");
50
51
  var TYPE_METHOD_MAP = {
51
52
  String: "string",
53
+ TinyInt: "tinyInteger",
52
54
  Int: "integer",
53
55
  BigInt: "bigInteger",
54
56
  Float: "double",
@@ -63,7 +65,9 @@ var TYPE_METHOD_MAP = {
63
65
  Json: "json",
64
66
  Email: "string",
65
67
  Password: "string",
66
- Enum: "enum"
68
+ Enum: "enum",
69
+ EnumRef: "string"
70
+ // EnumRef stores the enum value as string (lookup via schema)
67
71
  // Note: File type is now polymorphic - no column generated, uses files table
68
72
  };
69
73
  var PK_METHOD_MAP = {
@@ -91,7 +95,7 @@ function toTableName(schemaName) {
91
95
  return snakeCase + "s";
92
96
  }
93
97
  }
94
- function propertyToColumnMethod(propertyName, property) {
98
+ function propertyToColumnMethod(propertyName, property, options = {}) {
95
99
  if (property.type === "Association") {
96
100
  return null;
97
101
  }
@@ -105,6 +109,8 @@ function propertyToColumnMethod(propertyName, property) {
105
109
  const propWithLength = property;
106
110
  if (method === "string" && propWithLength.length) {
107
111
  args.push(propWithLength.length);
112
+ } else if (property.type === "EnumRef") {
113
+ args.push(50);
108
114
  }
109
115
  if (property.type === "Decimal") {
110
116
  const decimalProp = property;
@@ -128,12 +134,15 @@ function propertyToColumnMethod(propertyName, property) {
128
134
  if (baseProp.default !== void 0 && baseProp.default !== null) {
129
135
  modifiers.push({ method: "default", args: [baseProp.default] });
130
136
  }
131
- if (baseProp.unsigned && (method === "integer" || method === "bigInteger")) {
137
+ if (baseProp.unsigned && (method === "tinyInteger" || method === "integer" || method === "bigInteger")) {
132
138
  modifiers.push({ method: "unsigned" });
133
139
  }
134
- const displayName = property.displayName;
135
- if (displayName) {
136
- modifiers.push({ method: "comment", args: [displayName] });
140
+ const rawDisplayName = property.displayName;
141
+ if (rawDisplayName) {
142
+ const displayName = (0, import_omnify_types.resolveLocalizedString)(rawDisplayName, options.locale);
143
+ if (displayName) {
144
+ modifiers.push({ method: "comment", args: [displayName] });
145
+ }
137
146
  }
138
147
  return {
139
148
  name: columnName,
@@ -239,7 +248,7 @@ function generatePolymorphicColumns(propertyName, property, allSchemas) {
239
248
  ];
240
249
  return { typeColumn, idColumn, indexes };
241
250
  }
242
- function generateForeignKey(propertyName, property, allSchemas) {
251
+ function generateForeignKey(propertyName, property, allSchemas, options = {}) {
243
252
  if (property.type !== "Association") {
244
253
  return null;
245
254
  }
@@ -270,7 +279,10 @@ function generateForeignKey(propertyName, property, allSchemas) {
270
279
  modifiers.push({ method: "default", args: [assocProp.default] });
271
280
  }
272
281
  if (assocProp.displayName) {
273
- modifiers.push({ method: "comment", args: [assocProp.displayName] });
282
+ const displayName = (0, import_omnify_types.resolveLocalizedString)(assocProp.displayName, options.locale);
283
+ if (displayName) {
284
+ modifiers.push({ method: "comment", args: [displayName] });
285
+ }
274
286
  }
275
287
  const column = {
276
288
  name: columnName,
@@ -291,7 +303,7 @@ function generateForeignKey(propertyName, property, allSchemas) {
291
303
  };
292
304
  return { column, foreignKey, index };
293
305
  }
294
- function expandCompoundType(propName, property, customTypes) {
306
+ function expandCompoundType(propName, property, customTypes, options = {}) {
295
307
  const typeDef = customTypes.get(property.type);
296
308
  if (!typeDef || !typeDef.compound || !typeDef.expand) {
297
309
  return null;
@@ -305,13 +317,26 @@ function expandCompoundType(propName, property, customTypes) {
305
317
  type: "String"
306
318
  // Default type, will be overridden by sql definition
307
319
  };
308
- if (field.sql) {
320
+ const fieldOverrides = baseProp.fields;
321
+ const fieldOverride = fieldOverrides?.[field.suffix];
322
+ const fieldWithEnumRef = field;
323
+ if (fieldWithEnumRef.enumRef) {
324
+ expandedProp.type = "EnumRef";
325
+ expandedProp.enum = fieldWithEnumRef.enumRef;
326
+ if (fieldOverride?.nullable !== void 0) {
327
+ expandedProp.nullable = fieldOverride.nullable;
328
+ } else if (baseProp.nullable !== void 0) {
329
+ expandedProp.nullable = baseProp.nullable;
330
+ }
331
+ } else if (field.sql) {
309
332
  const sqlType = field.sql.sqlType.toUpperCase();
310
333
  if (sqlType === "VARCHAR" || sqlType === "CHAR" || sqlType === "STRING") {
311
334
  expandedProp.type = "String";
312
335
  if (field.sql.length) {
313
336
  expandedProp.length = field.sql.length;
314
337
  }
338
+ } else if (sqlType === "TINYINT") {
339
+ expandedProp.type = "TinyInt";
315
340
  } else if (sqlType === "INT" || sqlType === "INTEGER") {
316
341
  expandedProp.type = "Int";
317
342
  } else if (sqlType === "BIGINT") {
@@ -329,17 +354,29 @@ function expandCompoundType(propName, property, customTypes) {
329
354
  } else if (sqlType === "TIMESTAMP" || sqlType === "DATETIME") {
330
355
  expandedProp.type = "Timestamp";
331
356
  }
357
+ if (field.sql.unsigned) {
358
+ expandedProp.unsigned = true;
359
+ }
360
+ if (field.sql.default !== void 0) {
361
+ expandedProp.default = field.sql.default;
362
+ }
332
363
  if (field.sql.nullable !== void 0) {
333
364
  expandedProp.nullable = field.sql.nullable;
334
365
  } else if (baseProp.nullable !== void 0) {
335
366
  expandedProp.nullable = baseProp.nullable;
336
367
  }
337
- if (field.sql.default !== void 0) {
338
- expandedProp.default = field.sql.default;
368
+ if (fieldOverride?.nullable !== void 0) {
369
+ expandedProp.nullable = fieldOverride.nullable;
339
370
  }
340
371
  }
341
372
  if (baseProp.displayName) {
342
- expandedProp.displayName = `${baseProp.displayName} (${field.suffix})`;
373
+ const resolvedDisplayName = (0, import_omnify_types.resolveLocalizedString)(
374
+ baseProp.displayName,
375
+ options.locale
376
+ );
377
+ if (resolvedDisplayName) {
378
+ expandedProp.displayName = `${resolvedDisplayName} (${field.suffix})`;
379
+ }
343
380
  }
344
381
  expanded.push({
345
382
  name: columnName,
@@ -349,7 +386,8 @@ function expandCompoundType(propName, property, customTypes) {
349
386
  return expanded;
350
387
  }
351
388
  function schemaToBlueprint(schema, allSchemas, options = {}) {
352
- const { customTypes = /* @__PURE__ */ new Map() } = options;
389
+ const { customTypes = /* @__PURE__ */ new Map(), locale } = options;
390
+ const columnOptions = { locale };
353
391
  const tableName = toTableName(schema.name);
354
392
  const columns = [];
355
393
  const foreignKeys = [];
@@ -360,21 +398,21 @@ function schemaToBlueprint(schema, allSchemas, options = {}) {
360
398
  }
361
399
  if (schema.properties) {
362
400
  for (const [propName, property] of Object.entries(schema.properties)) {
363
- const expandedProps = expandCompoundType(propName, property, customTypes);
401
+ const expandedProps = expandCompoundType(propName, property, customTypes, columnOptions);
364
402
  if (expandedProps) {
365
403
  for (const { name: expandedName, property: expandedProp } of expandedProps) {
366
- const columnMethod2 = propertyToColumnMethod(expandedName, expandedProp);
404
+ const columnMethod2 = propertyToColumnMethod(expandedName, expandedProp, columnOptions);
367
405
  if (columnMethod2) {
368
406
  columns.push(columnMethod2);
369
407
  }
370
408
  }
371
409
  continue;
372
410
  }
373
- const columnMethod = propertyToColumnMethod(propName, property);
411
+ const columnMethod = propertyToColumnMethod(propName, property, columnOptions);
374
412
  if (columnMethod) {
375
413
  columns.push(columnMethod);
376
414
  }
377
- const fkResult = generateForeignKey(propName, property, allSchemas);
415
+ const fkResult = generateForeignKey(propName, property, allSchemas, columnOptions);
378
416
  if (fkResult) {
379
417
  columns.push(fkResult.column);
380
418
  foreignKeys.push(fkResult.foreignKey);
@@ -817,7 +855,8 @@ function generateMigrations(schemas, options = {}) {
817
855
  const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
818
856
  timestampOffset++;
819
857
  const blueprint = schemaToBlueprint(schema, schemas, {
820
- customTypes: options.customTypes
858
+ customTypes: options.customTypes,
859
+ locale: options.locale
821
860
  });
822
861
  const migration = generateCreateMigration(blueprint, {
823
862
  ...options,
@@ -1167,7 +1206,7 @@ function generateMigrationsFromChanges(changes, options = {}) {
1167
1206
  }
1168
1207
 
1169
1208
  // src/model/generator.ts
1170
- var import_omnify_types = require("@famgia/omnify-types");
1209
+ var import_omnify_types2 = require("@famgia/omnify-types");
1171
1210
 
1172
1211
  // src/utils.ts
1173
1212
  function toSnakeCase(str) {
@@ -1196,7 +1235,8 @@ var DEFAULT_OPTIONS = {
1196
1235
  modelNamespace: "App\\Models",
1197
1236
  baseModelClassName: "BaseModel",
1198
1237
  baseModelPath: "app/Models/OmnifyBase",
1199
- modelPath: "app/Models"
1238
+ modelPath: "app/Models",
1239
+ customTypes: /* @__PURE__ */ new Map()
1200
1240
  };
1201
1241
  function generateLocalizedDisplayNames(displayName, indent = " ") {
1202
1242
  if (displayName === void 0) {
@@ -1205,7 +1245,7 @@ function generateLocalizedDisplayNames(displayName, indent = " ") {
1205
1245
  if (typeof displayName === "string") {
1206
1246
  return `${indent}'en' => '${escapePhpString(displayName)}',`;
1207
1247
  }
1208
- if ((0, import_omnify_types.isLocaleMap)(displayName)) {
1248
+ if ((0, import_omnify_types2.isLocaleMap)(displayName)) {
1209
1249
  const entries = Object.entries(displayName).map(([locale, value]) => `${indent}'${locale}' => '${escapePhpString(value)}',`).join("\n");
1210
1250
  return entries;
1211
1251
  }
@@ -1225,7 +1265,7 @@ function generatePropertyLocalizedDisplayNames(schema, indent = " ") {
1225
1265
  entries.push(`${indent}'${snakeName}' => [
1226
1266
  ${innerIndent}'en' => '${escapePhpString(displayName)}',
1227
1267
  ${indent}],`);
1228
- } else if ((0, import_omnify_types.isLocaleMap)(displayName)) {
1268
+ } else if ((0, import_omnify_types2.isLocaleMap)(displayName)) {
1229
1269
  const localeEntries = Object.entries(displayName).map(([locale, value]) => `${innerIndent}'${locale}' => '${escapePhpString(value)}',`).join("\n");
1230
1270
  entries.push(`${indent}'${snakeName}' => [
1231
1271
  ${localeEntries}
@@ -1243,7 +1283,8 @@ function resolveOptions(options) {
1243
1283
  modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS.modelNamespace,
1244
1284
  baseModelClassName: options?.baseModelClassName ?? DEFAULT_OPTIONS.baseModelClassName,
1245
1285
  baseModelPath: options?.baseModelPath ?? DEFAULT_OPTIONS.baseModelPath,
1246
- modelPath: options?.modelPath ?? DEFAULT_OPTIONS.modelPath
1286
+ modelPath: options?.modelPath ?? DEFAULT_OPTIONS.modelPath,
1287
+ customTypes: options?.customTypes ?? /* @__PURE__ */ new Map()
1247
1288
  };
1248
1289
  }
1249
1290
  function getCastType(propDef) {
@@ -1374,7 +1415,10 @@ function generateEntityBaseModel(schema, schemas, options, stubContent, authStub
1374
1415
  }
1375
1416
  }
1376
1417
  } else if (propDef.type === "Password") {
1377
- fillable.push(` '${snakeName}',`);
1418
+ const propWithFillable = propDef;
1419
+ if (propWithFillable.fillable !== false) {
1420
+ fillable.push(` '${snakeName}',`);
1421
+ }
1378
1422
  hidden.push(` '${snakeName}',`);
1379
1423
  const cast = getCastType(propDef);
1380
1424
  if (cast) {
@@ -1384,10 +1428,58 @@ function generateEntityBaseModel(schema, schemas, options, stubContent, authStub
1384
1428
  const relMethod = generateFileRelation(propName, propDef);
1385
1429
  relations.push(relMethod);
1386
1430
  } else {
1387
- fillable.push(` '${snakeName}',`);
1388
- const cast = getCastType(propDef);
1389
- if (cast) {
1390
- casts.push(` '${snakeName}' => '${cast}',`);
1431
+ const propWithOptions = propDef;
1432
+ const isFillable = propWithOptions.fillable !== false;
1433
+ const isHidden = propWithOptions.hidden === true;
1434
+ const typeDef = options.customTypes.get(propDef.type);
1435
+ const isCompoundType = typeDef?.compound && typeDef.expand;
1436
+ if (isCompoundType && typeDef.expand) {
1437
+ const fieldOverrides = propWithOptions.fields ?? {};
1438
+ for (const field of typeDef.expand) {
1439
+ const suffixSnake = toSnakeCase(field.suffix);
1440
+ const fieldName = `${snakeName}_${suffixSnake}`;
1441
+ const override = fieldOverrides[field.suffix];
1442
+ const fieldFillable = override?.fillable !== void 0 ? override.fillable : isFillable;
1443
+ if (fieldFillable) {
1444
+ fillable.push(` '${fieldName}',`);
1445
+ }
1446
+ const fieldHidden = override?.hidden !== void 0 ? override.hidden : isHidden;
1447
+ if (fieldHidden) {
1448
+ hidden.push(` '${fieldName}',`);
1449
+ }
1450
+ }
1451
+ } else {
1452
+ if (isFillable) {
1453
+ fillable.push(` '${snakeName}',`);
1454
+ }
1455
+ const cast = getCastType(propDef);
1456
+ if (cast) {
1457
+ casts.push(` '${snakeName}' => '${cast}',`);
1458
+ }
1459
+ if (isHidden) {
1460
+ hidden.push(` '${snakeName}',`);
1461
+ }
1462
+ }
1463
+ if (typeDef?.compound && typeDef.accessors) {
1464
+ for (const accessor of typeDef.accessors) {
1465
+ const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;
1466
+ appends.push(` '${accessorName}',`);
1467
+ const methodName = toPascalCase(accessorName);
1468
+ const separator = accessor.separator ?? " ";
1469
+ const fieldRefs = accessor.fields.map((field) => {
1470
+ const fieldName = `${snakeName}_${toSnakeCase(field)}`;
1471
+ return `$this->${fieldName}`;
1472
+ });
1473
+ const accessorMethod = ` /**
1474
+ * Get the ${accessor.name.replace(/_/g, " ")} attribute.
1475
+ */
1476
+ public function get${methodName}Attribute(): ?string
1477
+ {
1478
+ $parts = array_filter([${fieldRefs.join(", ")}], fn($v) => $v !== null && $v !== '');
1479
+ return count($parts) > 0 ? implode('${separator}', $parts) : null;
1480
+ }`;
1481
+ relations.push(accessorMethod);
1482
+ }
1391
1483
  }
1392
1484
  }
1393
1485
  }
@@ -2598,7 +2690,8 @@ function laravelPlugin(options) {
2598
2690
  modelNamespace: resolved.modelNamespace,
2599
2691
  baseModelNamespace: resolved.baseModelNamespace,
2600
2692
  modelPath: resolved.modelsPath,
2601
- baseModelPath: resolved.baseModelsPath
2693
+ baseModelPath: resolved.baseModelsPath,
2694
+ customTypes: ctx.customTypes
2602
2695
  };
2603
2696
  const models = generateModels(ctx.schemas, modelOptions);
2604
2697
  const outputs = models.map((model) => ({