@zelgadis87/utils-core 4.0.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.
Files changed (134) hide show
  1. package/dist/Lazy.d.ts +21 -0
  2. package/dist/LazyAsync.d.ts +23 -0
  3. package/dist/Logger.d.ts +21 -0
  4. package/dist/Optional.d.ts +70 -0
  5. package/dist/async/CancelableDeferred.d.ts +17 -0
  6. package/dist/async/Deferred.d.ts +27 -0
  7. package/dist/async/RateThrottler.d.ts +12 -0
  8. package/dist/async/Semaphore.d.ts +10 -0
  9. package/dist/async/index.d.ts +4 -0
  10. package/dist/index.d.ts +11 -0
  11. package/dist/random/index.d.ts +2 -0
  12. package/dist/random/randomInterval.d.ts +1 -0
  13. package/dist/random/randomPercentage.d.ts +1 -0
  14. package/dist/sorting/ComparisonChain.d.ts +57 -0
  15. package/dist/sorting/Sorter.d.ts +100 -0
  16. package/dist/sorting/index.d.ts +4 -0
  17. package/dist/sorting/types.d.ts +5 -0
  18. package/dist/time/RandomTimeDuration.d.ts +9 -0
  19. package/dist/time/TimeBase.d.ts +38 -0
  20. package/dist/time/TimeDuration.d.ts +81 -0
  21. package/dist/time/TimeFrequency.d.ts +10 -0
  22. package/dist/time/TimeInstant.d.ts +137 -0
  23. package/dist/time/TimeInstantBuilder.d.ts +77 -0
  24. package/dist/time/TimeUnit.d.ts +17 -0
  25. package/dist/time/index.d.ts +6 -0
  26. package/dist/time/types.d.ts +26 -0
  27. package/dist/tsconfig.tsbuildinfo +1 -0
  28. package/dist/types/arrays.d.ts +33 -0
  29. package/dist/types/booleans.d.ts +2 -0
  30. package/dist/types/functions.d.ts +20 -0
  31. package/dist/types/index.d.ts +12 -0
  32. package/dist/types/json.d.ts +6 -0
  33. package/dist/types/nulls.d.ts +8 -0
  34. package/dist/types/numbers.d.ts +31 -0
  35. package/dist/types/promises.d.ts +6 -0
  36. package/dist/types/records.d.ts +14 -0
  37. package/dist/types/strings.d.ts +40 -0
  38. package/dist/upgrade/DataUpgrader.d.ts +22 -0
  39. package/dist/upgrade/errors.d.ts +12 -0
  40. package/dist/upgrade/getTransitionsPath.d.ts +3 -0
  41. package/dist/upgrade/index.d.ts +2 -0
  42. package/dist/upgrade/types.d.ts +31 -0
  43. package/dist/utils/asError.d.ts +1 -0
  44. package/dist/utils/bindThis.d.ts +1 -0
  45. package/dist/utils/constant.d.ts +8 -0
  46. package/dist/utils/entries.d.ts +4 -0
  47. package/dist/utils/groupBy.d.ts +7 -0
  48. package/dist/utils/iff.d.ts +8 -0
  49. package/dist/utils/index.d.ts +22 -0
  50. package/dist/utils/indexBy.d.ts +7 -0
  51. package/dist/utils/jsonCloneDeep.d.ts +2 -0
  52. package/dist/utils/math.d.ts +9 -0
  53. package/dist/utils/noop.d.ts +1 -0
  54. package/dist/utils/omit.d.ts +2 -0
  55. package/dist/utils/pad.d.ts +3 -0
  56. package/dist/utils/pluralize.d.ts +1 -0
  57. package/dist/utils/round.d.ts +8 -0
  58. package/dist/utils/sortBy.d.ts +7 -0
  59. package/dist/utils/throttle.d.ts +3 -0
  60. package/dist/utils/uniq.d.ts +1 -0
  61. package/dist/utils/uniqBy.d.ts +2 -0
  62. package/dist/utils/uniqByKey.d.ts +1 -0
  63. package/dist/utils/upsert.d.ts +0 -0
  64. package/dist/utils/withTryCatch.d.ts +2 -0
  65. package/dist/utils/withTryCatchAsync.d.ts +2 -0
  66. package/dist/utils/wrap.d.ts +1 -0
  67. package/esbuild/index.cjs +2670 -0
  68. package/esbuild/index.mjs +2518 -0
  69. package/package.json +159 -0
  70. package/src/Lazy.ts +77 -0
  71. package/src/LazyAsync.ts +100 -0
  72. package/src/Logger.ts +44 -0
  73. package/src/Optional.ts +172 -0
  74. package/src/async/CancelableDeferred.ts +36 -0
  75. package/src/async/Deferred.ts +84 -0
  76. package/src/async/RateThrottler.ts +46 -0
  77. package/src/async/Semaphore.ts +45 -0
  78. package/src/async/index.ts +6 -0
  79. package/src/index.ts +13 -0
  80. package/src/random/index.ts +3 -0
  81. package/src/random/randomInterval.ts +4 -0
  82. package/src/random/randomPercentage.ts +6 -0
  83. package/src/sorting/ComparisonChain.ts +209 -0
  84. package/src/sorting/Sorter.ts +357 -0
  85. package/src/sorting/index.ts +5 -0
  86. package/src/sorting/types.ts +7 -0
  87. package/src/time/RandomTimeDuration.ts +21 -0
  88. package/src/time/TimeBase.ts +113 -0
  89. package/src/time/TimeDuration.ts +296 -0
  90. package/src/time/TimeFrequency.ts +28 -0
  91. package/src/time/TimeInstant.ts +488 -0
  92. package/src/time/TimeInstantBuilder.ts +126 -0
  93. package/src/time/TimeUnit.ts +43 -0
  94. package/src/time/index.ts +8 -0
  95. package/src/time/types.ts +56 -0
  96. package/src/types/arrays.ts +89 -0
  97. package/src/types/booleans.ts +8 -0
  98. package/src/types/functions.ts +27 -0
  99. package/src/types/index.ts +18 -0
  100. package/src/types/json.ts +5 -0
  101. package/src/types/nulls.ts +33 -0
  102. package/src/types/numbers.ts +80 -0
  103. package/src/types/promises.ts +23 -0
  104. package/src/types/records.ts +21 -0
  105. package/src/types/strings.ts +143 -0
  106. package/src/upgrade/DataUpgrader.ts +100 -0
  107. package/src/upgrade/errors.ts +25 -0
  108. package/src/upgrade/getTransitionsPath.ts +89 -0
  109. package/src/upgrade/index.ts +4 -0
  110. package/src/upgrade/types.ts +36 -0
  111. package/src/utils/asError.ts +12 -0
  112. package/src/utils/bindThis.ts +4 -0
  113. package/src/utils/constant.ts +9 -0
  114. package/src/utils/entries.ts +13 -0
  115. package/src/utils/groupBy.ts +39 -0
  116. package/src/utils/iff.ts +26 -0
  117. package/src/utils/index.ts +24 -0
  118. package/src/utils/indexBy.ts +36 -0
  119. package/src/utils/jsonCloneDeep.ts +31 -0
  120. package/src/utils/math.ts +44 -0
  121. package/src/utils/noop.ts +2 -0
  122. package/src/utils/omit.ts +8 -0
  123. package/src/utils/pad.ts +20 -0
  124. package/src/utils/pluralize.ts +20 -0
  125. package/src/utils/round.ts +24 -0
  126. package/src/utils/sortBy.ts +27 -0
  127. package/src/utils/throttle.ts +10 -0
  128. package/src/utils/uniq.ts +6 -0
  129. package/src/utils/uniqBy.ts +15 -0
  130. package/src/utils/uniqByKey.ts +5 -0
  131. package/src/utils/upsert.ts +2 -0
  132. package/src/utils/withTryCatch.ts +10 -0
  133. package/src/utils/withTryCatchAsync.ts +6 -0
  134. package/src/utils/wrap.ts +4 -0
