@famgia/omnify-laravel 0.0.18 → 0.0.20

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/README.md CHANGED
@@ -90,11 +90,13 @@ const types = generateTypeScript(schemas, {
90
90
 
91
91
  - Laravel migration generation
92
92
  - TypeScript interface generation
93
+ - Eloquent model generation with localization support
93
94
  - Support for all Laravel column types
94
95
  - Relationship handling (belongsTo, hasMany, etc.)
95
96
  - Index and constraint generation
96
97
  - Enum type support
97
98
  - Plugin system with DAG-based generator ordering
99
+ - Multi-language displayName support (i18n)
98
100
 
99
101
  ## Generated Output
100
102
 
@@ -135,6 +137,134 @@ export interface User {
135
137
  }
136
138
  ```
137
139
 
140
+ ### Eloquent Models with Localized Display Names
141
+
142
+ The generator creates a clean model structure with separated locale data:
143
+
144
+ ```
145
+ app/Models/OmnifyBase/
146
+ ├── Traits/
147
+ │ └── HasLocalizedDisplayName.php # Reusable trait
148
+ ├── Locales/
149
+ │ ├── UserLocales.php # User locale data
150
+ │ ├── PostLocales.php # Post locale data
151
+ │ └── ...
152
+ ├── UserBaseModel.php # Clean base model
153
+ ├── PostBaseModel.php
154
+ └── ...
155
+ ```
156
+
157
+ #### Schema Definition with i18n
158
+
159
+ Define multi-language displayNames in your YAML schema:
160
+
161
+ ```yaml
162
+ # schemas/auth/User.yaml
163
+ name: User
164
+ displayName:
165
+ ja: ユーザー
166
+ en: User
167
+ vi: Người dùng
168
+
169
+ properties:
170
+ name:
171
+ type: String
172
+ displayName:
173
+ ja: 氏名
174
+ en: Full Name
175
+ vi: Họ tên
176
+
177
+ email:
178
+ type: String
179
+ unique: true
180
+ displayName:
181
+ ja: メールアドレス
182
+ en: Email Address
183
+ vi: Địa chỉ email
184
+ ```
185
+
186
+ #### Generated Locales Class
187
+
188
+ ```php
189
+ // app/Models/OmnifyBase/Locales/UserLocales.php
190
+ class UserLocales
191
+ {
192
+ public const DISPLAY_NAMES = [
193
+ 'ja' => 'ユーザー',
194
+ 'en' => 'User',
195
+ 'vi' => 'Người dùng',
196
+ ];
197
+
198
+ public const PROPERTY_DISPLAY_NAMES = [
199
+ 'name' => [
200
+ 'ja' => '氏名',
201
+ 'en' => 'Full Name',
202
+ 'vi' => 'Họ tên',
203
+ ],
204
+ // ...
205
+ ];
206
+ }
207
+ ```
208
+
209
+ #### Generated Base Model
210
+
211
+ ```php
212
+ // app/Models/OmnifyBase/UserBaseModel.php
213
+ use App\Models\OmnifyBase\Traits\HasLocalizedDisplayName;
214
+ use App\Models\OmnifyBase\Locales\UserLocales;
215
+
216
+ class UserBaseModel extends Authenticatable
217
+ {
218
+ use HasLocalizedDisplayName;
219
+
220
+ protected static array $localizedDisplayNames = UserLocales::DISPLAY_NAMES;
221
+ protected static array $localizedPropertyDisplayNames = UserLocales::PROPERTY_DISPLAY_NAMES;
222
+
223
+ // ... rest of model
224
+ }
225
+ ```
226
+
227
+ #### Using Localized Display Names in PHP
228
+
229
+ ```php
230
+ // Get model display name (uses Laravel's app()->getLocale())
231
+ User::displayName(); // "ユーザー" (if locale is 'ja')
232
+ User::displayName('en'); // "User"
233
+ User::displayName('vi'); // "Người dùng"
234
+
235
+ // Get property display name
236
+ User::propertyDisplayName('name'); // "氏名" (if locale is 'ja')
237
+ User::propertyDisplayName('name', 'en'); // "Full Name"
238
+
239
+ // Get all display names
240
+ User::allDisplayNames(); // ['ja' => 'ユーザー', 'en' => 'User', 'vi' => 'Người dùng']
241
+
242
+ // Get all property names for current locale
243
+ User::allPropertyDisplayNamesForLocale(); // ['name' => '氏名', 'email' => 'メールアドレス', ...]
244
+ ```
245
+
246
+ #### Locale Configuration
247
+
248
+ Configure locales in `omnify.config.ts`:
249
+
250
+ ```typescript
251
+ import { defineConfig } from '@famgia/omnify';
252
+ import laravel from '@famgia/omnify-laravel/plugin';
253
+
254
+ export default defineConfig({
255
+ schemasDir: './schemas',
256
+
257
+ // Locale configuration
258
+ locale: {
259
+ locales: ['ja', 'en', 'vi'],
260
+ defaultLocale: 'ja',
261
+ fallbackLocale: 'en',
262
+ },
263
+
264
+ plugins: [laravel()],
265
+ });
266
+ ```
267
+
138
268
  ## Creating Custom Plugins
139
269
 
140
270
  You can create your own generator plugins following this pattern:
@@ -1122,6 +1122,9 @@ function generateMigrationsFromChanges(changes, options = {}) {
1122
1122
  return migrations;
1123
1123
  }
1124
1124
 
1125
+ // src/model/generator.ts
1126
+ import { isLocaleMap } from "@famgia/omnify-types";
1127
+
1125
1128
  // src/utils.ts
1126
1129
  function toSnakeCase(str) {
1127
1130
  return str.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
@@ -1151,6 +1154,45 @@ var DEFAULT_OPTIONS = {
1151
1154
  baseModelPath: "app/Models/OmnifyBase",
1152
1155
  modelPath: "app/Models"
1153
1156
  };
1157
+ function generateLocalizedDisplayNames(displayName, indent = " ") {
1158
+ if (displayName === void 0) {
1159
+ return "";
1160
+ }
1161
+ if (typeof displayName === "string") {
1162
+ return `${indent}'en' => '${escapePhpString(displayName)}',`;
1163
+ }
1164
+ if (isLocaleMap(displayName)) {
1165
+ const entries = Object.entries(displayName).map(([locale, value]) => `${indent}'${locale}' => '${escapePhpString(value)}',`).join("\n");
1166
+ return entries;
1167
+ }
1168
+ return "";
1169
+ }
1170
+ function generatePropertyLocalizedDisplayNames(schema, indent = " ") {
1171
+ const properties = schema.properties ?? {};
1172
+ const entries = [];
1173
+ for (const [propName, propDef] of Object.entries(properties)) {
1174
+ const snakeName = toSnakeCase(propName);
1175
+ const displayName = propDef.displayName;
1176
+ if (displayName === void 0) {
1177
+ continue;
1178
+ }
1179
+ const innerIndent = indent + " ";
1180
+ if (typeof displayName === "string") {
1181
+ entries.push(`${indent}'${snakeName}' => [
1182
+ ${innerIndent}'en' => '${escapePhpString(displayName)}',
1183
+ ${indent}],`);
1184
+ } else if (isLocaleMap(displayName)) {
1185
+ const localeEntries = Object.entries(displayName).map(([locale, value]) => `${innerIndent}'${locale}' => '${escapePhpString(value)}',`).join("\n");
1186
+ entries.push(`${indent}'${snakeName}' => [
1187
+ ${localeEntries}
1188
+ ${indent}],`);
1189
+ }
1190
+ }
1191
+ return entries.join("\n");
1192
+ }
1193
+ function escapePhpString(str) {
1194
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1195
+ }
1154
1196
  function resolveOptions(options) {
1155
1197
  return {
1156
1198
  baseModelNamespace: options?.baseModelNamespace ?? DEFAULT_OPTIONS.baseModelNamespace,
@@ -1533,11 +1575,14 @@ use Illuminate\\Database\\Eloquent\\Relations\\MorphOne;
1533
1575
  use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
1534
1576
  use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
1535
1577
  use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
1578
+ use {{BASE_MODEL_NAMESPACE}}\\Traits\\HasLocalizedDisplayName;
1579
+ use {{BASE_MODEL_NAMESPACE}}\\Locales\\{{CLASS_NAME}}Locales;
1536
1580
  {{IMPORTS}}
1537
1581
 
1538
1582
  {{DOC_COMMENT}}
1539
1583
  class {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}
1540
1584
  {
1585
+ use HasLocalizedDisplayName;
1541
1586
  {{TRAITS}}
1542
1587
  /**
1543
1588
  * The table associated with the model.
@@ -1556,6 +1601,20 @@ class {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}
1556
1601
  */
1557
1602
  public $timestamps = {{TIMESTAMPS}};
1558
1603
 
1604
+ /**
1605
+ * Localized display names for this model.
1606
+ *
1607
+ * @var array<string, string>
1608
+ */
1609
+ protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;
1610
+
1611
+ /**
1612
+ * Localized display names for properties.
1613
+ *
1614
+ * @var array<string, array<string, string>>
1615
+ */
1616
+ protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;
1617
+
1559
1618
  /**
1560
1619
  * The attributes that are mass assignable.
1561
1620
  */
@@ -1612,12 +1671,15 @@ use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
1612
1671
  use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
1613
1672
  use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
1614
1673
  use Illuminate\\Notifications\\Notifiable;
1674
+ use {{BASE_MODEL_NAMESPACE}}\\Traits\\HasLocalizedDisplayName;
1675
+ use {{BASE_MODEL_NAMESPACE}}\\Locales\\{{CLASS_NAME}}Locales;
1615
1676
  {{IMPORTS}}
1616
1677
 
1617
1678
  {{DOC_COMMENT}}
1618
1679
  class {{CLASS_NAME}}BaseModel extends Authenticatable
1619
1680
  {
1620
1681
  use Notifiable;
1682
+ use HasLocalizedDisplayName;
1621
1683
  {{TRAITS}}
1622
1684
  /**
1623
1685
  * The table associated with the model.
@@ -1636,6 +1698,20 @@ class {{CLASS_NAME}}BaseModel extends Authenticatable
1636
1698
  */
1637
1699
  public $timestamps = {{TIMESTAMPS}};
1638
1700
 
1701
+ /**
1702
+ * Localized display names for this model.
1703
+ *
1704
+ * @var array<string, string>
1705
+ */
1706
+ protected static array $localizedDisplayNames = {{CLASS_NAME}}Locales::DISPLAY_NAMES;
1707
+
1708
+ /**
1709
+ * Localized display names for properties.
1710
+ *
1711
+ * @var array<string, array<string, string>>
1712
+ */
1713
+ protected static array $localizedPropertyDisplayNames = {{CLASS_NAME}}Locales::PROPERTY_DISPLAY_NAMES;
1714
+
1639
1715
  /**
1640
1716
  * The attributes that are mass assignable.
1641
1717
  */
@@ -1740,6 +1816,132 @@ class OmnifyServiceProvider extends ServiceProvider
1740
1816
  ]);
1741
1817
  }
1742
1818
  }
1819
+ `,
1820
+ "has-localized-display-name": `<?php
1821
+
1822
+ namespace {{BASE_MODEL_NAMESPACE}}\\Traits;
1823
+
1824
+ /**
1825
+ * Trait for localized display names.
1826
+ * Uses Laravel's app()->getLocale() for locale resolution.
1827
+ *
1828
+ * DO NOT EDIT - This file is auto-generated by Omnify.
1829
+ * Any changes will be overwritten on next generation.
1830
+ *
1831
+ * @generated by @famgia/omnify-laravel
1832
+ */
1833
+ trait HasLocalizedDisplayName
1834
+ {
1835
+ /**
1836
+ * Get the localized display name for this model.
1837
+ *
1838
+ * @param string|null $locale Locale code (defaults to app locale)
1839
+ * @return string
1840
+ */
1841
+ public static function displayName(?string $locale = null): string
1842
+ {
1843
+ $locale = $locale ?? app()->getLocale();
1844
+ $displayNames = static::$localizedDisplayNames ?? [];
1845
+
1846
+ return $displayNames[$locale]
1847
+ ?? $displayNames[config('app.fallback_locale', 'en')]
1848
+ ?? $displayNames[array_key_first($displayNames) ?? 'en']
1849
+ ?? class_basename(static::class);
1850
+ }
1851
+
1852
+ /**
1853
+ * Get all localized display names for this model.
1854
+ *
1855
+ * @return array<string, string>
1856
+ */
1857
+ public static function allDisplayNames(): array
1858
+ {
1859
+ return static::$localizedDisplayNames ?? [];
1860
+ }
1861
+
1862
+ /**
1863
+ * Get the localized display name for a property.
1864
+ *
1865
+ * @param string $property Property name
1866
+ * @param string|null $locale Locale code (defaults to app locale)
1867
+ * @return string
1868
+ */
1869
+ public static function propertyDisplayName(string $property, ?string $locale = null): string
1870
+ {
1871
+ $locale = $locale ?? app()->getLocale();
1872
+ $displayNames = static::$localizedPropertyDisplayNames[$property] ?? [];
1873
+
1874
+ return $displayNames[$locale]
1875
+ ?? $displayNames[config('app.fallback_locale', 'en')]
1876
+ ?? $displayNames[array_key_first($displayNames) ?? 'en']
1877
+ ?? $property;
1878
+ }
1879
+
1880
+ /**
1881
+ * Get all localized display names for a property.
1882
+ *
1883
+ * @param string $property Property name
1884
+ * @return array<string, string>
1885
+ */
1886
+ public static function allPropertyDisplayNames(string $property): array
1887
+ {
1888
+ return static::$localizedPropertyDisplayNames[$property] ?? [];
1889
+ }
1890
+
1891
+ /**
1892
+ * Get all property display names for a given locale.
1893
+ *
1894
+ * @param string|null $locale Locale code (defaults to app locale)
1895
+ * @return array<string, string>
1896
+ */
1897
+ public static function allPropertyDisplayNamesForLocale(?string $locale = null): array
1898
+ {
1899
+ $locale = $locale ?? app()->getLocale();
1900
+ $result = [];
1901
+
1902
+ foreach (static::$localizedPropertyDisplayNames ?? [] as $property => $displayNames) {
1903
+ $result[$property] = $displayNames[$locale]
1904
+ ?? $displayNames[config('app.fallback_locale', 'en')]
1905
+ ?? $displayNames[array_key_first($displayNames) ?? 'en']
1906
+ ?? $property;
1907
+ }
1908
+
1909
+ return $result;
1910
+ }
1911
+ }
1912
+ `,
1913
+ "locales": `<?php
1914
+
1915
+ namespace {{BASE_MODEL_NAMESPACE}}\\Locales;
1916
+
1917
+ /**
1918
+ * Localized display names for {{CLASS_NAME}}.
1919
+ *
1920
+ * DO NOT EDIT - This file is auto-generated by Omnify.
1921
+ * Any changes will be overwritten on next generation.
1922
+ *
1923
+ * @generated by @famgia/omnify-laravel
1924
+ */
1925
+ class {{CLASS_NAME}}Locales
1926
+ {
1927
+ /**
1928
+ * Localized display names for the model.
1929
+ *
1930
+ * @var array<string, string>
1931
+ */
1932
+ public const DISPLAY_NAMES = [
1933
+ {{LOCALIZED_DISPLAY_NAMES}}
1934
+ ];
1935
+
1936
+ /**
1937
+ * Localized display names for properties.
1938
+ *
1939
+ * @var array<string, array<string, string>>
1940
+ */
1941
+ public const PROPERTY_DISPLAY_NAMES = [
1942
+ {{LOCALIZED_PROPERTY_DISPLAY_NAMES}}
1943
+ ];
1944
+ }
1743
1945
  `
1744
1946
  };
1745
1947
  return stubs[stubName] ?? "";
@@ -1759,15 +1961,42 @@ function generateServiceProvider(schemas, options, stubContent) {
1759
1961
  schemaName: "__service_provider__"
1760
1962
  };
1761
1963
  }
