Browse Source

chore: adds DebuggableService class

e22m4u 3 months ago
parent
commit
d0bf6374e7
9 changed files with 295 additions and 0 deletions
  1. 41 0
      README.md
  2. 79 0
      dist/cjs/index.cjs
  3. 1 0
      eslint.config.js
  4. 1 0
      package.json
  5. 7 0
      src/debuggable-service.d.ts
  6. 87 0
      src/debuggable-service.js
  7. 77 0
      src/debuggable-service.spec.js
  8. 1 0
      src/index.d.ts
  9. 1 0
      src/index.js

+ 41 - 0
README.md

@@ -187,6 +187,47 @@ const foo4 = this.getService(Foo);        // возврат уже пересо
 console.log(foo3 === foo4);               // true
 ```
 
+## DebuggableService
+
+Данный класс расширяет базовый класс [Service](#service)
+возможностями по отладке, предоставляемые модулем 
+[@e22m4u/js-debug](https://www.npmjs.com/package/@e22m4u/js-debug#класс-debuggable) (см. раздел *Класс Debuggable*).
+
+```js
+import {apiClient} from './path/to/apiClient';
+import {DebuggableService} from '@e22m4u/js-service';
+
+process.env['DEBUGGER_NAMESPACE'] = 'myApp';
+process.env['DEBUG'] = 'myApp*';
+
+class UserService extends DebuggableService {
+  async getUserById(userId) {
+    // получение отладчика для данного метода и вызова
+    const debug = this.getDebuggerFor(this.getUserById);
+    debug('Fetching user with ID %v...', userId);
+    try {
+      const user = await apiClient.get(`/users/${userId}`);
+      debug.inspect('User data received:', user);
+      return user;
+    } catch (error) {
+      debug('Failed to fetch user. Error: %s', error.message);
+      throw error;
+    }
+  }
+}
+
+const userService = new UserService();
+await userService.getUserById(123);
+// myApp:userService:constructor:a4f1 Instantiated.
+// myApp:userService:getUserById:b9c2 Fetching user with ID 123...
+// myApp:userService:getUserById:b9c2 User data received:
+// myApp:userService:getUserById:b9c2   {
+// myApp:userService:getUserById:b9c2     id: 123,
+// myApp:userService:getUserById:b9c2     name: 'John Doe',
+// myApp:userService:getUserById:b9c2     email: 'john.doe@example.com'
+// myApp:userService:getUserById:b9c2   }
+```
+
 ## Тесты
 
 ```bash

+ 79 - 0
dist/cjs/index.cjs