package/package.json ADDED
@@ -0,0 +1,159 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package",
3
+ "name": "@zelgadis87/utils-core",
4
+ "version": "4.0.0",
5
+ "author": "Zelgadis87",
6
+ "license": "ISC",
7
+ "private": false,
8
+ "files": [
9
+ "/src",
10
+ "/dist",
11
+ "/esbuild"
12
+ ],
13
+ "wireit": {
14
+ "build:ts": {
15
+ "command": "tsc --emitDeclarationOnly",
16
+ "clean": "if-file-deleted",
17
+ "files": [
18
+ "./src/**"
19
+ ],
20
+ "output": [
21
+ "./dist/**"
22
+ ]
23
+ },
24
+ "build:cjs": {
25
+ "command": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=cjs --outfile=esbuild/index.cjs",
26
+ "clean": "if-file-deleted",
27
+ "files": [
28
+ "./src/**"
29
+ ],
30
+ "output": [
31
+ "./esbuild/index.cjs"
32
+ ]
33
+ },
34
+ "build:esm": {
35
+ "command": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --outfile=esbuild/index.mjs",
36
+ "clean": "if-file-deleted",
37
+ "files": [
38
+ "./src/**"
39
+ ],
40
+ "output": [
41
+ "./esbuild/index.mjs"
42
+ ]
43
+ },
44
+ "build": {
45
+ "dependencies": [
46
+ "build:ts",
47
+ "build:cjs",
48
+ "build:esm"
49
+ ]
50
+ },
51
+ "test": {
52
+ "command": "vitest run --passWithNoTests",
53
+ "clean": true,
54
+ "files": [
55
+ "./src/**/*.ts",
56
+ "./test/**/*.spec.ts"
57
+ ],
58
+ "output": []
59
+ },
60
+ "test:coverage": {
61
+ "command": "vitest run --coverage --passWithNoTests",
62
+ "clean": true,
63
+ "files": [
64
+ "./src/**/*.ts",
65
+ "./test/**/*.spec.ts"
66
+ ],
67
+ "output": [
68
+ "./coverage/*.*"
69
+ ]
70
+ },
71
+ "lint:strict": {
72
+ "command": "eslint .",
73
+ "dependencies": [],
74
+ "clean": false,
75
+ "files": [
76
+ "./*.ts"
77
+ ],
78
+ "output": []
79
+ },
80
+ "check": {
81
+ "dependencies": [
82
+ "lint:strict",
83
+ "test"
84
+ ]
85
+ },
86
+ "version": {
87
+ "dependencies": [
88
+ "build",
89
+ "check"
90
+ ]
91
+ },
92
+ "version:major": {
93
+ "command": "pnpm version major",
94
+ "dependencies": [
95
+ "version"
96
+ ],
97
+ "clean": false,
98
+ "files": [],
99
+ "output": []
100
+ },
101
+ "version:minor": {
102
+ "command": "pnpm version minor",
103
+ "dependencies": [
104
+ "version"
105
+ ],
106
+ "clean": false,
107
+ "files": [],
108
+ "output": []
109
+ },
110
+ "version:patch": {
111
+ "command": "pnpm version patch",
112
+ "dependencies": [
113
+ "version"
114
+ ],
115
+ "clean": false,
116
+ "files": [],
117
+ "output": []
118
+ }
119
+ },
120
+ "types": "./dist/index.d.ts",
121
+ "exports": {
122
+ ".": {
123
+ "import": "./esbuild/index.mjs",
124
+ "require": "./esbuild/index.cjs",
125
+ "types": "./dist/index.d.ts"
126
+ }
127
+ },
128
+ "devDependencies": {
129
+ "@stylistic/eslint-plugin-ts": "2.6.0-beta.1",
130
+ "@typescript-eslint/eslint-plugin": "rc-v8",
131
+ "@typescript-eslint/parser": "rc-v8",
132
+ "@vitest/coverage-v8": "^2.0.4",
133
+ "@vitest/ui": "^2.0.4",
134
+ "esbuild": "^0.23.0",
135
+ "eslint": "^9.8.0",
136
+ "rimraf": "^6.0.1",
137
+ "typescript": "^5.5.4",
138
+ "vitest": "^2.0.4",
139
+ "wireit": "^0.14.5"
140
+ },
141
+ "scripts": {
142
+ "clean": "rimraf .wireit dist esbuild coverage",
143
+ "build": "wireit",
144
+ "lint": "pnpm eslint .",
145
+ "lint:errors": "pnpm lint --quiet",
146
+ "lint:strict": "wireit",
147
+ "test": "wireit",
148
+ "test:watch": "vitest dev --passWithNoTests",
149
+ "test:ui": "vitest dev --ui --coverage --passWithNoTests",
150
+ "test:coverage": "wireit",
151
+ "check": "wireit",
152
+ "version:major": "wireit",
153
+ "version:minor": "wireit",
154
+ "version:patch": "wireit",
155
+ "create:major": "pnpm clean && pnpm version:major && pnpm publish",
156
+ "create:minor": "pnpm clean && pnpm version:minor && pnpm publish",
157
+ "create:patch": "pnpm clean && pnpm version:patch && pnpm publish"
158
+ }
159
+ }
package/src/Lazy.ts ADDED
@@ -0,0 +1,77 @@
1
+
2
+ import { ensureDefined } from "./types";
3
+
4
+ /**
5
+ * Class that stores a value that is computationally/memory intensive to initialize.
6
+ * The initialization of the value is done once and only if required (lazy initialization).
7
+ * @author gtomberli
8
+ */
9
+ export default class Lazy<T> {
10
+
11
+ private _value: T | undefined = undefined;
12
+ private _initialized: boolean = false;
13
+ private _generator: () => T;
14
+
15
+ private constructor( generator: () => T ) {
16
+ this._generator = ensureDefined( generator );
17
+ }
18
+
19
+ public get value(): T | undefined {
20
+ return this._value;
21
+ }
22
+
23
+ public getOrCreate(): T {
24
+ if ( !this._initialized ) {
25
+ this._value = this._generator();
26
+ this._initialized = true;
27
+ }
28
+ return this._value!;
29
+ }
30
+
31
+ public getOrThrow( errorMessage?: "Value not initialized" ): T {
32
+ if ( !this._initialized )
33
+ throw new Error( errorMessage );
34
+ return this._value!;
35
+ }
36
+
37
+ public or( t: T ): T {
38
+ if ( !this._initialized ) {
39
+ return t;
40
+ } else {
41
+ return this._value!;
42
+ }
43
+ }
44
+
45
+ public isPresent() {
46
+ return this._initialized;
47
+ }
48
+
49
+ public isEmpty() {
50
+ return !this._initialized;
51
+ }
52
+
53
+ public ifPresent( fn: (t: T) => void ): void {
54
+ if ( this.isPresent() ) {
55
+ fn( this._value! );
56
+ }
57
+ }
58
+
59
+ public ifEmpty( fn: () => void ): void {
60
+ if ( this.isEmpty() ) {
61
+ fn();
62
+ }
63
+ }
64
+
65
+ public apply( fnPresent: (t: T) => void, fnEmpty: () => void ): void {
66
+ if ( this.isPresent() ) {
67
+ fnPresent( this._value! );
68
+ } else {
69
+ fnEmpty( );
70
+ }
71
+ }
72
+
73
+ public static of<T>( generator: () => T ): Lazy<T> {
74
+ return new Lazy( generator );
75
+ }
76
+
77
+ }
@@ -0,0 +1,100 @@
1
+ import { ensureDefined } from "./types/nulls.js";
2
+
3
+ export default class LazyAsync<T> {
4
+
5
+ private _promise: Promise<T> | undefined = undefined;
6
+ private _pending: boolean = false;
7
+ private _resolvedValue: T | undefined = undefined;
8
+ private _error: Error | undefined = undefined;
9
+ private _generator: () => Promise<T>;
10
+
11
+ private constructor( generator: () => Promise<T> ) {
12
+ this._generator = ensureDefined( generator );
13
+ }
14
+
15
+ public getOrCreate(): Promise<T> {
16
+ if ( this.isEmpty() ) {
17
+ this._pending = true;
18
+ this._promise = this._generator();
19
+ this._promise.then( value => {
20
+ this._pending = false;
21
+ this._resolvedValue = value;
22
+ }, err => {
23
+ this._pending = false;
24
+ this._error = err;
25
+ } );
26
+ }
27
+ return this._promise as Promise<T>;
28
+ }
29
+
30
+ public isPresent() {
31
+ return this._promise !== undefined;
32
+ }
33
+
34
+ public isEmpty() {
35
+ return this._promise === undefined;
36
+ }
37
+
38
+ public isPending() {
39
+ return this.isPresent() && this._pending === true;
40
+ }
41
+
42
+ public isReady() {
43
+ return this.isPresent() && this._pending === false;
44
+ }
45
+
46
+ public isResolved() {
47
+ return this.isReady() && this._error === undefined;
48
+ }
49
+
50
+ public isError() {
51
+ return this.isReady() && this._error !== undefined;
52
+ }
53
+
54
+ public ifPresent( fn: ( t: Promise<T> ) => void ): void {
55
+ if ( this.isPresent() ) {
56
+ fn( this._promise! );
57
+ }
58
+ }
59
+
60
+ public ifEmpty( fn: () => void ): void {
61
+ if ( this.isEmpty() ) {
62
+ fn();
63
+ }
64
+ }
65
+
66
+ public ifPending( fn: ( t: Promise<T> ) => void ): void {
67
+ if ( this.isPending() ) {
68
+ fn( this._promise! );
69
+ }
70
+ }
71
+
72
+ public ifReady( fn: ( t: Promise<T> ) => void ): void {
73
+ if ( this.isReady() ) {
74
+ fn( this._promise! );
75
+ }
76
+ }
77
+
78
+ public ifResolved( fn: ( t: T ) => void ): void {
79
+ if ( this.isResolved() ) {
80
+ fn( this._resolvedValue! );
81
+ }
82
+ }
83
+
84
+ public ifError( fn: ( err: Error ) => void ): void {
85
+ if ( this.isError() ) {
86
+ fn( this._error! );
87
+ }
88
+ }
89
+
90
+ public getOrThrow( errorMessage?: "Value not initialized" ): Promise<T> | never {
91
+ if ( !this._promise )
92
+ throw new Error( errorMessage );
93
+ return this._promise;
94
+ }
95
+
96
+ public static of<T>( generator: () => Promise<T> ): LazyAsync<T> {
97
+ return new LazyAsync( generator );
98
+ }
99
+
100
+ }
package/src/Logger.ts ADDED
@@ -0,0 +1,44 @@
1
+ import TimeInstant from "./time/TimeInstant";
2
+ import noop from "./utils/noop";
3
+
4
+ const LEVELS = [ "log", "debug", "info", "warn", "error" ] as const;
5
+ type TLogLevel = keyof Console & typeof LEVELS[ number ]
6
+
7
+ const timestamp = () => TimeInstant.now().asTimeString();
8
+
9
+ type TLoggerOpts = {
10
+ console: Console;
11
+ enabled: boolean;
12
+ minLevel: Uppercase<TLogLevel>;
13
+ }
14
+
15
+ export default class Logger {
16
+
17
+ private enabled: boolean = true;
18
+ private console: Console;
19
+ private minLevel: number;
20
+
21
+ public constructor(
22
+ public readonly name: string,
23
+ args?: Partial<TLoggerOpts>
24
+ ) {
25
+ this.console = args?.console ?? globalThis.console;
26
+ this.enabled = args?.enabled ?? true;
27
+ this.minLevel = LEVELS.indexOf( ( args?.minLevel ?? "DEBUG" ).toLowerCase() as TLogLevel );
28
+ }
29
+
30
+ public get log() { return this.logWrap( 'log' ); }
31
+ public get debug() { return this.logWrap( 'debug' ); }
32
+ public get info() { return this.logWrap( 'info' ); }
33
+ public get warn() { return this.logWrap( 'warn' ); }
34
+ public get error() { return this.logWrap( 'error' ); }
35
+
36
+ private logWrap( methodName: TLogLevel ) {
37
+ if ( !this.console[ methodName ] )
38
+ throw new Error( 'Invalid method name: ' + methodName );
39
+ if ( !this.enabled || !this.console || LEVELS.indexOf( methodName ) < this.minLevel )
40
+ return noop;
41
+ return this.console[ methodName ].bind( this.console, timestamp(), methodName.toUpperCase(), this.name );
42
+ }
43
+
44
+ }
@@ -0,0 +1,172 @@
1
+ import { TConsumer, TFunction, TPredicate, TProducer, TVoidFunction } from "./types/functions.js";
2
+ import { isDefined, isNullOrUndefined } from "./types/nulls.js";
3
+
4
+ export class Optional<T> implements TOptional<T> {
5
+
6
+ private _present: boolean;
7
+ private _value: T | undefined;
8
+
9
+ private constructor( t: T | null | undefined ) {
10
+ const defined = isDefined( t );
11
+ this._value = defined ? t : undefined;
12
+ this._present = defined;
13
+ }
14
+
15
+ public get rawValue() {
16
+ return this._value;
17
+ }
18
+
19
+ public get(): T | never {
20
+ if ( this.isEmpty() )
21
+ throw new ErrorGetEmptyOptional();
22
+ return this.rawValue as T;
23
+ }
24
+
25
+ public set(t: T) {
26
+ if ( isNullOrUndefined( t ) )
27
+ throw new ErrorSetEmptyOptional();
28
+ this._value = t;
29
+ this._present = true;
30
+ }
31
+
32
+ public clear() {
33
+ this._value = undefined;
34
+ this._present = false;
35
+ }
36
+
37
+ public isEmpty(): this is TEmptyOptional<T> {
38
+ return !this._present;
39
+ }
40
+ public isPresent(): this is TPresentOptional<T> {
41
+ return this._present;
42
+ }
43
+
44
+ public ifEmpty( callback: TVoidFunction ) {
45
+ if ( this.isEmpty() )
46
+ callback();
47
+ }
48
+ public ifPresent( callback: TConsumer<T> ) {
49
+ if ( this.isPresent() )
50
+ callback( this.rawValue );
51
+ }
52
+ public apply( callbackIfPresent: TConsumer<T>, callbackIfEmpty: TVoidFunction ) {
53
+ if ( this.isEmpty() ) {
54
+ callbackIfEmpty();
55
+ } else {
56
+ callbackIfPresent( this.rawValue! );
57
+ }
58
+ }
59
+
60
+ public orElse( newValue: T | null | undefined ) {
61
+ if ( this.isEmpty() )
62
+ return Optional.ofNullable( newValue );
63
+ return this as TPresentOptional<T>;
64
+ }
65
+ public orElseGet( produceValue: TProducer<T | null | undefined> ) {
66
+ if ( this.isEmpty() ) {
67
+ const newValue = produceValue();
68
+ return Optional.ofNullable( newValue );
69
+ }
70
+ return this as TPresentOptional<T>;
71
+ }
72
+ public orElseThrow( produceError: TProducer<Error> ) {
73
+ if ( this.isEmpty() )
74
+ throw produceError();
75
+ return this as TPresentOptional<T>;
76
+ }
77
+
78
+ public mapTo<R>( mapper: TFunction<T, R | null | undefined> ) {
79
+ return this.flatMapTo( t => Optional.ofNullable( mapper( t ) ) );
80
+ }
81
+ public flatMapTo<R>( mapper: TFunction<T, TOptional<R>> ) {
82
+ if ( this.isPresent() ) {
83
+ const newValue = mapper( this.rawValue );
84
+ return newValue;
85
+ }
86
+ return this as TEmptyOptional<T>;
87
+ }
88
+
89
+ public filter( predicate: TPredicate<T> ): this | TEmptyOptional<T> {
90
+ if ( this.isPresent() ) {
91
+ if ( predicate( this.rawValue ) ) {
92
+ return this;
93
+ } else {
94
+ return Optional.empty();
95
+ }
96
+ } else {
97
+ return this;
98
+ }
99
+ }
100
+
101
+ public static empty<T>(): TEmptyOptional<T> {
102
+ return new Optional( undefined ) as any;
103
+ }
104
+ public static of<T>( t: T ): TPresentOptional<T> {
105
+ if ( isNullOrUndefined( t ) )
106
+ throw new ErrorCannotInstantiatePresentOptionalWithEmptyValue();
107
+ return new Optional( t ) as any;
108
+ }
109
+ public static ofNullable<T>( t: T | null | undefined ): TOptional<T> {
110
+ return new Optional( t ) as any;
111
+ }
112
+
113
+ }
114
+ export default Optional;
115
+
116
+ export type TOptional<T> = {
117
+ readonly rawValue: T | undefined;
118
+
119
+ /**
120
+ * @returns the currently stored value, if any; throws {@link ErrorGetEmptyOptional} otherwise;
121
+ */
122
+ get(): T | never;
123
+ /**
124
+ * Places a new value inside this optional. Throws {@link ErrorSetEmptyOptional} if t is null or undefined.
125
+ */
126
+ set(t: T): void;
127
+ /**
128
+ * Clears the current value from this optional, if any.
129
+ */
130
+ clear(): void;
131
+ isEmpty(): boolean;
132
+ isPresent(): boolean;
133
+
134
+ ifEmpty: ( callback: TVoidFunction ) => void;
135
+ ifPresent: ( callback: TConsumer<T> ) => void;
136
+ apply( callbackIfPresent: TConsumer<T>, callbackIfEmpty: TVoidFunction ): void;
137
+
138
+ orElse: ( ( newValue: T | null | undefined ) => TOptional<T> );
139
+ orElseGet: ( produceValue: TProducer<T | null | undefined> ) => TOptional<T>;
140
+ orElseThrow: ( produceError: TProducer<Error> ) => TPresentOptional<T>;
141
+
142
+ mapTo<R>( mapper: TFunction<T, R> ): TOptional<R>;
143
+ flatMapTo<R>( mapper: TFunction<T, TOptional<R>> ): TOptional<R>;
144
+
145
+ filter( predicate: TPredicate<T> ): TOptional<T>;
146
+ }
147
+ export type TEmptyOptional<T> = TOptional<T> & {
148
+ readonly rawValue: undefined;
149
+ isEmpty(): true;
150
+ isPresent(): false;
151
+ }
152
+ export type TPresentOptional<T> = TOptional<T> & {
153
+ readonly rawValue: T;
154
+ isEmpty(): false;
155
+ isPresent(): true;
156
+ }
157
+
158
+ export class ErrorGetEmptyOptional extends Error {
159
+ constructor() {
160
+ super( "Cannot retrieve a value from an EmptyOptional." );
161
+ }
162
+ }
163
+ export class ErrorSetEmptyOptional extends Error {
164
+ constructor() {
165
+ super( "Cannot set a null or undefined value." );
166
+ }
167
+ }
168
+ export class ErrorCannotInstantiatePresentOptionalWithEmptyValue extends Error {
169
+ constructor() {
170
+ super( "Cannot initialize a PresentOptional with a null or undefined value." );
171
+ }
172
+ }
@@ -0,0 +1,36 @@
1
+ import Deferred from "./Deferred.js";
2
+
3
+ interface ICancelablePromise<T> extends Promise<T> {
4
+ cancel(): void;
5
+ }
6
+
7
+ /** @deprecated use CancelableDeferredV2 instead. */
8
+ export default class CancelableDeferred<T = void> extends Deferred<T> implements ICancelablePromise<T> {
9
+
10
+ private _canceled: boolean;
11
+
12
+ public get canceled(): boolean { return this._canceled; }
13
+
14
+ constructor() {
15
+ super();
16
+ this._canceled = false;
17
+ }
18
+
19
+ public cancel() {
20
+ this._canceled = true;
21
+ }
22
+
23
+ protected override createInternals() {
24
+ let resolveSelf: ( value: T ) => void, rejectSelf: ( reason: Error ) => void;
25
+ const promise = new Promise<T>( ( resolve, reject ) => {
26
+ resolveSelf = ( value: T ) => { if ( !this._canceled ) resolve( value ); }
27
+ rejectSelf = ( reason: Error ) => { if ( !this._canceled ) reject( reason ); };
28
+ } );
29
+ return {
30
+ promise,
31
+ resolve: resolveSelf!,
32
+ reject: rejectSelf!,
33
+ };
34
+ }
35
+
36
+ }
@@ -0,0 +1,84 @@
1
+ import { TFunction } from "../types/functions.js";
2
+
3
+ type DeferredInternals<T> = {
4
+ promise: Promise<T>;
5
+ resolve: TFunction<T, void>;
6
+ reject: TFunction<Error, void>;
7
+ }
8
+
9
+ export interface ICancelablePromise<T> extends Promise<T> {
10
+ cancel(): void;
11
+ }
12
+
13
+ export class DeferredCanceledError extends Error { }
14
+
15
+ export class Deferred<T = void> implements Promise<T>, ICancelablePromise<T> {
16
+
17
+ private _pending: boolean;
18
+ private readonly _internals: DeferredInternals<T>;
19
+
20
+ 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; }
22
+
23
+ constructor() {
24
+ this._pending = true;
25
+ this._internals = this.createInternals();
26
+ }
27
+
28
+ public resolve( val: T ): void {
29
+ if ( !this._pending ) throw new Error( 'Illegal state exception' );
30
+ this._pending = false;
31
+ this._internals.resolve( val );
32
+ }
33
+
34
+ public reject( reason: Error ): void {
35
+ if ( !this._pending ) throw new Error( 'Illegal state exception' );
36
+ this._pending = false;
37
+ this._internals.reject( reason );
38
+ }
39
+
40
+ 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
+ return this._internals.promise.then( onFulfilled, onRejected );
42
+ }
43
+
44
+ public catch<R = T>( onRejected: ( ( reason: Error ) => R | PromiseLike<R> ) | null | undefined ): Promise<T | R> {
45
+ return this._internals.promise.catch( onRejected );
46
+ }
47
+
48
+ public finally( onfinally: ( () => void ) | null | undefined ): Promise<T> {
49
+ return this._internals.promise.finally( onfinally );
50
+ }
51
+
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
+ public get asPromise(): Promise<T> {
58
+ return this;
59
+ }
60
+
61
+ public get asCancelablePromise(): ICancelablePromise<T> {
62
+ return this;
63
+ }
64
+
65
+ protected createInternals() {
66
+ let resolveSelf: ( value: T ) => void, rejectSelf: ( reason: Error ) => void;
67
+ const promise = new Promise<T>( ( resolve, reject ) => {
68
+ resolveSelf = resolve;
69
+ rejectSelf = reject;
70
+ } );
71
+ return {
72
+ promise,
73
+ resolve: resolveSelf!,
74
+ reject: rejectSelf!,
75
+ };
76
+ }
77
+
78
+ get [ Symbol.toStringTag ]() {
79
+ return '[object Deferred]';
80
+ }
81
+
82
+ }
83
+
84
+ export default Deferred;