index.cjs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. var __defProp = Object.defineProperty;
  2. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  3. var __getOwnPropNames = Object.getOwnPropertyNames;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  6. var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
  7. var __export = (target, all) => {
  8. for (var name in all)
  9. __defProp(target, name, { get: all[name], enumerable: true });
  10. };
  11. var __copyProps = (to, from, except, desc) => {
  12. if (from && typeof from === "object" || typeof from === "function") {
  13. for (let key of __getOwnPropNames(from))
  14. if (!__hasOwnProp.call(to, key) && key !== except)
  15. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  16. }
  17. return to;
  18. };
  19. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  20. var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  21. // src/index.js
  22. var index_exports = {};
  23. __export(index_exports, {
  24. SERVICE_CLASS_NAME: () => SERVICE_CLASS_NAME,
  25. SERVICE_CONTAINER_CLASS_NAME: () => SERVICE_CONTAINER_CLASS_NAME,
  26. Service: () => Service,
  27. ServiceContainer: () => ServiceContainer,
  28. isServiceContainer: () => isServiceContainer
  29. });
  30. module.exports = __toCommonJS(index_exports);
  31. // src/errors/invalid-argument-error.js
  32. var import_js_format = require("@e22m4u/js-format");
  33. var _InvalidArgumentError = class _InvalidArgumentError extends import_js_format.Errorf {
  34. };
  35. __name(_InvalidArgumentError, "InvalidArgumentError");
  36. var InvalidArgumentError = _InvalidArgumentError;
  37. // src/service-container.js
  38. var SERVICE_CONTAINER_CLASS_NAME = "ServiceContainer";
  39. var _ServiceContainer = class _ServiceContainer {
  40. /**
  41. * Services map.
  42. *
  43. * @type {Map<any, any>}
  44. * @private
  45. */
  46. _services = /* @__PURE__ */ new Map();
  47. /**
  48. * Parent container.
  49. *
  50. * @type {ServiceContainer}
  51. * @private
  52. */
  53. _parent;
  54. /**
  55. * Constructor.
  56. *
  57. * @param {ServiceContainer|undefined} parent
  58. */
  59. constructor(parent = void 0) {
  60. if (parent != null) {
  61. if (!(parent instanceof _ServiceContainer))
  62. throw new InvalidArgumentError(
  63. 'The provided parameter "parent" of ServicesContainer.constructor must be an instance ServiceContainer, but %v given.',
  64. parent
  65. );
  66. this._parent = parent;
  67. }
  68. }
  69. /**
  70. * Получить родительский сервис-контейнер или выбросить ошибку.
  71. *
  72. * @returns {ServiceContainer}
  73. */
  74. getParent() {
  75. if (!this._parent)
  76. throw new InvalidArgumentError("The service container has no parent.");
  77. return this._parent;
  78. }
  79. /**
  80. * Проверить наличие родительского сервис-контейнера.
  81. *
  82. * @returns {boolean}
  83. */
  84. hasParent() {
  85. return Boolean(this._parent);
  86. }
  87. /**
  88. * Получить существующий или новый экземпляр.
  89. *
  90. * @param {*} ctor
  91. * @param {*} args
  92. * @returns {*}
  93. */
  94. get(ctor, ...args) {
  95. if (!ctor || typeof ctor !== "function")
  96. throw new InvalidArgumentError(
  97. "The first argument of ServicesContainer.get must be a class constructor, but %v given.",
  98. ctor
  99. );
  100. if (!this._services.has(ctor) && this._parent && this._parent.has(ctor)) {
  101. return this._parent.get(ctor);
  102. }
  103. let service = this._services.get(ctor);
  104. if (!service) {
  105. const ctors = this._services.keys();
  106. const inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  107. if (inheritedCtor) {
  108. service = this._services.get(inheritedCtor);
  109. ctor = inheritedCtor;
  110. }
  111. }
  112. if (!service || args.length) {
  113. service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  114. this._services.set(ctor, service);
  115. } else if (typeof service === "function") {
  116. service = service();
  117. this._services.set(ctor, service);
  118. }
  119. return service;
  120. }
  121. /**
  122. * Проверить существование конструктора в контейнере.
  123. *
  124. * @param {*} ctor
  125. * @returns {boolean}
  126. */
  127. has(ctor) {
  128. if (this._services.has(ctor)) return true;
  129. if (this._parent) return this._parent.has(ctor);
  130. const ctors = this._services.keys();
  131. const inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  132. if (inheritedCtor) return true;
  133. return false;
  134. }
  135. /**
  136. * Добавить конструктор в контейнер.
  137. *
  138. * @param {*} ctor
  139. * @param {*} args
  140. * @returns {this}
  141. */
  142. add(ctor, ...args) {
  143. if (!ctor || typeof ctor !== "function")
  144. throw new InvalidArgumentError(
  145. "The first argument of ServicesContainer.add must be a class constructor, but %v given.",
  146. ctor
  147. );
  148. const factory = /* @__PURE__ */ __name(() => Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args), "factory");
  149. this._services.set(ctor, factory);
  150. return this;
  151. }
  152. /**
  153. * Добавить конструктор и создать экземпляр.
  154. *
  155. * @param {*} ctor
  156. * @param {*} args
  157. * @returns {this}
  158. */
  159. use(ctor, ...args) {
  160. if (!ctor || typeof ctor !== "function")
  161. throw new InvalidArgumentError(
  162. "The first argument of ServicesContainer.use must be a class constructor, but %v given.",
  163. ctor
  164. );
  165. const service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  166. this._services.set(ctor, service);
  167. return this;
  168. }
  169. /**
  170. * Добавить конструктор и связанный экземпляр.
  171. *
  172. * @param {*} ctor
  173. * @param {*} service
  174. * @returns {this}
  175. */
  176. set(ctor, service) {
  177. if (!ctor || typeof ctor !== "function")
  178. throw new InvalidArgumentError(
  179. "The first argument of ServicesContainer.set must be a class constructor, but %v given.",
  180. ctor
  181. );
  182. if (!service || typeof service !== "object" || Array.isArray(service))
  183. throw new InvalidArgumentError(
  184. "The second argument of ServicesContainer.set must be an Object, but %v given.",
  185. service
  186. );
  187. this._services.set(ctor, service);
  188. return this;
  189. }
  190. };
  191. __name(_ServiceContainer, "ServiceContainer");
  192. /**
  193. * Kinds.
  194. *
  195. * @type {string[]}
  196. */
  197. __publicField(_ServiceContainer, "kinds", [SERVICE_CONTAINER_CLASS_NAME]);
  198. var ServiceContainer = _ServiceContainer;
  199. // src/utils/is-service-container.js
  200. function isServiceContainer(container) {
  201. return Boolean(
  202. container && typeof container === "object" && typeof container.constructor === "function" && Array.isArray(container.constructor.kinds) && container.constructor.kinds.includes(SERVICE_CONTAINER_CLASS_NAME)
  203. );
  204. }
  205. __name(isServiceContainer, "isServiceContainer");
  206. // src/service.js
  207. var SERVICE_CLASS_NAME = "Service";
  208. var _Service = class _Service {
  209. /**
  210. * Container.
  211. *
  212. * @type {ServiceContainer}
  213. */
  214. container;
  215. /**
  216. * Constructor.
  217. *
  218. * @param {ServiceContainer|undefined} container
  219. */
  220. constructor(container = void 0) {
  221. this.container = isServiceContainer(container) ? container : new ServiceContainer();
  222. }
  223. /**
  224. * Получить существующий или новый экземпляр.
  225. *
  226. * @param {*} ctor
  227. * @param {*} args
  228. * @returns {*}
  229. */
  230. getService(ctor, ...args) {
  231. return this.container.get(ctor, ...args);
  232. }
  233. /**
  234. * Проверка существования конструктора в контейнере.
  235. *
  236. * @param {*} ctor
  237. * @returns {boolean}
  238. */
  239. hasService(ctor) {
  240. return this.container.has(ctor);
  241. }
  242. /**
  243. * Добавить конструктор в контейнер.
  244. *
  245. * @param {*} ctor
  246. * @param {*} args
  247. * @returns {this}
  248. */
  249. addService(ctor, ...args) {
  250. this.container.add(ctor, ...args);
  251. return this;
  252. }
  253. /**
  254. * Добавить конструктор и создать экземпляр.
  255. *
  256. * @param {*} ctor
  257. * @param {*} args
  258. * @returns {this}
  259. */
  260. useService(ctor, ...args) {
  261. this.container.use(ctor, ...args);
  262. return this;
  263. }
  264. /**
  265. * Добавить конструктор и связанный экземпляр.
  266. *
  267. * @param {*} ctor
  268. * @param {*} service
  269. * @returns {this}
  270. */
  271. setService(ctor, service) {
  272. this.container.set(ctor, service);
  273. return this;
  274. }
  275. };
  276. __name(_Service, "Service");
  277. /**
  278. * Kinds.
  279. *
  280. * @type {string[]}
  281. */
  282. __publicField(_Service, "kinds", [SERVICE_CLASS_NAME]);
  283. var Service = _Service;
  284. // Annotate the CommonJS export names for ESM import in node:
  285. 0 && (module.exports = {
  286. SERVICE_CLASS_NAME,
  287. SERVICE_CONTAINER_CLASS_NAME,
  288. Service,
  289. ServiceContainer,
  290. isServiceContainer
  291. });