@proteinjs/service 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.2.0](https://github.com/proteinjs/service/compare/@proteinjs/service@1.1.1...@proteinjs/service@1.2.0) (2025-02-06)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * fix typing for the debounce config ([62bb2d6](https://github.com/proteinjs/service/commit/62bb2d646e2c71f2bf5300364cd92bbd95911f21))
12
+
13
+
14
+ ### Features
15
+
16
+ * method specific debouncers. allows one service to use multiple debouncers for each method in the service. ([00fa7b2](https://github.com/proteinjs/service/commit/00fa7b23c4960ad9a006d4791e9f5a12f9ab6c89))
17
+
18
+
19
+
20
+
21
+
6
22
  ## [1.1.1](https://github.com/proteinjs/service/compare/@proteinjs/service@1.1.0...@proteinjs/service@1.1.1) (2024-09-10)
7
23
 
8
24
 
@@ -10,6 +10,12 @@ type KeysWithoutService<T extends Service> = Diff<KeysWithoutIndexSignature<T>,
10
10
  type RetryConfig<T extends Service> = {
11
11
  [K in KeysWithoutService<T>]?: number;
12
12
  };
13
+ interface DebounceConfig {
14
+ waitTime: number;
15
+ }
16
+ type MethodDebounceConfig<T extends Service> = {
17
+ [K in KeysWithoutService<T>]?: DebounceConfig;
18
+ };
13
19
  export interface Service extends Loadable {
14
20
  serviceMetadata?: {
15
21
  auth?: {
@@ -36,9 +42,9 @@ export interface Service extends Loadable {
36
42
  * Create a factory that creates an instance of the Service. The Service instance is a
37
43
  * ServiceClient wrapped in the interface's api.
38
44
  * @param serviceInterfaceQualifiedName the package-qualified name of the service interface (ie. service-package-name/MyService)
39
- * @param debouncer optionally pass in an instance of debouncer if you want to limit service client calls
45
+ * @param debouncer pass in either a single debouncer instance or method-specific debounce configurations
40
46
  * @returns a function that creates a Service
41
47
  */
42
- export declare const serviceFactory: <T extends Service>(serviceInterfaceQualifiedName: string, debouncer?: Debouncer, retryConfig?: RetryConfig<T> | undefined) => () => T;
48
+ export declare const serviceFactory: <T extends Service>(serviceInterfaceQualifiedName: string, debouncer?: Debouncer | MethodDebounceConfig<T> | undefined, retryConfig?: RetryConfig<T> | undefined) => () => T;
43
49
  export {};
44
50
  //# sourceMappingURL=Service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Service.d.ts","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3G,CAAC;AACF,KAAK,yBAAyB,CAAC,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzD,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAG1C,KAAK,kBAAkB,CAAC,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;AAEpH,KAAK,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI;KACnC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM;CACtC,CAAC;AAEF,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,eAAe,CAAC,EAAE;QAChB,IAAI,CAAC,EAAE;YACL,2HAA2H;YAC3H,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,kIAAkI;YAClI,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,8HAA8H;YAC9H,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YACjB;;;;;eAKG;YACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;SAC1D,CAAC;QACF,uFAAuF;QACvF,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;CACzD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,qDACM,MAAM,cACzB,SAAS,sDAqBtB,CAAC"}
1
+ {"version":3,"file":"Service.d.ts","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAgB,MAAM,iBAAiB,CAAC;AAE1D,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3G,CAAC;AACF,KAAK,yBAAyB,CAAC,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzD,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAG1C,KAAK,kBAAkB,CAAC,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;AAEpH,KAAK,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI;KACnC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM;CACtC,CAAC;AAEF,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,oBAAoB,CAAC,CAAC,SAAS,OAAO,IAAI;KAC5C,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc;CAC9C,CAAC;AAEF,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,eAAe,CAAC,EAAE;QAChB,IAAI,CAAC,EAAE;YACL,2HAA2H;YAC3H,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,kIAAkI;YAClI,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,8HAA8H;YAC9H,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YACjB;;;;;eAKG;YACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;SAC1D,CAAC;QACF,uFAAuF;QACvF,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;CACzD;AAaD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,qDACM,MAAM,mHAkCtC,CAAC"}
@@ -3,11 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.serviceFactory = void 0;
4
4
  var reflection_1 = require("@proteinjs/reflection");
5
5
  var ServiceClient_1 = require("./ServiceClient");
6
+ var util_1 = require("@proteinjs/util");
7
+ var debouncerMap = {};
8
+ /** Retrieve an existing debouncer from the map or make a new one.
9
+ * This allows the debouncer instance per method to remain the same across multiple service calls.
10
+ */
11
+ function getOrCreateDebouncer(methodName, waitTime) {
12
+ if (!debouncerMap[methodName]) {
13
+ debouncerMap[methodName] = new util_1.Debouncer(waitTime);
14
+ }
15
+ return debouncerMap[methodName];
16
+ }
6
17
  /**
7
18
  * Create a factory that creates an instance of the Service. The Service instance is a
8
19
  * ServiceClient wrapped in the interface's api.
9
20
  * @param serviceInterfaceQualifiedName the package-qualified name of the service interface (ie. service-package-name/MyService)
10
- * @param debouncer optionally pass in an instance of debouncer if you want to limit service client calls
21
+ * @param debouncer pass in either a single debouncer instance or method-specific debounce configurations
11
22
  * @returns a function that creates a Service
12
23
  */
13
24
  var serviceFactory = function (serviceInterfaceQualifiedName, debouncer, retryConfig) {
@@ -17,13 +28,25 @@ var serviceFactory = function (serviceInterfaceQualifiedName, debouncer, retryCo
17
28
  for (var _i = 0, _a = serviceInterface.methods; _i < _a.length; _i++) {
18
29
  var method = _a[_i];
19
30
  var servicePath = "/service/".concat(serviceInterface.qualifiedName, "/").concat(method.name);
31
+ var methodName = method.name;
20
32
  var retryCount = 0;
21
- if (retryConfig && method.name in retryConfig) {
22
- var methodName = method.name;
33
+ if (retryConfig && methodName in retryConfig) {
23
34
  retryCount = retryConfig[methodName];
24
35
  }
25
- var serviceClient = new ServiceClient_1.ServiceClient(servicePath, method, debouncer, retryCount);
26
- service[method.name] = serviceClient.send.bind(serviceClient);
36
+ var methodDebouncer = void 0;
37
+ if (debouncer) {
38
+ if ((0, util_1.isInstanceOf)(debouncer, util_1.Debouncer)) {
39
+ methodDebouncer = debouncer;
40
+ }
41
+ else if (methodName in debouncer) {
42
+ var methodConfig = debouncer[methodName];
43
+ if (methodConfig) {
44
+ methodDebouncer = getOrCreateDebouncer(methodName, methodConfig.waitTime);
45
+ }
46
+ }
47
+ }
48
+ var serviceClient = new ServiceClient_1.ServiceClient(servicePath, method, methodDebouncer, retryCount);
49
+ service[methodName] = serviceClient.send.bind(serviceClient);
27
50
  }
28
51
  return service;
29
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Service.js","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":";;;AACA,oDAAmE;AACnE,iDAAgD;AAyChD;;;;;;GAMG;AACI,IAAM,cAAc,GAAG,UAC5B,6BAAqC,EACrC,SAAqB,EACrB,WAA4B;IAE5B,OAAO;QACL,IAAM,OAAO,GAAQ,EAAE,CAAC;QACxB,IAAM,gBAAgB,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QACzF,KAAqB,UAAwB,EAAxB,KAAA,gBAAgB,CAAC,OAAO,EAAxB,cAAwB,EAAxB,IAAwB,EAAE;YAA1C,IAAM,MAAM,SAAA;YACf,IAAM,WAAW,GAAG,mBAAY,gBAAgB,CAAC,aAAa,cAAI,MAAM,CAAC,IAAI,CAAE,CAAC;YAEhF,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,WAAW,IAAI,MAAM,CAAC,IAAI,IAAI,WAAW,EAAE;gBAC7C,IAAM,UAAU,GAAG,MAAM,CAAC,IAA6B,CAAC;gBACxD,UAAU,GAAG,WAAW,CAAC,UAAU,CAAE,CAAC;aACvC;YAED,IAAM,aAAa,GAAG,IAAI,6BAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACpF,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;SAC/D;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC,CAAC;AAvBW,QAAA,cAAc,kBAuBzB"}
1
+ {"version":3,"file":"Service.js","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":";;;AACA,oDAAmE;AACnE,iDAAgD;AAChD,wCAA0D;AAgD1D,IAAM,YAAY,GAAiC,EAAE,CAAC;AACtD;;GAEG;AACH,SAAS,oBAAoB,CAAC,UAAkB,EAAE,QAAgB;IAChE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE;QAC7B,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,gBAAS,CAAC,QAAQ,CAAC,CAAC;KACpD;IACD,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;GAMG;AACI,IAAM,cAAc,GAAG,UAC5B,6BAAqC,EACrC,SAA+C,EAC/C,WAA4B;IAE5B,OAAO;QACL,IAAM,OAAO,GAAQ,EAAE,CAAC;QACxB,IAAM,gBAAgB,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QACzF,KAAqB,UAAwB,EAAxB,KAAA,gBAAgB,CAAC,OAAO,EAAxB,cAAwB,EAAxB,IAAwB,EAAE;YAA1C,IAAM,MAAM,SAAA;YACf,IAAM,WAAW,GAAG,mBAAY,gBAAgB,CAAC,aAAa,cAAI,MAAM,CAAC,IAAI,CAAE,CAAC;YAChF,IAAM,UAAU,GAAG,MAAM,CAAC,IAA6B,CAAC;YAExD,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,WAAW,IAAI,UAAU,IAAI,WAAW,EAAE;gBAC5C,UAAU,GAAG,WAAW,CAAC,UAAU,CAAE,CAAC;aACvC;YAED,IAAI,eAAe,SAAuB,CAAC;YAC3C,IAAI,SAAS,EAAE;gBACb,IAAI,IAAA,mBAAY,EAAC,SAAS,EAAE,gBAAS,CAAC,EAAE;oBACtC,eAAe,GAAG,SAAsB,CAAC;iBAC1C;qBAAM,IAAI,UAAU,IAAI,SAAS,EAAE;oBAClC,IAAM,YAAY,GAAI,SAAqC,CAAC,UAAU,CAAC,CAAC;oBACxE,IAAI,YAAY,EAAE;wBAChB,eAAe,GAAG,oBAAoB,CAAC,UAAoB,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;qBACrF;iBACF;aACF;YAED,IAAM,aAAa,GAAG,IAAI,6BAAa,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;YAC1F,OAAO,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;SAC9D;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC,CAAC;AAnCW,QAAA,cAAc,kBAmCzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/service",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Service api",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -43,5 +43,5 @@
43
43
  },
44
44
  "main": "./dist/generated/index.js",
45
45
  "types": "./dist/generated/index.d.ts",
46
- "gitHead": "9e03cddf33d8d7d2becba67275e19adb67adaaf4"
46
+ "gitHead": "3de027b69d80594ca40d10c2069b6ec1ef119f89"
47
47
  }
package/src/Service.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { SerializableFunction, NotFunction } from '@proteinjs/serializer';
2
2
  import { Loadable, SourceRepository } from '@proteinjs/reflection';
3
3
  import { ServiceClient } from './ServiceClient';
4
- import { Debouncer } from '@proteinjs/util';
4
+ import { Debouncer, isInstanceOf } from '@proteinjs/util';
5
5
 
6
6
  type RemoveIndex<T> = {
7
7
  [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
@@ -18,6 +18,14 @@ type RetryConfig<T extends Service> = {
18
18
  [K in KeysWithoutService<T>]?: number;
19
19
  };
20
20
 
21
+ interface DebounceConfig {
22
+ waitTime: number;
23
+ }
24
+
25
+ type MethodDebounceConfig<T extends Service> = {
26
+ [K in KeysWithoutService<T>]?: DebounceConfig;
27
+ };
28
+
21
29
  export interface Service extends Loadable {
22
30
  serviceMetadata?: {
23
31
  auth?: {
@@ -41,16 +49,27 @@ export interface Service extends Loadable {
41
49
  [prop: string]: SerializableFunction | NotFunction<any>;
42
50
  }
43
51
 
52
+ const debouncerMap: { [key: string]: Debouncer } = {};
53
+ /** Retrieve an existing debouncer from the map or make a new one.
54
+ * This allows the debouncer instance per method to remain the same across multiple service calls.
55
+ */
56
+ function getOrCreateDebouncer(methodName: string, waitTime: number): Debouncer {
57
+ if (!debouncerMap[methodName]) {
58
+ debouncerMap[methodName] = new Debouncer(waitTime);
59
+ }
60
+ return debouncerMap[methodName];
61
+ }
62
+
44
63
  /**
45
64
  * Create a factory that creates an instance of the Service. The Service instance is a
46
65
  * ServiceClient wrapped in the interface's api.
47
66
  * @param serviceInterfaceQualifiedName the package-qualified name of the service interface (ie. service-package-name/MyService)
48
- * @param debouncer optionally pass in an instance of debouncer if you want to limit service client calls
67
+ * @param debouncer pass in either a single debouncer instance or method-specific debounce configurations
49
68
  * @returns a function that creates a Service
50
69
  */
51
70
  export const serviceFactory = <T extends Service>(
52
71
  serviceInterfaceQualifiedName: string,
53
- debouncer?: Debouncer,
72
+ debouncer?: MethodDebounceConfig<T> | Debouncer,
54
73
  retryConfig?: RetryConfig<T>
55
74
  ): (() => T) => {
56
75
  return () => {
@@ -58,15 +77,27 @@ export const serviceFactory = <T extends Service>(
58
77
  const serviceInterface = SourceRepository.get().interface(serviceInterfaceQualifiedName);
59
78
  for (const method of serviceInterface.methods) {
60
79
  const servicePath = `/service/${serviceInterface.qualifiedName}/${method.name}`;
80
+ const methodName = method.name as KeysWithoutService<T>;
61
81
 
62
82
  let retryCount = 0;
63
- if (retryConfig && method.name in retryConfig) {
64
- const methodName = method.name as KeysWithoutService<T>;
83
+ if (retryConfig && methodName in retryConfig) {
65
84
  retryCount = retryConfig[methodName]!;
66
85
  }
67
86
 
68
- const serviceClient = new ServiceClient(servicePath, method, debouncer, retryCount);
69
- service[method.name] = serviceClient.send.bind(serviceClient);
87
+ let methodDebouncer: Debouncer | undefined;
88
+ if (debouncer) {
89
+ if (isInstanceOf(debouncer, Debouncer)) {
90
+ methodDebouncer = debouncer as Debouncer;
91
+ } else if (methodName in debouncer) {
92
+ const methodConfig = (debouncer as MethodDebounceConfig<T>)[methodName];
93
+ if (methodConfig) {
94
+ methodDebouncer = getOrCreateDebouncer(methodName as string, methodConfig.waitTime);
95
+ }
96
+ }
97
+ }
98
+
99
+ const serviceClient = new ServiceClient(servicePath, method, methodDebouncer, retryCount);
100
+ service[methodName] = serviceClient.send.bind(serviceClient);
70
101
  }
71
102
 
72
103
  return service;