Skip to content

Commit ebd0b58

Browse files
committed
feat(typeorm): upgrade typeorm to v0.3 and address breaking changes
typeorm intorduced several breaking changes in v0.3.0. this refactors the library to account for those changes. specifically some changes to the repository interface and the removal of the ability to fetch a custom repository. BREAKING CHANGE: `EntityRepository` is replaced with `PolymorphicRepository`. `connection.getCustomRepository` is replaced with `AbstractPolymorphicRepository.createRepository`.
1 parent 2e996ec commit ebd0b58

10 files changed

+1143
-1154
lines changed

README.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,25 @@ This has worked for my use case however it might not for others. This is an exam
2323
### Extend the PolymorphicRepository
2424

2525
```ts
26-
@EntityRepository(AdvertEntity)
26+
import { PolymorphicRepository } from 'typeorm-polymorphic';
27+
28+
@PolymorphicRepository(AdvertEntity)
2729
export class AdvertRepository extends AbstractPolymorphicRepository<
2830
AdvertEntity
2931
> {}
3032
```
3133

34+
Then, to instantiate your repository you can call:
35+
36+
```ts
37+
import { AbstractPolymorphicRepository } from 'typeorm-polymorphic';
38+
39+
const repository = AbstractPolymorphicRepository.createRepository(
40+
dataSource, // where `dataSource` is a typeorm DataSource object
41+
AdvertRepository,
42+
);
43+
```
44+
3245
> The below decorators will only work when using the above abstract repository AbstractPolymorphicRepository
3346
3447
### Setup the entities
@@ -96,6 +109,9 @@ id | entityId | entityType
96109

97110
Both `PolymorphicChildren` and `PolymophicParent` are treated same. Currently some of the default values are different but eventually these method should be synonyms of one another. They have different names because it helped me describe the relationship directions which could be explained as 'parent' 'child' in different ways.
98111

112+
`PolymophicRepository` allows you to define a custom typeorm repository and then
113+
instantiate it later via `AbstractPolymorphicRepository.createRepository(...)`.
114+
99115
### Ambiguous direction
100116

101117
Both `PolymorphicParent` and `PolymorphicChildren` accepts either an array of types or a singular type

