e22m4u 2 лет назад
Родитель
Сommit
9cb946319f

+ 0 - 1
src/repository/index.js

@@ -1,3 +1,2 @@
 export * from './repository.js';
-export * from './repository-observer.js';
 export * from './repository-registry.js';

+ 0 - 165
src/repository/repository-observer.js

@@ -1,165 +0,0 @@
-import {Service} from '../service/index.js';
-import {isPromise} from 'mocha/lib/utils.js';
-import {InvalidArgumentError} from '../errors/index.js';
-import {DefinitionRegistry} from '../definition/index.js';
-
-/**
- * Repository event.
- *
- * @type {{
- *   BEFORE_UPDATE: string,
- *   AFTER_READ: string,
- *   BEFORE_READ: string,
- *   AFTER_DELETE: string,
- *   AFTER_CREATE: string,
- *   BEFORE_DELETE: string,
- *   BEFORE_CREATE: string,
- *   AFTER_UPDATE: string,
- * }}
- */
-export const RepositoryEvent = {
-  BEFORE_CREATE: 'beforeCreate',
-  BEFORE_READ: 'beforeRead',
-  BEFORE_UPDATE: 'beforeUpdate',
-  BEFORE_DELETE: 'beforeDelete',
-  AFTER_CREATE: 'afterCreate',
-  AFTER_READ: 'afterRead',
-  AFTER_UPDATE: 'afterUpdate',
-  AFTER_DELETE: 'afterDelete',
-};
-
-/**
- * Repository observer.
- */
-export class RepositoryObserver extends Service {
-  /**
-   * Handlers map.
-   *
-   * @example
-   * ```
-   * const eventsMap = this._handlersMap.get(modelName) || new Map();
-   * const handlers = eventsMap.get(eventName) || [];
-   * ```
-   *
-   * @type {Map<any, any>}
-   * @private
-   */
-  _handlersMap = new Map();
-
-  /**
-   * Observe.
-   *
-   * @param modelName
-   * @param eventName
-   * @param handler
-   */
-  observe(modelName, eventName, handler) {
-    if (arguments.length === 2) {
-      handler = eventName;
-      eventName = modelName;
-      modelName = null;
-    }
-    if (modelName || arguments.length === 3) {
-      if (!modelName || typeof modelName !== 'string')
-        throw new InvalidArgumentError(
-          'The parameter "modelName" of RepositoryObserver.observe ' +
-            'must be a non-empty String, but %s given.',
-          modelName,
-        );
-      if (!this.get(DefinitionRegistry).hasModel(modelName))
-        throw new InvalidArgumentError(
-          'Cannot observe repository of a not defined model %s.',
-          modelName,
-        );
-    }
-    if (!eventName || typeof eventName !== 'string') {
-      throw new InvalidArgumentError(
-        'The parameter "eventName" of RepositoryObserver.observe ' +
-          'must be a non-empty String, but %s given.',
-        eventName,
-      );
-    }
-    if (!handler || typeof handler !== 'function')
-      throw new InvalidArgumentError(
-        'The parameter "handler" of RepositoryObserver.observe ' +
-          'must be a Function, but %s given.',
-        handler,
-      );
-    const eventsMap = this._handlersMap.get(modelName) ?? new Map();
-    const handlers = eventsMap.get(eventName) ?? [];
-    handlers.push(handler);
-    eventsMap.set(eventName, handlers);
-    this._handlersMap.set(modelName, eventsMap);
-  }
-
-  /**
-   * Get handlers.
-   *
-   * @param {string} modelName
-   * @param {string} eventName
-   * @return {function[]}
-   * @private
-   */
-  _getHandlers(modelName, eventName) {
-    if (!modelName || typeof modelName !== 'string')
-      throw new InvalidArgumentError(
-        'The parameter "modelName" of RepositoryObserver._getHandlers ' +
-          'must be a non-empty String, but %s given.',
-        modelName,
-      );
-    if (!eventName || typeof eventName !== 'string')
-      throw new InvalidArgumentError(
-        'The parameter "eventName" of RepositoryObserver._getHandlers ' +
-          'must be a non-empty String, but %s given.',
-        eventName,
-      );
-    const rootEventsMap = this._handlersMap.get(null) ?? new Map();
-    const rootHandlers = rootEventsMap.get(eventName) ?? [];
-    const modelEventsMap = this._handlersMap.get(modelName) ?? new Map();
-    const modelHandlers = modelEventsMap.get(eventName) ?? [];
-    return [...rootHandlers, ...modelHandlers];
-  }
-
-  /**
-   * Emit.
-   *
-   * @param {string} modelName
-   * @param {string} eventName
-   * @param {string} methodName
-   * @param {object} context
-   * @return {Promise<unknown[]>}
-   */
-  emit(modelName, eventName, methodName, context) {
-    if (!modelName || typeof modelName !== 'string')
-      throw new InvalidArgumentError(
-        'The parameter "modelName" of RepositoryObserver.emit ' +
-          'must be a non-empty String, but %s given.',
-        modelName,
-      );
-    if (!eventName || typeof eventName !== 'string')
-      throw new InvalidArgumentError(
-        'The parameter "eventName" of RepositoryObserver.emit ' +
-          'must be a non-empty String, but %s given.',
-        eventName,
-      );
-    if (!methodName || typeof methodName !== 'string')
-      throw new InvalidArgumentError(
-        'The parameter "methodName" of RepositoryObserver.emit ' +
-          'must be a non-empty String, but %s given.',
-        methodName,
-      );
-    if (!context || typeof context !== 'object' || Array.isArray(context))
-      throw new InvalidArgumentError(
-        'The parameter "context" of RepositoryObserver.emit ' +
-          'must be an Object, but %s given.',
-        context,
-      );
-    const promises = [];
-    const handlers = this._getHandlers(modelName, eventName);
-    handlers.forEach(handler => {
-      const result = handler({modelName, eventName, methodName, ...context});
-      if (isPromise(result)) promises.push(result);
-    });
-    return Promise.all(promises);
-  }
-}

