@e22m4u/js-service
Version:
The Service Locator implementation for JavaScript
249 lines (244 loc) • 7.45 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/index.js
var src_exports = {};
__export(src_exports, {
SERVICE_CLASS_NAME: () => SERVICE_CLASS_NAME,
Service: () => Service,
ServiceContainer: () => ServiceContainer
});
module.exports = __toCommonJS(src_exports);
// src/errors/invalid-argument-error.js
var import_js_format = require("@e22m4u/js-format");
var _InvalidArgumentError = class _InvalidArgumentError extends import_js_format.Errorf {
};
__name(_InvalidArgumentError, "InvalidArgumentError");
var InvalidArgumentError = _InvalidArgumentError;
// src/service-container.js
var _ServiceContainer = class _ServiceContainer {
/**
* Services map.
*
* @type {Map<any, any>}
* @private
*/
_services = /* @__PURE__ */ new Map();
/**
* Parent container.
*
* @type {ServiceContainer}
* @private
*/
_parent;
/**
* Constructor.
*
* @param {ServiceContainer|undefined} parent
*/
constructor(parent = void 0) {
if (parent != null) {
if (!(parent instanceof _ServiceContainer))
throw new InvalidArgumentError(
'The provided parameter "parent" of ServicesContainer.constructor must be an instance ServiceContainer, but %v given.',
parent
);
this._parent = parent;
}
}
/**
* Получить существующий или новый экземпляр.
*
* @param {*} ctor
* @param {*} args
* @return {*}
*/
get(ctor, ...args) {
if (!ctor || typeof ctor !== "function")
throw new InvalidArgumentError(
"The first argument of ServicesContainer.get must be a class constructor, but %v given.",
ctor
);
if (!this._services.has(ctor) && this._parent && this._parent.has(ctor)) {
return this._parent.get(ctor);
}
let service = this._services.get(ctor);
if (!service || args.length) {
service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
this._services.set(ctor, service);
} else if (typeof service === "function") {
service = service();
this._services.set(ctor, service);
}
return service;
}
/**
* Проверка существования конструктора в контейнере.
*
* @param {*} ctor
* @return {boolean}
*/
has(ctor) {
if (this._services.has(ctor)) return true;
if (this._parent) return this._parent.has(ctor);
return false;
}
/**
* Добавить конструктор в контейнер.
*
* @param {*} ctor
* @param {*} args
* @return {this}
*/
add(ctor, ...args) {
if (!ctor || typeof ctor !== "function")
throw new InvalidArgumentError(
"The first argument of ServicesContainer.add must be a class constructor, but %v given.",
ctor
);
const factory = /* @__PURE__ */ __name(() => Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args), "factory");
this._services.set(ctor, factory);
return this;
}
/**
* Добавить конструктор и создать экземпляр.
*
* @param {*} ctor
* @param {*} args
* @return {this}
*/
use(ctor, ...args) {
if (!ctor || typeof ctor !== "function")
throw new InvalidArgumentError(
"The first argument of ServicesContainer.use must be a class constructor, but %v given.",
ctor
);
const service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
this._services.set(ctor, service);
return this;
}
/**
* Добавить конструктор и связанный экземпляр.
*
* @param {*} ctor
* @param {*} service
* @return {this}
*/
set(ctor, service) {
if (!ctor || typeof ctor !== "function")
throw new InvalidArgumentError(
"The first argument of ServicesContainer.set must be a class constructor, but %v given.",
ctor
);
if (!service || typeof service !== "object" || Array.isArray(service))
throw new InvalidArgumentError(
"The second argument of ServicesContainer.set must be an Object, but %v given.",
service
);
this._services.set(ctor, service);
return this;
}
};
__name(_ServiceContainer, "ServiceContainer");
var ServiceContainer = _ServiceContainer;
// src/service.js
var SERVICE_CLASS_NAME = "Service";
var _Service = class _Service {
/**
* Container.
*
* @type {ServiceContainer}
*/
container;
/**
* Constructor.
*
* @param {ServiceContainer|undefined} container
*/
constructor(container = void 0) {
this.container = container instanceof ServiceContainer ? container : new ServiceContainer();
}
/**
* Получить существующий или новый экземпляр.
*
* @param {*} ctor
* @param {*} args
* @return {*}
*/
getService(ctor, ...args) {
return this.container.get(ctor, ...args);
}
/**
* Проверка существования конструктора в контейнере.
*
* @param {*} ctor
* @return {boolean}
*/
hasService(ctor) {
return this.container.has(ctor);
}
/**
* Добавить конструктор в контейнер.
*
* @param {*} ctor
* @param {*} args
* @return {this}
*/
addService(ctor, ...args) {
this.container.add(ctor, ...args);
return this;
}
/**
* Добавить конструктор и создать экземпляр.
*
* @param {*} ctor
* @param {*} args
* @return {this}
*/
useService(ctor, ...args) {
this.container.use(ctor, ...args);
return this;
}
/**
* Добавить конструктор и связанный экземпляр.
*
* @param {*} ctor
* @param {*} service
* @return {this}
*/
setService(ctor, service) {
this.container.set(ctor, service);
return this;
}
};
__name(_Service, "Service");
/**
* Kinds.
*
* @type {string[]}
*/
__publicField(_Service, "kinds", [SERVICE_CLASS_NAME]);
var Service = _Service;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
SERVICE_CLASS_NAME,
Service,
ServiceContainer
});