index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
"use strict";
22
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
33
if (k2 === undefined) k2 = k;
4-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4+
var desc = Object.getOwnPropertyDescriptor(m, k);
5+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6+
desc = { enumerable: true, get: function() { return m[k]; } };
7+
}
8+
Object.defineProperty(o, k2, desc);
59
}) : (function(o, m, k, k2) {
610
if (k2 === undefined) k2 = k;
711
o[k2] = m[k];

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838
"prettier": "^2.2.1",
3939
"reflect-metadata": "^0.1.13",
4040
"ts-jest": "^26.4.4",
41-
"typeorm": "^0.2.29",
41+
"typeorm": "^0.3.12",
4242
"typescript": "^4.1.3"
4343
},
4444
"peerDependencies": {
45-
"typeorm": "^0.2.29 <= ^0.2.45"
45+
"typeorm": "^0.3.0"
4646
},
4747
"jest": {
4848
"moduleFileExtensions": [

src/__tests__/polymorphic.repository.spec.ts

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { Connection, createConnection, Repository } from 'typeorm';
1+
import { DataSource, Repository } from 'typeorm';
22
import { AdvertEntity } from './entities/advert.entity';
33
import { UserEntity } from './entities/user.entity';
44
import { config } from 'dotenv';
55
import { resolve } from 'path';
66
import { AdvertRepository } from './repository/advert.repository';
77
import { AbstractPolymorphicRepository } from '../';
8+
import { MerchantEntity } from './entities/merchant.entity';
89

910
describe('AbstractPolymorphicRepository', () => {
10-
let connection: Connection;
11+
let connection: DataSource;
1112

1213
let userRepository: Repository<UserEntity>;
1314
let repository: AbstractPolymorphicRepository<AdvertEntity>;
@@ -17,20 +18,21 @@ describe('AbstractPolymorphicRepository', () => {
1718
path: resolve(__dirname, '.', '..', '..', '.env'),
1819
});
1920

20-
connection = await createConnection({
21+
connection = new DataSource({
2122
type: 'mysql',
2223
host: process.env.TYPEORM_HOST,
2324
port: parseInt(process.env.TYPEORM_PORT as string, 10),
2425
username: process.env.TYPEORM_USERNAME,
2526
password: process.env.TYPEORM_PASSWORD,
26-
entities: ['./*/**/*.entity.ts'],
27+
entities: [UserEntity, AdvertEntity, MerchantEntity],
2728
synchronize: process.env.TYPEORM_SYNCHRONIZE === 'true',
2829
database: process.env.TYPEORM_DATABASE,
2930
});
31+
await connection.initialize();
3032
});
3133

3234
afterAll(async () => {
33-
await connection.close();
35+
await connection.destroy();
3436

3537
await userRepository.createQueryBuilder().delete().execute();
3638
await repository.createQueryBuilder().delete().execute();
@@ -44,7 +46,10 @@ describe('AbstractPolymorphicRepository', () => {
4446
describe('Childen', () => {
4547
describe('create', () => {
4648
it('Can create with parent', async () => {
47-
const repository = connection.getCustomRepository(AdvertRepository);
49+
const repository = AbstractPolymorphicRepository.createRepository(
50+
connection,
51+
AdvertRepository,
52+
);
4853

4954
const user = new UserEntity();
5055

@@ -59,7 +64,10 @@ describe('AbstractPolymorphicRepository', () => {
5964

6065
describe('save', () => {
6166
it('Can save cascade parent', async () => {
62-
const repository = connection.getCustomRepository(AdvertRepository);
67+
const repository = AbstractPolymorphicRepository.createRepository(
68+
connection,
69+
AdvertRepository,
70+
);
6371
const userRepository = connection.getRepository(UserEntity);
6472

6573
const user = await userRepository.save(new UserEntity());
@@ -79,7 +87,10 @@ describe('AbstractPolymorphicRepository', () => {
7987
});
8088

8189
it('Can save many with cascade parent', async () => {
82-
const repository = connection.getCustomRepository(AdvertRepository);
90+
const repository = AbstractPolymorphicRepository.createRepository(
91+
connection,
92+
AdvertRepository,
93+
);
8394
const userRepository = connection.getRepository(UserEntity);
8495

8596
const user = await userRepository.save(new UserEntity());
@@ -106,7 +117,10 @@ describe('AbstractPolymorphicRepository', () => {
106117

107118
describe('findOne', () => {
108119
it('Can find entity with parent', async () => {
109-
const repository = connection.getCustomRepository(AdvertRepository);
120+
const repository = AbstractPolymorphicRepository.createRepository(
121+
connection,
122+
AdvertRepository,
123+
);
110124
const userRepository = connection.getRepository(UserEntity);
111125

112126
const user = await userRepository.save(new UserEntity());
@@ -117,7 +131,7 @@ describe('AbstractPolymorphicRepository', () => {
117131
}),
118132
);
119133

120-
const result = await repository.findOne(advert.id);
134+
const result = await repository.findOne({ where: { id: advert.id } });
121135

122136
expect(result).toBeInstanceOf(AdvertEntity);
123137
expect(result?.owner).toBeInstanceOf(UserEntity);
@@ -128,7 +142,10 @@ describe('AbstractPolymorphicRepository', () => {
128142

129143
describe('find', () => {
130144
it('Can find entities with parent', async () => {
131-
const repository = connection.getCustomRepository(AdvertRepository);
145+
const repository = AbstractPolymorphicRepository.createRepository(
146+
connection,
147+
AdvertRepository,
148+
);
132149
const userRepository = connection.getRepository(UserEntity);
133150

134151
const user = await userRepository.save(new UserEntity());
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { EntityRepository } from 'typeorm';
1+
import { PolymorphicRepository } from '../../decorators';
22
import { AbstractPolymorphicRepository } from '../../polymorphic.repository';
33
import { AdvertEntity } from '../entities/advert.entity';
44

5-
@EntityRepository(AdvertEntity)
5+
@PolymorphicRepository(AdvertEntity)
66
export class AdvertRepository extends AbstractPolymorphicRepository<AdvertEntity> {}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { AbstractPolymorphicRepository } from '../../../dist';
2+
import { PolymorphicRepository } from '../../decorators';
23
import { UserEntity } from '../entities/user.entity';
34

5+
@PolymorphicRepository(UserEntity)
46
export class UserRepository extends AbstractPolymorphicRepository<UserEntity> {}

src/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const POLYMORPHIC_OPTIONS = 'POLYMORPHIC_OPTIONS';
22
export const POLYMORPHIC_KEY_SEPARATOR = '::';
3+
export const POLYMORPHIC_REPOSITORY = 'POLYMORPHIC_REPOSITORY';

src/decorators.ts

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1-
import { POLYMORPHIC_KEY_SEPARATOR, POLYMORPHIC_OPTIONS } from './constants';
1+
import {
2+
POLYMORPHIC_KEY_SEPARATOR,
3+
POLYMORPHIC_OPTIONS,
4+
POLYMORPHIC_REPOSITORY,
5+
} from './constants';
26
import {
37
PolymorphicDecoratorOptionsInterface,
48
PolymorphicMetadataOptionsInterface,
59
} from './polymorphic.interface';
610

7-
const polymorphicPropertyDecorator = (
8-
options: PolymorphicMetadataOptionsInterface,
9-
): PropertyDecorator => (target: Object, propertyKey: string) => {
10-
Reflect.defineMetadata(POLYMORPHIC_OPTIONS, true, target);
11-
Reflect.defineMetadata(
12-
`${POLYMORPHIC_OPTIONS}${POLYMORPHIC_KEY_SEPARATOR}${propertyKey}`,
13-
{
14-
propertyKey,
15-
...options,
16-
},
17-
target,
18-
);
19-
};
11+
const polymorphicPropertyDecorator =
12+
(options: PolymorphicMetadataOptionsInterface): PropertyDecorator =>
13+
(target: Object, propertyKey: string) => {
14+
Reflect.defineMetadata(POLYMORPHIC_OPTIONS, true, target);
15+
Reflect.defineMetadata(
16+
`${POLYMORPHIC_OPTIONS}${POLYMORPHIC_KEY_SEPARATOR}${propertyKey}`,
17+
{
18+
propertyKey,
19+
...options,
20+
},
21+
target,
22+
);
23+
};
2024

2125
export const PolymorphicChildren = (
2226
classType: () => Function[] | Function,
@@ -45,3 +49,14 @@ export const PolymorphicParent = (
4549
deleteBeforeUpdate: false,
4650
...options,
4751
});
52+
53+
export const PolymorphicRepository =
54+
(entity: Function): ClassDecorator =>
55+
(target: object, _key?: any, descriptor?: any) => {
56+
if (descriptor) {
57+
Reflect.defineMetadata(POLYMORPHIC_REPOSITORY, entity, descriptor.value);
58+
return descriptor;
59+
}
60+
Reflect.defineMetadata(POLYMORPHIC_REPOSITORY, entity, target);
61+
return target;
62+
};

0 commit comments

Comments
 (0)