+ 0 - 455
src/repository/repository-observer.spec.js

@@ -1,455 +0,0 @@
-import {expect} from 'chai';
-import {format} from 'util';
-import {Schema} from '../schema.js';
-import {RepositoryEvent} from './repository-observer.js';
-import {RepositoryObserver} from './repository-observer.js';
-
-const MODEL_NAME = 'model';
-const EVENT_NAME = RepositoryEvent.AFTER_CREATE;
-const METHOD_NAME = 'methodName';
-const HANDLER_FN = () => undefined;
-
-describe('RepositoryObserver', function () {
-  describe('observe', function () {
-    describe('2 arguments', function () {
-      it('adds an event handler of the root scope', function () {
-        const schema = new Schema();
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        const observer = schema.get(RepositoryObserver);
-        observer.observe(EVENT_NAME, HANDLER_FN);
-        const eventsMap = observer._handlersMap.get(null);
-        const listeners = eventsMap.get(EVENT_NAME);
-        expect(listeners).to.have.lengthOf(1);
-        expect(listeners).to.include(HANDLER_FN);
-      });
-
-      it('requires the "eventName" argument to be RepositoryEvent', function () {
-        const schema = new Schema();
-        const observer = schema.get(RepositoryObserver);
-        const throwable = v => () => observer.observe(v, HANDLER_FN);
-        const error = v =>
-          format(
-            'The parameter "eventName" of RepositoryObserver.observe ' +
-              'must be a non-empty String, but %s given.',
-            v,
-          );
-        expect(throwable()).to.throw(error('undefined'));
-        expect(throwable('')).to.throw(error('""'));
-        expect(throwable(10)).to.throw(error('10'));
-        expect(throwable(true)).to.throw(error('true'));
-        expect(throwable(false)).to.throw(error('false'));
-        expect(throwable([])).to.throw(error('Array'));
-        expect(throwable({})).to.throw(error('Object'));
-        expect(throwable(null)).to.throw(error('null'));
-        Object.values(RepositoryEvent).forEach(e => throwable(e)());
-      });
-
-      it('requires the "handler" argument to be a function', function () {
-        const schema = new Schema();
-        const observer = schema.get(RepositoryObserver);
-        const throwable = v => () => observer.observe(EVENT_NAME, v);
-        const error = v =>
-          format(
-            'The parameter "handler" of RepositoryObserver.observe ' +
-              'must be a Function, but %s given.',
-            v,
-          );
-        expect(throwable()).to.throw(error('undefined'));
-        expect(throwable('')).to.throw(error('""'));
-        expect(throwable('str')).to.throw(error('"str"'));
-        expect(throwable(10)).to.throw(error('10'));
-        expect(throwable(true)).to.throw(error('true'));
-        expect(throwable(false)).to.throw(error('false'));
-        expect(throwable([])).to.throw(error('Array'));
-        expect(throwable({})).to.throw(error('Object'));
-        expect(throwable(null)).to.throw(error('null'));
-        throwable(HANDLER_FN)();
-      });
-    });
-
-    describe('3 arguments', function () {
-      it('adds an event handler of a model scope', function () {
-        const schema = new Schema();
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        const observer = schema.get(RepositoryObserver);
-        observer.observe(MODEL_NAME, EVENT_NAME, HANDLER_FN);
-        const eventsMap = observer._handlersMap.get(MODEL_NAME);
-        const listeners = eventsMap.get(EVENT_NAME);
-        expect(listeners).to.have.lengthOf(1);
-        expect(listeners).to.include(HANDLER_FN);
-      });
-
-      it('requires the "modelName" argument to be a non-empty string', function () {
-        const schema = new Schema();
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        const observer = schema.get(RepositoryObserver);
-        const throwable = v => () =>
-          observer.observe(v, EVENT_NAME, HANDLER_FN);
-        const error = v =>
-          format(
-            'The parameter "modelName" of RepositoryObserver.observe ' +
-              'must be a non-empty String, but %s given.',
-            v,
-          );
-        expect(throwable()).to.throw(error('undefined'));
-        expect(throwable('')).to.throw(error('""'));
-        expect(throwable(10)).to.throw(error('10'));
-        expect(throwable(true)).to.throw(error('true'));
-        expect(throwable(false)).to.throw(error('false'));
-        expect(throwable([])).to.throw(error('Array'));
-        expect(throwable({})).to.throw(error('Object'));
-        expect(throwable(null)).to.throw(error('null'));
-        throwable(MODEL_NAME)();
-      });
-
-      it('requires the "modelName" argument to be a defined model', function () {
-        const schema = new Schema();
-        const observer = schema.get(RepositoryObserver);
-        const throwable = () =>
-          observer.observe('unknown', EVENT_NAME, HANDLER_FN);
-        expect(throwable).to.throw(
-          'Cannot observe repository of a not defined model "unknown".',
-        );
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        observer.observe(MODEL_NAME, EVENT_NAME, HANDLER_FN);
-      });
-
-      it('requires the "eventName" argument to be RepositoryEvent', function () {
-        const schema = new Schema();
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        const observer = schema.get(RepositoryObserver);
-        const throwable = v => () =>
-          observer.observe(MODEL_NAME, v, HANDLER_FN);
-        const error = v =>
-          format(
-            'The parameter "eventName" of RepositoryObserver.observe ' +
-              'must be a non-empty String, but %s given.',
-            v,
-          );
-        expect(throwable()).to.throw(error('undefined'));
-        expect(throwable('')).to.throw(error('""'));
-        expect(throwable(10)).to.throw(error('10'));
-        expect(throwable(true)).to.throw(error('true'));
-        expect(throwable(false)).to.throw(error('false'));
-        expect(throwable([])).to.throw(error('Array'));
-        expect(throwable({})).to.throw(error('Object'));
-        expect(throwable(null)).to.throw(error('null'));
-        Object.values(RepositoryEvent).forEach(e => throwable(e)());
-      });
-
-      it('requires the "handler" argument to be a function', function () {
-        const schema = new Schema();
-        schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-        schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-        const observer = schema.get(RepositoryObserver);
-        const throwable = v => () =>
-          observer.observe(MODEL_NAME, EVENT_NAME, v);
-        const error = v =>
-          format(
-            'The parameter "handler" of RepositoryObserver.observe ' +
-              'must be a Function, but %s given.',
-            v,
-          );
-        expect(throwable()).to.throw(error('undefined'));
-        expect(throwable('')).to.throw(error('""'));
-        expect(throwable('str')).to.throw(error('"str"'));
-        expect(throwable(10)).to.throw(error('10'));
-        expect(throwable(true)).to.throw(error('true'));
-        expect(throwable(false)).to.throw(error('false'));
-        expect(throwable([])).to.throw(error('Array'));
-        expect(throwable({})).to.throw(error('Object'));
-        expect(throwable(null)).to.throw(error('null'));
-        throwable(HANDLER_FN)();
-      });
-    });
-  });
-
-  describe('_getHandlers', function () {
-    it('returns an empty array if no handlers', function () {
-      const schema = new Schema();
-      const observer = schema.get(RepositoryObserver);
-      const result = observer._getHandlers(MODEL_NAME, EVENT_NAME);
-      expect(result).to.have.lengthOf(0);
-    });
-
-    it('returns model handlers that includes root handlers', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'modelA', datasource: 'datasource'});
-      schema.defineModel({name: 'modelB', datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const handler1 = () => undefined;
-      const handler2 = () => undefined;
-      const handler3 = () => undefined;
-      const handler4 = () => undefined;
-      const handler5 = () => undefined;
-      const handler6 = () => undefined;
-      const handler7 = () => undefined;
-      const event1 = 'event1';
-      const event2 = 'event2';
-      observer.observe(event1, handler1);
-      observer.observe(event1, handler2);
-      observer.observe(event2, handler3);
-      observer.observe('modelA', event1, handler4);
-      observer.observe('modelA', event1, handler5);
-      observer.observe('modelA', event2, handler6);
-      observer.observe('modelB', event1, handler7);
-      const result = observer._getHandlers('modelA', event1);
-      expect(result).to.be.eql([handler1, handler2, handler4, handler5]);
-    });
-
-    it('requires the "modelName" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () => observer._getHandlers(v, EVENT_NAME);
-      const error = v =>
-        format(
-          'The parameter "modelName" of RepositoryObserver._getHandlers ' +
-            'must be a non-empty String, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable({})).to.throw(error('Object'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable(MODEL_NAME)();
-    });
-
-    it('requires the "eventName" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () => observer._getHandlers(MODEL_NAME, v);
-      const error = v =>
-        format(
-          'The parameter "eventName" of RepositoryObserver._getHandlers ' +
-            'must be a non-empty String, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable({})).to.throw(error('Object'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable('eventName')();
-    });
-  });
-
-  describe('emit', function () {
-    it('requires the "modelName" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () =>
-        observer.emit(v, EVENT_NAME, METHOD_NAME, {});
-      const error = v =>
-        format(
-          'The parameter "modelName" of RepositoryObserver.emit ' +
-            'must be a non-empty String, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable({})).to.throw(error('Object'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable(MODEL_NAME)();
-    });
-
-    it('requires the "eventName" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () =>
-        observer.emit(MODEL_NAME, v, METHOD_NAME, {});
-      const error = v =>
-        format(
-          'The parameter "eventName" of RepositoryObserver.emit ' +
-            'must be a non-empty String, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable({})).to.throw(error('Object'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable('eventName')();
-    });
-
-    it('requires the "methodName" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () => observer.emit(MODEL_NAME, EVENT_NAME, v, {});
-      const error = v =>
-        format(
-          'The parameter "methodName" of RepositoryObserver.emit ' +
-            'must be a non-empty String, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable({})).to.throw(error('Object'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable(METHOD_NAME)();
-    });
-
-    it('requires the "context" argument to be a non-empty string', function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const throwable = v => () =>
-        observer.emit(MODEL_NAME, EVENT_NAME, METHOD_NAME, v);
-      const error = v =>
-        format(
-          'The parameter "context" of RepositoryObserver.emit ' +
-            'must be an Object, but %s given.',
-          v,
-        );
-      expect(throwable()).to.throw(error('undefined'));
-      expect(throwable('')).to.throw(error('""'));
-      expect(throwable(10)).to.throw(error('10'));
-      expect(throwable(true)).to.throw(error('true'));
-      expect(throwable(false)).to.throw(error('false'));
-      expect(throwable([])).to.throw(error('Array'));
-      expect(throwable(null)).to.throw(error('null'));
-      throwable({})();
-    });
-
-    it('returns a promise for synchronous handlers', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      schema.defineModel({name: 'modelB', datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      const throwable = () => {
-        throw new Error();
-      };
-      observer.observe(EVENT_NAME, handler1);
-      observer.observe(EVENT_NAME, handler2);
-      observer.observe('event2', throwable);
-      observer.observe(MODEL_NAME, EVENT_NAME, handler3);
-      observer.observe(MODEL_NAME, EVENT_NAME, handler4);
-      observer.observe(MODEL_NAME, 'event2', throwable);
-      observer.observe('modelB', EVENT_NAME, throwable);
-      const promise = observer.emit(MODEL_NAME, EVENT_NAME, METHOD_NAME, {});
-      expect(promise).to.be.instanceof(Promise);
-      await promise;
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
-    });
-
-    it('returns a promise of asynchronous handlers', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      schema.defineModel({name: 'modelB', datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const order = [];
-      const handler0ms = () => {
-        order.push(handler0ms);
-        return Promise.resolve();
-      };
-      const handler5ms = () => {
-        return new Promise(res => {
-          setTimeout(() => {
-            order.push(handler5ms);
-            res();
-          }, 5);
-        });
-      };
-      const syncHandler = () => order.push(syncHandler);
-      const handler3ms = () => {
-        return new Promise(res => {
-          setTimeout(() => {
-            order.push(handler3ms);
-            res();
-          }, 3);
-        });
-      };
-      const throwable = () => {
-        throw new Error();
-      };
-      observer.observe(EVENT_NAME, handler0ms);
-      observer.observe(EVENT_NAME, handler5ms);
-      observer.observe('event2', throwable);
-      observer.observe(MODEL_NAME, EVENT_NAME, syncHandler);
-      observer.observe(MODEL_NAME, EVENT_NAME, handler3ms);
-      observer.observe(MODEL_NAME, 'event2', throwable);
-      observer.observe('modelB', EVENT_NAME, throwable);
-      const promise = observer.emit(MODEL_NAME, EVENT_NAME, METHOD_NAME, {});
-      expect(promise).to.be.instanceof(Promise);
-      await promise;
-      expect(order).to.have.lengthOf(4);
-      expect(order).to.include(handler0ms);
-      expect(order).to.include(handler5ms);
-      expect(order).to.include(syncHandler);
-      expect(order).to.include(handler3ms);
-    });
-
-    it('executes handlers with the context object', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: MODEL_NAME, datasource: 'datasource'});
-      const observer = schema.get(RepositoryObserver);
-      const inputContext = {customProp: 'customProp'};
-      const context = {
-        modelName: MODEL_NAME,
-        eventName: EVENT_NAME,
-        methodName: METHOD_NAME,
-        ...inputContext,
-      };
-      let counter = 0;
-      const handler1 = ctx => {
-        expect(ctx).to.be.eql(context);
-        counter++;
-      };
-      const handler2 = ctx => {
-        return new Promise(res => {
-          setTimeout(() => {
-            expect(ctx).to.be.eql(context);
-            counter++;
-            res();
-          }, 3);
-        });
-      };
-      observer.observe(EVENT_NAME, handler1);
-      observer.observe(MODEL_NAME, EVENT_NAME, handler2);
-      await observer.emit(MODEL_NAME, EVENT_NAME, METHOD_NAME, inputContext);
-      expect(counter).to.be.eq(2);
-    });
-  });
-});

