e22m4u 1 год назад
Родитель
Сommit
e081017778
4 измененных файлов с 343 добавлено и 1 удалено
  1. 1 0
      .husky/pre-commit
  2. 10 0
      build-cjs.js
  3. 321 0
      dist/cjs/index.cjs
  4. 11 1
      package.json

+ 1 - 0
.husky/pre-commit

@@ -1,5 +1,6 @@
 npm run lint:fix
 npm run lint:fix
 npm run format
 npm run format
 npm run test
 npm run test
+npm run build:cjs
 
 
 git add -A
 git add -A

+ 10 - 0
build-cjs.js

@@ -0,0 +1,10 @@
+import * as esbuild from 'esbuild';
+
+await esbuild.build({
+  entryPoints: ['src/index.js'],
+  outfile: 'dist/cjs/index.cjs',
+  format: 'cjs',
+  platform: 'node',
+  target: ['node12'],
+  bundle: true,
+});

+ 321 - 0
dist/cjs/index.cjs

@@ -0,0 +1,321 @@
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+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);
+
+// src/index.js
+var src_exports = {};
+__export(src_exports, {
+  Service: () => Service,
+  ServiceContainer: () => ServiceContainer
+});
+module.exports = __toCommonJS(src_exports);
+
+// node_modules/@e22m4u/js-format/src/utils/is-class.js
+function isClass(value) {
+  if (!value) return false;
+  return typeof value === "function" && /^class\s/.test(Function.prototype.toString.call(value));
+}
+
+// node_modules/@e22m4u/js-format/src/value-to-string.js
+var BASE_CTOR_NAMES = [
+  "String",
+  "Number",
+  "Boolean",
+  "Object",
+  "Array",
+  "Function",
+  "Symbol",
+  "Map",
+  "Set",
+  "Date"
+];
+function valueToString(input) {
+  if (input == null) return String(input);
+  if (typeof input === "string") return `"${input}"`;
+  if (typeof input === "number" || typeof input === "boolean")
+    return String(input);
+  if (isClass(input)) return input.name ? input.name : "Class";
+  if (input.constructor && input.constructor.name)
+    return BASE_CTOR_NAMES.includes(input.constructor.name) ? input.constructor.name : `${input.constructor.name} (instance)`;
+  if (typeof input === "object" && input.constructor == null) return "Object";
+  return String(input);
+}
+
+// node_modules/@e22m4u/js-format/src/array-to-list.js
+var SEPARATOR = ", ";
+function arrayToList(input) {
+  if (Array.isArray(input) && input.length)
+    return input.map(valueToString).join(SEPARATOR);
+  return valueToString(input);
+}
+
+// node_modules/@e22m4u/js-format/src/format.js
+function format(pattern) {
+  if (pattern instanceof Date) {
+    pattern = pattern.toISOString();
+  } else if (typeof pattern !== "string") {
+    pattern = String(pattern);
+  }
+  const re = /(%?)(%([sdjvl]))/g;
+  const args = Array.prototype.slice.call(arguments, 1);
+  if (args.length) {
+    pattern = pattern.replace(re, function(match, escaped, ptn, flag) {
+      let arg = args.shift();
+      switch (flag) {
+        case "s":
+          arg = String(arg);
+          break;
+        case "d":
+          arg = Number(arg);
+          break;
+        case "j":
+          arg = JSON.stringify(arg);
+          break;
+        case "v":
+          arg = valueToString(arg);
+          break;
+        case "l":
+          arg = arrayToList(arg);
+          break;
+      }
+      if (!escaped) return arg;
+      args.unshift(arg);
+      return match;
+    });
+  }
+  if (args.length) pattern += " " + args.join(" ");
+  pattern = pattern.replace(/%{2}/g, "%");
+  return "" + pattern;
+}
+
+// node_modules/@e22m4u/js-format/src/errorf.js
+var Errorf = class extends Error {
+  /**
+   * Constructor.
+   *
+   * @param {string|undefined} pattern
+   * @param {any} args
+   */
+  constructor(pattern = void 0, ...args) {
+    const message = pattern != null ? format(pattern, ...args) : void 0;
+    super(message);
+  }
+};
+
+// src/errors/invalid-argument-error.js
+var InvalidArgumentError = class extends Errorf {
+};
+
+// 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 = "prototype" in ctor && ctor.prototype instanceof Service ? 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 = () => ctor.prototype instanceof Service ? new ctor(this, ...args) : new ctor(...args);
+    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 = ctor.prototype instanceof Service ? 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;
+  }
+};
+
+// src/service.js
+var Service = class {
+  /**
+   * 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;
+  }
+};
+// Annotate the CommonJS export names for ESM import in node:
+0 && (module.exports = {
+  Service,
+  ServiceContainer
+});

+ 11 - 1
package.json

@@ -3,13 +3,22 @@
   "version": "0.1.1",
   "version": "0.1.1",
   "description": "The Service Locator implementation for JavaScript",
   "description": "The Service Locator implementation for JavaScript",
   "type": "module",
   "type": "module",
-  "main": "src/index.js",
+  "module": "./src/index.js",
+  "main": "./dist/cjs/index.cjs",
+  "exports": {
+    "import": "./src/index.js",
+    "require": "./dist/cjs/index.cjs"
+  },
+  "engines": {
+    "node": ">=12"
+  },
   "scripts": {
   "scripts": {
     "lint": "tsc && eslint .",
     "lint": "tsc && eslint .",
     "lint:fix": "tsc && eslint . --fix",
     "lint:fix": "tsc && eslint . --fix",
     "format": "prettier --write \"./src/**/*.js\"",
     "format": "prettier --write \"./src/**/*.js\"",
     "test": "npm run lint && c8 --reporter=text-summary mocha",
     "test": "npm run lint && c8 --reporter=text-summary mocha",
     "test:coverage": "npm run lint && c8 --reporter=text mocha",
     "test:coverage": "npm run lint && c8 --reporter=text mocha",
+    "build:cjs": "node build-cjs.js",
     "prepare": "husky"
     "prepare": "husky"
   },
   },
   "repository": {
   "repository": {
@@ -34,6 +43,7 @@
     "@eslint/js": "~9.12.0",
     "@eslint/js": "~9.12.0",
     "c8": "~10.1.2",
     "c8": "~10.1.2",
     "chai": "~5.1.1",
     "chai": "~5.1.1",
+    "esbuild": "~0.24.0",
     "eslint": "~9.12.0",
     "eslint": "~9.12.0",
     "eslint-config-prettier": "~9.1.0",
     "eslint-config-prettier": "~9.1.0",
     "eslint-plugin-chai-expect": "~3.1.0",
     "eslint-plugin-chai-expect": "~3.1.0",