index.cjs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. * @param {*} ctor
  73. * @param {*} args
  74. * @return {*}
  75. */
  76. get(ctor, ...args) {
  77. if (!ctor || typeof ctor !== "function")
  78. throw new InvalidArgumentError(
  79. "The first argument of ServicesContainer.get must be a class constructor, but %v given.",
  80. ctor
  81. );
  82. if (!this._services.has(ctor) && this._parent && this._parent.has(ctor)) {
  83. return this._parent.get(ctor);
  84. }
  85. let service = this._services.get(ctor);
  86. if (!service) {
  87. const ctors = this._services.keys();
  88. const inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  89. if (inheritedCtor) {
  90. service = this._services.get(inheritedCtor);
  91. ctor = inheritedCtor;
  92. }
  93. }
  94. if (!service || args.length) {
  95. service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  96. this._services.set(ctor, service);
  97. } else if (typeof service === "function") {
  98. service = service();
  99. this._services.set(ctor, service);
  100. }
  101. return service;
  102. }
  103. /**
  104. * Проверка существования конструктора в контейнере.
  105. *
  106. * @param {*} ctor
  107. * @return {boolean}
  108. */
  109. has(ctor) {
  110. if (this._services.has(ctor)) return true;
  111. if (this._parent) return this._parent.has(ctor);
  112. const ctors = this._services.keys();
  113. const inheritedCtor = ctors.find((v) => v.prototype instanceof ctor);
  114. if (inheritedCtor) return true;
  115. return false;
  116. }
  117. /**
  118. * Добавить конструктор в контейнер.
  119. *
  120. * @param {*} ctor
  121. * @param {*} args
  122. * @return {this}
  123. */
  124. add(ctor, ...args) {
  125. if (!ctor || typeof ctor !== "function")
  126. throw new InvalidArgumentError(
  127. "The first argument of ServicesContainer.add must be a class constructor, but %v given.",
  128. ctor
  129. );
  130. const factory = /* @__PURE__ */ __name(() => Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args), "factory");
  131. this._services.set(ctor, factory);
  132. return this;
  133. }
  134. /**
  135. * Добавить конструктор и создать экземпляр.
  136. *
  137. * @param {*} ctor
  138. * @param {*} args
  139. * @return {this}
  140. */
  141. use(ctor, ...args) {
  142. if (!ctor || typeof ctor !== "function")
  143. throw new InvalidArgumentError(
  144. "The first argument of ServicesContainer.use must be a class constructor, but %v given.",
  145. ctor
  146. );
  147. const service = Array.isArray(ctor.kinds) && ctor.kinds.includes(SERVICE_CLASS_NAME) ? new ctor(this, ...args) : new ctor(...args);
  148. this._services.set(ctor, service);
  149. return this;
  150. }
  151. /**
  152. * Добавить конструктор и связанный экземпляр.
  153. *
  154. * @param {*} ctor
  155. * @param {*} service
  156. * @return {this}
  157. */
  158. set(ctor, service) {
  159. if (!ctor || typeof ctor !== "function")
  160. throw new InvalidArgumentError(
  161. "The first argument of ServicesContainer.set must be a class constructor, but %v given.",
  162. ctor
  163. );
  164. if (!service || typeof service !== "object" || Array.isArray(service))
  165. throw new InvalidArgumentError(
  166. "The second argument of ServicesContainer.set must be an Object, but %v given.",
  167. service
  168. );
  169. this._services.set(ctor, service);
  170. return this;
  171. }
  172. };
  173. __name(_ServiceContainer, "ServiceContainer");
  174. /**
  175. * Kinds.
  176. *
  177. * @type {string[]}
  178. */
  179. __publicField(_ServiceContainer, "kinds", [SERVICE_CONTAINER_CLASS_NAME]);
  180. var ServiceContainer = _ServiceContainer;
  181. // src/utils/is-service-container.js
  182. function isServiceContainer(container) {
  183. return Boolean(
  184. container && typeof container === "object" && typeof container.constructor === "function" && Array.isArray(container.constructor.kinds) && container.constructor.kinds.includes(SERVICE_CONTAINER_CLASS_NAME)
  185. );
  186. }
  187. __name(isServiceContainer, "isServiceContainer");
  188. // src/service.js
  189. var SERVICE_CLASS_NAME = "Service";
  190. var _Service = class _Service {
  191. /**
  192. * Container.
  193. *
  194. * @type {ServiceContainer}
  195. */
  196. container;
  197. /**
  198. * Constructor.
  199. *
  200. * @param {ServiceContainer|undefined} container
  201. */
  202. constructor(container = void 0) {
  203. this.container = isServiceContainer(container) ? container : new ServiceContainer();
  204. }
  205. /**
  206. * Получить существующий или новый экземпляр.
  207. *
  208. * @param {*} ctor
  209. * @param {*} args
  210. * @return {*}
  211. */
  212. getService(ctor, ...args) {
  213. return this.container.get(ctor, ...args);
  214. }
  215. /**
  216. * Проверка существования конструктора в контейнере.
  217. *
  218. * @param {*} ctor
  219. * @return {boolean}
  220. */
  221. hasService(ctor) {
  222. return this.container.has(ctor);
  223. }
  224. /**
  225. * Добавить конструктор в контейнер.
  226. *
  227. * @param {*} ctor
  228. * @param {*} args
  229. * @return {this}
  230. */
  231. addService(ctor, ...args) {
  232. this.container.add(ctor, ...args);
  233. return this;
  234. }
  235. /**
  236. * Добавить конструктор и создать экземпляр.
  237. *
  238. * @param {*} ctor
  239. * @param {*} args
  240. * @return {this}
  241. */
  242. useService(ctor, ...args) {
  243. this.container.use(ctor, ...args);
  244. return this;
  245. }
  246. /**
  247. * Добавить конструктор и связанный экземпляр.
  248. *
  249. * @param {*} ctor
  250. * @param {*} service
  251. * @return {this}
  252. */
  253. setService(ctor, service) {
  254. this.container.set(ctor, service);
  255. return this;
  256. }
  257. };
  258. __name(_Service, "Service");
  259. /**
  260. * Kinds.
  261. *
  262. * @type {string[]}
  263. */
  264. __publicField(_Service, "kinds", [SERVICE_CLASS_NAME]);
  265. var Service = _Service;
  266. // Annotate the CommonJS export names for ESM import in node:
  267. 0 && (module.exports = {
  268. SERVICE_CLASS_NAME,
  269. SERVICE_CONTAINER_CLASS_NAME,
  270. Service,
  271. ServiceContainer,
  272. isServiceContainer
  273. });