Skip to content

Commit

Permalink
refactor(repository): separate CRUD and transaction repos
Browse files Browse the repository at this point in the history
  • Loading branch information
Biniam Admikew committed Jul 25, 2019
1 parent 4549f96 commit 1b8a26c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {DefaultCrudRepository} from '@loopback/repository';
import {DefaultTransactionalRepository} from '@loopback/repository';
import {
CrudRepositoryCtor,
crudRepositoryTestSuite,
} from '@loopback/repository-tests';
import {MYSQL_CONFIG, MYSQL_FEATURES} from './mysql.datasource';

describe('MySQL + DefaultCrudRepository', () => {
describe('MySQL + DefaultTransactionalRepository', () => {
crudRepositoryTestSuite(
MYSQL_CONFIG,
// Workaround for https://github.com/microsoft/TypeScript/issues/31840
DefaultCrudRepository as CrudRepositoryCtor,
DefaultTransactionalRepository as CrudRepositoryCtor,
MYSQL_FEATURES,
);
});
3 changes: 2 additions & 1 deletion packages/repository-tests/src/crud/transactions.suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
juggler,
model,
property,
Transaction,
TransactionalRepository,
} from '@loopback/repository';
import {expect, skipIf, toJSON} from '@loopback/testlab';
Expand Down Expand Up @@ -103,7 +104,7 @@ export function transactionSuite(
});

it('ensures transactions are isolated', async () => {
const tx: juggler.Transaction = await repo.beginTransaction({
const tx: Transaction = await repo.beginTransaction({
isolationLevel: IsolationLevel.READ_COMMITTED,
});
const created = await repo.create(
Expand Down
2 changes: 1 addition & 1 deletion packages/repository-tests/src/types.repository-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export type CrudRepositoryCtor = new <
) => EntityCrudRepository<T, ID, Relations>;

/**
* A constructor of a class implementing CrudRepository interface,
* A constructor of a class implementing TransactionalRepository interface,
* accepting the Entity class (constructor) and a dataSource instance.
*/
export type TransactionalRepositoryCtor = new <
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {expect} from '@loopback/testlab';
import {
bindModel,
DefaultCrudRepository,
DefaultTransactionalRepository,
Entity,
EntityNotFoundError,
juggler,
Expand Down Expand Up @@ -413,14 +414,14 @@ describe('DefaultCrudRepository', () => {
});

it(`throws error when execute() not implemented by ds connector`, async () => {
const repo = new DefaultCrudRepository(Note, ds);
const repo = new DefaultTransactionalRepository(Note, ds);
await expect(repo.execute('query', [])).to.be.rejectedWith(
'execute() must be implemented by the connector',
);
});

it('throws an error when beginTransaction() not implemented', async () => {
const repo = new DefaultCrudRepository(Note, ds);
const repo = new DefaultTransactionalRepository(Note, ds);
await expect(repo.beginTransaction({})).to.be.rejectedWith(
'beginTransaction must be function implemented by the connector',
);
Expand All @@ -431,7 +432,7 @@ describe('DefaultCrudRepository', () => {
connector: CrudConnectorStub,
});

const repo = new DefaultCrudRepository(Note, crudDs);
const repo = new DefaultTransactionalRepository(Note, crudDs);
const res = await repo.beginTransaction();
expect(res).to.be.instanceOf(TransactionClass);
});
Expand Down
30 changes: 21 additions & 9 deletions packages/repository/src/repositories/legacy-juggler-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class DefaultCrudRepository<
T extends Entity,
ID,
Relations extends object = {}
> implements TransactionalRepository<T, ID, Relations> {
> implements EntityCrudRepository<T, ID, Relations> {
modelClass: juggler.PersistedModelClass;

/**
Expand Down Expand Up @@ -439,14 +439,6 @@ export class DefaultCrudRepository<
}
}

async beginTransaction(
options?: IsolationLevel | Options,
): Promise<Transaction> {
return (await this.dataSource.beginTransaction(options as (
| juggler.IsolationLevel
| Options))) as Transaction;
}

async count(where?: Where<T>, options?: Options): Promise<Count> {
const result = await ensurePromise(this.modelClass.count(where, options));
return {count: result};
Expand All @@ -472,3 +464,23 @@ export class DefaultCrudRepository<
return models.map(m => this.toEntity<R>(m));
}
}

/**
* Default implementation of CRUD repository using legacy juggler model
* and data source with beginTransaction() method for connectors which
* support Transactions
*/

export class DefaultTransactionalRepository<
T extends Entity,
ID,
Relations extends object = {}
> extends DefaultCrudRepository<T, ID, Relations>
implements TransactionalRepository<T, ID, Relations> {
async beginTransaction(
options?: IsolationLevel | Options,
): Promise<Transaction> {
const dsOptions: juggler.IsolationLevel | Options = options || {};
return (await this.dataSource.beginTransaction(dsOptions)) as Transaction;
}
}

0 comments on commit 1b8a26c

Please sign in to comment.