1964
+ function generateLocalizedDisplayNameTrait(options, stubContent) {
1965
+ const content = stubContent.replace(/\{\{BASE_MODEL_NAMESPACE\}\}/g, options.baseModelNamespace);
1966
+ return {
1967
+ path: `${options.baseModelPath}/Traits/HasLocalizedDisplayName.php`,
1968
+ content,
1969
+ type: "trait",
1970
+ overwrite: true,
1971
+ // Always overwrite trait
1972
+ schemaName: "__trait__"
1973
+ };
1974
+ }
1975
+ function generateLocalesClass(schema, options, stubContent) {
1976
+ const className = toPascalCase(schema.name);
1977
+ const localizedDisplayNames = generateLocalizedDisplayNames(schema.displayName);
1978
+ const localizedPropertyDisplayNames = generatePropertyLocalizedDisplayNames(schema);
1979
+ const content = stubContent.replace(/\{\{BASE_MODEL_NAMESPACE\}\}/g, options.baseModelNamespace).replace(/\{\{CLASS_NAME\}\}/g, className).replace(/\{\{LOCALIZED_DISPLAY_NAMES\}\}/g, localizedDisplayNames).replace(/\{\{LOCALIZED_PROPERTY_DISPLAY_NAMES\}\}/g, localizedPropertyDisplayNames);
1980
+ return {
1981
+ path: `${options.baseModelPath}/Locales/${className}Locales.php`,
1982
+ content,
1983
+ type: "locales",
1984
+ overwrite: true,
1985
+ // Always overwrite locales
1986
+ schemaName: schema.name
1987
+ };
1988
+ }
1762
1989
  function generateModels(schemas, options) {
1763
1990
  const resolved = resolveOptions(options);
1764
1991
  const models = [];
1765
1992
  models.push(generateBaseModel(schemas, resolved, getStubContent("base-model")));
1993
+ models.push(generateLocalizedDisplayNameTrait(resolved, getStubContent("has-localized-display-name")));
1766
1994
  models.push(generateServiceProvider(schemas, resolved, getStubContent("service-provider")));
1767
1995
  for (const schema of Object.values(schemas)) {
1768
1996
  if (schema.kind === "enum") {
1769
1997
  continue;
1770
1998
  }
1999
+ models.push(generateLocalesClass(schema, resolved, getStubContent("locales")));
1771
2000
  models.push(generateEntityBaseModel(
1772
2001
  schema,
1773
2002
  schemas,
@@ -2434,4 +2663,4 @@ export {
2434
2663
  generateMigrationsFromChanges,
2435
2664
  laravelPlugin
2436
2665
  };
2437
- //# sourceMappingURL=chunk-H37M25AK.js.map
2666
+ //# sourceMappingURL=chunk-ILSNN7UV.js.map