@omnifyjp/ts 1.0.0 → 1.0.1
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.
|
@@ -48,7 +48,7 @@ function generateBaseModel(name, schema, reader, config) {
|
|
|
48
48
|
const hidden = buildHidden(properties, expandedProperties, propertyOrder);
|
|
49
49
|
const appends = buildAppends(expandedProperties);
|
|
50
50
|
const casts = buildCasts(properties, expandedProperties, propertyOrder);
|
|
51
|
-
const relations = buildRelations(properties, propertyOrder, modelNamespace, reader);
|
|
51
|
+
const relations = buildRelations(name, properties, propertyOrder, modelNamespace, reader);
|
|
52
52
|
const accessors = buildAccessors(expandedProperties);
|
|
53
53
|
const primaryKey = options['primaryKey'] ?? 'id';
|
|
54
54
|
const rawId = options.id;
|
|
@@ -354,8 +354,9 @@ function buildCasts(properties, expandedProperties, propertyOrder) {
|
|
|
354
354
|
return '';
|
|
355
355
|
return casts.map(c => ` ${c}`).join('\n') + '\n';
|
|
356
356
|
}
|
|
357
|
-
function buildRelations(properties, propertyOrder, modelNamespace, reader) {
|
|
357
|
+
function buildRelations(schemaName, properties, propertyOrder, modelNamespace, reader) {
|
|
358
358
|
const methods = [];
|
|
359
|
+
const sourceTableName = reader.getTableName(schemaName);
|
|
359
360
|
for (const propName of propertyOrder) {
|
|
360
361
|
const prop = properties[propName];
|
|
361
362
|
if (!prop || prop['type'] !== 'Association')
|
|
@@ -363,7 +364,8 @@ function buildRelations(properties, propertyOrder, modelNamespace, reader) {
|
|
|
363
364
|
// Resolve namespace per-target (package schemas use their own namespace)
|
|
364
365
|
const target = prop['target'] ?? '';
|
|
365
366
|
const ns = target ? reader.resolveModelNamespace(target, modelNamespace) : modelNamespace;
|
|
366
|
-
const
|
|
367
|
+
const targetTableName = target ? reader.getTableName(target) : '';
|
|
368
|
+
const result = buildRelation(propName, prop, ns, { sourceTableName, targetTableName });
|
|
367
369
|
if (result) {
|
|
368
370
|
methods.push('\n' + result.method);
|
|
369
371
|
}
|
|
@@ -12,6 +12,10 @@ export declare function toCamelCase(value: string): string;
|
|
|
12
12
|
* Handles common cases: -y → -ies, -s/-sh/-ch/-x/-z → -es, default → -s
|
|
13
13
|
*/
|
|
14
14
|
export declare function pluralize(value: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Singularize a word (simple English rules — reverse of pluralize).
|
|
17
|
+
*/
|
|
18
|
+
export declare function singularize(value: string): string;
|
|
15
19
|
/** Convert a schema name to a table name (snake_case + pluralized). */
|
|
16
20
|
export declare function toTableName(schemaName: string): string;
|
|
17
21
|
/**
|
|
@@ -38,6 +38,30 @@ export function pluralize(value) {
|
|
|
38
38
|
}
|
|
39
39
|
return value + 's';
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Singularize a word (simple English rules — reverse of pluralize).
|
|
43
|
+
*/
|
|
44
|
+
export function singularize(value) {
|
|
45
|
+
// Already singular or empty
|
|
46
|
+
if (!value || value.length <= 2)
|
|
47
|
+
return value;
|
|
48
|
+
if (value.endsWith('ies')) {
|
|
49
|
+
return value.slice(0, -3) + 'y';
|
|
50
|
+
}
|
|
51
|
+
if (value.endsWith('ves')) {
|
|
52
|
+
// knives → knife, leaves → leaf
|
|
53
|
+
const stem = value.slice(0, -3);
|
|
54
|
+
// Try -fe first (e.g., "knives" → "knife"), fallback to -f (e.g., "leaves" → "leaf")
|
|
55
|
+
return stem + 'f';
|
|
56
|
+
}
|
|
57
|
+
if (value.endsWith('ses') || value.endsWith('shes') || value.endsWith('ches') || value.endsWith('xes') || value.endsWith('zes')) {
|
|
58
|
+
return value.slice(0, -2);
|
|
59
|
+
}
|
|
60
|
+
if (value.endsWith('s') && !value.endsWith('ss')) {
|
|
61
|
+
return value.slice(0, -1);
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
41
65
|
/** Convert a schema name to a table name (snake_case + pluralized). */
|
|
42
66
|
export function toTableName(schemaName) {
|
|
43
67
|
return pluralize(toSnakeCase(schemaName));
|
|
@@ -5,8 +5,14 @@ interface RelationResult {
|
|
|
5
5
|
method: string;
|
|
6
6
|
imports: string[];
|
|
7
7
|
}
|
|
8
|
+
interface RelationContext {
|
|
9
|
+
sourceTableName: string;
|
|
10
|
+
targetTableName: string;
|
|
11
|
+
}
|
|
8
12
|
/** Build Eloquent relation method PHP code. */
|
|
9
|
-
export declare function buildRelation(propName: string, property: Record<string, unknown>, modelNamespace: string): RelationResult | null;
|
|
13
|
+
export declare function buildRelation(propName: string, property: Record<string, unknown>, modelNamespace: string, context?: RelationContext): RelationResult | null;
|
|
14
|
+
/** Generate pivot table name matching Go's GeneratePivotTableName logic. */
|
|
15
|
+
export declare function generatePivotTableName(sourceTable: string, targetTable: string): string;
|
|
10
16
|
/** Get the return type hint for a relation. */
|
|
11
17
|
export declare function getReturnType(relation: string): string;
|
|
12
18
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Port of RelationBuilder.php — generates Eloquent relation methods.
|
|
3
3
|
*/
|
|
4
|
-
import { toSnakeCase, toCamelCase } from './naming-helper.js';
|
|
4
|
+
import { toSnakeCase, toCamelCase, singularize } from './naming-helper.js';
|
|
5
5
|
/** Build Eloquent relation method PHP code. */
|
|
6
|
-
export function buildRelation(propName, property, modelNamespace) {
|
|
6
|
+
export function buildRelation(propName, property, modelNamespace, context) {
|
|
7
7
|
const relation = property['relation'] ?? '';
|
|
8
8
|
const target = property['target'] ?? '';
|
|
9
9
|
const imports = [];
|
|
@@ -19,7 +19,7 @@ export function buildRelation(propName, property, modelNamespace) {
|
|
|
19
19
|
method = hasMany(propName, property, target, modelNamespace);
|
|
20
20
|
break;
|
|
21
21
|
case 'ManyToMany':
|
|
22
|
-
method = belongsToMany(propName, property, target, modelNamespace);
|
|
22
|
+
method = belongsToMany(propName, property, target, modelNamespace, context);
|
|
23
23
|
break;
|
|
24
24
|
case 'MorphTo':
|
|
25
25
|
method = morphTo(propName);
|
|
@@ -35,6 +35,11 @@ export function buildRelation(propName, property, modelNamespace) {
|
|
|
35
35
|
return null;
|
|
36
36
|
return { method, imports };
|
|
37
37
|
}
|
|
38
|
+
/** Generate pivot table name matching Go's GeneratePivotTableName logic. */
|
|
39
|
+
export function generatePivotTableName(sourceTable, targetTable) {
|
|
40
|
+
const tables = [singularize(sourceTable), singularize(targetTable)].sort();
|
|
41
|
+
return tables.join('_');
|
|
42
|
+
}
|
|
38
43
|
/** Get the return type hint for a relation. */
|
|
39
44
|
export function getReturnType(relation) {
|
|
40
45
|
switch (relation) {
|
|
@@ -90,8 +95,11 @@ function hasMany(propName, property, target, ns) {
|
|
|
90
95
|
return $this->hasMany(${fqcn}::class, '${foreignKey}');
|
|
91
96
|
}`;
|
|
92
97
|
}
|
|
93
|
-
function belongsToMany(propName, property, target, ns) {
|
|
94
|
-
|
|
98
|
+
function belongsToMany(propName, property, target, ns, context) {
|
|
99
|
+
let joinTable = property['joinTable'] ?? '';
|
|
100
|
+
if (!joinTable && context?.sourceTableName && context?.targetTableName) {
|
|
101
|
+
joinTable = generatePivotTableName(context.sourceTableName, context.targetTableName);
|
|
102
|
+
}
|
|
95
103
|
const methodName = toCamelCase(propName);
|
|
96
104
|
const pivotFields = property['pivotFields'] ?? {};
|
|
97
105
|
const fqcn = `\\${ns}\\${target}`;
|