@idlebox/common 1.3.15 → 1.3.16
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 → lib}/common-alpha.d.ts +10 -0
- package/{dist → lib}/common-beta.d.ts +10 -0
- package/{dist → lib}/common-public.d.ts +10 -0
- package/{dist → lib}/common.d.ts +10 -0
- package/lib/function/callbackList.cjs +4 -0
- package/lib/function/callbackList.cjs.map +1 -1
- package/lib/function/callbackList.js +4 -0
- package/lib/function/callbackList.js.map +1 -1
- package/lib/string/concatType.generated.cjs +8 -0
- package/lib/string/concatType.generated.cjs.map +1 -1
- package/lib/string/concatType.generated.js +8 -0
- package/lib/string/concatType.generated.js.map +1 -1
- package/{dist → lib}/tsdoc-metadata.json +1 -1
- package/package.json +12 -12
- package/src/array/arrayDiff.ts +31 -0
- package/src/array/arraySame.ts +15 -0
- package/src/array/arrayUnique.ts +50 -0
- package/src/array/normalizeArray.ts +13 -0
- package/src/array/sortAlpha.ts +15 -0
- package/src/date/consts.ts +5 -0
- package/src/date/isInvalid.ts +6 -0
- package/src/date/sibling.ts +28 -0
- package/src/date/timeString.ts +150 -0
- package/src/date/unix.ts +13 -0
- package/src/debugging/serializable.ts +146 -0
- package/src/debugging/tryInspect.ts +37 -0
- package/src/error/convertUnknown.ts +10 -0
- package/src/error/getFrame.ts +13 -0
- package/src/function/asyncCallbackList.ts +75 -0
- package/src/function/callbackList.ts +88 -0
- package/src/function/delayCallbackList.ts +45 -0
- package/src/function/functionName.ts +39 -0
- package/src/index.generated.ts +289 -0
- package/src/lifecycle/dispose/bridges/rxjs.ts +6 -0
- package/src/lifecycle/dispose/disposableEvent.ts +117 -0
- package/src/lifecycle/dispose/disposedError.ts +16 -0
- package/src/lifecycle/dispose/lifecycle.async.ts +61 -0
- package/src/lifecycle/dispose/lifecycle.global.ts +61 -0
- package/src/lifecycle/dispose/lifecycle.sync.ts +79 -0
- package/src/lifecycle/dispose/lifecycle.ts +28 -0
- package/src/lifecycle/event/event.ts +81 -0
- package/src/lifecycle/event/memorized.ts +39 -0
- package/src/lifecycle/promise/cancel.ts +16 -0
- package/src/lifecycle/promise/cancellationToken/driver.browser.ts +55 -0
- package/src/lifecycle/promise/cancellationToken/driver.common.ts +43 -0
- package/src/lifecycle/promise/cancellationToken/source.ts +48 -0
- package/src/lifecycle/promise/deferredPromise.ts +104 -0
- package/src/lifecycle/timeout/timeout.ts +48 -0
- package/src/lifecycle/timeout/timeoutError.ts +16 -0
- package/src/log/logger.ts +148 -0
- package/src/mapSet/customSet.ts +91 -0
- package/src/mapSet/extendMap.ts +40 -0
- package/src/misc/assertNotNull.ts +21 -0
- package/src/object/definePublicConstant.ts +10 -0
- package/src/object/initOnRead.ts +27 -0
- package/src/object/objectPath.ts +10 -0
- package/src/object/objectSame.ts +52 -0
- package/src/path/isAbsolute.ts +11 -0
- package/src/path/normalizePath.ts +8 -0
- package/src/path/pathArray.ts +42 -0
- package/src/platform/globalObject.ts +22 -0
- package/src/platform/globalSingleton.ts +82 -0
- package/src/platform/globalSymbol.ts +36 -0
- package/src/platform/os.ts +46 -0
- package/src/promise/awaitIterator.ts +19 -0
- package/src/promise/finishAllPromise.ts +50 -0
- package/src/promise/promiseBool.ts +10 -0
- package/src/promise/promisePool.ts +40 -0
- package/src/promise/timeoutPromisePool.ts +22 -0
- package/src/reflection/classes/hookClass.ts +47 -0
- package/src/reflection/classes/singleton.ts +33 -0
- package/src/reflection/methods/bind.ts +30 -0
- package/src/reflection/methods/initOnRead.ts +11 -0
- package/src/reflection/methods/memorize.ts +33 -0
- package/src/string/castCase.ts +44 -0
- package/src/string/concatType.generated.ts +265 -0
- package/src/string/concatType.generator.ts +31 -0
- package/src/string/escapeRegexp.ts +4 -0
- package/src/string/pad2.ts +11 -0
- package/src/string/sizeString.ts +52 -0
- package/src/tsconfig.json +14 -0
- package/src/typingHelper/deep.partial.ts +16 -0
- package/src/typingHelper/deep.readonly.ts +16 -0
- package/src/typingHelper/deep.required.ts +16 -0
- package/src/typingHelper/deep.writable.ts +16 -0
- package/src/typingHelper/literal.ts +1 -0
- package/docs/common.api.json +0 -21737
- package/docs/common.api.md +0 -1139
- package/docs/package-public.d.ts +0 -952
- package/docs/tsdoc-metadata.json +0 -11
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
declare const window: any;
|
|
2
|
+
declare const EventTarget: any;
|
|
3
|
+
declare const Element: any;
|
|
4
|
+
|
|
5
|
+
type ScalarTypes =
|
|
6
|
+
| bigint
|
|
7
|
+
| number
|
|
8
|
+
| Number
|
|
9
|
+
| boolean
|
|
10
|
+
| Boolean
|
|
11
|
+
| string
|
|
12
|
+
| String
|
|
13
|
+
| symbol
|
|
14
|
+
| undefined
|
|
15
|
+
| null
|
|
16
|
+
| Date
|
|
17
|
+
| RegExp
|
|
18
|
+
| Function;
|
|
19
|
+
|
|
20
|
+
export function isScalar(value: any): value is ScalarTypes {
|
|
21
|
+
switch (typeof value) {
|
|
22
|
+
case 'bigint':
|
|
23
|
+
case 'number':
|
|
24
|
+
case 'boolean':
|
|
25
|
+
case 'string':
|
|
26
|
+
case 'symbol':
|
|
27
|
+
case 'undefined':
|
|
28
|
+
case 'function':
|
|
29
|
+
return true;
|
|
30
|
+
case 'object':
|
|
31
|
+
return (
|
|
32
|
+
value === null ||
|
|
33
|
+
value instanceof Date ||
|
|
34
|
+
value instanceof Boolean ||
|
|
35
|
+
value instanceof String ||
|
|
36
|
+
value instanceof Number ||
|
|
37
|
+
value instanceof RegExp
|
|
38
|
+
);
|
|
39
|
+
default:
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export enum SerializableKind {
|
|
45
|
+
Invalid = 0,
|
|
46
|
+
Primitive,
|
|
47
|
+
Manual,
|
|
48
|
+
Other,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isSerializable(value: any): SerializableKind {
|
|
52
|
+
const t = typeof value;
|
|
53
|
+
switch (t) {
|
|
54
|
+
case 'bigint':
|
|
55
|
+
// @ts-expect-error
|
|
56
|
+
case 'number':
|
|
57
|
+
if (isNaN(value) || Infinity === value || -Infinity === value) {
|
|
58
|
+
return SerializableKind.Invalid;
|
|
59
|
+
}
|
|
60
|
+
case 'boolean':
|
|
61
|
+
case 'string':
|
|
62
|
+
case 'undefined':
|
|
63
|
+
return SerializableKind.Primitive;
|
|
64
|
+
case 'object':
|
|
65
|
+
if (!value) {
|
|
66
|
+
return SerializableKind.Invalid;
|
|
67
|
+
}
|
|
68
|
+
if ('toJSON' in value || Symbol.toPrimitive in value) {
|
|
69
|
+
return SerializableKind.Manual;
|
|
70
|
+
}
|
|
71
|
+
if (
|
|
72
|
+
value instanceof Map ||
|
|
73
|
+
value instanceof WeakMap ||
|
|
74
|
+
value instanceof Set ||
|
|
75
|
+
value instanceof WeakSet ||
|
|
76
|
+
value instanceof RegExp ||
|
|
77
|
+
value instanceof Promise ||
|
|
78
|
+
value === Math
|
|
79
|
+
) {
|
|
80
|
+
return SerializableKind.Invalid;
|
|
81
|
+
}
|
|
82
|
+
if (typeof window === 'object') {
|
|
83
|
+
if (value instanceof EventTarget) {
|
|
84
|
+
return SerializableKind.Invalid;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if ('then' in value && typeof value['then'] === 'function') {
|
|
88
|
+
return SerializableKind.Invalid;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return SerializableKind.Other;
|
|
92
|
+
}
|
|
93
|
+
return SerializableKind.Invalid;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getTypeOf(value: any) {
|
|
97
|
+
const t = typeof value;
|
|
98
|
+
switch (t) {
|
|
99
|
+
case 'bigint':
|
|
100
|
+
case 'number':
|
|
101
|
+
case 'boolean':
|
|
102
|
+
case 'string':
|
|
103
|
+
case 'symbol':
|
|
104
|
+
case 'undefined':
|
|
105
|
+
case 'function':
|
|
106
|
+
return t;
|
|
107
|
+
}
|
|
108
|
+
if (value === null) return 'null';
|
|
109
|
+
if (value instanceof Promise) return 'Promise';
|
|
110
|
+
if (value instanceof Error) return 'Error';
|
|
111
|
+
|
|
112
|
+
if (typeof window === 'object') {
|
|
113
|
+
if (value instanceof Element) return 'DOM';
|
|
114
|
+
if (value instanceof EventTarget) return 'EventTarget';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (value instanceof String) return 'string';
|
|
118
|
+
if (value instanceof Number) return 'number';
|
|
119
|
+
if (value instanceof Boolean) return 'boolean';
|
|
120
|
+
if (value instanceof Date) return 'datetime';
|
|
121
|
+
if (value instanceof RegExp) return 'regexp';
|
|
122
|
+
|
|
123
|
+
return 'unknown';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function assertSerializable(value: any) {
|
|
127
|
+
if (!value) return;
|
|
128
|
+
|
|
129
|
+
assertSerializableWalker(value, '$');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function assertSerializableWalker(data: any, path: string) {
|
|
133
|
+
const type = isSerializable(data);
|
|
134
|
+
if (type === SerializableKind.Invalid) {
|
|
135
|
+
console.error('在对象中发现不可序列化的数据: 路径为 %s, 可能的类型为: %s\n%j', path, getTypeOf(data), data);
|
|
136
|
+
throw new TypeError(`对象路径 ${path} 无法序列化`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (type === SerializableKind.Manual || type === SerializableKind.Primitive) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const [key, value] of Object.entries(data)) {
|
|
144
|
+
assertSerializableWalker(value, `${path}/${key}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const inspect = Symbol.for('nodejs.util.inspect.custom'); // high version node
|
|
2
|
+
const inspectOld = tryGetSymbol();
|
|
3
|
+
|
|
4
|
+
declare const global: any;
|
|
5
|
+
|
|
6
|
+
function tryGetSymbol() {
|
|
7
|
+
try {
|
|
8
|
+
const r = global.require;
|
|
9
|
+
return r('util').inspect.custom;
|
|
10
|
+
} catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* try to call `inspect` method of an object, if not exists, call `toString`.
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
export function tryInspect(object: any) {
|
|
20
|
+
if (!object || typeof object !== 'object') {
|
|
21
|
+
return JSON.stringify(object);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (object[inspect]) {
|
|
25
|
+
return object[inspect]();
|
|
26
|
+
} else if (inspectOld && object[inspectOld]) {
|
|
27
|
+
return object[inspectOld]();
|
|
28
|
+
} else if (object['inspect']) {
|
|
29
|
+
return object['inspect']();
|
|
30
|
+
} else if (object[Symbol.toStringTag]) {
|
|
31
|
+
return object[Symbol.toStringTag]();
|
|
32
|
+
} else if (object.toJSON) {
|
|
33
|
+
return object.toJSON();
|
|
34
|
+
} else {
|
|
35
|
+
return '' + object;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getErrorFrame } from './getFrame';
|
|
2
|
+
|
|
3
|
+
export function convertCatchedError(e: unknown): Error {
|
|
4
|
+
if (e instanceof Error) {
|
|
5
|
+
return e;
|
|
6
|
+
} else {
|
|
7
|
+
console.error('Catched invalid error at %s, type %s, value %s.', getErrorFrame(new Error(), 1), typeof e, e);
|
|
8
|
+
return new Error('Invalid: ' + e);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get nth line of Error.stack
|
|
3
|
+
* @returns {string} if frame greater than max, return ''
|
|
4
|
+
*/
|
|
5
|
+
export function getErrorFrame(e: Error, frame: number): string {
|
|
6
|
+
if (e && e.stack) {
|
|
7
|
+
const stackArr = e.stack.split('\n');
|
|
8
|
+
if (stackArr.length > frame + 1) {
|
|
9
|
+
return stackArr[frame + 1].trim();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { nameFunction } from './functionName';
|
|
2
|
+
|
|
3
|
+
export interface MyAsyncCallback<Argument extends unknown[]> {
|
|
4
|
+
displayName?: string;
|
|
5
|
+
|
|
6
|
+
(...param: Argument): Promise<void | undefined | boolean> | void | undefined | boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* like CallbackList, but async
|
|
11
|
+
*/
|
|
12
|
+
export class AsyncCallbackList<Argument extends unknown[]> {
|
|
13
|
+
protected list: MyAsyncCallback<Argument>[] = [];
|
|
14
|
+
protected running: boolean = false;
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
this.run = (this.run as any).bind(this);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
count() {
|
|
21
|
+
return this.list.length;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
reset() {
|
|
25
|
+
if (this.running) {
|
|
26
|
+
throw new Error("Can not reset when it's running.");
|
|
27
|
+
}
|
|
28
|
+
this.list.length = 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param name optional name of `item` (will assign displayName to `item`)
|
|
33
|
+
* @returns function list length
|
|
34
|
+
*/
|
|
35
|
+
add(item: MyAsyncCallback<Argument>, name?: string): number {
|
|
36
|
+
if (this.running) {
|
|
37
|
+
throw new Error("Can not add callback when it's running.");
|
|
38
|
+
}
|
|
39
|
+
if (name) {
|
|
40
|
+
nameFunction(name, item);
|
|
41
|
+
}
|
|
42
|
+
return this.list.push(item);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @returns if removed: return `item`; if did not exists: return null
|
|
47
|
+
*/
|
|
48
|
+
remove(item: MyAsyncCallback<Argument>): null | MyAsyncCallback<Argument> {
|
|
49
|
+
if (this.running) {
|
|
50
|
+
throw new Error("Can not remove callback when it's running.");
|
|
51
|
+
}
|
|
52
|
+
const found = this.list.indexOf(item);
|
|
53
|
+
if (found !== -1) {
|
|
54
|
+
return this.list.splice(found, 1)[0];
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Stop run if one callback return `true`
|
|
61
|
+
* @returns {boolean} true if one callback return true
|
|
62
|
+
*/
|
|
63
|
+
async run(...argument: Argument): Promise<boolean> {
|
|
64
|
+
this.running = true;
|
|
65
|
+
let ret: boolean | undefined | void;
|
|
66
|
+
for (const cb of this.list) {
|
|
67
|
+
ret = await cb(...argument);
|
|
68
|
+
if (ret === true) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
this.running = false;
|
|
73
|
+
return ret || false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { nameFunction } from './functionName';
|
|
2
|
+
|
|
3
|
+
export interface MyCallback<Argument extends unknown[]> {
|
|
4
|
+
displayName?: string;
|
|
5
|
+
|
|
6
|
+
(...param: Argument): any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Manage a list of callback
|
|
11
|
+
*/
|
|
12
|
+
export class CallbackList<Argument extends unknown[]> {
|
|
13
|
+
protected list: MyCallback<Argument>[] = [];
|
|
14
|
+
protected running: boolean = false;
|
|
15
|
+
protected stop: boolean = false;
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
this.run = (this.run as any).bind(this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
count() {
|
|
22
|
+
return this.list.length;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* remove all callback
|
|
27
|
+
*/
|
|
28
|
+
reset() {
|
|
29
|
+
if (this.running) {
|
|
30
|
+
throw new Error("Can not reset when it's running.");
|
|
31
|
+
}
|
|
32
|
+
this.list.length = 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param name optional name of `item` (will assign displayName to `item`)
|
|
37
|
+
* @returns function list length
|
|
38
|
+
*/
|
|
39
|
+
add(item: MyCallback<Argument>, name?: string): number {
|
|
40
|
+
if (this.running) {
|
|
41
|
+
throw new Error("Can not add callback when it's running.");
|
|
42
|
+
}
|
|
43
|
+
if (name) {
|
|
44
|
+
nameFunction(name, item);
|
|
45
|
+
}
|
|
46
|
+
return this.list.push(item);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @returns if removed: return `item`; if did not exists: return null
|
|
51
|
+
*/
|
|
52
|
+
remove(item: MyCallback<Argument>): null | MyCallback<Argument> {
|
|
53
|
+
if (this.running) {
|
|
54
|
+
throw new Error("Can not remove callback when it's running.");
|
|
55
|
+
}
|
|
56
|
+
const found = this.list.indexOf(item);
|
|
57
|
+
if (found !== -1) {
|
|
58
|
+
return this.list.splice(found, 1)[0];
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* in a callback, call this.stopRun() to stop remain callbacks (not by return false)
|
|
65
|
+
* @returns {boolean} true if every callback called, false if stop in middle
|
|
66
|
+
*/
|
|
67
|
+
run(...argument: Argument): boolean {
|
|
68
|
+
if (this.running) {
|
|
69
|
+
throw new Error("can not run CallbackList in it's callback.");
|
|
70
|
+
}
|
|
71
|
+
this.stop = false;
|
|
72
|
+
|
|
73
|
+
this.running = true;
|
|
74
|
+
for (const cb of this.list) {
|
|
75
|
+
if (this.stop) break;
|
|
76
|
+
cb(...argument);
|
|
77
|
+
}
|
|
78
|
+
this.running = false;
|
|
79
|
+
|
|
80
|
+
const ret = !this.stop;
|
|
81
|
+
this.stop = false;
|
|
82
|
+
return ret;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
stopRun() {
|
|
86
|
+
this.stop = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { nameFunction } from './functionName';
|
|
2
|
+
|
|
3
|
+
export interface MyDelayCallback<Argument extends unknown[]> {
|
|
4
|
+
displayName?: string;
|
|
5
|
+
|
|
6
|
+
(...param: Argument): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* remember arguments after run
|
|
11
|
+
* run all later added function with memorized argument
|
|
12
|
+
*/
|
|
13
|
+
export class DelayCallbackList<Argument extends unknown[]> {
|
|
14
|
+
private delayArgument?: Argument;
|
|
15
|
+
private delayComplete: boolean = false;
|
|
16
|
+
|
|
17
|
+
protected list?: MyDelayCallback<Argument>[] = [];
|
|
18
|
+
|
|
19
|
+
count() {
|
|
20
|
+
return this.list?.length ?? 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
add(item: MyDelayCallback<Argument>, name?: string) {
|
|
24
|
+
if (name) {
|
|
25
|
+
nameFunction(name, item);
|
|
26
|
+
}
|
|
27
|
+
if (this.delayComplete) {
|
|
28
|
+
item(...this.delayArgument!);
|
|
29
|
+
} else {
|
|
30
|
+
this.list!.push(item);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
run(argument: Argument) {
|
|
35
|
+
if (this.delayComplete) {
|
|
36
|
+
throw new Error('call to delay callback twice!');
|
|
37
|
+
}
|
|
38
|
+
this.delayComplete = true;
|
|
39
|
+
this.delayArgument = argument;
|
|
40
|
+
this.list!.forEach((cb) => {
|
|
41
|
+
cb(...argument);
|
|
42
|
+
});
|
|
43
|
+
delete this.list;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function with displayName
|
|
3
|
+
*/
|
|
4
|
+
export interface NamedFunction extends Function {
|
|
5
|
+
displayName: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get displayName/name of a function
|
|
10
|
+
*/
|
|
11
|
+
export function functionName(func: Function) {
|
|
12
|
+
return (func as NamedFunction).displayName || func.name;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Set displayName of a function
|
|
17
|
+
*/
|
|
18
|
+
export function nameFunction<T extends Function>(name: string, func: T): T & NamedFunction {
|
|
19
|
+
return Object.assign(func, {
|
|
20
|
+
displayName: name,
|
|
21
|
+
inspect() {
|
|
22
|
+
return `[Function: ${name}]`;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface MaybeNamedFunction extends Function {
|
|
28
|
+
displayName?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Assert function must have oneof displayName/name property
|
|
33
|
+
*/
|
|
34
|
+
export function assertFunctionHasName(func: MaybeNamedFunction) {
|
|
35
|
+
if (!func.displayName && !func.name) {
|
|
36
|
+
console.error(func);
|
|
37
|
+
throw new TypeError('function must have name!');
|
|
38
|
+
}
|
|
39
|
+
}
|