Skip to content

Commit 8bae584

Browse files
committed
Merge branch 'master' into feature/update-docs-associations
2 parents ef2ecc2 + f25f2c9 commit 8bae584

File tree

14 files changed

+418
-40
lines changed

14 files changed

+418
-40
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
language: node_js
22

33
node_js:
4-
- "6.1"
4+
- "7"
5+
6+
before_install:
7+
- npm i -g npm@5
58

69
install:
710
- npm install

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ should appear as a column in the database, require the `@Column` annotation.
6565

6666
### `@Table`
6767
The `@Table` annotation can be used without passing any parameters. To specify some more define options, use
68-
an object literal (all [define options](http://docs.sequelizejs.com/en/v3/api/sequelize/#definemodelname-attributes-options-model)
68+
an object literal (all [define options](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration)
6969
from sequelize are valid):
7070
```typescript
7171
@Table({
@@ -79,7 +79,7 @@ class Person extends Model<Person> {}
7979
Decorator | Description
8080
--------------------------------------|---------------------
8181
`@Table` | sets `options.tableName=<CLASS_NAME>` and `options.modelName=<CLASS_NAME>` automatically
82-
`@Table(options: DefineOptions)` | sets [define options](http://docs.sequelizejs.com/en/v3/api/sequelize/#definemodelname-attributes-options-model) (also sets `options.tableName=<CLASS_NAME>` and `options.modelName=<CLASS_NAME>` if not already defined by define options)
82+
`@Table(options: DefineOptions)` | sets [define options](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration) (also sets `options.tableName=<CLASS_NAME>` and `options.modelName=<CLASS_NAME>` if not already defined by define options)
8383

8484
#### Primary key
8585
A primary key (`id`) will be inherited from base class `Model`. This primary key is by default an `INTEGER` and has
@@ -124,7 +124,7 @@ import {DataType} from 'sequelize-typescript';
124124
name: string;
125125
```
126126
Or for a more detailed column description, use an object literal
127-
(all [attribute options](http://docs.sequelizejs.com/en/v3/api/sequelize/#definemodelname-attributes-options-model)
127+
(all [attribute options](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration)
128128
from sequelize are valid):
129129
```typescript
130130
@Column({
@@ -138,9 +138,9 @@ from sequelize are valid):
138138

139139
Decorator | Description
140140
--------------------------------------|---------------------
141-
`@Column` | tries to infer [dataType](http://docs.sequelizejs.com/en/v3/docs/models-definition/#data-types) from js type
142-
`@Column(dataType: DateType)` | sets [dataType](http://docs.sequelizejs.com/en/v3/docs/models-definition/#data-types) explicitly
143-
`@Column(options: AttributeOptions)` | sets [attribute options](http://docs.sequelizejs.com/en/v3/api/sequelize/#definemodelname-attributes-options-model)
141+
`@Column` | tries to infer [dataType](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#data-types) from js type
142+
`@Column(dataType: DateType)` | sets [dataType](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#data-types) explicitly
143+
`@Column(options: AttributeOptions)` | sets [attribute options](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#configuration)
144144

145145
#### *Shortcuts*
146146
If you're in love with decorators: *sequelize-typescript* provides some more of them. The following decorators can be
@@ -185,7 +185,7 @@ class Person extends Model<Person> {
185185

186186
## Usage
187187
Except for minor variations *sequelize-typescript* will work like pure sequelize.
188-
(See sequelize [docs](http://docs.sequelizejs.com/en/v3/docs/models-usage/))
188+
(See sequelize [docs](http://docs.sequelizejs.com/manual/tutorial/models-usage.html))
189189
### Configuration
190190
To make the defined models available, you have to configure a `Sequelize` instance from `sequelize-typescript`(!).
191191
```typescript
@@ -233,7 +233,7 @@ person.save();
233233

234234
### Find and update
235235
Finding and updating entries do also work like using native sequelize. So see sequelize
236-
[docs](http://docs.sequelizejs.com/en/v3/docs/models-usage/) for more details.
236+
[docs](http://docs.sequelizejs.com/manual/tutorial/models-usage.html) for more details.
237237
```typescript
238238
Person
239239
.findOne<Person>()
@@ -444,7 +444,7 @@ validation instead, you can do so by simply adding the validate options *as* dec
444444
So that `validate.isEmail=true` becomes `@IsEmail`, `validate.equals='value'` becomes `@Equals('value')`
445445
and so on. Please notice, that a validator, that expects a boolean, is translated to an annotation without a parameter.
446446

447-
See sequelize [docs](http://docs.sequelizejs.com/en/v3/docs/models-definition/#validations)
447+
See sequelize [docs](http://docs.sequelizejs.com/manual/tutorial/models-definition.html#validations)
448448
for all validators.
449449

450450
### Exceptions
@@ -514,7 +514,7 @@ export class Shoe extends Model<Shoe> {
514514
Scopes can be defined with annotations as well. The scope options are mostly the same like in native
515515
sequelize except of the way how model classes are referenced. So instead of referencing them directly a getter
516516
function `() => Model` is used instead.
517-
(See sequelize [docs](http://docs.sequelizejs.com/en/v3/docs/scopes/) for more details)
517+
(See sequelize [docs](http://docs.sequelizejs.com/manual/tutorial/scopes.html) for more details)
518518

519519
### `@DefaultScope` and `@Scopes`
520520
```typescript

lib/annotations/ForeignKey.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import {AssociationForeignKeyOptions} from 'sequelize';
12
import {Model} from "../models/Model";
23
import {addForeignKey} from "../services/association";
34

4-
export function ForeignKey(relatedClassGetter: () => typeof Model): Function {
5+
export function ForeignKey(relatedClassGetter: () => typeof Model, options?: AssociationForeignKeyOptions): Function {
56

67
return (target: any, propertyName: string) => {
78

8-
addForeignKey(target, relatedClassGetter, propertyName);
9+
if (!options) {
10+
options = {name: propertyName};
11+
} else if (!options.name) {
12+
options.name = propertyName;
13+
}
14+
15+
addForeignKey(target, relatedClassGetter, options);
916
};
1017
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1+
import {AssociationOptionsBelongsTo} from 'sequelize';
2+
13
import {Model} from "../../models/Model";
24
import {BELONGS_TO, addAssociation} from "../../services/association";
35

46
export function BelongsTo(relatedClassGetter: () => typeof Model,
5-
foreignKey?: string): Function {
7+
options?: string | AssociationOptionsBelongsTo): Function {
68

79
return (target: any, propertyName: string) => {
810

11+
if (typeof options === 'string') {
12+
options = {foreignKey: {name: options}};
13+
}
14+
915
addAssociation(
1016
target,
1117
BELONGS_TO,
1218
relatedClassGetter,
1319
propertyName,
14-
foreignKey
20+
options
1521
);
1622
};
1723
}

lib/annotations/association/BelongsToMany.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1+
import {AssociationOptionsBelongsToMany} from 'sequelize';
2+
13
import {Model} from "../../models/Model";
24
import {BELONGS_TO_MANY, addAssociation} from "../../services/association";
35

46
export function BelongsToMany(relatedClassGetter: () => typeof Model,
57
through: (() => typeof Model)|string,
6-
foreignKey?: string,
8+
options?: string | AssociationOptionsBelongsToMany,
79
otherKey?: string): Function {
810

911
return (target: any, propertyName: string) => {
10-
12+
if (typeof options === 'string') {
13+
// don't worry, through is mainly here to avoid TS error; actual through value is resolved later
14+
options = {through: '', foreignKey: {name: options}};
15+
}
1116
addAssociation(
1217
target,
1318
BELONGS_TO_MANY,
1419
relatedClassGetter,
1520
propertyName,
16-
foreignKey,
21+
options,
1722
otherKey,
1823
through
1924
);
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import {AssociationOptionsHasMany} from 'sequelize';
2+
13
import {Model} from "../../models/Model";
24
import {HAS_MANY, addAssociation} from "../../services/association";
35

46
export function HasMany(relatedClassGetter: () => typeof Model,
5-
foreignKey?: string): Function {
7+
options?: string | AssociationOptionsHasMany): Function {
68

79
return (target: any, propertyName: string) => {
8-
10+
if (typeof options === 'string') {
11+
options = {foreignKey: {name: options}};
12+
}
913
addAssociation(
1014
target,
1115
HAS_MANY,
1216
relatedClassGetter,
1317
propertyName,
14-
foreignKey
18+
options
1519
);
1620
};
1721
}

lib/annotations/association/HasOne.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import {AssociationOptionsHasOne} from 'sequelize';
2+
13
import {Model} from "../../models/Model";
24
import {addAssociation, HAS_ONE} from "../../services/association";
35

46
export function HasOne(relatedClassGetter: () => typeof Model,
5-
foreignKey?: string): Function {
7+
options?: string | AssociationOptionsHasOne): Function {
68

79
return (target: any, propertyName: string) => {
8-
10+
if (typeof options === 'string') {
11+
options = {foreignKey: {name: options}};
12+
}
913
addAssociation(
1014
target,
1115
HAS_ONE,
1216
relatedClassGetter,
1317
propertyName,
14-
foreignKey
18+
options
1519
);
1620
};
1721
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {AssociationOptionsBelongsTo, AssociationOptionsBelongsToMany, AssociationOptionsHasMany,
2+
AssociationOptionsHasOne, AssociationOptionsManyToMany} from 'sequelize';
13
import {Model} from "../models/Model";
24

35
export interface ISequelizeAssociation {
@@ -6,7 +8,8 @@ export interface ISequelizeAssociation {
68
relatedClassGetter: () => typeof Model;
79
through?: string;
810
throughClassGetter?: () => typeof Model;
9-
foreignKey?: string;
11+
options?: AssociationOptionsBelongsTo | AssociationOptionsBelongsToMany | AssociationOptionsHasMany |
12+
AssociationOptionsHasOne | AssociationOptionsManyToMany;
1013
otherKey?: string;
1114
as: string;
1215
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import {AssociationForeignKeyOptions} from 'sequelize';
12
import {Model} from "../models/Model";
23

34
export interface ISequelizeForeignKeyConfig {
45

56
relatedClassGetter: () => typeof Model;
6-
foreignKey: string;
7+
options: string | AssociationForeignKeyOptions;
78
}

lib/models/BaseSequelize.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {merge} from 'lodash';
12
import {Model} from "./Model";
23
import {getModels} from "../services/models";
34
import {getAssociations, BELONGS_TO_MANY} from "../services/association";
@@ -89,7 +90,6 @@ export abstract class BaseSequelize {
8990

9091
associations.forEach(association => {
9192

92-
const foreignKey = association.foreignKey || getForeignKey(model, association);
9393
const relatedClass = association.relatedClassGetter();
9494
let through;
9595
let otherKey;
@@ -126,12 +126,17 @@ export abstract class BaseSequelize {
126126
}
127127
}
128128

129-
model[association.relation](relatedClass, {
129+
// ensure association options by default have most explicit foreignKey options
130+
// so it merges properly with different foreignKey option permutations, or is overrwritten
131+
// completely by options.foreignKey
132+
const foreignKey = getForeignKey(model, association);
133+
const options = merge({foreignKey: {name: foreignKey}}, association.options,
134+
{
130135
as: association.as,
131136
through,
132-
foreignKey,
133137
otherKey
134138
});
139+
model[association.relation](relatedClass, options);
135140

136141
// The associations has to be adjusted
137142
const _association = model['associations'][association.as];

0 commit comments

Comments
 (0)