+ 12 - 184
src/repository/repository.js

@@ -1,40 +1,8 @@
 import {Service} from '../service/index.js';
 import {AdapterRegistry} from '../adapter/index.js';
 import {InvalidArgumentError} from '../errors/index.js';
-import {RepositoryEvent} from './repository-observer.js';
 import {DefinitionRegistry} from '../definition/index.js';
 import {ModelDefinitionUtils} from '../definition/index.js';
-import {RepositoryObserver} from './repository-observer.js';
-
-/**
- * Repository method.
- *
- * @type {{
- *   DELETE: string,
- *   DELETE_BY_ID: string,
- *   CREATE: string,
- *   EXISTS: string,
- *   PATCH_BY_ID: string,
- *   FIND: string,
- *   FIND_BY_ID: string,
- *   COUNT: string,
- *   REPLACE_BY_ID: string,
- *   REPLACE_OR_CREATE: string,
- * }}
- */
-export const RepositoryMethod = {
-  CREATE: 'create',
-  REPLACE_BY_ID: 'replaceById',
-  REPLACE_OR_CREATE: 'replaceOrCreate',
-  PATCH_BY_ID: 'patchById',
-  FIND: 'find',
-  FIND_ONE: 'findOne',
-  FIND_BY_ID: 'findById',
-  DELETE: 'delete',
-  DELETE_BY_ID: 'deleteById',
-  EXISTS: 'exists',
-  COUNT: 'count',
-};
 
 /**
  * Repository.
@@ -90,7 +58,7 @@ export class Repository extends Service {
   /**
    * Get adapter.
    *
-   * @return {Promise<Object>}
+   * @return {Promise<Adapter>}
    */
   async getAdapter() {
     return this.get(AdapterRegistry).getAdapter(this.datasourceName);
@@ -104,22 +72,8 @@ export class Repository extends Service {
    * @return {Promise<object>}
    */
   async create(data, filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_CREATE,
-      RepositoryMethod.CREATE,
-      {data, filter},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.create(this.modelName, data, filter);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_CREATE,
-      RepositoryMethod.CREATE,
-      {data, filter, result},
-    );
-    return result;
+    return adapter.create(this.modelName, data, filter);
   }
 
   /**
@@ -131,22 +85,8 @@ export class Repository extends Service {
    * @return {Promise<object>}
    */
   async replaceById(id, data, filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_UPDATE,
-      RepositoryMethod.REPLACE_BY_ID,
-      {id, data, filter},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.replaceById(this.modelName, id, data, filter);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_UPDATE,
-      RepositoryMethod.REPLACE_BY_ID,
-      {id, data, filter, result},
-    );
-    return result;
+    return adapter.replaceById(this.modelName, id, data, filter);
   }
 
   /**
@@ -174,22 +114,8 @@ export class Repository extends Service {
    * @return {Promise<object>}
    */
   async patchById(id, data, filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_UPDATE,
-      RepositoryMethod.PATCH_BY_ID,
-      {id, data, filter},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.patchById(this.modelName, id, data, filter);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_UPDATE,
-      RepositoryMethod.PATCH_BY_ID,
-      {id, data, filter, result},
-    );
-    return result;
+    return adapter.patchById(this.modelName, id, data, filter);
   }
 
   /**
@@ -199,22 +125,8 @@ export class Repository extends Service {
    * @return {Promise<object[]>}
    */
   async find(filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_READ,
-      RepositoryMethod.FIND,
-      {filter},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.find(this.modelName, filter);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_READ,
-      RepositoryMethod.FIND,
-      {filter, result},
-    );
-    return result;
+    return adapter.find(this.modelName, filter);
   }
 
   /**
@@ -224,25 +136,11 @@ export class Repository extends Service {
    * @return {Promise<object|undefined>}
    */
   async findOne(filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_READ,
-      RepositoryMethod.FIND_ONE,
-      {filter},
-    );
     const adapter = await this.getAdapter();
     filter = filter ?? {};
     filter.limit = 1;
