index.cjs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  7. var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  21. var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  22. // src/index.js
  23. var index_exports = {};
  24. __export(index_exports, {
  25. DebuggableService: () => DebuggableService,
  26. SERVICE_CLASS_NAME: () => SERVICE_CLASS_NAME,
  27. SERVICE_CONTAINER_CLASS_NAME: () => SERVICE_CONTAINER_CLASS_NAME,
  28. Service: () => Service,
  29. ServiceContainer: () => ServiceContainer,
  30. isServiceContainer: () => isServiceContainer
  31. });
  32. module.exports = __toCommonJS(index_exports);
  33. // src/errors/invalid-argument-error.js
  34. var import_js_format = require("@e22m4u/js-format");
  35. var _InvalidArgumentError = class _InvalidArgumentError extends import_js_format.Errorf {
  36. };
  37. __name(_InvalidArgumentError, "InvalidArgumentError");
  38. var InvalidArgumentError = _InvalidArgumentError;
  39. // src/service-container.js
  40. var SERVICE_CONTAINER_CLASS_NAME = "ServiceContainer";
  41. var _ServiceContainer = class _ServiceContainer {
  42. /**
  43. * Services map.
  44. *
  45. * @type {Map<any, any>}
  46. * @private
  47. */
  48. _services = /* @__PURE__ */ new Map();
  49. /**
  50. * Parent container.
  51. *
  52. * @type {ServiceContainer}
  53. * @private
  54. */
  55. _parent;
  56. /**
  57. * Constructor.
  58. *
  59. * @param {ServiceContainer|undefined} parent
  60. */
  61. constructor(parent = void 0) {
  62. if (parent != null) {
  63. if (!(parent instanceof _ServiceContainer))
  64. throw new InvalidArgumentError(
  65. 'The provided parameter "parent" of ServicesContainer.constructor must be an instance ServiceContainer, but %v given.',
  66. parent
  67. );
  68. this._parent = parent;
  69. }
  70. }
  71. /**
  72. * Получить родительский сервис-контейнер или выбросить ошибку.
  73. *
  74. * @returns {ServiceContainer}
  75. */
  76. getParent() {
  77. if (!this._parent)
  78. throw new InvalidArgumentError("The service container has no parent.");
  79. return this._parent;
  80. }
  81. /**
  82. * Проверить наличие родительского сервис-контейнера.
  83. *
  84. * @returns {boolean}
  85. */
  86. hasParent() {
  87. return Boolean(this._parent);
  88. }
  89. /**
  90. * Получить существующий или новый экземпляр.
  91. *
  92. * @param {*} ctor
  93. * @param {*} args
  94. * @returns {*}
  95. */
  96. get(ctor, ...args) {
  97. if (!ctor || typeof ctor !== "function")
  98. throw new InvalidArgumentError(
  99. "The first argument of ServicesContainer.get must be a class constructor, but %v given.",
  100. ctor
  101. );
  102. const isCtorRegistered = this._services.has(ctor);
  103. let service = this._services.get(ctor);
  104. let inheritedCtor = void 0;
  105. if (!service) {
  106. const ctors = Array.from(this._services.keys());
  107. inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  108. if (inheritedCtor) service = this._services.get(inheritedCtor);
  109. }
  110. if (!service && !isCtorRegistered && !inheritedCtor && this._parent && this._parent.has(ctor)) {
  111. return this._parent.get(ctor, ...args);
  112. }
  113. if (!isCtorRegistered && inheritedCtor) {
  114. ctor = inheritedCtor;
  115. }
  116. if (!service || args.length) {
  117. service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  118. this._services.set(ctor, service);
  119. } else if (typeof service === "function") {
  120. service = service();
  121. this._services.set(ctor, service);
  122. }
  123. return service;
  124. }
  125. /**
  126. * Получить существующий или новый экземпляр,
  127. * только если конструктор зарегистрирован.
  128. *
  129. * @param {*} ctor
  130. * @param {*} args
  131. * @returns {*}
  132. */
  133. getRegistered(ctor, ...args) {
  134. if (!this.has(ctor))
  135. throw new InvalidArgumentError(
  136. "The constructor %v is not registered.",
  137. ctor
  138. );
  139. return this.get(ctor, ...args);
  140. }
  141. /**
  142. * Проверить существование конструктора в контейнере.
  143. *
  144. * @param {*} ctor
  145. * @returns {boolean}
  146. */
  147. has(ctor) {
  148. if (this._services.has(ctor)) return true;
  149. const ctors = Array.from(this._services.keys());
  150. const inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  151. if (inheritedCtor) return true;
  152. if (this._parent) return this._parent.has(ctor);
  153. return false;
  154. }
  155. /**
  156. * Добавить конструктор в контейнер.
  157. *
  158. * @param {*} ctor
  159. * @param {*} args
  160. * @returns {this}
  161. */
  162. add(ctor, ...args) {
  163. if (!ctor || typeof ctor !== "function")
  164. throw new InvalidArgumentError(
  165. "The first argument of ServicesContainer.add must be a class constructor, but %v given.",
  166. ctor
  167. );
  168. const factory = /* @__PURE__ */ __name(() => Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args), "factory");
  169. this._services.set(ctor, factory);
  170. return this;
  171. }
  172. /**
  173. * Добавить конструктор и создать экземпляр.
  174. *
  175. * @param {*} ctor
  176. * @param {*} args
  177. * @returns {this}
  178. */
  179. use(ctor, ...args) {
  180. if (!ctor || typeof ctor !== "function")
  181. throw new InvalidArgumentError(
  182. "The first argument of ServicesContainer.use must be a class constructor, but %v given.",
  183. ctor
  184. );
  185. const service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  186. this._services.set(ctor, service);
  187. return this;
  188. }
  189. /**
  190. * Добавить конструктор и связанный экземпляр.
  191. *
  192. * @param {*} ctor
  193. * @param {*} service
  194. * @returns {this}
  195. */
  196. set(ctor, service) {
  197. if (!ctor || typeof ctor !== "function")
  198. throw new InvalidArgumentError(
  199. "The first argument of ServicesContainer.set must be a class constructor, but %v given.",
  200. ctor
  201. );
  202. if (!service || typeof service !== "object" || Array.isArray(service))
  203. throw new InvalidArgumentError(
  204. "The second argument of ServicesContainer.set must be an Object, but %v given.",
  205. service
  206. );
  207. this._services.set(ctor, service);
  208. return this;
  209. }
  210. /**
  211. * Найти сервис удовлетворяющий условию.
  212. *
  213. * @param {function(Function, ServiceContainer): boolean} predicate
  214. * @param {boolean} noParent
  215. * @returns {*}
  216. */
  217. find(predicate, noParent = false) {
  218. if (typeof predicate !== "function") {
  219. throw new InvalidArgumentError(
  220. "The first argument of ServiceContainer.find must be a function, but %v given.",
  221. predicate
  222. );
  223. }
  224. const isRecursive = !noParent;
  225. let currentContainer = this;
  226. do {
  227. for (const ctor of currentContainer._services.keys()) {
  228. if (predicate(ctor, currentContainer) === true) {
  229. return this.get(ctor);
  230. }
  231. }
  232. if (isRecursive && currentContainer.hasParent()) {
  233. currentContainer = currentContainer.getParent();
  234. } else {
  235. currentContainer = null;
  236. }
  237. } while (currentContainer);
  238. return void 0;
  239. }
  240. };
  241. __name(_ServiceContainer, "ServiceContainer");
  242. /**
  243. * Kinds.
  244. *
  245. * @type {string[]}
  246. */
  247. __publicField(_ServiceContainer, "kinds", [SERVICE_CONTAINER_CLASS_NAME]);
  248. var ServiceContainer = _ServiceContainer;
  249. // src/utils/is-service-container.js
  250. function isServiceContainer(container) {
  251. return Boolean(
  252. container && typeof container === "object" && typeof container.constructor === "function" && Array.isArray(container.constructor.kinds) && container.constructor.kinds.includes(SERVICE_CONTAINER_CLASS_NAME)
  253. );
  254. }
  255. __name(isServiceContainer, "isServiceContainer");
  256. // src/service.js
  257. var SERVICE_CLASS_NAME = "Service";
  258. var _Service = class _Service {
  259. /**
  260. * Container.
  261. *
  262. * @type {ServiceContainer}
  263. */
  264. container;
  265. /**
  266. * Constructor.
  267. *
  268. * @param {ServiceContainer|undefined} container
  269. */
  270. constructor(container = void 0) {
  271. this.container = isServiceContainer(container) ? container : new ServiceContainer();
  272. }
  273. /**
  274. * Получить существующий или новый экземпляр.
  275. *
  276. * @param {*} ctor
  277. * @param {*} args
  278. * @returns {*}
  279. */
  280. getService(ctor, ...args) {
  281. return this.container.get(ctor, ...args);
  282. }
  283. /**
  284. * Получить существующий или новый экземпляр,
  285. * только если конструктор зарегистрирован.
  286. *
  287. * @param {*} ctor
  288. * @param {*} args
  289. * @returns {*}
  290. */
  291. getRegisteredService(ctor, ...args) {
  292. return this.container.getRegistered(ctor, ...args);
  293. }
  294. /**
  295. * Проверка существования конструктора в контейнере.
  296. *
  297. * @param {*} ctor
  298. * @returns {boolean}
  299. */
  300. hasService(ctor) {
  301. return this.container.has(ctor);
  302. }
  303. /**
  304. * Добавить конструктор в контейнер.
  305. *
  306. * @param {*} ctor
  307. * @param {*} args
  308. * @returns {this}
  309. */
  310. addService(ctor, ...args) {
  311. this.container.add(ctor, ...args);
  312. return this;
  313. }
  314. /**
  315. * Добавить конструктор и создать экземпляр.
  316. *
  317. * @param {*} ctor
  318. * @param {*} args
  319. * @returns {this}
  320. */
  321. useService(ctor, ...args) {
  322. this.container.use(ctor, ...args);
  323. return this;
  324. }
  325. /**
  326. * Добавить конструктор и связанный экземпляр.
  327. *
  328. * @param {*} ctor
  329. * @param {*} service
  330. * @returns {this}
  331. */
  332. setService(ctor, service) {
  333. this.container.set(ctor, service);
  334. return this;
  335. }
  336. /**
  337. * Найти сервис удовлетворяющий условию.
  338. *
  339. * @param {function(Function, ServiceContainer): boolean} predicate
  340. * @param {boolean} noParent
  341. * @returns {*}
  342. */
  343. findService(predicate, noParent = false) {
  344. return this.container.find(predicate, noParent);
  345. }
  346. };
  347. __name(_Service, "Service");
  348. /**
  349. * Kinds.
  350. *
  351. * @type {string[]}
  352. */
  353. __publicField(_Service, "kinds", [SERVICE_CLASS_NAME]);
  354. var Service = _Service;
  355. // src/debuggable-service.js
  356. var import_js_debug = require("@e22m4u/js-debug");
  357. var _DebuggableService = class _DebuggableService extends import_js_debug.Debuggable {
  358. /**
  359. * Service.
  360. *
  361. * @type {Service}
  362. */
  363. _service;
  364. /**
  365. * Container.
  366. *
  367. * @type {ServiceContainer}
  368. */
  369. get container() {
  370. return this._service.container;
  371. }
  372. /**
  373. * Получить существующий или новый экземпляр.
  374. *
  375. * @type {Service['getService']}
  376. */
  377. get getService() {
  378. return this._service.getService;
  379. }
  380. /**
  381. * Получить существующий или новый экземпляр,
  382. * только если конструктор зарегистрирован.
  383. *
  384. * @type {Service['getRegisteredService']}
  385. */
  386. get getRegisteredService() {
  387. return this._service.getRegisteredService;
  388. }
  389. /**
  390. * Проверка существования конструктора в контейнере.
  391. *
  392. * @type {Service['hasService']}
  393. */
  394. get hasService() {
  395. return this._service.hasService;
  396. }
  397. /**
  398. * Добавить конструктор в контейнер.
  399. *
  400. * @type {Service['addService']}
  401. */
  402. get addService() {
  403. return this._service.addService;
  404. }
  405. /**
  406. * Добавить конструктор и создать экземпляр.
  407. *
  408. * @type {Service['useService']}
  409. */
  410. get useService() {
  411. return this._service.useService;
  412. }
  413. /**
  414. * Добавить конструктор и связанный экземпляр.
  415. *
  416. * @type {Service['setService']}
  417. */
  418. get setService() {
  419. return this._service.setService;
  420. }
  421. /**
  422. * Найти сервис удовлетворяющий условию.
  423. *
  424. * @type {Service['findService']}
  425. */
  426. get findService() {
  427. return this._service.findService;
  428. }
  429. /**
  430. * Constructor.
  431. *
  432. * @param {ServiceContainer|undefined} container
  433. * @param {import('@e22m4u/js-debug').DebuggableOptions|undefined} options
  434. */
  435. constructor(container = void 0, options = void 0) {
  436. super(options);
  437. this._service = new Service(container);
  438. }
  439. };
  440. __name(_DebuggableService, "DebuggableService");
  441. /**
  442. * Kinds.
  443. *
  444. * @type {string[]}
  445. */
  446. __publicField(_DebuggableService, "kinds", Service.kinds);
  447. var DebuggableService = _DebuggableService;
  448. // Annotate the CommonJS export names for ESM import in node:
  449. 0 && (module.exports = {
  450. DebuggableService,
  451. SERVICE_CLASS_NAME,
  452. SERVICE_CONTAINER_CLASS_NAME,
  453. Service,
  454. ServiceContainer,
  455. isServiceContainer
  456. });