@xylabs/threads 4.5.0 → 4.5.1
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/dist/esm/master/pool-types.js +11 -11
- package/dist/esm/master/pool.js +4 -6
- package/dist/esm/ponyfills.js +20 -0
- package/dist/esm/types/master.js +6 -6
- package/dist/esm/types/messages.js +13 -12
- package/dist/master/pool-types.d.ts +18 -21
- package/dist/master/pool-types.js +11 -11
- package/dist/master/pool.d.ts +1 -10
- package/dist/master/pool.js +4 -6
- package/dist/ponyfills.d.ts +8 -0
- package/dist/ponyfills.js +20 -0
- package/dist/types/master.d.ts +11 -13
- package/dist/types/master.js +6 -6
- package/dist/types/messages.d.ts +18 -22
- package/dist/types/messages.js +13 -12
- package/package.json +4 -3
- package/src/master/pool-types.ts +18 -22
- package/src/master/pool.ts +5 -7
- package/src/ponyfills.ts +31 -0
- package/src/types/master.ts +12 -14
- package/src/types/messages.ts +18 -26
- package/dist/enum.d.ts +0 -5
- package/dist/enum.js +0 -7
- package/dist/esm/enum.js +0 -7
- package/src/enum.ts +0 -87
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PoolEventType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
initialized
|
|
7
|
-
taskCanceled
|
|
8
|
-
taskCompleted
|
|
9
|
-
taskFailed
|
|
10
|
-
taskQueued
|
|
11
|
-
taskQueueDrained
|
|
12
|
-
taskStart
|
|
13
|
-
terminated
|
|
14
|
-
});
|
|
4
|
+
var PoolEventType;
|
|
5
|
+
(function (PoolEventType) {
|
|
6
|
+
PoolEventType["initialized"] = "initialized";
|
|
7
|
+
PoolEventType["taskCanceled"] = "taskCanceled";
|
|
8
|
+
PoolEventType["taskCompleted"] = "taskCompleted";
|
|
9
|
+
PoolEventType["taskFailed"] = "taskFailed";
|
|
10
|
+
PoolEventType["taskQueued"] = "taskQueued";
|
|
11
|
+
PoolEventType["taskQueueDrained"] = "taskQueueDrained";
|
|
12
|
+
PoolEventType["taskStart"] = "taskStart";
|
|
13
|
+
PoolEventType["terminated"] = "terminated";
|
|
14
|
+
})(PoolEventType || (exports.PoolEventType = PoolEventType = {}));
|
package/dist/esm/master/pool.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Thread = exports.PoolEventType = exports.Pool = void 0;
|
|
7
7
|
const debug_1 = __importDefault(require("debug"));
|
|
8
8
|
const observable_fns_1 = require("observable-fns");
|
|
9
|
+
const ponyfills_1 = require("../ponyfills");
|
|
9
10
|
const implementation_1 = require("./implementation");
|
|
10
11
|
const pool_types_1 = require("./pool-types");
|
|
11
12
|
const thread_1 = require("./thread");
|
|
@@ -120,10 +121,7 @@ class WorkerPool {
|
|
|
120
121
|
this.eventSubject.next({ type: pool_types_1.PoolEventType.taskQueueDrained });
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
this.run(availableWorker, nextTask)
|
|
124
|
-
this.debug('Error while running task:', error);
|
|
125
|
-
this.eventSubject.error(error);
|
|
126
|
-
});
|
|
124
|
+
this.run(availableWorker, nextTask);
|
|
127
125
|
}
|
|
128
126
|
taskCompletion(taskID) {
|
|
129
127
|
return new Promise((resolve, reject) => {
|
|
@@ -155,7 +153,7 @@ class WorkerPool {
|
|
|
155
153
|
throw this.initErrors[0];
|
|
156
154
|
}
|
|
157
155
|
if (allowResolvingImmediately && this.taskQueue.length === 0) {
|
|
158
|
-
await
|
|
156
|
+
await (0, ponyfills_1.allSettled)(getCurrentlyRunningTasks());
|
|
159
157
|
return taskFailures;
|
|
160
158
|
}
|
|
161
159
|
await new Promise((resolve, reject) => {
|
|
@@ -169,7 +167,7 @@ class WorkerPool {
|
|
|
169
167
|
},
|
|
170
168
|
});
|
|
171
169
|
});
|
|
172
|
-
await
|
|
170
|
+
await (0, ponyfills_1.allSettled)(getCurrentlyRunningTasks());
|
|
173
171
|
failureSubscription.unsubscribe();
|
|
174
172
|
return taskFailures;
|
|
175
173
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allSettled = allSettled;
|
|
4
|
+
function allSettled(values) {
|
|
5
|
+
return Promise.all(values.map((item) => {
|
|
6
|
+
const onFulfill = (value) => {
|
|
7
|
+
return { status: 'fulfilled', value };
|
|
8
|
+
};
|
|
9
|
+
const onReject = (reason) => {
|
|
10
|
+
return { reason, status: 'rejected' };
|
|
11
|
+
};
|
|
12
|
+
const itemPromise = Promise.resolve(item);
|
|
13
|
+
try {
|
|
14
|
+
return itemPromise.then(onFulfill, onReject);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return Promise.reject(error);
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
}
|
package/dist/esm/types/master.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WorkerEventType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
internalError
|
|
7
|
-
message
|
|
8
|
-
termination
|
|
9
|
-
});
|
|
4
|
+
var WorkerEventType;
|
|
5
|
+
(function (WorkerEventType) {
|
|
6
|
+
WorkerEventType["internalError"] = "internalError";
|
|
7
|
+
WorkerEventType["message"] = "message";
|
|
8
|
+
WorkerEventType["termination"] = "termination";
|
|
9
|
+
})(WorkerEventType || (exports.WorkerEventType = WorkerEventType = {}));
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WorkerMessageType = exports.MasterMessageType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
cancel
|
|
7
|
-
run
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
var MasterMessageType;
|
|
5
|
+
(function (MasterMessageType) {
|
|
6
|
+
MasterMessageType["cancel"] = "cancel";
|
|
7
|
+
MasterMessageType["run"] = "run";
|
|
8
|
+
})(MasterMessageType || (exports.MasterMessageType = MasterMessageType = {}));
|
|
9
|
+
var WorkerMessageType;
|
|
10
|
+
(function (WorkerMessageType) {
|
|
11
|
+
WorkerMessageType["error"] = "error";
|
|
12
|
+
WorkerMessageType["init"] = "init";
|
|
13
|
+
WorkerMessageType["result"] = "result";
|
|
14
|
+
WorkerMessageType["running"] = "running";
|
|
15
|
+
WorkerMessageType["uncaughtError"] = "uncaughtError";
|
|
16
|
+
})(WorkerMessageType || (exports.WorkerMessageType = WorkerMessageType = {}));
|
|
@@ -1,45 +1,42 @@
|
|
|
1
|
-
import type { EnumValue } from '../enum';
|
|
2
|
-
import { Enum } from '../enum';
|
|
3
1
|
import type { Thread } from './thread';
|
|
4
|
-
export declare
|
|
5
|
-
initialized
|
|
6
|
-
taskCanceled
|
|
7
|
-
taskCompleted
|
|
8
|
-
taskFailed
|
|
9
|
-
taskQueued
|
|
10
|
-
taskQueueDrained
|
|
11
|
-
taskStart
|
|
12
|
-
terminated
|
|
13
|
-
}
|
|
14
|
-
export type PoolEventType = EnumValue<typeof PoolEventType>;
|
|
2
|
+
export declare enum PoolEventType {
|
|
3
|
+
initialized = "initialized",
|
|
4
|
+
taskCanceled = "taskCanceled",
|
|
5
|
+
taskCompleted = "taskCompleted",
|
|
6
|
+
taskFailed = "taskFailed",
|
|
7
|
+
taskQueued = "taskQueued",
|
|
8
|
+
taskQueueDrained = "taskQueueDrained",
|
|
9
|
+
taskStart = "taskStart",
|
|
10
|
+
terminated = "terminated"
|
|
11
|
+
}
|
|
15
12
|
export type TaskRunFunction<ThreadType extends Thread, Return> = (worker: ThreadType) => Promise<Return>;
|
|
16
13
|
export type PoolEvent<ThreadType extends Thread> = {
|
|
17
|
-
type:
|
|
14
|
+
type: PoolEventType.initialized;
|
|
18
15
|
size: number;
|
|
19
16
|
} | {
|
|
20
|
-
type:
|
|
17
|
+
type: PoolEventType.taskQueued;
|
|
21
18
|
taskID: number;
|
|
22
19
|
} | {
|
|
23
|
-
type:
|
|
20
|
+
type: PoolEventType.taskQueueDrained;
|
|
24
21
|
} | {
|
|
25
|
-
type:
|
|
22
|
+
type: PoolEventType.taskStart;
|
|
26
23
|
taskID: number;
|
|
27
24
|
workerID: number;
|
|
28
25
|
} | {
|
|
29
|
-
type:
|
|
26
|
+
type: PoolEventType.taskCompleted;
|
|
30
27
|
returnValue: any;
|
|
31
28
|
taskID: number;
|
|
32
29
|
workerID: number;
|
|
33
30
|
} | {
|
|
34
|
-
type:
|
|
31
|
+
type: PoolEventType.taskFailed;
|
|
35
32
|
error: Error;
|
|
36
33
|
taskID: number;
|
|
37
34
|
workerID: number;
|
|
38
35
|
} | {
|
|
39
|
-
type:
|
|
36
|
+
type: PoolEventType.taskCanceled;
|
|
40
37
|
taskID: number;
|
|
41
38
|
} | {
|
|
42
|
-
type:
|
|
39
|
+
type: PoolEventType.terminated;
|
|
43
40
|
remainingQueue: Array<QueuedTask<ThreadType, any>>;
|
|
44
41
|
};
|
|
45
42
|
export interface WorkerDescriptor<ThreadType extends Thread> {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PoolEventType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
initialized
|
|
7
|
-
taskCanceled
|
|
8
|
-
taskCompleted
|
|
9
|
-
taskFailed
|
|
10
|
-
taskQueued
|
|
11
|
-
taskQueueDrained
|
|
12
|
-
taskStart
|
|
13
|
-
terminated
|
|
14
|
-
});
|
|
4
|
+
var PoolEventType;
|
|
5
|
+
(function (PoolEventType) {
|
|
6
|
+
PoolEventType["initialized"] = "initialized";
|
|
7
|
+
PoolEventType["taskCanceled"] = "taskCanceled";
|
|
8
|
+
PoolEventType["taskCompleted"] = "taskCompleted";
|
|
9
|
+
PoolEventType["taskFailed"] = "taskFailed";
|
|
10
|
+
PoolEventType["taskQueued"] = "taskQueued";
|
|
11
|
+
PoolEventType["taskQueueDrained"] = "taskQueueDrained";
|
|
12
|
+
PoolEventType["taskStart"] = "taskStart";
|
|
13
|
+
PoolEventType["terminated"] = "terminated";
|
|
14
|
+
})(PoolEventType || (exports.PoolEventType = PoolEventType = {}));
|
package/dist/master/pool.d.ts
CHANGED
|
@@ -20,16 +20,7 @@ interface PoolOptions {
|
|
|
20
20
|
size?: number;
|
|
21
21
|
}
|
|
22
22
|
declare class WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {
|
|
23
|
-
static EventType:
|
|
24
|
-
initialized: "initialized";
|
|
25
|
-
taskCanceled: "taskCanceled";
|
|
26
|
-
taskCompleted: "taskCompleted";
|
|
27
|
-
taskFailed: "taskFailed";
|
|
28
|
-
taskQueued: "taskQueued";
|
|
29
|
-
taskQueueDrained: "taskQueueDrained";
|
|
30
|
-
taskStart: "taskStart";
|
|
31
|
-
terminated: "terminated";
|
|
32
|
-
}>;
|
|
23
|
+
static EventType: typeof PoolEventType;
|
|
33
24
|
private readonly debug;
|
|
34
25
|
private readonly eventObservable;
|
|
35
26
|
private readonly options;
|
package/dist/master/pool.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Thread = exports.PoolEventType = exports.Pool = void 0;
|
|
7
7
|
const debug_1 = __importDefault(require("debug"));
|
|
8
8
|
const observable_fns_1 = require("observable-fns");
|
|
9
|
+
const ponyfills_1 = require("../ponyfills");
|
|
9
10
|
const implementation_1 = require("./implementation");
|
|
10
11
|
const pool_types_1 = require("./pool-types");
|
|
11
12
|
const thread_1 = require("./thread");
|
|
@@ -120,10 +121,7 @@ class WorkerPool {
|
|
|
120
121
|
this.eventSubject.next({ type: pool_types_1.PoolEventType.taskQueueDrained });
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
this.run(availableWorker, nextTask)
|
|
124
|
-
this.debug('Error while running task:', error);
|
|
125
|
-
this.eventSubject.error(error);
|
|
126
|
-
});
|
|
124
|
+
this.run(availableWorker, nextTask);
|
|
127
125
|
}
|
|
128
126
|
taskCompletion(taskID) {
|
|
129
127
|
return new Promise((resolve, reject) => {
|
|
@@ -155,7 +153,7 @@ class WorkerPool {
|
|
|
155
153
|
throw this.initErrors[0];
|
|
156
154
|
}
|
|
157
155
|
if (allowResolvingImmediately && this.taskQueue.length === 0) {
|
|
158
|
-
await
|
|
156
|
+
await (0, ponyfills_1.allSettled)(getCurrentlyRunningTasks());
|
|
159
157
|
return taskFailures;
|
|
160
158
|
}
|
|
161
159
|
await new Promise((resolve, reject) => {
|
|
@@ -169,7 +167,7 @@ class WorkerPool {
|
|
|
169
167
|
},
|
|
170
168
|
});
|
|
171
169
|
});
|
|
172
|
-
await
|
|
170
|
+
await (0, ponyfills_1.allSettled)(getCurrentlyRunningTasks());
|
|
173
171
|
failureSubscription.unsubscribe();
|
|
174
172
|
return taskFailures;
|
|
175
173
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allSettled = allSettled;
|
|
4
|
+
function allSettled(values) {
|
|
5
|
+
return Promise.all(values.map((item) => {
|
|
6
|
+
const onFulfill = (value) => {
|
|
7
|
+
return { status: 'fulfilled', value };
|
|
8
|
+
};
|
|
9
|
+
const onReject = (reason) => {
|
|
10
|
+
return { reason, status: 'rejected' };
|
|
11
|
+
};
|
|
12
|
+
const itemPromise = Promise.resolve(item);
|
|
13
|
+
try {
|
|
14
|
+
return itemPromise.then(onFulfill, onReject);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return Promise.reject(error);
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
}
|
package/dist/types/master.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { Observable } from 'observable-fns';
|
|
2
|
-
import type { EnumValue } from '../enum';
|
|
3
|
-
import { Enum } from '../enum';
|
|
4
2
|
import type { ObservablePromise } from '../observable-promise';
|
|
5
3
|
import type { $errors, $events, $terminate, $worker } from '../symbols';
|
|
6
4
|
import type { TransferDescriptor } from '../transferable';
|
|
@@ -39,8 +37,9 @@ interface AnyFunctionThread extends PrivateThreadProps {
|
|
|
39
37
|
interface AnyModuleThread extends PrivateThreadProps {
|
|
40
38
|
}
|
|
41
39
|
export type Thread = AnyFunctionThread | AnyModuleThread;
|
|
40
|
+
export type TransferList = Transferable[];
|
|
42
41
|
export interface Worker extends EventTarget {
|
|
43
|
-
postMessage(value: any, transferList?:
|
|
42
|
+
postMessage(value: any, transferList?: TransferList): void;
|
|
44
43
|
terminate(callback?: (error?: Error, exitCode?: number) => void): void | Promise<number>;
|
|
45
44
|
}
|
|
46
45
|
export interface ThreadsWorkerOptions extends WorkerOptions {
|
|
@@ -55,7 +54,7 @@ export interface ThreadsWorkerOptions extends WorkerOptions {
|
|
|
55
54
|
}
|
|
56
55
|
export declare class WorkerImplementation extends EventTarget implements Worker {
|
|
57
56
|
constructor(path: string, options?: ThreadsWorkerOptions);
|
|
58
|
-
postMessage(value: any, transferList?:
|
|
57
|
+
postMessage(value: any, transferList?: TransferList): void;
|
|
59
58
|
terminate(): void | Promise<number>;
|
|
60
59
|
}
|
|
61
60
|
export declare class BlobWorker extends WorkerImplementation {
|
|
@@ -66,22 +65,21 @@ export interface ImplementationExport {
|
|
|
66
65
|
blob: typeof BlobWorker;
|
|
67
66
|
default: typeof WorkerImplementation;
|
|
68
67
|
}
|
|
69
|
-
export declare
|
|
70
|
-
internalError
|
|
71
|
-
message
|
|
72
|
-
termination
|
|
73
|
-
}
|
|
74
|
-
export type WorkerEventType = EnumValue<typeof WorkerEventType>;
|
|
68
|
+
export declare enum WorkerEventType {
|
|
69
|
+
internalError = "internalError",
|
|
70
|
+
message = "message",
|
|
71
|
+
termination = "termination"
|
|
72
|
+
}
|
|
75
73
|
export interface WorkerInternalErrorEvent {
|
|
76
74
|
error: Error;
|
|
77
|
-
type:
|
|
75
|
+
type: WorkerEventType.internalError;
|
|
78
76
|
}
|
|
79
77
|
export interface WorkerMessageEvent<Data> {
|
|
80
78
|
data: Data;
|
|
81
|
-
type:
|
|
79
|
+
type: WorkerEventType.message;
|
|
82
80
|
}
|
|
83
81
|
export interface WorkerTerminationEvent {
|
|
84
|
-
type:
|
|
82
|
+
type: WorkerEventType.termination;
|
|
85
83
|
}
|
|
86
84
|
export type WorkerEvent = WorkerInternalErrorEvent | WorkerMessageEvent<any> | WorkerTerminationEvent;
|
|
87
85
|
export {};
|
package/dist/types/master.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WorkerEventType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
internalError
|
|
7
|
-
message
|
|
8
|
-
termination
|
|
9
|
-
});
|
|
4
|
+
var WorkerEventType;
|
|
5
|
+
(function (WorkerEventType) {
|
|
6
|
+
WorkerEventType["internalError"] = "internalError";
|
|
7
|
+
WorkerEventType["message"] = "message";
|
|
8
|
+
WorkerEventType["termination"] = "termination";
|
|
9
|
+
})(WorkerEventType || (exports.WorkerEventType = WorkerEventType = {}));
|
package/dist/types/messages.d.ts
CHANGED
|
@@ -1,36 +1,32 @@
|
|
|
1
|
-
import type { EnumValue } from '../enum';
|
|
2
|
-
import { Enum } from '../enum';
|
|
3
1
|
export interface SerializedError {
|
|
4
2
|
__error_marker: '$$error';
|
|
5
3
|
message: string;
|
|
6
4
|
name: string;
|
|
7
5
|
stack?: string;
|
|
8
6
|
}
|
|
9
|
-
export declare
|
|
10
|
-
cancel
|
|
11
|
-
run
|
|
12
|
-
}
|
|
13
|
-
export type MasterMessageType = EnumValue<typeof MasterMessageType>;
|
|
7
|
+
export declare enum MasterMessageType {
|
|
8
|
+
cancel = "cancel",
|
|
9
|
+
run = "run"
|
|
10
|
+
}
|
|
14
11
|
export type MasterJobCancelMessage = {
|
|
15
|
-
type:
|
|
12
|
+
type: MasterMessageType.cancel;
|
|
16
13
|
uid: number;
|
|
17
14
|
};
|
|
18
15
|
export type MasterJobRunMessage = {
|
|
19
|
-
type:
|
|
16
|
+
type: MasterMessageType.run;
|
|
20
17
|
uid: number;
|
|
21
18
|
method?: string;
|
|
22
19
|
args: any[];
|
|
23
20
|
};
|
|
24
|
-
export declare
|
|
25
|
-
error
|
|
26
|
-
init
|
|
27
|
-
result
|
|
28
|
-
running
|
|
29
|
-
uncaughtError
|
|
30
|
-
}
|
|
31
|
-
export type WorkerMessageType = EnumValue<typeof WorkerMessageType>;
|
|
21
|
+
export declare enum WorkerMessageType {
|
|
22
|
+
error = "error",
|
|
23
|
+
init = "init",
|
|
24
|
+
result = "result",
|
|
25
|
+
running = "running",
|
|
26
|
+
uncaughtError = "uncaughtError"
|
|
27
|
+
}
|
|
32
28
|
export type WorkerUncaughtErrorMessage = {
|
|
33
|
-
type:
|
|
29
|
+
type: WorkerMessageType.uncaughtError;
|
|
34
30
|
error: {
|
|
35
31
|
message: string;
|
|
36
32
|
name: string;
|
|
@@ -38,7 +34,7 @@ export type WorkerUncaughtErrorMessage = {
|
|
|
38
34
|
};
|
|
39
35
|
};
|
|
40
36
|
export type WorkerInitMessage = {
|
|
41
|
-
type:
|
|
37
|
+
type: WorkerMessageType.init;
|
|
42
38
|
exposed: {
|
|
43
39
|
type: 'function';
|
|
44
40
|
} | {
|
|
@@ -47,18 +43,18 @@ export type WorkerInitMessage = {
|
|
|
47
43
|
};
|
|
48
44
|
};
|
|
49
45
|
export type WorkerJobErrorMessage = {
|
|
50
|
-
type:
|
|
46
|
+
type: WorkerMessageType.error;
|
|
51
47
|
uid: number;
|
|
52
48
|
error: SerializedError;
|
|
53
49
|
};
|
|
54
50
|
export type WorkerJobResultMessage = {
|
|
55
|
-
type:
|
|
51
|
+
type: WorkerMessageType.result;
|
|
56
52
|
uid: number;
|
|
57
53
|
complete?: true;
|
|
58
54
|
payload?: any;
|
|
59
55
|
};
|
|
60
56
|
export type WorkerJobStartMessage = {
|
|
61
|
-
type:
|
|
57
|
+
type: WorkerMessageType.running;
|
|
62
58
|
uid: number;
|
|
63
59
|
resultType: 'observable' | 'promise';
|
|
64
60
|
};
|
package/dist/types/messages.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WorkerMessageType = exports.MasterMessageType = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
cancel
|
|
7
|
-
run
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
var MasterMessageType;
|
|
5
|
+
(function (MasterMessageType) {
|
|
6
|
+
MasterMessageType["cancel"] = "cancel";
|
|
7
|
+
MasterMessageType["run"] = "run";
|
|
8
|
+
})(MasterMessageType || (exports.MasterMessageType = MasterMessageType = {}));
|
|
9
|
+
var WorkerMessageType;
|
|
10
|
+
(function (WorkerMessageType) {
|
|
11
|
+
WorkerMessageType["error"] = "error";
|
|
12
|
+
WorkerMessageType["init"] = "init";
|
|
13
|
+
WorkerMessageType["result"] = "result";
|
|
14
|
+
WorkerMessageType["running"] = "running";
|
|
15
|
+
WorkerMessageType["uncaughtError"] = "uncaughtError";
|
|
16
|
+
})(WorkerMessageType || (exports.WorkerMessageType = WorkerMessageType = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xylabs/threads",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.1",
|
|
4
4
|
"description": "Web workers & worker threads as simple as a function call",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"@rollup/plugin-commonjs": "^28.0.2",
|
|
96
96
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
97
97
|
"@types/debug": "^4.1.12",
|
|
98
|
-
"@types/node": "^22.10.
|
|
98
|
+
"@types/node": "^22.10.10",
|
|
99
99
|
"@xylabs/ts-scripts-yarn3": "^4.2.6",
|
|
100
100
|
"cross-env": "^7.0.3",
|
|
101
101
|
"puppet-run": "^0.11.4",
|
|
@@ -104,8 +104,9 @@
|
|
|
104
104
|
"rollup": "^4.31.0",
|
|
105
105
|
"threads-plugin": "^1.4.0",
|
|
106
106
|
"tiny-worker": "^2.3.0",
|
|
107
|
+
"tslib": "^2.8.1",
|
|
107
108
|
"typescript": "^5.7.3",
|
|
108
|
-
"vitest": "^3.0.
|
|
109
|
+
"vitest": "^3.0.4",
|
|
109
110
|
"webpack": "^5.97.1"
|
|
110
111
|
},
|
|
111
112
|
"optionalDependencies": {
|
package/src/master/pool-types.ts
CHANGED
|
@@ -1,61 +1,57 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/member-ordering */
|
|
3
|
-
import type { EnumValue } from '../enum'
|
|
4
|
-
import { Enum } from '../enum'
|
|
5
3
|
import type { Thread } from './thread'
|
|
6
4
|
|
|
7
5
|
/** Pool event type. Specifies the type of each `PoolEvent`. */
|
|
8
|
-
export
|
|
9
|
-
initialized
|
|
10
|
-
taskCanceled
|
|
11
|
-
taskCompleted
|
|
12
|
-
taskFailed
|
|
13
|
-
taskQueued
|
|
14
|
-
taskQueueDrained
|
|
15
|
-
taskStart
|
|
16
|
-
terminated
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type PoolEventType = EnumValue<typeof PoolEventType>
|
|
6
|
+
export enum PoolEventType {
|
|
7
|
+
initialized = 'initialized',
|
|
8
|
+
taskCanceled = 'taskCanceled',
|
|
9
|
+
taskCompleted = 'taskCompleted',
|
|
10
|
+
taskFailed = 'taskFailed',
|
|
11
|
+
taskQueued = 'taskQueued',
|
|
12
|
+
taskQueueDrained = 'taskQueueDrained',
|
|
13
|
+
taskStart = 'taskStart',
|
|
14
|
+
terminated = 'terminated',
|
|
15
|
+
}
|
|
20
16
|
|
|
21
17
|
export type TaskRunFunction<ThreadType extends Thread, Return> = (worker: ThreadType) => Promise<Return>
|
|
22
18
|
|
|
23
19
|
/** Pool event. Subscribe to those events using `pool.events()`. Useful for debugging. */
|
|
24
20
|
export type PoolEvent<ThreadType extends Thread> =
|
|
25
21
|
| {
|
|
26
|
-
type:
|
|
22
|
+
type: PoolEventType.initialized
|
|
27
23
|
size: number
|
|
28
24
|
}
|
|
29
25
|
| {
|
|
30
|
-
type:
|
|
26
|
+
type: PoolEventType.taskQueued
|
|
31
27
|
taskID: number
|
|
32
28
|
}
|
|
33
29
|
| {
|
|
34
|
-
type:
|
|
30
|
+
type: PoolEventType.taskQueueDrained
|
|
35
31
|
}
|
|
36
32
|
| {
|
|
37
|
-
type:
|
|
33
|
+
type: PoolEventType.taskStart
|
|
38
34
|
taskID: number
|
|
39
35
|
workerID: number
|
|
40
36
|
}
|
|
41
37
|
| {
|
|
42
|
-
type:
|
|
38
|
+
type: PoolEventType.taskCompleted
|
|
43
39
|
returnValue: any
|
|
44
40
|
taskID: number
|
|
45
41
|
workerID: number
|
|
46
42
|
}
|
|
47
43
|
| {
|
|
48
|
-
type:
|
|
44
|
+
type: PoolEventType.taskFailed
|
|
49
45
|
error: Error
|
|
50
46
|
taskID: number
|
|
51
47
|
workerID: number
|
|
52
48
|
}
|
|
53
49
|
| {
|
|
54
|
-
type:
|
|
50
|
+
type: PoolEventType.taskCanceled
|
|
55
51
|
taskID: number
|
|
56
52
|
}
|
|
57
53
|
| {
|
|
58
|
-
type:
|
|
54
|
+
type: PoolEventType.terminated
|
|
59
55
|
remainingQueue: Array<QueuedTask<ThreadType, any>>
|
|
60
56
|
}
|
|
61
57
|
|
package/src/master/pool.ts
CHANGED
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
/* eslint-disable unicorn/no-array-reduce */
|
|
7
7
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
8
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
9
|
-
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
10
10
|
import DebugLogger from 'debug'
|
|
11
11
|
import {
|
|
12
12
|
multicast, Observable, Subject,
|
|
13
13
|
} from 'observable-fns'
|
|
14
14
|
|
|
15
|
+
import { allSettled } from '../ponyfills'
|
|
15
16
|
import { defaultPoolSize } from './implementation'
|
|
16
17
|
import type {
|
|
17
18
|
PoolEvent, QueuedTask, TaskRunFunction, WorkerDescriptor,
|
|
@@ -223,10 +224,7 @@ class WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {
|
|
|
223
224
|
return
|
|
224
225
|
}
|
|
225
226
|
|
|
226
|
-
this.run(availableWorker, nextTask)
|
|
227
|
-
this.debug('Error while running task:', error)
|
|
228
|
-
this.eventSubject.error(error)
|
|
229
|
-
})
|
|
227
|
+
this.run(availableWorker, nextTask)
|
|
230
228
|
}
|
|
231
229
|
|
|
232
230
|
private taskCompletion(taskID: number) {
|
|
@@ -261,7 +259,7 @@ class WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {
|
|
|
261
259
|
throw this.initErrors[0]
|
|
262
260
|
}
|
|
263
261
|
if (allowResolvingImmediately && this.taskQueue.length === 0) {
|
|
264
|
-
await
|
|
262
|
+
await allSettled(getCurrentlyRunningTasks())
|
|
265
263
|
return taskFailures
|
|
266
264
|
}
|
|
267
265
|
|
|
@@ -277,7 +275,7 @@ class WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {
|
|
|
277
275
|
})
|
|
278
276
|
})
|
|
279
277
|
|
|
280
|
-
await
|
|
278
|
+
await allSettled(getCurrentlyRunningTasks())
|
|
281
279
|
failureSubscription.unsubscribe()
|
|
282
280
|
|
|
283
281
|
return taskFailures
|
package/src/ponyfills.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
export type SettlementResult<T> =
|
|
3
|
+
| {
|
|
4
|
+
status: 'fulfilled'
|
|
5
|
+
value: T
|
|
6
|
+
}
|
|
7
|
+
| {
|
|
8
|
+
reason: any
|
|
9
|
+
status: 'rejected'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Based on <https://github.com/es-shims/Promise.allSettled/blob/master/implementation.js>
|
|
13
|
+
export function allSettled<T>(values: T[]): Promise<Array<SettlementResult<T>>> {
|
|
14
|
+
return Promise.all(
|
|
15
|
+
values.map((item) => {
|
|
16
|
+
const onFulfill = (value: T) => {
|
|
17
|
+
return { status: 'fulfilled', value } as const
|
|
18
|
+
}
|
|
19
|
+
const onReject = (reason: any) => {
|
|
20
|
+
return { reason, status: 'rejected' } as const
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const itemPromise = Promise.resolve(item)
|
|
24
|
+
try {
|
|
25
|
+
return itemPromise.then(onFulfill, onReject)
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return Promise.reject(error)
|
|
28
|
+
}
|
|
29
|
+
}),
|
|
30
|
+
)
|
|
31
|
+
}
|
package/src/types/master.ts
CHANGED
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
// See <https://github.com/microsoft/TypeScript/issues/28009>
|
|
7
7
|
import type { Observable } from 'observable-fns'
|
|
8
8
|
|
|
9
|
-
import type { EnumValue } from '../enum'
|
|
10
|
-
import { Enum } from '../enum'
|
|
11
9
|
import type { ObservablePromise } from '../observable-promise'
|
|
12
10
|
import type {
|
|
13
11
|
$errors, $events, $terminate, $worker,
|
|
@@ -66,9 +64,11 @@ interface AnyModuleThread extends PrivateThreadProps {
|
|
|
66
64
|
/** Worker thread. Either a `FunctionThread` or a `ModuleThread`. */
|
|
67
65
|
export type Thread = AnyFunctionThread | AnyModuleThread
|
|
68
66
|
|
|
67
|
+
export type TransferList = Transferable[]
|
|
68
|
+
|
|
69
69
|
/** Worker instance. Either a web worker or a node.js Worker provided by `worker_threads` or `tiny-worker`. */
|
|
70
70
|
export interface Worker extends EventTarget {
|
|
71
|
-
postMessage(value: any, transferList?:
|
|
71
|
+
postMessage(value: any, transferList?: TransferList): void
|
|
72
72
|
/** In nodejs 10+ return type is Promise while with tiny-worker and in browser return type is void */
|
|
73
73
|
terminate(callback?: (error?: Error, exitCode?: number) => void): void | Promise<number>
|
|
74
74
|
}
|
|
@@ -93,7 +93,7 @@ export interface ThreadsWorkerOptions extends WorkerOptions {
|
|
|
93
93
|
/** Worker implementation. Either web worker or a node.js Worker class. */
|
|
94
94
|
export declare class WorkerImplementation extends EventTarget implements Worker {
|
|
95
95
|
constructor(path: string, options?: ThreadsWorkerOptions)
|
|
96
|
-
postMessage(value: any, transferList?:
|
|
96
|
+
postMessage(value: any, transferList?: TransferList): void
|
|
97
97
|
terminate(): void | Promise<number>
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -109,26 +109,24 @@ export interface ImplementationExport {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/** Event as emitted by worker thread. Subscribe to using `Thread.events(thread)`. */
|
|
112
|
-
export
|
|
113
|
-
internalError
|
|
114
|
-
message
|
|
115
|
-
termination
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export type WorkerEventType = EnumValue<typeof WorkerEventType>
|
|
112
|
+
export enum WorkerEventType {
|
|
113
|
+
internalError = 'internalError',
|
|
114
|
+
message = 'message',
|
|
115
|
+
termination = 'termination',
|
|
116
|
+
}
|
|
119
117
|
|
|
120
118
|
export interface WorkerInternalErrorEvent {
|
|
121
119
|
error: Error
|
|
122
|
-
type:
|
|
120
|
+
type: WorkerEventType.internalError
|
|
123
121
|
}
|
|
124
122
|
|
|
125
123
|
export interface WorkerMessageEvent<Data> {
|
|
126
124
|
data: Data
|
|
127
|
-
type:
|
|
125
|
+
type: WorkerEventType.message
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
export interface WorkerTerminationEvent {
|
|
131
|
-
type:
|
|
129
|
+
type: WorkerEventType.termination
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
export type WorkerEvent = WorkerInternalErrorEvent | WorkerMessageEvent<any> | WorkerTerminationEvent
|
package/src/types/messages.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
|
|
3
|
-
import type { EnumValue } from '../enum'
|
|
4
|
-
import { Enum } from '../enum'
|
|
5
|
-
|
|
6
2
|
/* eslint-disable @typescript-eslint/member-ordering */
|
|
7
3
|
export interface SerializedError {
|
|
8
4
|
__error_marker: '$$error'
|
|
@@ -14,20 +10,18 @@ export interface SerializedError {
|
|
|
14
10
|
/////////////////////////////
|
|
15
11
|
// Messages sent by master:
|
|
16
12
|
|
|
17
|
-
export
|
|
18
|
-
cancel
|
|
19
|
-
run
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type MasterMessageType = EnumValue<typeof MasterMessageType>
|
|
13
|
+
export enum MasterMessageType {
|
|
14
|
+
cancel = 'cancel',
|
|
15
|
+
run = 'run',
|
|
16
|
+
}
|
|
23
17
|
|
|
24
18
|
export type MasterJobCancelMessage = {
|
|
25
|
-
type:
|
|
19
|
+
type: MasterMessageType.cancel
|
|
26
20
|
uid: number
|
|
27
21
|
}
|
|
28
22
|
|
|
29
23
|
export type MasterJobRunMessage = {
|
|
30
|
-
type:
|
|
24
|
+
type: MasterMessageType.run
|
|
31
25
|
uid: number
|
|
32
26
|
method?: string
|
|
33
27
|
args: any[]
|
|
@@ -36,18 +30,16 @@ export type MasterJobRunMessage = {
|
|
|
36
30
|
////////////////////////////
|
|
37
31
|
// Messages sent by worker:
|
|
38
32
|
|
|
39
|
-
export
|
|
40
|
-
error
|
|
41
|
-
init
|
|
42
|
-
result
|
|
43
|
-
running
|
|
44
|
-
uncaughtError
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type WorkerMessageType = EnumValue<typeof WorkerMessageType>
|
|
33
|
+
export enum WorkerMessageType {
|
|
34
|
+
error = 'error',
|
|
35
|
+
init = 'init',
|
|
36
|
+
result = 'result',
|
|
37
|
+
running = 'running',
|
|
38
|
+
uncaughtError = 'uncaughtError',
|
|
39
|
+
}
|
|
48
40
|
|
|
49
41
|
export type WorkerUncaughtErrorMessage = {
|
|
50
|
-
type:
|
|
42
|
+
type: WorkerMessageType.uncaughtError
|
|
51
43
|
error: {
|
|
52
44
|
message: string
|
|
53
45
|
name: string
|
|
@@ -56,25 +48,25 @@ export type WorkerUncaughtErrorMessage = {
|
|
|
56
48
|
}
|
|
57
49
|
|
|
58
50
|
export type WorkerInitMessage = {
|
|
59
|
-
type:
|
|
51
|
+
type: WorkerMessageType.init
|
|
60
52
|
exposed: { type: 'function' } | { type: 'module'; methods: string[] }
|
|
61
53
|
}
|
|
62
54
|
|
|
63
55
|
export type WorkerJobErrorMessage = {
|
|
64
|
-
type:
|
|
56
|
+
type: WorkerMessageType.error
|
|
65
57
|
uid: number
|
|
66
58
|
error: SerializedError
|
|
67
59
|
}
|
|
68
60
|
|
|
69
61
|
export type WorkerJobResultMessage = {
|
|
70
|
-
type:
|
|
62
|
+
type: WorkerMessageType.result
|
|
71
63
|
uid: number
|
|
72
64
|
complete?: true
|
|
73
65
|
payload?: any
|
|
74
66
|
}
|
|
75
67
|
|
|
76
68
|
export type WorkerJobStartMessage = {
|
|
77
|
-
type:
|
|
69
|
+
type: WorkerMessageType.running
|
|
78
70
|
uid: number
|
|
79
71
|
resultType: 'observable' | 'promise'
|
|
80
72
|
}
|
package/dist/enum.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare const Enum: <const T extends Record<string | number | symbol, unknown>>(obj: Readonly<T>) => Enum<T>;
|
|
2
|
-
export type Enum<T extends Readonly<Record<string | number | symbol, unknown>>> = {
|
|
3
|
-
readonly [K in keyof T]: T[K];
|
|
4
|
-
};
|
|
5
|
-
export type EnumValue<T extends Record<string | number | symbol, unknown>, K = Enum<T>> = K[keyof K];
|
package/dist/enum.js
DELETED
package/dist/esm/enum.js
DELETED
package/src/enum.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transforms a given record object into a readonly "enum-like" structure while preserving
|
|
3
|
-
* the literal types of its values. This allows you to use the returned object both at runtime
|
|
4
|
-
* (for lookups) and at compile time (for strongly typed values).
|
|
5
|
-
*
|
|
6
|
-
* To maintain literal types (i.e., prevent them from being widened to `string`, `number`, etc.),
|
|
7
|
-
* ensure you annotate your object with `as const` before passing it to `Enum`.
|
|
8
|
-
*
|
|
9
|
-
* @template T - A record type with string keys and any kind of values.
|
|
10
|
-
* @param obj - A readonly record object annotated with `as const`.
|
|
11
|
-
* @returns A readonly version of the provided record, preserving exact literal value types.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* // Defining a record with literal types using as const:
|
|
16
|
-
* const DnsRecordType = Enum({
|
|
17
|
-
* A: 1,
|
|
18
|
-
* AAAA: 28,
|
|
19
|
-
* CAA: 257,
|
|
20
|
-
* CNAME: 5,
|
|
21
|
-
* DNAME: 39,
|
|
22
|
-
* MX: 15,
|
|
23
|
-
* NS: 2,
|
|
24
|
-
* PTR: 12,
|
|
25
|
-
* SOA: 6,
|
|
26
|
-
* SPF: 99,
|
|
27
|
-
* SRV: 33,
|
|
28
|
-
* TXT: 16,
|
|
29
|
-
* } as const);
|
|
30
|
-
*
|
|
31
|
-
* // DnsRecordType is now a readonly object:
|
|
32
|
-
* // {
|
|
33
|
-
* // readonly A: 1;
|
|
34
|
-
* // readonly AAAA: 28;
|
|
35
|
-
* // readonly CAA: 257;
|
|
36
|
-
* // readonly CNAME: 5;
|
|
37
|
-
* // readonly DNAME: 39;
|
|
38
|
-
* // readonly MX: 15;
|
|
39
|
-
* // readonly NS: 2;
|
|
40
|
-
* // readonly PTR: 12;
|
|
41
|
-
* // readonly SOA: 6;
|
|
42
|
-
* // readonly SPF: 99;
|
|
43
|
-
* // readonly SRV: 33;
|
|
44
|
-
* // readonly TXT: 16;
|
|
45
|
-
* // }
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export const Enum = <const T extends Record<string | number | symbol, unknown>>(obj: Readonly<T>): Enum<T> => {
|
|
49
|
-
return obj
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* A utility type that, given a `Record<string, unknown>`, returns a readonly version
|
|
54
|
-
* of that record. This results in a type where all properties of `T` are readonly.
|
|
55
|
-
*
|
|
56
|
-
* @template T - The record type to make readonly.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* // Given a record:
|
|
61
|
-
* export const DnsRecordType = Enum({
|
|
62
|
-
* A: 1,
|
|
63
|
-
* AAAA: 28,
|
|
64
|
-
* CAA: 257,
|
|
65
|
-
* CNAME: 5,
|
|
66
|
-
* DNAME: 39,
|
|
67
|
-
* MX: 15,
|
|
68
|
-
* NS: 2,
|
|
69
|
-
* PTR: 12,
|
|
70
|
-
* SOA: 6,
|
|
71
|
-
* SPF: 99,
|
|
72
|
-
* SRV: 33,
|
|
73
|
-
* TXT: 16,
|
|
74
|
-
* })
|
|
75
|
-
*
|
|
76
|
-
* // Now the type inference will preserve the literal types:
|
|
77
|
-
* export type DnsRecordType = Enum<typeof DnsRecordType>
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
export type Enum<T extends Readonly<Record<string | number | symbol, unknown>>> = {
|
|
81
|
-
readonly [K in keyof T]: T[K]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* A utility type that, given an `Enum` object, returns the union of its values.
|
|
86
|
-
*/
|
|
87
|
-
export type EnumValue<T extends Record<string | number | symbol, unknown>, K = Enum<T>> = K[keyof K]
|