-    const resultArray = await adapter.find(this.modelName, filter);
-    const result = resultArray.length ? resultArray[0] : undefined;
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_READ,
-      RepositoryMethod.FIND_ONE,
-      {filter, result},
-    );
-    return result;
+    const result = await adapter.find(this.modelName, filter);
+    return result.length ? result[0] : undefined;
   }
 
   /**
@@ -253,22 +151,8 @@ export class Repository extends Service {
    * @return {Promise<object>}
    */
   async findById(id, filter = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_READ,
-      RepositoryMethod.FIND_BY_ID,
-      {id, filter},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.findById(this.modelName, id, filter);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_READ,
-      RepositoryMethod.FIND_BY_ID,
-      {id, filter, result},
-    );
-    return result;
+    return adapter.findById(this.modelName, id, filter);
   }
 
   /**
@@ -278,22 +162,8 @@ export class Repository extends Service {
    * @return {Promise<number>}
    */
   async delete(where = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_DELETE,
-      RepositoryMethod.DELETE,
-      {where},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.delete(this.modelName, where);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_DELETE,
-      RepositoryMethod.DELETE,
-      {where, result},
-    );
-    return result;
+    return adapter.delete(this.modelName, where);
   }
 
   /**
@@ -303,22 +173,8 @@ export class Repository extends Service {
    * @return {Promise<boolean>}
    */
   async deleteById(id) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_DELETE,
