@pezkuwi/util 14.0.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/README.md +17 -0
- package/package.json +49 -0
- package/src/array/chunk.spec.ts +29 -0
- package/src/array/chunk.ts +35 -0
- package/src/array/filter.spec.ts +20 -0
- package/src/array/filter.ts +24 -0
- package/src/array/flatten.spec.ts +33 -0
- package/src/array/flatten.ts +51 -0
- package/src/array/index.ts +14 -0
- package/src/array/range.spec.ts +29 -0
- package/src/array/range.ts +31 -0
- package/src/array/shuffle.spec.ts +39 -0
- package/src/array/shuffle.ts +27 -0
- package/src/array/unzip.spec.ts +14 -0
- package/src/array/unzip.ts +18 -0
- package/src/array/zip.spec.ts +26 -0
- package/src/array/zip.ts +17 -0
- package/src/assert.spec.ts +40 -0
- package/src/assert.ts +50 -0
- package/src/bi/consts.ts +112 -0
- package/src/bi/helpers.ts +23 -0
- package/src/bi/index.ts +16 -0
- package/src/bi/max.spec.ts +32 -0
- package/src/bi/min.spec.ts +26 -0
- package/src/bi/min.ts +16 -0
- package/src/bi/sqrt.spec.ts +59 -0
- package/src/bi/sqrt.ts +43 -0
- package/src/bi/toBigInt.spec.ts +69 -0
- package/src/bi/toBigInt.ts +33 -0
- package/src/bi/toHex.spec.ts +56 -0
- package/src/bi/toHex.ts +16 -0
- package/src/bi/toU8a.spec.ts +99 -0
- package/src/bi/toU8a.ts +72 -0
- package/src/bn/bn.ts +6 -0
- package/src/bn/consts.spec.ts +38 -0
- package/src/bn/consts.ts +112 -0
- package/src/bn/fromHex.spec.ts +15 -0
- package/src/bn/fromHex.ts +4 -0
- package/src/bn/index.ts +18 -0
- package/src/bn/max.spec.ts +32 -0
- package/src/bn/min.spec.ts +26 -0
- package/src/bn/min.ts +36 -0
- package/src/bn/sqrt.spec.ts +37 -0
- package/src/bn/sqrt.ts +50 -0
- package/src/bn/toBn.spec.ts +53 -0
- package/src/bn/toBn.ts +43 -0
- package/src/bn/toHex.spec.ts +50 -0
- package/src/bn/toHex.ts +27 -0
- package/src/bn/toU8a.spec.ts +60 -0
- package/src/bn/toU8a.ts +45 -0
- package/src/buffer/index.ts +8 -0
- package/src/buffer/toU8a.spec.ts +20 -0
- package/src/buffer/toU8a.ts +20 -0
- package/src/bundle.ts +35 -0
- package/src/compact/addLength.spec.ts +14 -0
- package/src/compact/addLength.ts +24 -0
- package/src/compact/defaults.ts +7 -0
- package/src/compact/fromU8a.spec.ts +84 -0
- package/src/compact/fromU8a.ts +109 -0
- package/src/compact/index.ts +28 -0
- package/src/compact/stripLength.spec.ts +17 -0
- package/src/compact/stripLength.ts +26 -0
- package/src/compact/toU8a.spec.ts +59 -0
- package/src/compact/toU8a.ts +53 -0
- package/src/compact/types.ts +4 -0
- package/src/detectPackage.spec.ts +110 -0
- package/src/detectPackage.ts +138 -0
- package/src/extractTime.spec.ts +21 -0
- package/src/extractTime.ts +71 -0
- package/src/float/index.ts +4 -0
- package/src/float/toU8a.spec.ts +52 -0
- package/src/float/toU8a.ts +30 -0
- package/src/format/formatBalance.spec.ts +296 -0
- package/src/format/formatBalance.ts +177 -0
- package/src/format/formatDate.spec.ts +17 -0
- package/src/format/formatDate.ts +22 -0
- package/src/format/formatDecimal.spec.ts +28 -0
- package/src/format/formatDecimal.ts +22 -0
- package/src/format/formatElapsed.spec.ts +44 -0
- package/src/format/formatElapsed.ts +35 -0
- package/src/format/formatNumber.spec.ts +60 -0
- package/src/format/formatNumber.ts +29 -0
- package/src/format/getSeparator.spec.ts +53 -0
- package/src/format/getSeparator.ts +15 -0
- package/src/format/index.ts +9 -0
- package/src/format/si.ts +52 -0
- package/src/has.spec.ts +12 -0
- package/src/has.ts +38 -0
- package/src/hex/addPrefix.spec.ts +32 -0
- package/src/hex/addPrefix.ts +26 -0
- package/src/hex/fixLength.spec.ts +38 -0
- package/src/hex/fixLength.ts +36 -0
- package/src/hex/hasPrefix.spec.ts +32 -0
- package/src/hex/hasPrefix.ts +24 -0
- package/src/hex/index.ts +16 -0
- package/src/hex/stripPrefix.spec.ts +44 -0
- package/src/hex/stripPrefix.ts +30 -0
- package/src/hex/toBigInt.spec.ts +74 -0
- package/src/hex/toBigInt.ts +19 -0
- package/src/hex/toBn.spec.ts +74 -0
- package/src/hex/toBn.ts +40 -0
- package/src/hex/toNumber.spec.ts +20 -0
- package/src/hex/toNumber.ts +24 -0
- package/src/hex/toString.spec.ts +20 -0
- package/src/hex/toString.ts +25 -0
- package/src/hex/toU8a.spec.ts +76 -0
- package/src/hex/toU8a.ts +68 -0
- package/src/hex/toU8aBuffer.spec.ts +38 -0
- package/src/hex/toU8aBuffer.ts +52 -0
- package/src/index.spec.ts +12 -0
- package/src/index.ts +6 -0
- package/src/is/array.spec.ts +20 -0
- package/src/is/array.ts +10 -0
- package/src/is/ascii.spec.ts +49 -0
- package/src/is/ascii.ts +52 -0
- package/src/is/bigInt.spec.ts +26 -0
- package/src/is/bigInt.ts +20 -0
- package/src/is/bn.spec.ts +21 -0
- package/src/is/bn.ts +23 -0
- package/src/is/boolean.spec.ts +26 -0
- package/src/is/boolean.ts +20 -0
- package/src/is/buffer.spec.ts +26 -0
- package/src/is/buffer.ts +28 -0
- package/src/is/childClass.spec.ts +36 -0
- package/src/is/childClass.ts +29 -0
- package/src/is/class.spec.ts +37 -0
- package/src/is/class.ts +12 -0
- package/src/is/codec.spec.ts +52 -0
- package/src/is/codec.ts +26 -0
- package/src/is/compact.spec.ts +27 -0
- package/src/is/compact.ts +19 -0
- package/src/is/error.spec.ts +20 -0
- package/src/is/error.ts +23 -0
- package/src/is/function.spec.ts +20 -0
- package/src/is/function.ts +23 -0
- package/src/is/helpers.ts +23 -0
- package/src/is/hex.spec.ts +77 -0
- package/src/is/hex.ts +36 -0
- package/src/is/index.ts +36 -0
- package/src/is/instanceOf.spec.ts +48 -0
- package/src/is/instanceOf.ts +24 -0
- package/src/is/ip.spec.ts +50 -0
- package/src/is/ip.ts +56 -0
- package/src/is/jsonObject.spec.ts +51 -0
- package/src/is/jsonObject.ts +45 -0
- package/src/is/null.spec.ts +20 -0
- package/src/is/null.ts +20 -0
- package/src/is/number.spec.ts +20 -0
- package/src/is/number.ts +20 -0
- package/src/is/object.spec.ts +32 -0
- package/src/is/object.ts +24 -0
- package/src/is/observable.spec.ts +26 -0
- package/src/is/observable.ts +22 -0
- package/src/is/promise.spec.ts +32 -0
- package/src/is/promise.ts +6 -0
- package/src/is/riscv.spec.ts +36 -0
- package/src/is/riscv.ts +27 -0
- package/src/is/string.spec.ts +32 -0
- package/src/is/string.ts +22 -0
- package/src/is/testChain.spec.ts +25 -0
- package/src/is/testChain.ts +12 -0
- package/src/is/toBigInt.spec.ts +22 -0
- package/src/is/toBigInt.ts +8 -0
- package/src/is/toBn.spec.ts +25 -0
- package/src/is/toBn.ts +8 -0
- package/src/is/u8a.spec.ts +42 -0
- package/src/is/u8a.ts +25 -0
- package/src/is/undefined.spec.ts +23 -0
- package/src/is/undefined.ts +21 -0
- package/src/is/utf8.spec.ts +42 -0
- package/src/is/utf8.ts +207 -0
- package/src/is/wasm.spec.ts +20 -0
- package/src/is/wasm.ts +17 -0
- package/src/lazy.spec.ts +71 -0
- package/src/lazy.ts +63 -0
- package/src/logger.spec.ts +188 -0
- package/src/logger.ts +160 -0
- package/src/memoize.spec.ts +79 -0
- package/src/memoize.ts +49 -0
- package/src/mod.ts +4 -0
- package/src/nextTick.ts +26 -0
- package/src/noop.ts +16 -0
- package/src/number/index.ts +9 -0
- package/src/number/toHex.spec.ts +44 -0
- package/src/number/toHex.ts +27 -0
- package/src/number/toU8a.spec.ts +50 -0
- package/src/number/toU8a.ts +25 -0
- package/src/object/clear.spec.ts +14 -0
- package/src/object/clear.ts +16 -0
- package/src/object/copy.spec.ts +17 -0
- package/src/object/copy.ts +12 -0
- package/src/object/entries.spec.ts +20 -0
- package/src/object/entries.ts +12 -0
- package/src/object/index.ts +10 -0
- package/src/object/keys.spec.ts +19 -0
- package/src/object/keys.ts +10 -0
- package/src/object/property.spec.ts +149 -0
- package/src/object/property.ts +39 -0
- package/src/object/spread.spec.ts +36 -0
- package/src/object/spread.ts +38 -0
- package/src/object/values.spec.ts +19 -0
- package/src/object/values.ts +10 -0
- package/src/packageDetect.ts +13 -0
- package/src/packageInfo.ts +6 -0
- package/src/promisify.spec.ts +50 -0
- package/src/promisify.ts +30 -0
- package/src/string/camelCase.spec.ts +119 -0
- package/src/string/camelCase.ts +79 -0
- package/src/string/index.ts +12 -0
- package/src/string/lowerFirst.spec.ts +41 -0
- package/src/string/lowerFirst.ts +46 -0
- package/src/string/pascalCase.spec.ts +26 -0
- package/src/string/shorten.spec.ts +38 -0
- package/src/string/shorten.ts +24 -0
- package/src/string/toHex.spec.ts +26 -0
- package/src/string/toHex.ts +27 -0
- package/src/string/toU8a.spec.ts +31 -0
- package/src/string/toU8a.ts +28 -0
- package/src/string/upperFirst.spec.ts +41 -0
- package/src/stringify.spec.ts +33 -0
- package/src/stringify.ts +20 -0
- package/src/test/index.ts +4 -0
- package/src/test/performance.ts +92 -0
- package/src/types.ts +100 -0
- package/src/u8a/cmp.spec.ts +62 -0
- package/src/u8a/cmp.ts +50 -0
- package/src/u8a/concat.spec.ts +42 -0
- package/src/u8a/concat.ts +60 -0
- package/src/u8a/concatBuffer.ts +34 -0
- package/src/u8a/empty.spec.ts +46 -0
- package/src/u8a/empty.ts +22 -0
- package/src/u8a/eq.spec.ts +113 -0
- package/src/u8a/eq.ts +46 -0
- package/src/u8a/fixLength.spec.ts +34 -0
- package/src/u8a/fixLength.ts +34 -0
- package/src/u8a/index.ts +22 -0
- package/src/u8a/sorted.spec.ts +20 -0
- package/src/u8a/sorted.ts +22 -0
- package/src/u8a/toBigInt.spec.ts +106 -0
- package/src/u8a/toBigInt.ts +100 -0
- package/src/u8a/toBn.spec.ts +106 -0
- package/src/u8a/toBn.ts +101 -0
- package/src/u8a/toBuffer.spec.ts +20 -0
- package/src/u8a/toBuffer.ts +28 -0
- package/src/u8a/toFloat.spec.ts +86 -0
- package/src/u8a/toFloat.ts +26 -0
- package/src/u8a/toHex.spec.ts +94 -0
- package/src/u8a/toHex.ts +68 -0
- package/src/u8a/toHexBuffer.spec.ts +63 -0
- package/src/u8a/toHexBuffer.ts +30 -0
- package/src/u8a/toNumber.spec.ts +47 -0
- package/src/u8a/toNumber.ts +80 -0
- package/src/u8a/toString.spec.ts +36 -0
- package/src/u8a/toString.ts +26 -0
- package/src/u8a/toU8a.spec.ts +63 -0
- package/src/u8a/toU8a.ts +46 -0
- package/src/u8a/wrap.spec.ts +139 -0
- package/src/u8a/wrap.ts +65 -0
- package/tsconfig.build.json +19 -0
- package/tsconfig.spec.json +17 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { perf } from '../test/index.js';
|
|
7
|
+
import { objectProperties, objectProperty } from './index.js';
|
|
8
|
+
|
|
9
|
+
describe('objectProperty/objectProperties', (): void => {
|
|
10
|
+
it('sets a property', (): void => {
|
|
11
|
+
const test: { a?: unknown } = {};
|
|
12
|
+
|
|
13
|
+
expect(test.a).toEqual(undefined);
|
|
14
|
+
|
|
15
|
+
objectProperty(test, 'a', () => 2);
|
|
16
|
+
|
|
17
|
+
expect(Object.prototype.hasOwnProperty.call(test, 'a')).toBe(true);
|
|
18
|
+
expect('a' in test).toEqual(true);
|
|
19
|
+
expect(test.a).toEqual(2);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('does not override an existing property (record)', (): void => {
|
|
23
|
+
const test = { a: 1 };
|
|
24
|
+
|
|
25
|
+
expect(test.a).toEqual(1);
|
|
26
|
+
|
|
27
|
+
objectProperty(test, 'a', () => 2);
|
|
28
|
+
|
|
29
|
+
expect(test.a).toEqual(1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('does not override an existing property (class)', (): void => {
|
|
33
|
+
class Test {
|
|
34
|
+
b = 1;
|
|
35
|
+
|
|
36
|
+
get a () {
|
|
37
|
+
return 1 + 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const test = new Test();
|
|
42
|
+
|
|
43
|
+
expect(test.a).toEqual(1);
|
|
44
|
+
expect(test.b).toEqual(1);
|
|
45
|
+
|
|
46
|
+
objectProperty(test, 'a', () => 2);
|
|
47
|
+
objectProperty(test, 'b', () => 2);
|
|
48
|
+
|
|
49
|
+
expect(test.a).toEqual(1);
|
|
50
|
+
expect(test.b).toEqual(1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('does not override an existing property (inherited)', (): void => {
|
|
54
|
+
class Parent extends Map<string, unknown> {
|
|
55
|
+
constructor () {
|
|
56
|
+
super();
|
|
57
|
+
|
|
58
|
+
this.set('a', 1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get a (): unknown {
|
|
62
|
+
return this.get('a');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
class Child extends Parent {
|
|
67
|
+
constructor () {
|
|
68
|
+
super();
|
|
69
|
+
|
|
70
|
+
this.set('b', 1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get b (): unknown {
|
|
74
|
+
return this.get('b');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const test = new Child() as unknown as { a: number; b: number; c?: number };
|
|
79
|
+
|
|
80
|
+
expect(test.a).toEqual(1);
|
|
81
|
+
expect(test.b).toEqual(1);
|
|
82
|
+
expect(test.c).toEqual(undefined);
|
|
83
|
+
|
|
84
|
+
objectProperties(test, ['a', 'b', 'c'], () => 2);
|
|
85
|
+
|
|
86
|
+
expect(test.a).toEqual(1);
|
|
87
|
+
expect(test.b).toEqual(1);
|
|
88
|
+
expect(test.c).toEqual(2);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('works with this used in classes', (): void => {
|
|
92
|
+
class Test extends Map<string, unknown> {
|
|
93
|
+
constructor () {
|
|
94
|
+
super();
|
|
95
|
+
|
|
96
|
+
this.set('a', 1);
|
|
97
|
+
|
|
98
|
+
objectProperty(this, 'a', (k) => this.get(k));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const test = new Test() as unknown as { a: number };
|
|
103
|
+
|
|
104
|
+
expect(test.a).toEqual(1);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('works with this used in classes (multiples)', (): void => {
|
|
108
|
+
class Test extends Map<string, unknown> {
|
|
109
|
+
constructor () {
|
|
110
|
+
super();
|
|
111
|
+
|
|
112
|
+
this.set('a', 1);
|
|
113
|
+
this.set('b', 2);
|
|
114
|
+
|
|
115
|
+
objectProperties(this, ['a', 'b'], (k) => this.get(k));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const test = new Test() as unknown as { a: number; b: number };
|
|
120
|
+
|
|
121
|
+
expect(test.a).toEqual(1);
|
|
122
|
+
expect(test.b).toEqual(2);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('calls back with the key name (single)', (): void => {
|
|
126
|
+
const test: { a?: number } = {};
|
|
127
|
+
const getter = jest.fn(() => 123);
|
|
128
|
+
|
|
129
|
+
objectProperty(test, 'a', getter);
|
|
130
|
+
|
|
131
|
+
expect(getter).not.toHaveBeenCalled();
|
|
132
|
+
expect(test.a).toEqual(123);
|
|
133
|
+
expect(getter).toHaveBeenCalledWith('a', 0, expect.objectContaining({}));
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('calls back with the key name & index (numtiple)', (): void => {
|
|
137
|
+
const test: { a?: number; b?: number; c?: number } = {};
|
|
138
|
+
const getter = jest.fn(() => 123);
|
|
139
|
+
|
|
140
|
+
objectProperties(test, ['a', 'b', 'c'], getter);
|
|
141
|
+
|
|
142
|
+
expect(getter).not.toHaveBeenCalled();
|
|
143
|
+
expect(test.b).toEqual(123);
|
|
144
|
+
expect(getter).toHaveBeenCalledWith('b', 1, expect.objectContaining({}));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
perf('objectProperties (obj)', 50_000, [[]], () => objectProperties({}, ['foo', 'bar', 'baz'], (k) => k));
|
|
148
|
+
perf('objectProperties (map)', 50_000, [[]], () => objectProperties(new Map(), ['foo', 'bar', 'baz'], (k) => k));
|
|
149
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @name objectProperty
|
|
6
|
+
* @summary Assign a get property on the input object
|
|
7
|
+
*/
|
|
8
|
+
export function objectProperty <S> (that: object, key: string, getter: (key: string, index: number, self: S) => unknown, getName?: (key: string, index: number) => string, index = 0): void {
|
|
9
|
+
const name = getName
|
|
10
|
+
? getName(key, index)
|
|
11
|
+
: key;
|
|
12
|
+
|
|
13
|
+
// There are 3 approaches here -
|
|
14
|
+
// - Object.prototype.hasOwnProperty.call(that, key) - this only checks the current class, i.e
|
|
15
|
+
// will retuirn false if the property is set in the parent class
|
|
16
|
+
// - isUndefined(...) - this may yield a false positive when the property is there, but not set.
|
|
17
|
+
// Additionally, on pre-defined getters it may make a call
|
|
18
|
+
// - key in that - Does not need to be combined with either of the above and checks the full chain
|
|
19
|
+
if (!(name in that)) {
|
|
20
|
+
Object.defineProperty(that, name, {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
// Unlike in lazy, we always call into the upper function, i.e. this method
|
|
23
|
+
// does not cache old values (it is expected to be used for dynamic values)
|
|
24
|
+
get: function (): unknown {
|
|
25
|
+
return getter(key, index, this as S);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @name objectProperties
|
|
33
|
+
* @summary Assign get properties on the input object
|
|
34
|
+
*/
|
|
35
|
+
export function objectProperties <S> (that: object, keys: string[], getter: (key: string, index: number, self: S) => unknown, getName?: (key: string, index: number) => string): void {
|
|
36
|
+
for (let i = 0, count = keys.length; i < count; i++) {
|
|
37
|
+
objectProperty(that, keys[i], getter, getName, i);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { perf } from '../test/index.js';
|
|
7
|
+
import { objectSpread } from './index.js';
|
|
8
|
+
|
|
9
|
+
describe('objectSpread', (): void => {
|
|
10
|
+
it('spreads obj sources', (): void => {
|
|
11
|
+
expect(
|
|
12
|
+
objectSpread({}, { a: 1, b: 2, c: 3 }, { d: 4, e: 5, f: 6 })
|
|
13
|
+
).toEqual({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('spreads map sources', (): void => {
|
|
17
|
+
expect(
|
|
18
|
+
objectSpread({}, new Map<string, number>([['a', 1], ['b', 2], ['c', 3]]), new Map<string, number>([['d', 4], ['e', 5], ['f', 6]]))
|
|
19
|
+
).toEqual({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('spreads an object from multiple sources', (): void => {
|
|
23
|
+
expect(
|
|
24
|
+
objectSpread({ a: 1 }, { b: 2 }, { a: 2, c: { d: 3, e: 4 } }, new Map<string, unknown>([['f', 5], ['g', 6], ['h', { i: 7, k: 8 }]]))
|
|
25
|
+
).toEqual({ a: 2, b: 2, c: { d: 3, e: 4 }, f: 5, g: 6, h: { i: 7, k: 8 } });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('spreads an object from multiple sources (with null & undefined)', (): void => {
|
|
29
|
+
expect(
|
|
30
|
+
objectSpread({ a: 1 }, null, { b: 2 }, undefined, { a: 2, c: { d: 3, e: 4 } })
|
|
31
|
+
).toEqual({ a: 2, b: 2, c: { d: 3, e: 4 } });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
perf('objectSpread (obj)', 350_000, [[{}, { a: 1, b: 2, c: 3 }, { d: 4, e: 5, f: 6 }]], objectSpread);
|
|
35
|
+
perf('objectSpread (map)', 350_000, [[{}, new Map<string, number>([['a', 1], ['b', 2], ['c', 3]]), new Map<string, number>([['d', 4], ['e', 5], ['f', 6]])]], objectSpread);
|
|
36
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @name objectSpread
|
|
6
|
+
* @summary Concats all sources into the destination
|
|
7
|
+
* @description Spreads object properties while maintaining object integrity
|
|
8
|
+
*/
|
|
9
|
+
export function objectSpread <T extends object> (dest: object, ...sources: (object | undefined | null)[]): T {
|
|
10
|
+
const filterProps = new Set(['__proto__', 'constructor', 'prototype']);
|
|
11
|
+
|
|
12
|
+
for (let i = 0, count = sources.length; i < count; i++) {
|
|
13
|
+
const src = sources[i];
|
|
14
|
+
|
|
15
|
+
if (src) {
|
|
16
|
+
if (typeof (src as Map<string, unknown>).entries === 'function') {
|
|
17
|
+
for (const [key, value] of (src as Map<string, unknown>).entries()) {
|
|
18
|
+
if (!filterProps.has(key)) {
|
|
19
|
+
(dest as Record<string, unknown>)[key] = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
// Create a clean copy of the source object
|
|
24
|
+
const sanitizedSrc = Object.create(null) as Record<string, unknown>;
|
|
25
|
+
|
|
26
|
+
for (const [key, value] of Object.entries(src)) {
|
|
27
|
+
if (!filterProps.has(key)) {
|
|
28
|
+
sanitizedSrc[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Object.assign(dest, sanitizedSrc);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return dest as T;
|
|
38
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { objectValues } from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('objectValues', (): void => {
|
|
9
|
+
it('extracts all values', (): void => {
|
|
10
|
+
const o = { a: 1, b: 2, c: 3 };
|
|
11
|
+
const values = objectValues(o);
|
|
12
|
+
|
|
13
|
+
expect(values).toEqual([1, 2, 3]);
|
|
14
|
+
|
|
15
|
+
for (const v of values) {
|
|
16
|
+
expect(v).toBeDefined();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @name objectValues
|
|
6
|
+
* @summary A version of Object.values that is typed for TS
|
|
7
|
+
*/
|
|
8
|
+
export function objectValues<T extends object> (obj: T): T[keyof T][] {
|
|
9
|
+
return Object.values(obj) as T[keyof T][];
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// Do not edit, auto-generated by @polkadot/dev
|
|
5
|
+
// (packageInfo imports will be kept as-is, user-editable)
|
|
6
|
+
|
|
7
|
+
import { packageInfo as decoderInfo } from '@pezkuwi/x-textdecoder';
|
|
8
|
+
import { packageInfo as encoderInfo } from '@pezkuwi/x-textencoder';
|
|
9
|
+
|
|
10
|
+
import { detectPackage } from './detectPackage.js';
|
|
11
|
+
import { packageInfo } from './packageInfo.js';
|
|
12
|
+
|
|
13
|
+
detectPackage(packageInfo, null, [decoderInfo, encoderInfo]);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { promisify } from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('promisify', (): void => {
|
|
9
|
+
it('handles functions with no parameters (resolve)', (): Promise<void> => {
|
|
10
|
+
const fn = (cb: (error: null, value: [boolean, string, number]) => void): void =>
|
|
11
|
+
cb(null, [true, 'test', 1]);
|
|
12
|
+
|
|
13
|
+
return promisify(null, fn).then((result): void => {
|
|
14
|
+
expect(result).toEqual([true, 'test', 1]);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('handles functions with no parameters (reject)', (): Promise<void> => {
|
|
19
|
+
const fn = (cb: (error: Error, result?: boolean) => void): void =>
|
|
20
|
+
cb(new Error('test reject'));
|
|
21
|
+
|
|
22
|
+
return promisify(null, fn)
|
|
23
|
+
.then((): void => {
|
|
24
|
+
throw new Error('Received unexpected result');
|
|
25
|
+
})
|
|
26
|
+
.catch((error: Error): void => {
|
|
27
|
+
// eslint-disable-next-line jest/no-conditional-expect
|
|
28
|
+
expect(error.message).toEqual('test reject');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('handles functions with parameters (resolve)', (): Promise<void> => {
|
|
33
|
+
const fn = (a: number, b: boolean, cb: (error: Error | null, result?: [number, boolean]) => void): void =>
|
|
34
|
+
cb(null, [a, b]);
|
|
35
|
+
|
|
36
|
+
return promisify(null, fn, 2, false).then((result: [number, boolean]): void => {
|
|
37
|
+
expect(result).toEqual([2, false]);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('handles functions with parameters (reject)', (): Promise<void> => {
|
|
42
|
+
const fn = (a: number, b: boolean, c: string, cb: (error: Error | null, result?: [number, boolean, string]) => void): void =>
|
|
43
|
+
cb(new Error(`test reject: ${a},${b.toString()},${c}`));
|
|
44
|
+
|
|
45
|
+
return promisify(null, fn, 3, 'string', true).catch((error: Error): void => {
|
|
46
|
+
// eslint-disable-next-line jest/no-conditional-expect
|
|
47
|
+
expect(error.message).toEqual('test reject: 3,string,true');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
package/src/promisify.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @name promisify
|
|
6
|
+
* @summary Wraps an async callback into a `Promise`
|
|
7
|
+
* @description
|
|
8
|
+
* Wraps the supplied async function `fn` that has a standard JS callback `(error: Error, result: any)` into a `Promise`, passing the supplied parameters. When `error` is set, the Promise is rejected, else the Promise resolves with the `result` value.
|
|
9
|
+
* @example
|
|
10
|
+
* <BR>
|
|
11
|
+
*
|
|
12
|
+
* ```javascript
|
|
13
|
+
* const { promisify } from '@pezkuwi/util';
|
|
14
|
+
*
|
|
15
|
+
* await promisify(null, ((a, cb) => cb(null, a), true); // resolves with `true`
|
|
16
|
+
* await promisify(null, (cb) => cb(new Error('error!'))); // rejects with `error!`
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
export function promisify <R = any> (self: unknown, fn: (...params: any[]) => any, ...params: any[]): Promise<R> {
|
|
21
|
+
return new Promise((resolve, reject): void => {
|
|
22
|
+
fn.apply(self, params.concat((error: Error | null, result?: R): void => {
|
|
23
|
+
if (error) {
|
|
24
|
+
reject(error);
|
|
25
|
+
} else {
|
|
26
|
+
resolve(result as R);
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { getRandomValues } from '@pezkuwi/x-randomvalues';
|
|
7
|
+
|
|
8
|
+
import { arrayRange } from '../array/index.js';
|
|
9
|
+
import { perf } from '../test/index.js';
|
|
10
|
+
import { stringCamelCase, stringUpperFirst } from './index.js';
|
|
11
|
+
|
|
12
|
+
const SEPS = [' ', '_', '-', '.', ','];
|
|
13
|
+
const words = 'bring|brisk|broccoli|broken|bronze|broom|brother|brown|brush|bubble|buddy|budget|buffalo|build|bulb|bulk|bullet|bundle|bunker|burden'.split('|');
|
|
14
|
+
|
|
15
|
+
function randomAsNumber (): number {
|
|
16
|
+
const rand = getRandomValues(new Uint8Array(4));
|
|
17
|
+
|
|
18
|
+
return rand.reduce((v, t) => (v * t) + v, 0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const randomWords = arrayRange(256).map((): [string] => {
|
|
22
|
+
let result = '';
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < 6; i++) {
|
|
25
|
+
let word = words[randomAsNumber() % words.length];
|
|
26
|
+
|
|
27
|
+
if (randomAsNumber() % 2) {
|
|
28
|
+
word = stringUpperFirst(word);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (i === 0) {
|
|
32
|
+
result = word;
|
|
33
|
+
} else {
|
|
34
|
+
result += `${SEPS[randomAsNumber() % SEPS.length]}${word}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return [result];
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('stringCamelCase', (): void => {
|
|
42
|
+
it('works correctly', (): void => {
|
|
43
|
+
expect(
|
|
44
|
+
stringCamelCase('Snake_case-...SomethingSomething spaced')
|
|
45
|
+
).toBe('snakeCaseSomethingSomethingSpaced');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('works correctly for String (class', (): void => {
|
|
49
|
+
expect(
|
|
50
|
+
stringCamelCase(String('Foo_bar-baz---test-_ spaced....Extra'))
|
|
51
|
+
).toBe('fooBarBazTestSpacedExtra');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('adjusts all-uppercase', (): void => {
|
|
55
|
+
expect(
|
|
56
|
+
stringCamelCase('DEDUP_KEY_PREFIX')
|
|
57
|
+
).toEqual('dedupKeyPrefix');
|
|
58
|
+
expect(
|
|
59
|
+
stringCamelCase(String('DEDUP_KEY_PREFIX'))
|
|
60
|
+
).toEqual('dedupKeyPrefix');
|
|
61
|
+
expect(
|
|
62
|
+
stringCamelCase('SOMETHING')
|
|
63
|
+
).toEqual('something');
|
|
64
|
+
expect(
|
|
65
|
+
stringCamelCase('NMap')
|
|
66
|
+
).toEqual('nMap');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('adjusts all-uppercase + digits', (): void => {
|
|
70
|
+
expect(
|
|
71
|
+
stringCamelCase('SS58 PreFIX')
|
|
72
|
+
).toEqual('ss58PreFIX');
|
|
73
|
+
expect(
|
|
74
|
+
stringCamelCase('SS58Prefix')
|
|
75
|
+
).toEqual('ss58Prefix');
|
|
76
|
+
expect(
|
|
77
|
+
stringCamelCase('UUID64')
|
|
78
|
+
).toEqual('uuid64');
|
|
79
|
+
expect(
|
|
80
|
+
stringCamelCase('BLAKE2B')
|
|
81
|
+
).toEqual('blake2b');
|
|
82
|
+
expect(
|
|
83
|
+
stringCamelCase('NFTOrder')
|
|
84
|
+
).toEqual('nftOrder');
|
|
85
|
+
expect(
|
|
86
|
+
stringCamelCase('EVM')
|
|
87
|
+
).toEqual('evm');
|
|
88
|
+
expect(
|
|
89
|
+
stringCamelCase('A')
|
|
90
|
+
).toEqual('a');
|
|
91
|
+
expect(
|
|
92
|
+
stringCamelCase('A1')
|
|
93
|
+
).toEqual('a1');
|
|
94
|
+
expect(
|
|
95
|
+
stringCamelCase('A1b')
|
|
96
|
+
).toEqual('a1b');
|
|
97
|
+
expect(
|
|
98
|
+
stringCamelCase('A1B')
|
|
99
|
+
).toEqual('a1b');
|
|
100
|
+
expect(
|
|
101
|
+
stringCamelCase('RawVRFOutput')
|
|
102
|
+
).toEqual('rawVRFOutput');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('adjusts with leading _', (): void => {
|
|
106
|
+
expect(
|
|
107
|
+
stringCamelCase('_reserved')
|
|
108
|
+
).toEqual('reserved');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('adjusts with minimal chars per part', (): void => {
|
|
112
|
+
expect(
|
|
113
|
+
stringCamelCase('_a_b_c_def')
|
|
114
|
+
).toEqual('aBCDef');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
perf('stringCamelCase (random)', 100_000, randomWords, stringCamelCase);
|
|
118
|
+
perf('stringCamelCase (NFTOrder)', 100_000, [['NFTOrder']], stringCamelCase);
|
|
119
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { AnyString } from '../types.js';
|
|
5
|
+
|
|
6
|
+
export const CC_TO_UP = new Array<string>(256);
|
|
7
|
+
export const CC_TO_LO = new Array<string>(256);
|
|
8
|
+
|
|
9
|
+
for (let i = 0, count = CC_TO_UP.length; i < count; i++) {
|
|
10
|
+
CC_TO_LO[i] = String.fromCharCode(i).toLowerCase();
|
|
11
|
+
CC_TO_UP[i] = String.fromCharCode(i).toUpperCase();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** @internal */
|
|
15
|
+
function formatAllCaps (w: string): string {
|
|
16
|
+
return w.slice(0, w.length - 1).toLowerCase() + CC_TO_UP[w.charCodeAt(w.length - 1)];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*
|
|
22
|
+
* Inspired by https://stackoverflow.com/a/2970667
|
|
23
|
+
*
|
|
24
|
+
* This is not as optimal as the original SO answer (we split into per-word),
|
|
25
|
+
* however it does pass the tests (which the SO version doesn't) and is still
|
|
26
|
+
* a major improvement over the original camelcase npm package -
|
|
27
|
+
*
|
|
28
|
+
* camelcase: 20.88 μs/op
|
|
29
|
+
* this: 1.00 μs/op
|
|
30
|
+
*
|
|
31
|
+
* Caveat of this: only Ascii, but acceptable for the intended usecase
|
|
32
|
+
*/
|
|
33
|
+
function converter (format: (w: string, i: number) => string): (value: AnyString) => string {
|
|
34
|
+
return (value: AnyString): string => {
|
|
35
|
+
const parts = value
|
|
36
|
+
// replace all separators (including consequtive) with spaces
|
|
37
|
+
.replace(/[-_., ]+/g, ' ')
|
|
38
|
+
// we don't want leading or trailing spaces
|
|
39
|
+
.trim()
|
|
40
|
+
// split into words
|
|
41
|
+
.split(' ');
|
|
42
|
+
let result = '';
|
|
43
|
+
|
|
44
|
+
for (let i = 0, count = parts.length; i < count; i++) {
|
|
45
|
+
const w = parts[i];
|
|
46
|
+
|
|
47
|
+
// apply the formatting
|
|
48
|
+
result += format(
|
|
49
|
+
/^[\dA-Z]+$/.test(w)
|
|
50
|
+
// all full uppercase + letters are changed to lowercase
|
|
51
|
+
? w.toLowerCase()
|
|
52
|
+
// all consecutive capitals + letters are changed to lowercase
|
|
53
|
+
// e.g. UUID64 -> uuid64, while preserving splits, eg. NFTOrder -> nftOrder
|
|
54
|
+
: w.replace(/^[\dA-Z]{2,}[^a-z]/, formatAllCaps),
|
|
55
|
+
i
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @name stringCamelCase
|
|
65
|
+
* @summary Convert a dash/dot/underscore/space separated Ascii string/String to camelCase
|
|
66
|
+
*/
|
|
67
|
+
export const stringCamelCase = /*#__PURE__*/ converter((w, i) =>
|
|
68
|
+
// lowercase for first letter/first word, else uppercase first, rest unchanged
|
|
69
|
+
(i ? CC_TO_UP[w.charCodeAt(0)] : CC_TO_LO[w.charCodeAt(0)]) + w.slice(1)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @name stringPascalCase
|
|
74
|
+
* @summary Convert a dash/dot/underscore/space separated Ascii string/String to PascalCase
|
|
75
|
+
*/
|
|
76
|
+
export const stringPascalCase = /*#__PURE__*/ converter((w) =>
|
|
77
|
+
// uppercase the first character, leave the rest unchanged
|
|
78
|
+
CC_TO_UP[w.charCodeAt(0)] + w.slice(1)
|
|
79
|
+
);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @summary Utility methods to convert to work with `string` values
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { stringCamelCase, stringPascalCase } from './camelCase.js';
|
|
9
|
+
export { stringLowerFirst, stringUpperFirst } from './lowerFirst.js';
|
|
10
|
+
export { stringShorten } from './shorten.js';
|
|
11
|
+
export { stringToHex } from './toHex.js';
|
|
12
|
+
export { stringToU8a } from './toU8a.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// <reference types="@polkadot/dev-test/globals.d.ts" />
|
|
5
|
+
|
|
6
|
+
import { perf } from '../test/index.js';
|
|
7
|
+
import { stringLowerFirst } from './index.js';
|
|
8
|
+
|
|
9
|
+
describe('stringLowerFirst', (): void => {
|
|
10
|
+
it("lowers the first letter if it's a capital letter", (): void => {
|
|
11
|
+
expect(
|
|
12
|
+
stringLowerFirst('ABC')
|
|
13
|
+
).toBe('aBC');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("lowers the first letter if it's a capital letter (String)", (): void => {
|
|
17
|
+
expect(
|
|
18
|
+
stringLowerFirst(String('ABC'))
|
|
19
|
+
).toBe('aBC');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("lowers the first letter if it's a lowercase letter", (): void => {
|
|
23
|
+
expect(
|
|
24
|
+
stringLowerFirst('abc')
|
|
25
|
+
).toBe('abc');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('returns undefined as empty', (): void => {
|
|
29
|
+
expect(
|
|
30
|
+
stringLowerFirst()
|
|
31
|
+
).toBe('');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns null as empty', (): void => {
|
|
35
|
+
expect(
|
|
36
|
+
stringLowerFirst(null)
|
|
37
|
+
).toBe('');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
perf('stringLowerFirst', 1_000_000, [['HelloWorldSomething']], stringLowerFirst);
|
|
41
|
+
});
|