Skip to content

Commit 79e9fa9

Browse files
committed
refactor(relationships): simplify parent/child properties to allow method reusability
1 parent b6224f6 commit 79e9fa9

File tree

1 file changed

+61
-42
lines changed

1 file changed

+61
-42
lines changed

src/model/relationship.ts

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,79 @@ import RelationshipTypes from '../enums/relationship_types.js'
33
import type Model from './index.js'
44
import type ModelColumn from './column.js'
55

6+
export type ModelRelationshipInfo = {
7+
type: RelationshipTypes
8+
modelName: string
9+
modelColumn: string
10+
tableName: string
11+
tableColumn: string
12+
}
13+
614
export default class ModelRelationship {
715
declare foreignKey: string
16+
declare parent: ModelRelationshipInfo
17+
declare child: ModelRelationshipInfo
818

9-
declare parentType: RelationshipTypes
10-
declare parentModelName: string
11-
declare parentModelColumn: string
12-
declare parentTableName: string
13-
declare parentTableColumn: string
14-
15-
declare childType: RelationshipTypes
16-
declare childModelName: string
17-
declare childModelColumn: string
18-
declare childTableName: string
19-
declare childTableColumn: string
20-
21-
constructor(type: RelationshipTypes, column: ModelColumn, tables: Model[]) {
19+
constructor(type: RelationshipTypes, column: ModelColumn, models: Model[]) {
2220
const isBelongsTo = type === RelationshipTypes.BELONGS_TO
23-
const local = tables.find((table) => table.tableName === column.tableName)
24-
const foreign = tables.find((table) => table.tableName === column.foreignKeyTable)
21+
const local = models.find((model) => model.tableName === column.tableName)
22+
const foreign = models.find((model) => model.tableName === column.foreignKeyTable)
2523

26-
const [parentTable, childTable] = isBelongsTo ? [foreign, local] : [local, foreign]
24+
const [parentModel, childModel] = isBelongsTo ? [foreign, local] : [local, foreign]
2725
const [parentColumn, childColumn] = isBelongsTo
2826
? [column.foreignKeyColumn, column.columnName]
2927
: [column.columnName, column.foreignKeyColumn]
3028

3129
this.foreignKey = `${column.foreignKeyTable}.${column.foreignKeyColumn}`
3230

33-
this.parentTableName = parentTable!.tableName
34-
this.childTableName = childTable!.tableName
31+
this.parent = {
32+
type: type,
33+
tableName: parentModel!.tableName,
34+
tableColumn: parentColumn!,
35+
modelName: parentModel!.name,
36+
modelColumn: this.#getModelColumn(parentModel!, parentColumn!),
37+
}
38+
39+
this.child = {
40+
type: type,
41+
tableName: childModel!.tableName,
42+
tableColumn: childColumn!,
43+
modelName: childModel!.name,
44+
modelColumn: this.#getModelColumn(childModel!, childColumn!),
45+
}
46+
47+
this.#setTypes(type, column, models)
48+
}
3549

36-
this.parentTableColumn = parentColumn!
37-
this.childTableColumn = childColumn!
50+
getDefinitions(modelName: string) {
51+
const definitions = []
3852

39-
this.parentModelName = parentTable!.name
40-
this.childModelName = childTable!.name
53+
if (modelName === this.parent.modelName) {
54+
definitions.push(this.#getDefinition(this.parent))
55+
}
4156

42-
this.parentModelColumn = this.#getModelColumn(parentTable!, this.parentTableColumn)
43-
this.childModelColumn = this.#getModelColumn(childTable!, this.childTableColumn)
57+
if (modelName === this.child.modelName) {
58+
definitions.push(this.#getDefinition(this.child))
59+
}
4460

45-
this.#setTypes(type, column, tables)
61+
return definitions
4662
}
4763

48-
toDefinition() {
49-
// TODO
64+
#getDefinition(info: ModelRelationshipInfo) {
65+
return {
66+
decorator: `@${info.type}(() => ${info.modelName})`,
67+
property: `declare ${info.modelColumn}: ${string.capitalCase(info.type)}<typeof ${info.modelName}>`,
68+
}
5069
}
5170

5271
#getModelColumn(model: Model, tableColumnName: string) {
5372
return model.columns.find(({ columnName }) => columnName === tableColumnName)!.name
5473
}
5574

56-
#setTypes(type: RelationshipTypes, column: ModelColumn, tables: Model[]) {
57-
const tableNamesSingular = tables
58-
.filter((table) => table.tableName !== column.tableName)
59-
.map((table) => string.singular(table.tableName))
75+
#setTypes(type: RelationshipTypes, column: ModelColumn, models: Model[]) {
76+
const tableNamesSingular = models
77+
.filter((model) => model.tableName !== column.tableName)
78+
.map((model) => string.singular(model.tableName))
6079

6180
const tableNameSingular = string.singular(column.tableName)
6281
const startsWithTable = tableNamesSingular.find((name) => tableNameSingular.startsWith(name))
@@ -66,23 +85,23 @@ export default class ModelRelationship {
6685
// if start & end are both tables and their joined values match the current table
6786
// then, assume it's a many-to-many
6887
if (tableNameSingular === pivotName || type === RelationshipTypes.MANY_TO_MANY) {
69-
this.childType = RelationshipTypes.MANY_TO_MANY
70-
this.parentType = RelationshipTypes.MANY_TO_MANY
88+
this.child.type = RelationshipTypes.MANY_TO_MANY
89+
this.parent.type = RelationshipTypes.MANY_TO_MANY
7190
return
7291
}
7392

7493
// if relation is belongs to, assume the other side is has many
7594
// note: the difference between has one & has many cannot be determined
7695
// so we pick the more common and move on
7796
if (type === RelationshipTypes.BELONGS_TO) {
78-
this.childType = type
79-
this.parentType = RelationshipTypes.HAS_MANY
97+
this.child.type = type
98+
this.parent.type = RelationshipTypes.HAS_MANY
8099
return
81100
}
82101

83102
// otherwise, child is likely belongs to
84-
this.parentType = type
85-
this.childType = RelationshipTypes.BELONGS_TO
103+
this.parent.type = type
104+
this.child.type = RelationshipTypes.BELONGS_TO
86105
}
87106

88107
static parse(models: Model[]) {
@@ -94,17 +113,17 @@ export default class ModelRelationship {
94113

95114
if (!relationship) return
96115

97-
const parent = relationships.get(relationship.parentModelName) ?? new Map()
116+
const parent = relationships.get(relationship.parent.modelName) ?? new Map()
98117

99118
parent.set(relationship.foreignKey, relationship)
100-
relationships.set(relationship.parentModelName, parent)
119+
relationships.set(relationship.parent.modelName, parent)
101120

102-
if (relationship.parentModelName === relationship.childModelName) return
121+
if (relationship.parent.modelName === relationship.child.modelName) return
103122

104-
const child = relationships.get(relationship.childModelName) ?? new Map()
123+
const child = relationships.get(relationship.child.modelName) ?? new Map()
105124

106125
child.set(relationship.foreignKey, relationship)
107-
relationships.set(relationship.childModelName, child)
126+
relationships.set(relationship.child.modelName, child)
108127
})
109128
})
110129

0 commit comments

Comments
 (0)