-      RepositoryMethod.DELETE_BY_ID,
-      {id},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.deleteById(this.modelName, id);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_DELETE,
-      RepositoryMethod.DELETE_BY_ID,
-      {id, result},
-    );
-    return result;
+    return adapter.deleteById(this.modelName, id);
   }
 
   /**
@@ -328,22 +184,8 @@ export class Repository extends Service {
    * @return {Promise<boolean>}
    */
   async exists(id) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_READ,
-      RepositoryMethod.EXISTS,
-      {id},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.exists(this.modelName, id);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_READ,
-      RepositoryMethod.EXISTS,
-      {id, result},
-    );
-    return result;
+    return adapter.exists(this.modelName, id);
   }
 
   /**
@@ -353,21 +195,7 @@ export class Repository extends Service {
    * @return {Promise<number>}
    */
   async count(where = undefined) {
-    const observer = this.get(RepositoryObserver);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.BEFORE_READ,
-      RepositoryMethod.COUNT,
-      {where},
-    );
     const adapter = await this.getAdapter();
-    const result = await adapter.count(this.modelName, where);
-    await observer.emit(
-      this.modelName,
-      RepositoryEvent.AFTER_READ,
-      RepositoryMethod.COUNT,
-      {where, result},
-    );
-    return result;
+    return adapter.count(this.modelName, where);
   }
 }

