@@ -3,60 +3,79 @@ import RelationshipTypes from '../enums/relationship_types.js'
3
3
import type Model from './index.js'
4
4
import type ModelColumn from './column.js'
5
5
6
+ export type ModelRelationshipInfo = {
7
+ type : RelationshipTypes
8
+ modelName : string
9
+ modelColumn : string
10
+ tableName : string
11
+ tableColumn : string
12
+ }
13
+
6
14
export default class ModelRelationship {
7
15
declare foreignKey : string
16
+ declare parent : ModelRelationshipInfo
17
+ declare child : ModelRelationshipInfo
8
18
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 [ ] ) {
22
20
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 )
25
23
26
- const [ parentTable , childTable ] = isBelongsTo ? [ foreign , local ] : [ local , foreign ]
24
+ const [ parentModel , childModel ] = isBelongsTo ? [ foreign , local ] : [ local , foreign ]
27
25
const [ parentColumn , childColumn ] = isBelongsTo
28
26
? [ column . foreignKeyColumn , column . columnName ]
29
27
: [ column . columnName , column . foreignKeyColumn ]
30
28
31
29
this . foreignKey = `${ column . foreignKeyTable } .${ column . foreignKeyColumn } `
32
30
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
+ }
35
49
36
- this . parentTableColumn = parentColumn !
37
- this . childTableColumn = childColumn !
50
+ getDefinitions ( modelName : string ) {
51
+ const definitions = [ ]
38
52
39
- this . parentModelName = parentTable ! . name
40
- this . childModelName = childTable ! . name
53
+ if ( modelName === this . parent . modelName ) {
54
+ definitions . push ( this . #getDefinition( this . parent ) )
55
+ }
41
56
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
+ }
44
60
45
- this . #setTypes ( type , column , tables )
61
+ return definitions
46
62
}
47
63
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
+ }
50
69
}
51
70
52
71
#getModelColumn( model : Model , tableColumnName : string ) {
53
72
return model . columns . find ( ( { columnName } ) => columnName === tableColumnName ) ! . name
54
73
}
55
74
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 ) )
60
79
61
80
const tableNameSingular = string . singular ( column . tableName )
62
81
const startsWithTable = tableNamesSingular . find ( ( name ) => tableNameSingular . startsWith ( name ) )
@@ -66,23 +85,23 @@ export default class ModelRelationship {
66
85
// if start & end are both tables and their joined values match the current table
67
86
// then, assume it's a many-to-many
68
87
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
71
90
return
72
91
}
73
92
74
93
// if relation is belongs to, assume the other side is has many
75
94
// note: the difference between has one & has many cannot be determined
76
95
// so we pick the more common and move on
77
96
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
80
99
return
81
100
}
82
101
83
102
// 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
86
105
}
87
106
88
107
static parse ( models : Model [ ] ) {
@@ -94,17 +113,17 @@ export default class ModelRelationship {
94
113
95
114
if ( ! relationship ) return
96
115
97
- const parent = relationships . get ( relationship . parentModelName ) ?? new Map ( )
116
+ const parent = relationships . get ( relationship . parent . modelName ) ?? new Map ( )
98
117
99
118
parent . set ( relationship . foreignKey , relationship )
100
- relationships . set ( relationship . parentModelName , parent )
119
+ relationships . set ( relationship . parent . modelName , parent )
101
120
102
- if ( relationship . parentModelName === relationship . childModelName ) return
121
+ if ( relationship . parent . modelName === relationship . child . modelName ) return
103
122
104
- const child = relationships . get ( relationship . childModelName ) ?? new Map ( )
123
+ const child = relationships . get ( relationship . child . modelName ) ?? new Map ( )
105
124
106
125
child . set ( relationship . foreignKey , relationship )
107
- relationships . set ( relationship . childModelName , child )
126
+ relationships . set ( relationship . child . modelName , child )
108
127
} )
109
128
} )
110
129
0 commit comments