@famgia/omnify-laravel 0.0.17 → 0.0.19
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 +130 -0
- package/dist/{chunk-52JAFQBQ.js → chunk-ILSNN7UV.js} +403 -14
- package/dist/chunk-ILSNN7UV.js.map +1 -0
- package/dist/index.cjs +401 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1 -1
- package/dist/plugin.cjs +682 -12
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-52JAFQBQ.js.map +0 -1
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:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/plugin.ts
|
|
2
|
-
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
|
|
5
5
|
// src/migration/schema-builder.ts
|
|
@@ -14,6 +14,7 @@ var TYPE_METHOD_MAP = {
|
|
|
14
14
|
LongText: "longText",
|
|
15
15
|
Date: "date",
|
|
16
16
|
Time: "time",
|
|
17
|
+
DateTime: "dateTime",
|
|
17
18
|
Timestamp: "timestamp",
|
|
18
19
|
Json: "json",
|
|
19
20
|
Email: "string",
|
|
@@ -86,6 +87,10 @@ function propertyToColumnMethod(propertyName, property) {
|
|
|
86
87
|
if (baseProp.unsigned && (method === "integer" || method === "bigInteger")) {
|
|
87
88
|
modifiers.push({ method: "unsigned" });
|
|
88
89
|
}
|
|
90
|
+
const displayName = property.displayName;
|
|
91
|
+
if (displayName) {
|
|
92
|
+
modifiers.push({ method: "comment", args: [displayName] });
|
|
93
|
+
}
|
|
89
94
|
return {
|
|
90
95
|
name: columnName,
|
|
91
96
|
method,
|
|
@@ -220,6 +225,9 @@ function generateForeignKey(propertyName, property, allSchemas) {
|
|
|
220
225
|
if (assocProp.default !== void 0 && assocProp.default !== null) {
|
|
221
226
|
modifiers.push({ method: "default", args: [assocProp.default] });
|
|
222
227
|
}
|
|
228
|
+
if (assocProp.displayName) {
|
|
229
|
+
modifiers.push({ method: "comment", args: [assocProp.displayName] });
|
|
230
|
+
}
|
|
223
231
|
const column = {
|
|
224
232
|
name: columnName,
|
|
225
233
|
method,
|
|
@@ -239,7 +247,65 @@ function generateForeignKey(propertyName, property, allSchemas) {
|
|
|
239
247
|
};
|
|
240
248
|
return { column, foreignKey, index };
|
|
241
249
|
}
|
|
242
|
-
function
|
|
250
|
+
function expandCompoundType(propName, property, customTypes) {
|
|
251
|
+
const typeDef = customTypes.get(property.type);
|
|
252
|
+
if (!typeDef || !typeDef.compound || !typeDef.expand) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
const expanded = [];
|
|
256
|
+
const baseProp = property;
|
|
257
|
+
for (const field of typeDef.expand) {
|
|
258
|
+
const suffixSnake = toColumnName(field.suffix);
|
|
259
|
+
const columnName = `${propName}_${suffixSnake}`;
|
|
260
|
+
const expandedProp = {
|
|
261
|
+
type: "String"
|
|
262
|
+
// Default type, will be overridden by sql definition
|
|
263
|
+
};
|
|
264
|
+
if (field.sql) {
|
|
265
|
+
const sqlType = field.sql.sqlType.toUpperCase();
|
|
266
|
+
if (sqlType === "VARCHAR" || sqlType === "CHAR" || sqlType === "STRING") {
|
|
267
|
+
expandedProp.type = "String";
|
|
268
|
+
if (field.sql.length) {
|
|
269
|
+
expandedProp.length = field.sql.length;
|
|
270
|
+
}
|
|
271
|
+
} else if (sqlType === "INT" || sqlType === "INTEGER") {
|
|
272
|
+
expandedProp.type = "Int";
|
|
273
|
+
} else if (sqlType === "BIGINT") {
|
|
274
|
+
expandedProp.type = "BigInt";
|
|
275
|
+
} else if (sqlType === "TEXT") {
|
|
276
|
+
expandedProp.type = "Text";
|
|
277
|
+
} else if (sqlType === "BOOLEAN" || sqlType === "BOOL") {
|
|
278
|
+
expandedProp.type = "Boolean";
|
|
279
|
+
} else if (sqlType === "DECIMAL") {
|
|
280
|
+
expandedProp.type = "Decimal";
|
|
281
|
+
if (field.sql.precision) expandedProp.precision = field.sql.precision;
|
|
282
|
+
if (field.sql.scale) expandedProp.scale = field.sql.scale;
|
|
283
|
+
} else if (sqlType === "DATE") {
|
|
284
|
+
expandedProp.type = "Date";
|
|
285
|
+
} else if (sqlType === "TIMESTAMP" || sqlType === "DATETIME") {
|
|
286
|
+
expandedProp.type = "Timestamp";
|
|
287
|
+
}
|
|
288
|
+
if (field.sql.nullable !== void 0) {
|
|
289
|
+
expandedProp.nullable = field.sql.nullable;
|
|
290
|
+
} else if (baseProp.nullable !== void 0) {
|
|
291
|
+
expandedProp.nullable = baseProp.nullable;
|
|
292
|
+
}
|
|
293
|
+
if (field.sql.default !== void 0) {
|
|
294
|
+
expandedProp.default = field.sql.default;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (baseProp.displayName) {
|
|
298
|
+
expandedProp.displayName = `${baseProp.displayName} (${field.suffix})`;
|
|
299
|
+
}
|
|
300
|
+
expanded.push({
|
|
301
|
+
name: columnName,
|
|
302
|
+
property: expandedProp
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return expanded;
|
|
306
|
+
}
|
|
307
|
+
function schemaToBlueprint(schema, allSchemas, options = {}) {
|
|
308
|
+
const { customTypes = /* @__PURE__ */ new Map() } = options;
|
|
243
309
|
const tableName = toTableName(schema.name);
|
|
244
310
|
const columns = [];
|
|
245
311
|
const foreignKeys = [];
|
|
@@ -250,6 +316,16 @@ function schemaToBlueprint(schema, allSchemas) {
|
|
|
250
316
|
}
|
|
251
317
|
if (schema.properties) {
|
|
252
318
|
for (const [propName, property] of Object.entries(schema.properties)) {
|
|
319
|
+
const expandedProps = expandCompoundType(propName, property, customTypes);
|
|
320
|
+
if (expandedProps) {
|
|
321
|
+
for (const { name: expandedName, property: expandedProp } of expandedProps) {
|
|
322
|
+
const columnMethod2 = propertyToColumnMethod(expandedName, expandedProp);
|
|
323
|
+
if (columnMethod2) {
|
|
324
|
+
columns.push(columnMethod2);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
253
329
|
const columnMethod = propertyToColumnMethod(propName, property);
|
|
254
330
|
if (columnMethod) {
|
|
255
331
|
columns.push(columnMethod);
|
|
@@ -696,7 +772,9 @@ function generateMigrations(schemas, options = {}) {
|
|
|
696
772
|
const timestamp = options.timestamp ?? generateTimestamp();
|
|
697
773
|
const offsetTimestamp = incrementTimestamp(timestamp, timestampOffset);
|
|
698
774
|
timestampOffset++;
|
|
699
|
-
const blueprint = schemaToBlueprint(schema, schemas
|
|
775
|
+
const blueprint = schemaToBlueprint(schema, schemas, {
|
|
776
|
+
customTypes: options.customTypes
|
|
777
|
+
});
|
|
700
778
|
const migration = generateCreateMigration(blueprint, {
|
|
701
779
|
...options,
|
|
702
780
|
timestamp: offsetTimestamp
|
|
@@ -774,6 +852,7 @@ var TYPE_METHOD_MAP2 = {
|
|
|
774
852
|
LongText: "longText",
|
|
775
853
|
Date: "date",
|
|
776
854
|
Time: "time",
|
|
855
|
+
DateTime: "dateTime",
|
|
777
856
|
Timestamp: "timestamp",
|
|
778
857
|
Json: "json",
|
|
779
858
|
Email: "string",
|
|
@@ -1043,6 +1122,9 @@ function generateMigrationsFromChanges(changes, options = {}) {
|
|
|
1043
1122
|
return migrations;
|
|
1044
1123
|
}
|
|
1045
1124
|
|
|
1125
|
+
// src/model/generator.ts
|
|
1126
|
+
import { isLocaleMap } from "@famgia/omnify-types";
|
|
1127
|
+
|
|
1046
1128
|
// src/utils.ts
|
|
1047
1129
|
function toSnakeCase(str) {
|
|
1048
1130
|
return str.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toLowerCase();
|
|
@@ -1072,6 +1154,45 @@ var DEFAULT_OPTIONS = {
|
|
|
1072
1154
|
baseModelPath: "app/Models/OmnifyBase",
|
|
1073
1155
|
modelPath: "app/Models"
|
|
1074
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
|
+
}
|
|
1075
1196
|
function resolveOptions(options) {
|
|
1076
1197
|
return {
|
|
1077
1198
|
baseModelNamespace: options?.baseModelNamespace ?? DEFAULT_OPTIONS.baseModelNamespace,
|
|
@@ -1454,11 +1575,14 @@ use Illuminate\\Database\\Eloquent\\Relations\\MorphOne;
|
|
|
1454
1575
|
use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
|
|
1455
1576
|
use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
|
|
1456
1577
|
use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
|
|
1578
|
+
use {{BASE_MODEL_NAMESPACE}}\\Traits\\HasLocalizedDisplayName;
|
|
1579
|
+
use {{BASE_MODEL_NAMESPACE}}\\Locales\\{{CLASS_NAME}}Locales;
|
|
1457
1580
|
{{IMPORTS}}
|
|
1458
1581
|
|
|
1459
1582
|
{{DOC_COMMENT}}
|
|
1460
1583
|
class {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}
|
|
1461
1584
|
{
|
|
1585
|
+
use HasLocalizedDisplayName;
|
|
1462
1586
|
{{TRAITS}}
|
|
1463
1587
|
/**
|
|
1464
1588
|
* The table associated with the model.
|
|
@@ -1477,6 +1601,20 @@ class {{CLASS_NAME}}BaseModel extends {{BASE_MODEL_CLASS}}
|
|
|
1477
1601
|
*/
|
|
1478
1602
|
public $timestamps = {{TIMESTAMPS}};
|
|
1479
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
|
+
|
|
1480
1618
|
/**
|
|
1481
1619
|
* The attributes that are mass assignable.
|
|
1482
1620
|
*/
|
|
@@ -1533,12 +1671,15 @@ use Illuminate\\Database\\Eloquent\\Relations\\MorphMany;
|
|
|
1533
1671
|
use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany;
|
|
1534
1672
|
use Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;
|
|
1535
1673
|
use Illuminate\\Notifications\\Notifiable;
|
|
1674
|
+
use {{BASE_MODEL_NAMESPACE}}\\Traits\\HasLocalizedDisplayName;
|
|
1675
|
+
use {{BASE_MODEL_NAMESPACE}}\\Locales\\{{CLASS_NAME}}Locales;
|
|
1536
1676
|
{{IMPORTS}}
|
|
1537
1677
|
|
|
1538
1678
|
{{DOC_COMMENT}}
|
|
1539
1679
|
class {{CLASS_NAME}}BaseModel extends Authenticatable
|
|
1540
1680
|
{
|
|
1541
1681
|
use Notifiable;
|
|
1682
|
+
use HasLocalizedDisplayName;
|
|
1542
1683
|
{{TRAITS}}
|
|
1543
1684
|
/**
|
|
1544
1685
|
* The table associated with the model.
|
|
@@ -1557,6 +1698,20 @@ class {{CLASS_NAME}}BaseModel extends Authenticatable
|
|
|
1557
1698
|
*/
|
|
1558
1699
|
public $timestamps = {{TIMESTAMPS}};
|
|
1559
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
|
+
|
|
1560
1715
|
/**
|
|
1561
1716
|
* The attributes that are mass assignable.
|
|
1562
1717
|
*/
|
|
@@ -1661,6 +1816,132 @@ class OmnifyServiceProvider extends ServiceProvider
|
|
|
1661
1816
|
]);
|
|
1662
1817
|
}
|
|
1663
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
|
+
}
|
|
1664
1945
|
`
|
|
1665
1946
|
};
|
|
1666
1947
|
return stubs[stubName] ?? "";
|
|
@@ -1680,15 +1961,42 @@ function generateServiceProvider(schemas, options, stubContent) {
|
|
|
1680
1961
|
schemaName: "__service_provider__"
|
|
1681
1962
|
};
|
|
1682
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
|
+
}
|
|
1683
1989
|
function generateModels(schemas, options) {
|
|
1684
1990
|
const resolved = resolveOptions(options);
|
|
1685
1991
|
const models = [];
|
|
1686
1992
|
models.push(generateBaseModel(schemas, resolved, getStubContent("base-model")));
|
|
1993
|
+
models.push(generateLocalizedDisplayNameTrait(resolved, getStubContent("has-localized-display-name")));
|
|
1687
1994
|
models.push(generateServiceProvider(schemas, resolved, getStubContent("service-provider")));
|
|
1688
1995
|
for (const schema of Object.values(schemas)) {
|
|
1689
1996
|
if (schema.kind === "enum") {
|
|
1690
1997
|
continue;
|
|
1691
1998
|
}
|
|
1999
|
+
models.push(generateLocalesClass(schema, resolved, getStubContent("locales")));
|
|
1692
2000
|
models.push(generateEntityBaseModel(
|
|
1693
2001
|
schema,
|
|
1694
2002
|
schemas,
|
|
@@ -2054,6 +2362,24 @@ function getFactoryPath(factory) {
|
|
|
2054
2362
|
}
|
|
2055
2363
|
|
|
2056
2364
|
// src/plugin.ts
|
|
2365
|
+
function getExistingMigrationTables(migrationsDir) {
|
|
2366
|
+
const existingTables = /* @__PURE__ */ new Set();
|
|
2367
|
+
if (!existsSync(migrationsDir)) {
|
|
2368
|
+
return existingTables;
|
|
2369
|
+
}
|
|
2370
|
+
try {
|
|
2371
|
+
const files = readdirSync(migrationsDir);
|
|
2372
|
+
const createMigrationPattern = /^\d{4}_\d{2}_\d{2}_\d{6}_create_(.+)_table\.php$/;
|
|
2373
|
+
for (const file of files) {
|
|
2374
|
+
const match = file.match(createMigrationPattern);
|
|
2375
|
+
if (match) {
|
|
2376
|
+
existingTables.add(match[1]);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
} catch {
|
|
2380
|
+
}
|
|
2381
|
+
return existingTables;
|
|
2382
|
+
}
|
|
2057
2383
|
var LARAVEL_CONFIG_SCHEMA = {
|
|
2058
2384
|
fields: [
|
|
2059
2385
|
{
|
|
@@ -2137,18 +2463,81 @@ function laravelPlugin(options) {
|
|
|
2137
2463
|
generate: async (ctx) => {
|
|
2138
2464
|
const migrationOptions = {
|
|
2139
2465
|
connection: resolved.connection,
|
|
2140
|
-
timestamp: resolved.timestamp
|
|
2466
|
+
timestamp: resolved.timestamp,
|
|
2467
|
+
customTypes: ctx.customTypes
|
|
2141
2468
|
};
|
|
2142
|
-
const
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
tableName: migration.tables[0],
|
|
2149
|
-
migrationType: migration.type
|
|
2469
|
+
const outputs = [];
|
|
2470
|
+
const migrationsDir = join(ctx.cwd, resolved.migrationsPath);
|
|
2471
|
+
const existingTables = getExistingMigrationTables(migrationsDir);
|
|
2472
|
+
if (ctx.changes !== void 0) {
|
|
2473
|
+
if (ctx.changes.length === 0) {
|
|
2474
|
+
return outputs;
|
|
2150
2475
|
}
|
|
2151
|
-
|
|
2476
|
+
const addedSchemaNames = new Set(
|
|
2477
|
+
ctx.changes.filter((c) => c.changeType === "added").map((c) => c.schemaName)
|
|
2478
|
+
);
|
|
2479
|
+
if (addedSchemaNames.size > 0) {
|
|
2480
|
+
const addedSchemas = Object.fromEntries(
|
|
2481
|
+
Object.entries(ctx.schemas).filter(([name]) => addedSchemaNames.has(name))
|
|
2482
|
+
);
|
|
2483
|
+
const createMigrations = generateMigrations(addedSchemas, migrationOptions);
|
|
2484
|
+
for (const migration of createMigrations) {
|
|
2485
|
+
const tableName = migration.tables[0];
|
|
2486
|
+
if (existingTables.has(tableName)) {
|
|
2487
|
+
ctx.logger.debug(`Skipping CREATE for ${tableName} (already exists)`);
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2490
|
+
outputs.push({
|
|
2491
|
+
path: getMigrationPath(migration, resolved.migrationsPath),
|
|
2492
|
+
content: migration.content,
|
|
2493
|
+
type: "migration",
|
|
2494
|
+
metadata: {
|
|
2495
|
+
tableName,
|
|
2496
|
+
migrationType: "create"
|
|
2497
|
+
}
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
const alterChanges = ctx.changes.filter(
|
|
2502
|
+
(c) => c.changeType === "modified" || c.changeType === "removed"
|
|
2503
|
+
);
|
|
2504
|
+
if (alterChanges.length > 0) {
|
|
2505
|
+
const alterMigrations = generateMigrationsFromChanges(
|
|
2506
|
+
alterChanges,
|
|
2507
|
+
migrationOptions
|
|
2508
|
+
);
|
|
2509
|
+
for (const migration of alterMigrations) {
|
|
2510
|
+
outputs.push({
|
|
2511
|
+
path: getMigrationPath(migration, resolved.migrationsPath),
|
|
2512
|
+
content: migration.content,
|
|
2513
|
+
type: "migration",
|
|
2514
|
+
metadata: {
|
|
2515
|
+
tableName: migration.tables[0],
|
|
2516
|
+
migrationType: migration.type
|
|
2517
|
+
}
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
} else {
|
|
2522
|
+
const migrations = generateMigrations(ctx.schemas, migrationOptions);
|
|
2523
|
+
for (const migration of migrations) {
|
|
2524
|
+
const tableName = migration.tables[0];
|
|
2525
|
+
if (migration.type === "create" && existingTables.has(tableName)) {
|
|
2526
|
+
ctx.logger.debug(`Skipping migration for ${tableName} (already exists)`);
|
|
2527
|
+
continue;
|
|
2528
|
+
}
|
|
2529
|
+
outputs.push({
|
|
2530
|
+
path: getMigrationPath(migration, resolved.migrationsPath),
|
|
2531
|
+
content: migration.content,
|
|
2532
|
+
type: "migration",
|
|
2533
|
+
metadata: {
|
|
2534
|
+
tableName,
|
|
2535
|
+
migrationType: migration.type
|
|
2536
|
+
}
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
return outputs;
|
|
2152
2541
|
}
|
|
2153
2542
|
};
|
|
2154
2543
|
const modelGenerator = {
|
|
@@ -2274,4 +2663,4 @@ export {
|
|
|
2274
2663
|
generateMigrationsFromChanges,
|
|
2275
2664
|
laravelPlugin
|
|
2276
2665
|
};
|
|
2277
|
-
//# sourceMappingURL=chunk-
|
|
2666
|
+
//# sourceMappingURL=chunk-ILSNN7UV.js.map
|