@@ -22,6 +22,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
 // src/index.js
 var index_exports = {};
 __export(index_exports, {
+  DebuggableService: () => DebuggableService,
   SERVICE_CLASS_NAME: () => SERVICE_CLASS_NAME,
   SERVICE_CONTAINER_CLASS_NAME: () => SERVICE_CONTAINER_CLASS_NAME,
   Service: () => Service,
@@ -286,8 +287,86 @@ __name(_Service, "Service");
  */
 __publicField(_Service, "kinds", [SERVICE_CLASS_NAME]);
 var Service = _Service;
+
+// src/debuggable-service.js
+var import_js_debug = require("@e22m4u/js-debug");
+var _DebuggableService = class _DebuggableService extends import_js_debug.Debuggable {
+  /**
+   * Service.
+   *
+   * @type {Service}
+   */
+  _service;
+  /**
+   * Container.
+   *
+   * @type {ServiceContainer}
+   */
+  get container() {
+    return this._service.container;
+  }
+  /**
+   * Get service.
+   *
+   * @type {Service['getService']}
+   */
+  get getService() {
+    return this._service.getService;
+  }
+  /**
+   * Has service.
+   *
+   * @type {Service['hasService']}
+   */
+  get hasService() {
+    return this._service.hasService;
+  }
+  /**
+   * Add service.
+   *
+   * @type {Service['addService']}
+   */
+  get addService() {
+    return this._service.addService;
+  }
+  /**
+   * Use service.
+   *
+   * @type {Service['useService']}
+   */
+  get useService() {
+    return this._service.useService;
+  }
+  /**
+   * Set service.
+   *
+   * @type {Service['setService']}
+   */
+  get setService() {
+    return this._service.setService;
+  }
+  /**
+   * Constructor.
+   *
+   * @param {ServiceContainer|undefined} container
+   * @param {import('@e22m4u/js-debug').DebuggableOptions|undefined} options
+   */
+  constructor(container = void 0, options = void 0) {
+    super(options);
+    this._service = new Service(container);
+  }
+};
+__name(_DebuggableService, "DebuggableService");
+/**
+ * Kinds.
+ *
+ * @type {string[]}
+ */
+__publicField(_DebuggableService, "kinds", Service.kinds);
+var DebuggableService = _DebuggableService;
 // Annotate the CommonJS export names for ESM import in node:
 0 && (module.exports = {
+  DebuggableService,
   SERVICE_CLASS_NAME,
   SERVICE_CONTAINER_CLASS_NAME,
   Service,

+ 1 - 0
eslint.config.js

@@ -10,6 +10,7 @@ export default [{
     globals: {
       ...globals.es2021,
       ...globals.mocha,
+      ...globals.node,
     },
   },
   plugins: {

+ 1 - 0
package.json

@@ -37,6 +37,7 @@
     "prepare": "husky"
   },
   "dependencies": {
+    "@e22m4u/js-debug": "~0.2.2",
     "@e22m4u/js-format": "~0.1.8"
   },
   "devDependencies": {

+ 7 - 0
src/debuggable-service.d.ts

@@ -0,0 +1,7 @@
+import {Service} from './service.js';
+import {Debuggable} from '@e22m4u/js-debug';
+
+/**
+ * Debuggable service.
+ */
+export type DebuggableService = Debuggable & Service;

+ 87 - 0
src/debuggable-service.js

@@ -0,0 +1,87 @@
+import {Service} from './service.js';
+import {Debuggable} from '@e22m4u/js-debug';
+import {ServiceContainer} from './service-container.js';
+
+/**
+ * Debuggable service.
+ */
+export class DebuggableService extends Debuggable {
+  /**
+   * Kinds.
+   *
+   * @type {string[]}
+   */
+  static kinds = Service.kinds;
+
+  /**
+   * Service.
+   *
+   * @type {Service}
+   */
+  _service;
+
+  /**
+   * Container.
+   *
+   * @type {ServiceContainer}
+   */
+  get container() {
+    return this._service.container;
+  }
+
+  /**
+   * Get service.
+   *
+   * @type {Service['getService']}
+   */
+  get getService() {
+    return this._service.getService;
+  }
+
+  /**
+   * Has service.
+   *
+   * @type {Service['hasService']}
+   */
+  get hasService() {
+    return this._service.hasService;
+  }
+
+  /**
+   * Add service.
+   *
+   * @type {Service['addService']}
+   */
+  get addService() {
+    return this._service.addService;
+  }
+
+  /**
+   * Use service.
+   *
+   * @type {Service['useService']}
+   */
+  get useService() {
+    return this._service.useService;
+  }
+
+  /**
+   * Set service.
+   *
+   * @type {Service['setService']}
+   */
+  get setService() {
+    return this._service.setService;
+  }
+
+  /**
+   * Constructor.
+   *
+   * @param {ServiceContainer|undefined} container
+   * @param {import('@e22m4u/js-debug').DebuggableOptions|undefined} options
+   */
+  constructor(container = undefined, options = undefined) {
+    super(options);
+    this._service = new Service(container);
+  }
+}

+ 77 - 0
src/debuggable-service.spec.js

@@ -0,0 +1,77 @@
+import {expect} from 'chai';
+import {Service} from './service.js';
+import {Debuggable} from '@e22m4u/js-debug';
+import {ServiceContainer} from './service-container.js';
+import {DebuggableService} from './debuggable-service.js';
+
+describe('DebuggableService', function () {
+  it('should be instantiated correctly without arguments', function () {
+    const debuggableService = new DebuggableService();
+    expect(debuggableService).to.be.an.instanceOf(DebuggableService);
+    expect(debuggableService).to.be.an.instanceOf(Debuggable);
+    expect(debuggableService.container).to.be.an.instanceOf(ServiceContainer);
+  });
+
+  it('should accept an existing ServiceContainer', function () {
+    const container = new ServiceContainer();
+    const debuggableService = new DebuggableService(container);
+    expect(debuggableService.container).to.eq(container);
+  });
+
+  it('should inherit the static "kinds" property from Service', function () {
+    expect(DebuggableService.kinds).to.eql(Service.kinds);
+  });
+
+  it('should pass options to the Debuggable constructor', function () {
+    const options = {namespace: 'myNamespace'};
+    const debuggableService = new DebuggableService(undefined, options);
+    expect(debuggableService.debug.state.nsSegments).to.eql([
+      'myNamespace',
+      'debuggableService',
+    ]);
+  });
+
+  describe('service method delegation', function () {
+    let debuggableService;
+
+    beforeEach(function () {
+      debuggableService = new DebuggableService();
+    });
+
+    it("should delegate the 'container' getter to the internal service's container", function () {
+      expect(debuggableService.container).to.eq(
+        debuggableService._service.container,
+      );
+    });
+
+    it("should delegate the 'getService' getter to the internal service's getService method", function () {
+      expect(debuggableService.getService).to.eq(
+        debuggableService._service.getService,
+      );
+    });
+
+    it("should delegate the 'hasService' getter to the internal service's hasService method", function () {
+      expect(debuggableService.hasService).to.eq(
+        debuggableService._service.hasService,
+      );
+    });
+
+    it("should delegate the 'addService' getter to the internal service's addService method", function () {
+      expect(debuggableService.addService).to.eq(
+        debuggableService._service.addService,
+      );
+    });
+
+    it("should delegate the 'useService' getter to the internal service's useService method", function () {
+      expect(debuggableService.useService).to.eq(
+        debuggableService._service.useService,
+      );
+    });
+
+    it("should delegate the 'setService' getter to the internal service's setService method", function () {
+      expect(debuggableService.setService).to.eq(
+        debuggableService._service.setService,
+      );
+    });
+  });
+});

+ 1 - 0
src/index.d.ts

@@ -1,4 +1,5 @@
 export * from './types.js';
 export * from './service.js';
 export * from './service-container.js';
+export * from './debuggable-service.js';
 export * from './utils/is-service-container.js';

+ 1 - 0
src/index.js

@@ -1,3 +1,4 @@
 export * from './service.js';
 export * from './service-container.js';
+export * from './debuggable-service.js';
 export * from './utils/is-service-container.js';