@zelgadis87/utils-core 4.0.1 → 4.1.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@zelgadis87/utils-core",
4
- "version": "4.0.1",
4
+ "version": "4.1.0",
5
5
  "author": "Zelgadis87",
6
6
  "license": "ISC",
7
7
  "private": false,
@@ -4,7 +4,7 @@ interface ICancelablePromise<T> extends Promise<T> {
4
4
  cancel(): void;
5
5
  }
6
6
 
7
- /** @deprecated use CancelableDeferredV2 instead. */
7
+ /** @deprecated use Deferred instead. */
8
8
  export default class CancelableDeferred<T = void> extends Deferred<T> implements ICancelablePromise<T> {
9
9
 
10
10
  private _canceled: boolean;
@@ -10,7 +10,11 @@ export interface ICancelablePromise<T> extends Promise<T> {
10
10
  cancel(): void;
11
11
  }
12
12
 
13
- export class DeferredCanceledError extends Error { }
13
+ export class DeferredCanceledError extends Error {
14
+ constructor() {
15
+ super( "Execution canceled" );
16
+ }
17
+ }
14
18
 
15
19
  export class Deferred<T = void> implements Promise<T>, ICancelablePromise<T> {
16
20
 
@@ -18,7 +22,9 @@ export class Deferred<T = void> implements Promise<T>, ICancelablePromise<T> {
18
22
  private readonly _internals: DeferredInternals<T>;
19
23
 
20
24
  public get pending(): boolean { return this._pending; }
21
- /** @deprecated: Use resolve, then and catch directly; use asPromise to return a promise type. */ public get promise(): Promise<T> { return this._internals.promise; }
25
+
26
+ /** @deprecated: Use resolve, then and catch directly; use asPromise to return a promise type. */
27
+ public get promise(): Promise<T> { return this._internals.promise; }
22
28
 
23
29
  constructor() {
24
30
  this._pending = true;
@@ -26,16 +32,43 @@ export class Deferred<T = void> implements Promise<T>, ICancelablePromise<T> {
26
32
  }
27
33
 
28
34
  public resolve( val: T ): void {
29
- if ( !this._pending ) throw new Error( 'Illegal state exception' );
35
+ if ( !this._pending )
36
+ throw new Error( 'Illegal state exception' );
37
+ this.resolveIfPending( val );
38
+ }
39
+
40
+ public reject( reason: Error ): void {
41
+ if ( !this._pending )
42
+ throw new Error( 'Illegal state exception' );
43
+ this.rejectIfPending( reason );
44
+ }
45
+
46
+ public cancel(): void {
47
+ if ( !this._pending )
48
+ throw new Error( 'Illegal state exception' );
49
+ this.cancelIfPending();
50
+ }
51
+
52
+ public resolveIfPending( val: T ): void {
53
+ if ( !this._pending )
54
+ return;
30
55
  this._pending = false;
31
56
  this._internals.resolve( val );
32
57
  }
33
58
 
34
- public reject( reason: Error ): void {
35
- if ( !this._pending ) throw new Error( 'Illegal state exception' );
59
+ public rejectIfPending( reason: Error ): void {
60
+ if ( !this._pending )
61
+ return;
36
62
  this._pending = false;
37
63
  this._internals.reject( reason );
38
64
  }
65
+
66
+ public cancelIfPending(): void {
67
+ if ( !this._pending )
68
+ return;
69
+ this.reject( new DeferredCanceledError() );
70
+ }
71
+
39
72
 
40
73
  public then<R = T, S = T>( onFulfilled: ( ( value: T ) => R | PromiseLike<R> ) | null | undefined, onRejected?: ( ( reason: Error ) => S | PromiseLike<S> ) | null | undefined ): Promise<R | S> {
41
74
  return this._internals.promise.then( onFulfilled, onRejected );
@@ -49,11 +82,6 @@ export class Deferred<T = void> implements Promise<T>, ICancelablePromise<T> {
49
82
  return this._internals.promise.finally( onfinally );
50
83
  }
51
84
 
52
- public cancel(): void {
53
- if ( !this._pending ) throw new Error( 'Illegal state exception' );
54
- this._internals.reject( new DeferredCanceledError( 'Execution aborted by the user' ) );
55
- }
56
-
57
85
  public get asPromise(): Promise<T> {
58
86
  return this;
59
87
  }
@@ -3,32 +3,35 @@ import Deferred from "./Deferred";
3
3
 
4
4
  export class Semaphore {
5
5
 
6
- private readonly _waitingRequests: Deferred<void>[];
6
+ private readonly _queuedRequests: Deferred<void>[];
7
+ private _inProgress = 0;
7
8
 
8
9
  constructor(
9
10
  private _availableSlots: number = 1
10
11
  ) {
11
- this._waitingRequests = [];
12
+ this._queuedRequests = [];
12
13
  }
13
14
 
14
15
  private async _awaitSlot(): Promise<void> {
15
16
  if ( this._availableSlots > 0 ) {
16
17
  this._availableSlots -= 1;
18
+ this._inProgress += 1;
17
19
  return void 0;
18
20
  } else {
19
21
  // Semaphore implementation using promises.
20
22
  const deferred = new Deferred();
21
- this._waitingRequests.push( deferred );
23
+ this._queuedRequests.push( deferred );
22
24
  return deferred.asPromise;
23
25
  }
24
26
  }
25
27
 
26
28
  private _releaseSlot() {
27
- const waitingSlotToResolve = this._waitingRequests.shift();
29
+ const waitingSlotToResolve = this._queuedRequests.shift();
28
30
  if ( waitingSlotToResolve ) {
29
31
  waitingSlotToResolve.resolve();
30
32
  } else {
31
33
  this._availableSlots += 1;
34
+ this._inProgress -= 1;
32
35
  }
33
36
  }
34
37
 
@@ -40,6 +43,18 @@ export class Semaphore {
40
43
  } );
41
44
  }
42
45
 
46
+ public get availableSlots() {
47
+ return this._availableSlots;
48
+ }
49
+
50
+ public get queueSize() {
51
+ return this._queuedRequests.length;
52
+ }
53
+
54
+ public get inProgressSize() {
55
+ return this._inProgress;
56
+ }
57
+
43
58
  }
44
59
 
45
60
  export default Semaphore;
@@ -0,0 +1,19 @@
1
+
2
+ /**
3
+ * Define a new type that is true if T is the empty object, false otherwise.
4
+ */
5
+ export type TIsEmptyObject<T> = keyof T extends never ? true : false;
6
+
7
+ /**
8
+ * Defines a new type that is the empty array, if T is an empty object, or is the array containing T if T is not the empty object.<br/>
9
+ * This type can be used as function argument, to conditionally require an argument based on type T.<br/>
10
+ * Usage example:
11
+ * ```
12
+ * type TMetadata = { a: {}, b: {}, c: { x: 1 } };
13
+ * function foo<X extends keyof TMetadata>( type: X, metadata: TMetadata[X] ) { ... };
14
+ * export function fooWrapper<X extends keyof TMetadata>( type: X, ...args: TConditionalOptionalType<TMetadata[X]> ) {
15
+ * const bar = foo( type, args.length === 0 ? void 0 : args[ 0 ] );
16
+ * }
17
+ * ```
18
+ */
19
+ export type TConditionalOptionalType<T> = TIsEmptyObject<T> extends true ? [] : [ T ];
@@ -8,6 +8,7 @@ export type TPrimitive = string | number | boolean | null;
8
8
 
9
9
  export * from './arrays';
10
10
  export * from './booleans.ts';
11
+ export * from './empties.ts';
11
12
  export * from './errors.ts';
12
13
  export * from './functions';
13
14
  export * from './json';