@omnifyjp/ts 5.9.20 → 6.0.0

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.
@@ -719,14 +719,22 @@ function buildRelations(schemaName, properties, propertyOrder, modelNamespace, r
719
719
  // columns the user added are unreachable through the relation.
720
720
  const relation = prop['relation'] ?? '';
721
721
  let pivotProperties;
722
+ let pivotTableName;
722
723
  if (relation === 'ManyToMany' && target) {
723
724
  const pivotName = [schemaName, target].sort().join('');
724
725
  const pivotSchema = reader.getSchema(pivotName);
726
+ const conventionalPivotTable = [toSnakeCase(schemaName), toSnakeCase(target)].sort().join('_');
727
+ const resolvedPivotTable = pivotSchema ? reader.getTableName(pivotName) : '';
728
+ if (resolvedPivotTable && resolvedPivotTable !== conventionalPivotTable) {
729
+ pivotTableName = resolvedPivotTable;
730
+ }
725
731
  if (pivotSchema?.properties) {
726
- pivotProperties = Object.keys(pivotSchema.properties).map(toSnakeCase);
732
+ pivotProperties = Object.entries(pivotSchema.properties).map(([propName, prop]) => prop.type === 'Association' && !prop.mappedBy
733
+ ? prop.column || toFkColumnName(propName)
734
+ : toSnakeCase(propName));
727
735
  }
728
736
  }
729
- const result = buildRelation(propName, prop, ns, { sourceTableName, targetTableName, pivotProperties });
737
+ const result = buildRelation(propName, prop, ns, { sourceTableName, targetTableName, pivotProperties, pivotTableName });
730
738
  if (result) {
731
739
  methods.push('\n' + result.method);
732
740
  declaredMethods.add(toCamelCase(propName));
@@ -126,6 +126,11 @@ function generateBasePolicyClass(name, schema, reader, config) {
126
126
  methods.push(buildMethod('forceDelete', modelName, true, forceDeleteBody));
127
127
  }
128
128
  const cidrHelper = needsCidrHelper ? buildCidrHelper() : '';
129
+ const imports = [...new Set([
130
+ `use ${modelNamespace}\\${modelName};`,
131
+ 'use App\\Models\\User;',
132
+ 'use Illuminate\\Auth\\Access\\HandlesAuthorization;',
133
+ ])].join('\n');
129
134
  const content = `<?php
130
135
 
131
136
  namespace ${baseNamespace};
@@ -137,9 +142,7 @@ namespace ${baseNamespace};
137
142
  * @generated by omnify
138
143
  */
139
144
 
140
- use ${modelNamespace}\\${modelName};
141
- use App\\Models\\User;
142
- use Illuminate\\Auth\\Access\\HandlesAuthorization;
145
+ ${imports}
143
146
 
144
147
  class ${modelName}PolicyBase
145
148
  {
@@ -8,6 +8,9 @@ interface RelationResult {
8
8
  interface RelationContext {
9
9
  sourceTableName: string;
10
10
  targetTableName: string;
11
+ /** Non-conventional physical table resolved from an explicit pivot schema.
12
+ * Omitted when Laravel can infer the joining table from model basenames. */
13
+ pivotTableName?: string;
11
14
  /** Property names declared on the explicit `kind: pivot` schema for
12
15
  * this M2M (e.g. `["position", "notes"]`). Surfaced in the generated
13
16
  * `belongsToMany()` chain via `->withPivot(...)` so consumers can
@@ -17,8 +20,8 @@ interface RelationContext {
17
20
  }
18
21
  /** Build Eloquent relation method PHP code. */
19
22
  export declare function buildRelation(propName: string, property: Record<string, unknown>, modelNamespace: string, context?: RelationContext): RelationResult | null;
20
- /** Generate pivot table name matching Go's GeneratePivotTableName logic. */
21
- export declare function generatePivotTableName(sourceTable: string, targetTable: string): string;
23
+ /** Generate the table name Laravel's joiningTable() infers from model basenames. */
24
+ export declare function generatePivotTableName(sourceModel: string, targetModel: string): string;
22
25
  /** Get the return type hint for a relation. */
23
26
  export declare function getReturnType(relation: string): string;
24
27
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Port of RelationBuilder.php — generates Eloquent relation methods.
3
3
  */
4
- import { toSnakeCase, toCamelCase, toFkColumnName, singularize } from './naming-helper.js';
4
+ import { toSnakeCase, toCamelCase, toFkColumnName } from './naming-helper.js';
5
5
  /** Build Eloquent relation method PHP code. */
6
6
  export function buildRelation(propName, property, modelNamespace, context) {
7
7
  const relation = property['relation'] ?? '';
@@ -41,10 +41,9 @@ export function buildRelation(propName, property, modelNamespace, context) {
41
41
  return null;
42
42
  return { method, imports };
43
43
  }
44
- /** Generate pivot table name matching Go's GeneratePivotTableName logic. */
45
- export function generatePivotTableName(sourceTable, targetTable) {
46
- const tables = [singularize(sourceTable), singularize(targetTable)].sort();
47
- return tables.join('_') + '_pivot';
44
+ /** Generate the table name Laravel's joiningTable() infers from model basenames. */
45
+ export function generatePivotTableName(sourceModel, targetModel) {
46
+ return [toSnakeCase(sourceModel), toSnakeCase(targetModel)].sort().join('_');
48
47
  }
49
48
  /** Get the return type hint for a relation. */
50
49
  export function getReturnType(relation) {
@@ -122,20 +121,21 @@ export function formatOrderByChain(orderBy) {
122
121
  .join('');
123
122
  }
124
123
  function belongsToMany(propName, property, target, ns, context) {
125
- let joinTable = property['joinTable'] ?? '';
126
- if (!joinTable && context?.sourceTableName && context?.targetTableName) {
127
- joinTable = generatePivotTableName(context.sourceTableName, context.targetTableName);
128
- }
124
+ const joinTable = property['joinTable'] || context?.pivotTableName || '';
129
125
  const methodName = toCamelCase(propName);
130
126
  const fqcn = `\\${ns}\\${target}`;
131
- let chain = `$this->belongsToMany(${fqcn}::class, '${joinTable}')`;
127
+ let chain = joinTable
128
+ ? `$this->belongsToMany(${fqcn}::class, '${joinTable}')`
129
+ : `$this->belongsToMany(${fqcn}::class)`;
132
130
  // withPivot for every column declared on the explicit `kind: pivot`
133
131
  // schema (resolved upstream and passed via context.pivotProperties).
134
132
  // The legacy `pivotFields:` block on the M2M property was removed in
135
133
  // v5.0.0; pivot columns now live on the pivot schema itself.
136
134
  const pivotCols = context?.pivotProperties ?? [];
137
135
  if (pivotCols.length > 0) {
138
- const fields = pivotCols.map(k => `'${toSnakeCase(k)}'`).join(', ');
136
+ // Callers pass physical column names. Association properties on an
137
+ // explicit pivot are resolved to `<name>_id` before reaching here.
138
+ const fields = pivotCols.map(k => `'${k}'`).join(', ');
139
139
  chain += `\n ->withPivot(${fields})`;
140
140
  }
141
141
  chain += `\n ->withTimestamps()`;
package/dist/types.d.ts CHANGED
@@ -338,6 +338,8 @@ export interface PropertyDefinition {
338
338
  readonly morphName?: string;
339
339
  readonly joinTable?: string;
340
340
  readonly mappedBy?: string;
341
+ /** Physical FK column override for owning ManyToOne/OneToOne associations. */
342
+ readonly column?: string;
341
343
  readonly orderBy?: readonly OrderByItem[];
342
344
  readonly useCurrent?: boolean;
343
345
  readonly deprecated?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnifyjp/ts",
3
- "version": "5.9.20",
3
+ "version": "6.0.0",
4
4
  "description": "TypeScript model type generator from Omnify schemas.json",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",