+ 54 - 945
src/repository/repository.spec.js

@@ -1,1070 +1,179 @@
 import {expect} from 'chai';
 import {Schema} from '../schema.js';
-import {RepositoryMethod} from './repository.js';
-import {RepositoryEvent} from './repository-observer.js';
-import {RepositoryObserver} from './repository-observer.js';
 import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../definition/index.js';
 
 describe('Repository', function () {
   describe('create', function () {
-    it('emits the "beforeCreate" event with specific context', async function () {
+    it('creates a new item from the given data', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
       const data = {foo: 'bar'};
-      const filter = {};
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.CREATE,
-        eventName: RepositoryEvent.BEFORE_CREATE,
-        data,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_CREATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_CREATE, modelHandler);
       const rep = schema.getRepository('model');
-      const result = await rep.create(data, filter);
-      expect(result).to.containSubset(data);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterCreate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const data = {foo: 'bar'};
-      const filter = {};
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.CREATE,
-        eventName: RepositoryEvent.AFTER_CREATE,
-        data,
-        filter,
-      };
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_CREATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_CREATE, modelHandler);
-      const rep = schema.getRepository('model');
-      const result = await rep.create(data, filter);
-      expect(result).to.containSubset(data);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeCreate" and "afterCreate" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_CREATE, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_CREATE, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_CREATE, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_CREATE, handler4);
-      const rep = schema.getRepository('model');
-      await rep.create({});
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      const result = await rep.create(data);
+      expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], ...data});
     });
   });
 
   describe('replaceById', function () {
-    it('emits the "beforeUpdate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const data = {foo: 'bar'};
-      const filter = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_UPDATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_UPDATE, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create(data);
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.REPLACE_BY_ID,
-        eventName: RepositoryEvent.BEFORE_UPDATE,
-        id: created[DEF_PK],
-        data,
-        filter,
-      };
-      const result = await rep.replaceById(context.id, data, filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterUpdate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const data = {foo: 'bar'};
-      const filter = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.REPLACE_BY_ID,
-        eventName: RepositoryEvent.AFTER_UPDATE,
-        data,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_UPDATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_UPDATE, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create(data);
-      context.id = created[DEF_PK];
-      const result = await rep.replaceById(context.id, data, filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeUpdate" and "afterUpdate" in order', async function () {
+    it('replaces an item by the given id', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_UPDATE, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_UPDATE, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_UPDATE, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_UPDATE, handler4);
       const rep = schema.getRepository('model');
-      const data = {foo: 'bar'};
-      const created = await rep.create(data);
-      await rep.replaceById(created[DEF_PK], data);
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      const created = await rep.create({foo: 'bar'});
+      const result = await rep.replaceById(created[DEF_PK], {baz: 'qux'});
+      expect(result).to.be.eql({[DEF_PK]: created[DEF_PK], baz: 'qux'});
     });
   });
 
   describe('patchById', function () {
-    it('emits the "beforeUpdate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const data = {foo: 'bar'};
-      const filter = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_UPDATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_UPDATE, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create(data);
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.PATCH_BY_ID,
-        eventName: RepositoryEvent.BEFORE_UPDATE,
-        id: created[DEF_PK],
-        data,
-        filter,
-      };
-      const result = await rep.patchById(context.id, data, filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterUpdate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const data = {foo: 'bar'};
-      const filter = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.PATCH_BY_ID,
-        eventName: RepositoryEvent.AFTER_UPDATE,
-        data,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_UPDATE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_UPDATE, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create(data);
-      context.id = created[DEF_PK];
-      const result = await rep.patchById(context.id, data, filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeUpdate" and "afterUpdate" in order', async function () {
+    it('patches an item by the given id', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_UPDATE, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_UPDATE, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_UPDATE, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_UPDATE, handler4);
       const rep = schema.getRepository('model');
-      const data = {foo: 'bar'};
-      const created = await rep.create(data);
-      await rep.patchById(created[DEF_PK], data);
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      const created = await rep.create({foo: 'bar'});
+      const result = await rep.patchById(created[DEF_PK], {baz: 'qux'});
+      expect(result).to.be.eql({
+        [DEF_PK]: created[DEF_PK],
+        foo: 'bar',
+        baz: 'qux',
+      });
     });
   });
 
   describe('find', function () {
-    it('emits the "beforeRead" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND,
-        eventName: RepositoryEvent.BEFORE_READ,
-        filter,
-      };
-      const result = await rep.find(filter);
-      expect(result).to.be.eql([created]);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterRead" event with specific context', async function () {
+    it('returns all items', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND,
-        eventName: RepositoryEvent.AFTER_READ,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, modelHandler);
       const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      const result = await rep.find(filter);
-      expect(result).to.be.eql([created]);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
+      const created1 = await rep.create({foo: 'bar'});
+      const created2 = await rep.create({baz: 'qux'});
+      const result = await rep.find();
+      expect(result).to.be.eql([created1, created2]);
     });
 
