@mocks-server/core
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -17,2 +17,7 @@ # Change Log | ||
- Remove "onLoadMocks" method, use "onChangeMocks" | ||
- Remove the addition of extra properties when reading files. Define a name for the behavior with a mandatory option. | ||
- Remove "restart" method, use "restartServer" | ||
- Remove behavior "name" property. Use id instead. | ||
- Remove behaviors "currentName" getter. Use "currentId" instead | ||
- Remove behaviors "names" getter. Use "ids" instead | ||
@@ -25,2 +30,21 @@ ## [unreleased] | ||
## [1.3.0] - 2020-01-03 | ||
### Added | ||
- Behaviors can now be defined in json format. | ||
- Add behavior "id" property, to be used instead of "name". | ||
- Accept new options object as second argument when defining behaviors programmatically. "id" can be provided as an option. | ||
- Add behaviors "currentId" and "ids" getters, to be used instead of "currentName" and "names" | ||
- Add stop method to plugins. | ||
- Pass new method "load" to plugins, which allows to load fixtures or behaviors definitions programmatically. | ||
- Add "restartServer" method, which should be used instead of "restart". | ||
- Accept "displayName" property in plugins, which improves traces. | ||
- Accept "id" property in fixtures. | ||
### Changed | ||
- Convert filesHandler into a plugin. Load it always internally. | ||
### Fixed | ||
- Plugins start method was not being called again when core "start" method was called. | ||
- Prevent exit process when there is an error loading files. | ||
## [1.2.0] - 2019-12-22 | ||
@@ -27,0 +51,0 @@ ### Added |
{ | ||
"name": "@mocks-server/core", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Pluggable mocks server supporting multiple api behaviors", | ||
@@ -57,14 +57,14 @@ "keywords": [ | ||
"devDependencies": { | ||
"coveralls": "^3.0.7", | ||
"eslint": "6.6.0", | ||
"eslint-config-prettier": "6.5.0", | ||
"eslint-plugin-prettier": "^3.1.1", | ||
"husky": "3.0.9", | ||
"coveralls": "^3.0.9", | ||
"eslint": "6.8.0", | ||
"eslint-config-prettier": "6.9.0", | ||
"eslint-plugin-prettier": "^3.1.2", | ||
"husky": "3.1.0", | ||
"is-promise": "^2.1.0", | ||
"jest": "24.9.0", | ||
"lint-staged": "^9.4.2", | ||
"lint-staged": "^9.5.0", | ||
"prettier": "^1.19.1", | ||
"request": "^2.88.0", | ||
"request-promise": "^4.2.5", | ||
"sinon": "^7.5.0", | ||
"sinon": "^8.0.1", | ||
"strip-ansi": "6.0.0", | ||
@@ -71,0 +71,0 @@ "tree-kill-sync": "^1.0.0" |
@@ -19,4 +19,7 @@ [![Build status][travisci-image]][travisci-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Quality Gate][quality-gate-image]][quality-gate-url] | ||
* [Get started](https://www.mocks-server.org/docs/get-started-intro) | ||
* [Tutorials](https://www.mocks-server.org/docs/tutorials-static) | ||
* [Guides](https://www.mocks-server.org/docs/guides-defining-fixtures) | ||
* [Configuration](https://www.mocks-server.org/docs/configuration-options) | ||
* [Plugins](https://www.mocks-server.org/docs/plugins-inquirer-cli) | ||
* [Integrations](https://www.mocks-server.org/docs/integrations-cypress) | ||
* [Api](https://www.mocks-server.org/docs/advanced-programmatic-usage) | ||
@@ -23,0 +26,0 @@ ## Contributing |
@@ -13,8 +13,12 @@ /* | ||
const { INIT, START, LOAD_FILES, CHANGE_MOCKS, CHANGE_SETTINGS } = require("./eventNames"); | ||
const { INIT, START, STOP, LOAD_MOCKS, CHANGE_MOCKS, CHANGE_SETTINGS } = require("./eventNames"); | ||
const tracer = require("./tracer"); | ||
const Orchestrator = require("./Orchestrator"); | ||
const Loaders = require("./Loaders"); | ||
const Plugins = require("./plugins/Plugins"); | ||
const Server = require("./server/Server"); | ||
const tracer = require("./tracer"); | ||
const Mocks = require("./mocks/Mocks"); | ||
const Settings = require("./settings/Settings"); | ||
const Plugins = require("./Plugins"); | ||
@@ -24,11 +28,14 @@ class Core { | ||
this._eventEmitter = new EventEmitter(); | ||
this._settings = new Settings( | ||
{ | ||
onlyProgrammaticOptions: coreOptions.onlyProgrammaticOptions | ||
}, | ||
this._eventEmitter | ||
); | ||
this._mocks = new Mocks(this._settings, this._eventEmitter, this); | ||
this._server = new Server(this._mocks, this._settings, this._eventEmitter, this); | ||
this._plugins = new Plugins(coreOptions.plugins, this); | ||
this._settings = new Settings(this._eventEmitter, { | ||
onlyProgrammaticOptions: coreOptions.onlyProgrammaticOptions | ||
}); | ||
this._loaders = new Loaders(this); | ||
this._plugins = new Plugins(coreOptions.plugins, this._loaders, this); | ||
this._mocks = new Mocks(this._eventEmitter, this._settings, this._loaders, this); | ||
this._server = new Server(this._eventEmitter, this._settings, this._mocks, this); | ||
this._orchestrator = new Orchestrator(this._eventEmitter, this._mocks, this._server); | ||
this._inited = false; | ||
@@ -57,3 +64,2 @@ this._startPluginsPromise = null; | ||
await this.init(); // in case it has not been initializated manually before | ||
await this._mocks.start(); | ||
await this._server.start(); | ||
@@ -69,5 +75,16 @@ return this._startPlugins().then(() => { | ||
} | ||
return this._startPluginsPromise; | ||
return this._startPluginsPromise.then(() => { | ||
this._startPluginsPromise = null; | ||
}); | ||
} | ||
async _stopPlugins() { | ||
if (!this._stopPluginsPromise) { | ||
this._stopPluginsPromise = this._plugins.stop(); | ||
} | ||
return this._stopPluginsPromise.then(() => { | ||
this._stopPluginsPromise = null; | ||
}); | ||
} | ||
// TODO, deprecate method, use addRouter | ||
@@ -105,6 +122,7 @@ addCustomRouter(path, router) { | ||
onLoadFiles(cb) { | ||
tracer.deprecationWarn("onLoadFiles", "onChangeMocks"); | ||
const removeCallback = () => { | ||
this._eventEmitter.removeListener(LOAD_FILES, cb); | ||
this._eventEmitter.removeListener(LOAD_MOCKS, cb); | ||
}; | ||
this._eventEmitter.on(LOAD_FILES, cb); | ||
this._eventEmitter.on(LOAD_MOCKS, cb); | ||
return removeCallback; | ||
@@ -135,10 +153,18 @@ } | ||
async stop() { | ||
await this._server.stop(); | ||
return this._stopPlugins().then(() => { | ||
this._eventEmitter.emit(STOP, this); | ||
}); | ||
} | ||
// Expose Server methods and getters | ||
stop() { | ||
this._mocks.stop(); | ||
return this._server.stop(); | ||
// TODO, deprecate method, use restartServer | ||
restart() { | ||
tracer.deprecationWarn("restart", "restartServer"); | ||
return this.restartServer(); | ||
} | ||
restart() { | ||
restartServer() { | ||
return this._server.restart(); | ||
@@ -145,0 +171,0 @@ } |
@@ -14,3 +14,4 @@ /* | ||
START: "start", | ||
LOAD_FILES: "load:files", | ||
STOP: "stop", | ||
LOAD_MOCKS: "load:mocks", | ||
CHANGE_FIXTURES: "change:fixtures", | ||
@@ -17,0 +18,0 @@ CHANGE_MOCKS: "change:mocks", |
@@ -14,6 +14,9 @@ /* | ||
const tracer = require("../tracer"); | ||
const FixturesGroup = require("./FixturesGroup"); | ||
class Behavior { | ||
constructor(fixtures = [], parent = null) { | ||
constructor(fixtures = [], options = {}, parent = null) { | ||
this._id = options.id; | ||
this._initialFixtures = [...fixtures]; | ||
@@ -24,8 +27,8 @@ this._fixtures = new FixturesGroup(this._initialFixtures); | ||
extend(fixtures) { | ||
return new Behavior(this._initialFixtures.concat(fixtures), this); | ||
extend(fixtures, options) { | ||
return new Behavior(this._initialFixtures.concat(fixtures), options, this); | ||
} | ||
async init(fixturesHandler) { | ||
await this._fixtures.init(fixturesHandler); | ||
async init(fixturesHandler, allFixtures) { | ||
await this._fixtures.init(fixturesHandler, allFixtures); | ||
return Promise.resolve(this); | ||
@@ -38,3 +41,3 @@ } | ||
get isMocksServerBehavior() { | ||
get isBehaviorInstance() { | ||
return true; | ||
@@ -48,14 +51,26 @@ } | ||
get extendedFrom() { | ||
return this._parent ? this._parent.name : null; | ||
return this._parent ? this._parent.id : null; | ||
} | ||
// TODO, deprecate. Use id instead | ||
get name() { | ||
return this._name; // Prepared for defining behavior names based on property, file name, etc. | ||
tracer.deprecationWarn("name", "id"); | ||
return this._id; | ||
} | ||
set name(name) { | ||
this._name = name; | ||
// TODO, deprecate. Use id instead | ||
set name(id) { | ||
tracer.deprecationWarn("name", "id"); | ||
this._id = id; | ||
} | ||
get id() { | ||
return this._id; | ||
} | ||
set id(id) { | ||
this._id = id; | ||
} | ||
} | ||
module.exports = Behavior; |
@@ -16,3 +16,3 @@ /* | ||
const { compact } = require("lodash"); | ||
const { compact, uniqBy } = require("lodash"); | ||
@@ -22,11 +22,9 @@ const tracer = require("../tracer"); | ||
const { CHANGE_MOCKS, CHANGE_FIXTURES, CHANGE_SETTINGS } = require("../eventNames"); | ||
const { CHANGE_MOCKS } = require("../eventNames"); | ||
class Behaviors { | ||
constructor(filesHandler, settings, eventEmitter) { | ||
this._filesHandler = filesHandler; | ||
constructor(loaders, settings, eventEmitter) { | ||
this._loaders = loaders; | ||
this._settings = settings; | ||
this._eventEmitter = eventEmitter; | ||
this._onLoadFixtures = this._onLoadFixtures.bind(this); | ||
this._onChangeSettings = this._onChangeSettings.bind(this); | ||
this._noBehavior = new Behavior(); | ||
@@ -38,17 +36,14 @@ } | ||
this._allFixtures = allFixtures; | ||
this._eventEmitter.on(CHANGE_FIXTURES, this._onLoadFixtures); | ||
this._eventEmitter.on(CHANGE_SETTINGS, this._onChangeSettings); | ||
await this._noBehavior.init(this._fixturesHandler); | ||
return this._loadBehaviors(); | ||
await this._noBehavior.init(this._fixturesHandler, allFixtures); | ||
return Promise.resolve(); | ||
} | ||
async _loadBehaviors() { | ||
async process() { | ||
tracer.debug("Processing behaviors"); | ||
this._collection = await this._getBehaviorsCollection(); | ||
this._filesHandler.cleanContentsCustomProperties(); | ||
this._behaviors = this._getBehaviorsObject(); | ||
this._names = Object.keys(this._behaviors); | ||
this._ids = Object.keys(this._behaviors); | ||
this._current = this._settings.get("behavior"); | ||
tracer.verbose(`Loaded ${this._collection.length} behaviors`); | ||
tracer.verbose(`Processed ${this._collection.length} behaviors`); | ||
@@ -59,5 +54,5 @@ try { | ||
tracer.warn(`Defined behavior "${this._current}" was not found.`); | ||
this._current = this._names[0]; | ||
this._current = this._ids[0]; | ||
if (this._current) { | ||
tracer.warn(`Inititializing with first found behavior: "${this._names[0]}"`); | ||
tracer.warn(`Inititializing with first found behavior: "${this._ids[0]}"`); | ||
this._settings.set("behavior", this._current); | ||
@@ -71,38 +66,81 @@ } | ||
_onLoadFixtures() { | ||
this._loadBehaviors(); | ||
_isBehaviorDefinition(object) { | ||
return !!( | ||
!(object instanceof Behavior) && | ||
object.fixtures && | ||
Array.isArray(object.fixtures) && | ||
object.id | ||
); | ||
} | ||
_onChangeSettings(changeDetails) { | ||
if (changeDetails.hasOwnProperty("behavior")) { | ||
this.current = changeDetails.behavior; | ||
} | ||
_factorial(number) { | ||
if (number <= 1) return 1; | ||
return number * this._factorial(number - 1); | ||
} | ||
_getBehaviorsCollection() { | ||
const mocksFolderContents = this._filesHandler.contents; | ||
const initBehaviors = []; | ||
const behaviors = {}; | ||
mocksFolderContents.forEach(object => { | ||
// TODO, register more behavior parsers | ||
if (object.isMocksServerBehavior) { | ||
initBehaviors.push( | ||
object | ||
.init(this._fixturesHandler) | ||
.then(initedBehavior => { | ||
initedBehavior.name = initedBehavior.name || object._mocksServer_lastPath; | ||
behaviors[initedBehavior.name] = initedBehavior.name; | ||
this._allFixtures.add(initedBehavior.fixtures); | ||
return Promise.resolve(initedBehavior); | ||
}) | ||
.catch(err => { | ||
tracer.error("Error initializing behavior"); | ||
tracer.debug(err.toString()); | ||
return Promise.resolve(); | ||
}) | ||
_areAllCandidatesChecked() { | ||
return this._behaviorsCandidates.length > this._factorial(this._loaders.contents.length); | ||
} | ||
_initBehavior(index, initedBehaviors) { | ||
const object = this._behaviorsCandidates[index]; | ||
let behaviorCandidate = object; | ||
// Behaviors defined in json file | ||
if (this._isBehaviorDefinition(object)) { | ||
if (object.from) { | ||
const parentBehavior = initedBehaviors.find( | ||
behavior => behavior && behavior.id === object.from | ||
); | ||
if (parentBehavior) { | ||
behaviorCandidate = parentBehavior.extend(object.fixtures); | ||
behaviorCandidate.id = object.id; | ||
} else { | ||
if (!this._areAllCandidatesChecked()) { | ||
this._behaviorsCandidates.push(object); | ||
} | ||
return Promise.resolve(); | ||
} | ||
} else { | ||
behaviorCandidate = new Behavior(object.fixtures, { id: object.id }); | ||
} | ||
} | ||
// Behaviors instantiated directly in JS files | ||
if (behaviorCandidate.isBehaviorInstance) { | ||
return behaviorCandidate | ||
.init(this._fixturesHandler, this._allFixtures) | ||
.then(initedBehavior => { | ||
// TODO, remove the addition of extra properties when reading files. Define a mandatory id for the behavior. | ||
initedBehavior.id = initedBehavior.id || object._mocksServer_lastPath; | ||
this._allFixtures.add(initedBehavior.fixtures); | ||
return Promise.resolve(initedBehavior); | ||
}) | ||
.catch(err => { | ||
tracer.error("Error initializing behavior"); | ||
tracer.debug(err.toString()); | ||
return Promise.resolve(); | ||
}); | ||
} | ||
return Promise.resolve(); | ||
} | ||
_initBehaviors(index = 0, initedBehaviors = []) { | ||
if (index >= this._behaviorsCandidates.length) { | ||
return Promise.resolve(initedBehaviors); | ||
} | ||
return this._initBehavior(index, initedBehaviors).then(initedBehavior => { | ||
initedBehaviors.push(initedBehavior); | ||
return this._initBehaviors(index + 1, initedBehaviors); | ||
}); | ||
return Promise.all(initBehaviors).then(initedBehaviors => { | ||
return Promise.resolve(compact(initedBehaviors)); | ||
} | ||
_getBehaviorsCollection() { | ||
this._behaviorsCandidates = [...this._loaders.contents]; | ||
return this._initBehaviors().then(initedBehaviors => { | ||
// TODO, remove the addition of extra properties when reading files. Define mandatory id for the behavior. | ||
this._loaders.contents.forEach(content => { | ||
if (content._mocksServer_lastPath) { | ||
delete content._mocksServer_lastPath; | ||
} | ||
}); | ||
return Promise.resolve(uniqBy(compact(initedBehaviors), behavior => behavior.id)); | ||
}); | ||
@@ -112,18 +150,18 @@ } | ||
_getBehaviorsObject() { | ||
const behaviorsByName = {}; | ||
const behaviorsById = {}; | ||
this._collection.map(behavior => { | ||
behaviorsByName[behavior.name] = behavior; | ||
behaviorsById[behavior.id] = behavior; | ||
}); | ||
return behaviorsByName; | ||
return behaviorsById; | ||
} | ||
_checkCurrent(behaviorName) { | ||
if (!this._names.includes(behaviorName)) { | ||
throw Boom.badData(`Behavior not found: ${behaviorName}`); | ||
_checkCurrent(behaviorId) { | ||
if (!this._ids.includes(behaviorId)) { | ||
throw Boom.badData(`Behavior not found: ${behaviorId}`); | ||
} | ||
} | ||
set current(behaviorName) { | ||
this._checkCurrent(behaviorName); | ||
this._current = behaviorName; | ||
set current(behaviorId) { | ||
this._checkCurrent(behaviorId); | ||
this._current = behaviorId; | ||
} | ||
@@ -139,14 +177,26 @@ | ||
// TODO, deprecate, use ids instead | ||
get names() { | ||
return this._names; | ||
tracer.deprecationWarn("names", "ids"); | ||
return this._ids; | ||
} | ||
get ids() { | ||
return this._ids; | ||
} | ||
get count() { | ||
return this._names.length; | ||
return this._ids.length; | ||
} | ||
// TODO, deprecate, use currentId instead | ||
get currentName() { | ||
tracer.deprecationWarn("currentName", "currentId"); | ||
return this._current; | ||
} | ||
get currentId() { | ||
return this._current; | ||
} | ||
get collection() { | ||
@@ -153,0 +203,0 @@ return this._collection; |
@@ -17,10 +17,5 @@ /* | ||
const { LOAD_FILES, CHANGE_FIXTURES } = require("../eventNames"); | ||
class Fixtures { | ||
constructor(filesHandler, settings, eventEmitter) { | ||
this._filesHandler = filesHandler; | ||
this._settings = settings; | ||
this._eventEmitter = eventEmitter; | ||
this._onLoadFiles = this._onLoadFiles.bind(this); | ||
constructor(loaders) { | ||
this._loaders = loaders; | ||
} | ||
@@ -30,4 +25,3 @@ | ||
this._fixturesHandler = fixturesHandler; | ||
this._eventEmitter.on(LOAD_FILES, this._onLoadFiles); | ||
return this._loadFixtures(); | ||
return Promise.resolve(); | ||
} | ||
@@ -47,16 +41,11 @@ | ||
async _loadFixtures() { | ||
async process() { | ||
tracer.debug("Processing fixtures"); | ||
this._fixtures = await this._getFixtures(); | ||
this._eventEmitter.emit(CHANGE_FIXTURES); | ||
tracer.verbose(`Processed ${this._fixtures.collection.length} fixtures`); | ||
return Promise.resolve(); | ||
} | ||
_onLoadFiles() { | ||
this._loadFixtures(); | ||
} | ||
_getFixtures() { | ||
const fixtures = new FixturesGroup(this._filesHandler.contents); | ||
const fixtures = new FixturesGroup(this._loaders.contents); | ||
return fixtures.init(this._fixturesHandler); | ||
@@ -63,0 +52,0 @@ } |
@@ -14,2 +14,5 @@ /* | ||
const { compact } = require("lodash"); | ||
const tracer = require("../tracer"); | ||
class FixturesGroup { | ||
@@ -20,3 +23,23 @@ constructor(fixtures = []) { | ||
async init(fixturesHandler) { | ||
_convertStringReferences(allFixtures) { | ||
if (allFixtures) { | ||
this._fixtures = compact( | ||
this._fixtures.map(fixture => { | ||
if (typeof fixture === "string") { | ||
const realFixture = allFixtures.collection.find(existantFixture => { | ||
return existantFixture.id === fixture; | ||
}); | ||
if (!realFixture) { | ||
tracer.debug(`Fixture with id "${fixture}" was not found and will be ignored`); | ||
} | ||
return realFixture; | ||
} | ||
return fixture; | ||
}) | ||
); | ||
} | ||
} | ||
async init(fixturesHandler, allFixtures) { | ||
this._convertStringReferences(allFixtures); | ||
this._collection = await fixturesHandler.getCollection(this._fixtures); | ||
@@ -23,0 +46,0 @@ return Promise.resolve(this); |
@@ -36,2 +36,5 @@ /* | ||
fixtures.map(fixture => { | ||
if (fixture && fixture.isFixtureHandler) { | ||
return fixture; | ||
} | ||
const Handler = this._getHandler(fixture); | ||
@@ -44,2 +47,3 @@ if (Handler) { | ||
} | ||
newFixture.isFixtureHandler = true; | ||
addedFixtures.push(newFixture); | ||
@@ -46,0 +50,0 @@ return newFixture; |
@@ -13,3 +13,2 @@ /* | ||
const Behaviors = require("./Behaviors"); | ||
const FilesHandler = require("./FilesHandler"); | ||
const FixturesHandler = require("./FixturesHandler"); | ||
@@ -20,14 +19,14 @@ const FixtureHandler = require("./FixtureHandler"); | ||
class Mocks { | ||
constructor(settings, eventEmitter, core) { | ||
constructor(eventEmitter, settings, loaders, core) { | ||
this._eventEmitter = eventEmitter; | ||
this._settings = settings; | ||
this._eventEmitter = eventEmitter; | ||
this._loaders = loaders; | ||
this._fixturesHandler = new FixturesHandler(core); | ||
this._fixturesHandler.addHandler(FixtureHandler); | ||
this._filesHandler = new FilesHandler(this._settings, this._eventEmitter); | ||
this._fixtures = new Fixtures(this._filesHandler, this._settings, this._eventEmitter); | ||
this._behaviors = new Behaviors(this._filesHandler, this._settings, this._eventEmitter); | ||
this._fixtures = new Fixtures(this._loaders); | ||
this._behaviors = new Behaviors(this._loaders, this._settings, this._eventEmitter); | ||
} | ||
async init() { | ||
await this._filesHandler.init(); | ||
await this._fixtures.init(this._fixturesHandler); | ||
@@ -38,14 +37,11 @@ await this._behaviors.init(this._fixturesHandler, this._fixtures); | ||
async stop() { | ||
await this._filesHandler.stop(); | ||
addFixturesHandler(Handler) { | ||
this._fixturesHandler.addHandler(Handler); | ||
} | ||
async start() { | ||
await this._filesHandler.start(); | ||
async processLoadedMocks() { | ||
await this._fixtures.process(); | ||
return this._behaviors.process(); | ||
} | ||
addFixturesHandler(Handler) { | ||
this._fixturesHandler.addHandler(Handler); | ||
} | ||
get behaviors() { | ||
@@ -52,0 +48,0 @@ return this._behaviors; |
@@ -21,7 +21,5 @@ /* | ||
const { CHANGE_SETTINGS } = require("../eventNames"); | ||
class Server { | ||
constructor(mocks, settings, eventEmitter, core) { | ||
// TODO, deprecate, the core is being passed only to maintain temporarily backward retrocompaitbility with API. This is not published in documentation. | ||
constructor(eventEmitter, settings, mocks, core) { | ||
// TODO, deprecate, the core is being passed only to maintain temporarily backward retrocompaitbility with API plugin. This is not published in documentation. | ||
this._core = core; // Use this reference only to provide it to external functions for customization purposes | ||
@@ -35,3 +33,2 @@ this._mocks = mocks; | ||
this._startServer = this._startServer.bind(this); | ||
this._onChangeSettings = this._onChangeSettings.bind(this); | ||
} | ||
@@ -46,12 +43,5 @@ | ||
}); | ||
this._eventEmitter.on(CHANGE_SETTINGS, this._onChangeSettings); | ||
return Promise.resolve(); | ||
} | ||
_onChangeSettings(changeDetails) { | ||
if (changeDetails.hasOwnProperty("port") || changeDetails.hasOwnProperty("host")) { | ||
this.restart(); | ||
} | ||
} | ||
_initServer() { | ||
@@ -58,0 +48,0 @@ if (this._serverInitted) { |
@@ -18,3 +18,3 @@ /* | ||
class Settings { | ||
constructor(coreOptions, eventEmitter) { | ||
constructor(eventEmitter, coreOptions) { | ||
this._eventEmitter = eventEmitter; | ||
@@ -21,0 +21,0 @@ this._optionsHandler = new Options(coreOptions); |
80751
25
1695
50