-    it('emits "beforeRead" and "afterRead" in order', async function () {
+    it('returns found items by the "where" clause', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, handler4);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      await rep.find();
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      const created = await rep.create({baz: 'qux'});
+      const result = await rep.find({where: {baz: 'qux'}});
+      expect(result).to.be.eql([created]);
     });
   });
 
   describe('findOne', function () {
-    it('emits the "beforeRead" event with specific context', async function () {
+    it('returns a first item', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, modelHandler);
       const rep = schema.getRepository('model');
       const created = await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND_ONE,
-        eventName: RepositoryEvent.BEFORE_READ,
-        filter,
-      };
-      const result = await rep.findOne(filter);
+      await rep.create({baz: 'qux'});
+      const result = await rep.findOne();
       expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
     });
 
-    it('emits the "afterRead" event with specific context', async function () {
+    it('returns a found item by the "where" clause', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND_ONE,
-        eventName: RepositoryEvent.AFTER_READ,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      const result = await rep.findOne(filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeRead" and "afterRead" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, handler4);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      await rep.findOne();
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      const created = await rep.create({baz: 'qux'});
+      const result = await rep.findOne({where: {baz: 'qux'}});
+      expect(result).to.be.eql(created);
     });
   });
 
   describe('findById', function () {
-    it('emits the "beforeRead" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND_BY_ID,
-        eventName: RepositoryEvent.BEFORE_READ,
-        id: created[DEF_PK],
-        filter,
-      };
-      const result = await rep.findById(context[DEF_PK], filter);
-      expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterRead" event with specific context', async function () {
+    it('returns an item by the given id', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const filter = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.FIND_BY_ID,
-        eventName: RepositoryEvent.AFTER_READ,
-        filter,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, modelHandler);
       const rep = schema.getRepository('model');
       const created = await rep.create({foo: 'bar'});
-      context.id = created[DEF_PK];
-      const result = await rep.findById(context.id, filter);
+      const result = await rep.findById(created[DEF_PK]);
       expect(result).to.be.eql(created);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeRead" and "afterRead" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, handler4);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      await rep.findById(created[DEF_PK]);
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
     });
   });
 
   describe('delete', function () {
-    it('emits the "beforeDelete" event with specific context', async function () {
+    it('removes all items', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const where = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_DELETE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_DELETE, modelHandler);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.DELETE,
-        eventName: RepositoryEvent.BEFORE_DELETE,
-        where,
-      };
-      const result = await rep.delete(where);
-      expect(result).to.be.eq(1);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
+      await rep.create({baz: 'qux'});
+      const result = await rep.delete();
+      expect(result).to.be.eq(2);
     });
 
-    it('emits the "afterRead" event with specific context', async function () {
+    it('removes found items by the "where" clause', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const where = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.DELETE,
-        eventName: RepositoryEvent.AFTER_DELETE,
-        where,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_DELETE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_DELETE, modelHandler);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      const result = await rep.delete(where);
-      expect(result).to.be.eq(1);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeDelete" and "afterDelete" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_DELETE, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_DELETE, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_DELETE, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_DELETE, handler4);
-      const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      await rep.delete();
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      await rep.create({baz: 'qux'});
+      const result = await rep.delete({foo: 'bar'});
+      expect(result).to.be.eql(2);
     });
   });
 
   describe('deleteById', function () {
-    it('emits the "beforeDelete" event with specific context', async function () {
+    it('removes an item by the given id', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_DELETE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_DELETE, modelHandler);
       const rep = schema.getRepository('model');
       const created = await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.DELETE_BY_ID,
-        eventName: RepositoryEvent.BEFORE_DELETE,
-        id: created[DEF_PK],
-      };
-      const result = await rep.deleteById(context.id);
+      const result = await rep.deleteById(created[DEF_PK]);
       expect(result).to.be.true;
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterUpdate" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.DELETE_BY_ID,
-        eventName: RepositoryEvent.AFTER_DELETE,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_DELETE, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_DELETE, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      context.id = created[DEF_PK];
-      const result = await rep.deleteById(context.id);
-      expect(result).to.be.true;
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeDelete" and "afterDelete" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_DELETE, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_DELETE, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_DELETE, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_DELETE, handler4);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      await rep.deleteById(created[DEF_PK]);
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
     });
   });
 
   describe('exists', function () {
-    it('emits the "beforeRead" event with specific context', async function () {
+    it('returns true if the given id exists', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, modelHandler);
       const rep = schema.getRepository('model');
       const created = await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.EXISTS,
-        eventName: RepositoryEvent.BEFORE_READ,
-        id: created[DEF_PK],
-      };
-      const result = await rep.exists(context.id);
+      const result = await rep.exists(created[DEF_PK]);
       expect(result).to.be.true;
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-    });
-
-    it('emits the "afterRead" event with specific context', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.EXISTS,
-        eventName: RepositoryEvent.AFTER_READ,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, modelHandler);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      context.id = created[DEF_PK];
-      const result = await rep.exists(context.id);
-      expect(result).to.be.true;
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeRead" and "afterRead" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, handler4);
-      const rep = schema.getRepository('model');
-      const created = await rep.create({foo: 'bar'});
-      await rep.exists(created[DEF_PK]);
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
     });
   });
 
   describe('count', function () {
-    it('emits the "beforeRead" event with specific context', async function () {
+    it('counts all items', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const where = {};
-      const rootHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.be.eql(context);
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, modelHandler);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.COUNT,
-        eventName: RepositoryEvent.BEFORE_READ,
-        where,
-      };
-      const result = await rep.count(where);
-      expect(result).to.be.eq(1);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
+      await rep.create({baz: 'qux'});
+      const result = await rep.count();
+      expect(result).to.be.eq(2);
     });
 
-    it('emits the "afterRead" event with specific context', async function () {
+    it('counts found items by the "where" clause', async function () {
       const schema = new Schema();
       schema.defineDatasource({name: 'datasource', adapter: 'memory'});
       schema.defineModel({name: 'model', datasource: 'datasource'});
-      let rootHandlerExecuted = false;
-      let modelHandlerExecuted = false;
-      const where = {};
-      let rootHandlerResult;
-      let modelHandlerResult;
-      const context = {
-        modelName: 'model',
-        methodName: RepositoryMethod.COUNT,
-        eventName: RepositoryEvent.AFTER_READ,
-        where,
-      };
-      const rootHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        rootHandlerResult = ctx.result;
-        rootHandlerExecuted = true;
-      };
-      const modelHandler = ctx => {
-        expect(ctx).to.containSubset(context);
-        modelHandlerResult = ctx.result;
-        modelHandlerExecuted = true;
-      };
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, rootHandler);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, modelHandler);
       const rep = schema.getRepository('model');
       await rep.create({foo: 'bar'});
-      const result = await rep.count(where);
-      expect(result).to.be.eq(1);
-      expect(rootHandlerExecuted).to.be.true;
-      expect(modelHandlerExecuted).to.be.true;
-      expect(result).to.be.eq(rootHandlerResult);
-      expect(result).to.be.eq(modelHandlerResult);
-    });
-
-    it('emits "beforeRead" and "afterRead" in order', async function () {
-      const schema = new Schema();
-      schema.defineDatasource({name: 'datasource', adapter: 'memory'});
-      schema.defineModel({name: 'model', datasource: 'datasource'});
-      const order = [];
-      const handler1 = () => order.push(handler1);
-      const handler2 = () => order.push(handler2);
-      const handler3 = () => order.push(handler3);
-      const handler4 = () => order.push(handler4);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.BEFORE_READ, handler1);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.BEFORE_READ, handler2);
-      schema
-        .get(RepositoryObserver)
-        .observe(RepositoryEvent.AFTER_READ, handler3);
-      schema
-        .get(RepositoryObserver)
-        .observe('model', RepositoryEvent.AFTER_READ, handler4);
-      const rep = schema.getRepository('model');
-      await rep.count();
-      expect(order).to.be.eql([handler1, handler2, handler3, handler4]);
+      await rep.create({foo: 'bar'});
+      await rep.create({baz: 'qux'});
+      const result = await rep.count({foo: 'bar'});
+      expect(result).to.be.eq(2);
     });
   });
 });