@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.
Files changed (260) hide show
  1. package/README.md +17 -0
  2. package/package.json +49 -0
  3. package/src/array/chunk.spec.ts +29 -0
  4. package/src/array/chunk.ts +35 -0
  5. package/src/array/filter.spec.ts +20 -0
  6. package/src/array/filter.ts +24 -0
  7. package/src/array/flatten.spec.ts +33 -0
  8. package/src/array/flatten.ts +51 -0
  9. package/src/array/index.ts +14 -0
  10. package/src/array/range.spec.ts +29 -0
  11. package/src/array/range.ts +31 -0
  12. package/src/array/shuffle.spec.ts +39 -0
  13. package/src/array/shuffle.ts +27 -0
  14. package/src/array/unzip.spec.ts +14 -0
  15. package/src/array/unzip.ts +18 -0
  16. package/src/array/zip.spec.ts +26 -0
  17. package/src/array/zip.ts +17 -0
  18. package/src/assert.spec.ts +40 -0
  19. package/src/assert.ts +50 -0
  20. package/src/bi/consts.ts +112 -0
  21. package/src/bi/helpers.ts +23 -0
  22. package/src/bi/index.ts +16 -0
  23. package/src/bi/max.spec.ts +32 -0
  24. package/src/bi/min.spec.ts +26 -0
  25. package/src/bi/min.ts +16 -0
  26. package/src/bi/sqrt.spec.ts +59 -0
  27. package/src/bi/sqrt.ts +43 -0
  28. package/src/bi/toBigInt.spec.ts +69 -0
  29. package/src/bi/toBigInt.ts +33 -0
  30. package/src/bi/toHex.spec.ts +56 -0
  31. package/src/bi/toHex.ts +16 -0
  32. package/src/bi/toU8a.spec.ts +99 -0
  33. package/src/bi/toU8a.ts +72 -0
  34. package/src/bn/bn.ts +6 -0
  35. package/src/bn/consts.spec.ts +38 -0
  36. package/src/bn/consts.ts +112 -0
  37. package/src/bn/fromHex.spec.ts +15 -0
  38. package/src/bn/fromHex.ts +4 -0
  39. package/src/bn/index.ts +18 -0
  40. package/src/bn/max.spec.ts +32 -0
  41. package/src/bn/min.spec.ts +26 -0
  42. package/src/bn/min.ts +36 -0
  43. package/src/bn/sqrt.spec.ts +37 -0
  44. package/src/bn/sqrt.ts +50 -0
  45. package/src/bn/toBn.spec.ts +53 -0
  46. package/src/bn/toBn.ts +43 -0
  47. package/src/bn/toHex.spec.ts +50 -0
  48. package/src/bn/toHex.ts +27 -0
  49. package/src/bn/toU8a.spec.ts +60 -0
  50. package/src/bn/toU8a.ts +45 -0
  51. package/src/buffer/index.ts +8 -0
  52. package/src/buffer/toU8a.spec.ts +20 -0
  53. package/src/buffer/toU8a.ts +20 -0
  54. package/src/bundle.ts +35 -0
  55. package/src/compact/addLength.spec.ts +14 -0
  56. package/src/compact/addLength.ts +24 -0
  57. package/src/compact/defaults.ts +7 -0
  58. package/src/compact/fromU8a.spec.ts +84 -0
  59. package/src/compact/fromU8a.ts +109 -0
  60. package/src/compact/index.ts +28 -0
  61. package/src/compact/stripLength.spec.ts +17 -0
  62. package/src/compact/stripLength.ts +26 -0
  63. package/src/compact/toU8a.spec.ts +59 -0
  64. package/src/compact/toU8a.ts +53 -0
  65. package/src/compact/types.ts +4 -0
  66. package/src/detectPackage.spec.ts +110 -0
  67. package/src/detectPackage.ts +138 -0
  68. package/src/extractTime.spec.ts +21 -0
  69. package/src/extractTime.ts +71 -0
  70. package/src/float/index.ts +4 -0
  71. package/src/float/toU8a.spec.ts +52 -0
  72. package/src/float/toU8a.ts +30 -0
  73. package/src/format/formatBalance.spec.ts +296 -0
  74. package/src/format/formatBalance.ts +177 -0
  75. package/src/format/formatDate.spec.ts +17 -0
  76. package/src/format/formatDate.ts +22 -0
  77. package/src/format/formatDecimal.spec.ts +28 -0
  78. package/src/format/formatDecimal.ts +22 -0
  79. package/src/format/formatElapsed.spec.ts +44 -0
  80. package/src/format/formatElapsed.ts +35 -0
  81. package/src/format/formatNumber.spec.ts +60 -0
  82. package/src/format/formatNumber.ts +29 -0
  83. package/src/format/getSeparator.spec.ts +53 -0
  84. package/src/format/getSeparator.ts +15 -0
  85. package/src/format/index.ts +9 -0
  86. package/src/format/si.ts +52 -0
  87. package/src/has.spec.ts +12 -0
  88. package/src/has.ts +38 -0
  89. package/src/hex/addPrefix.spec.ts +32 -0
  90. package/src/hex/addPrefix.ts +26 -0
  91. package/src/hex/fixLength.spec.ts +38 -0
  92. package/src/hex/fixLength.ts +36 -0
  93. package/src/hex/hasPrefix.spec.ts +32 -0
  94. package/src/hex/hasPrefix.ts +24 -0
  95. package/src/hex/index.ts +16 -0
  96. package/src/hex/stripPrefix.spec.ts +44 -0
  97. package/src/hex/stripPrefix.ts +30 -0
  98. package/src/hex/toBigInt.spec.ts +74 -0
  99. package/src/hex/toBigInt.ts +19 -0
  100. package/src/hex/toBn.spec.ts +74 -0
  101. package/src/hex/toBn.ts +40 -0
  102. package/src/hex/toNumber.spec.ts +20 -0
  103. package/src/hex/toNumber.ts +24 -0
  104. package/src/hex/toString.spec.ts +20 -0
  105. package/src/hex/toString.ts +25 -0
  106. package/src/hex/toU8a.spec.ts +76 -0
  107. package/src/hex/toU8a.ts +68 -0
  108. package/src/hex/toU8aBuffer.spec.ts +38 -0
  109. package/src/hex/toU8aBuffer.ts +52 -0
  110. package/src/index.spec.ts +12 -0
  111. package/src/index.ts +6 -0
  112. package/src/is/array.spec.ts +20 -0
  113. package/src/is/array.ts +10 -0
  114. package/src/is/ascii.spec.ts +49 -0
  115. package/src/is/ascii.ts +52 -0
  116. package/src/is/bigInt.spec.ts +26 -0
  117. package/src/is/bigInt.ts +20 -0
  118. package/src/is/bn.spec.ts +21 -0
  119. package/src/is/bn.ts +23 -0
  120. package/src/is/boolean.spec.ts +26 -0
  121. package/src/is/boolean.ts +20 -0
  122. package/src/is/buffer.spec.ts +26 -0
  123. package/src/is/buffer.ts +28 -0
  124. package/src/is/childClass.spec.ts +36 -0
  125. package/src/is/childClass.ts +29 -0
  126. package/src/is/class.spec.ts +37 -0
  127. package/src/is/class.ts +12 -0
  128. package/src/is/codec.spec.ts +52 -0
  129. package/src/is/codec.ts +26 -0
  130. package/src/is/compact.spec.ts +27 -0
  131. package/src/is/compact.ts +19 -0
  132. package/src/is/error.spec.ts +20 -0
  133. package/src/is/error.ts +23 -0
  134. package/src/is/function.spec.ts +20 -0
  135. package/src/is/function.ts +23 -0
  136. package/src/is/helpers.ts +23 -0
  137. package/src/is/hex.spec.ts +77 -0
  138. package/src/is/hex.ts +36 -0
  139. package/src/is/index.ts +36 -0
  140. package/src/is/instanceOf.spec.ts +48 -0
  141. package/src/is/instanceOf.ts +24 -0
  142. package/src/is/ip.spec.ts +50 -0
  143. package/src/is/ip.ts +56 -0
  144. package/src/is/jsonObject.spec.ts +51 -0
  145. package/src/is/jsonObject.ts +45 -0
  146. package/src/is/null.spec.ts +20 -0
  147. package/src/is/null.ts +20 -0
  148. package/src/is/number.spec.ts +20 -0
  149. package/src/is/number.ts +20 -0
  150. package/src/is/object.spec.ts +32 -0
  151. package/src/is/object.ts +24 -0
  152. package/src/is/observable.spec.ts +26 -0
  153. package/src/is/observable.ts +22 -0
  154. package/src/is/promise.spec.ts +32 -0
  155. package/src/is/promise.ts +6 -0
  156. package/src/is/riscv.spec.ts +36 -0
  157. package/src/is/riscv.ts +27 -0
  158. package/src/is/string.spec.ts +32 -0
  159. package/src/is/string.ts +22 -0
  160. package/src/is/testChain.spec.ts +25 -0
  161. package/src/is/testChain.ts +12 -0
  162. package/src/is/toBigInt.spec.ts +22 -0
  163. package/src/is/toBigInt.ts +8 -0
  164. package/src/is/toBn.spec.ts +25 -0
  165. package/src/is/toBn.ts +8 -0
  166. package/src/is/u8a.spec.ts +42 -0
  167. package/src/is/u8a.ts +25 -0
  168. package/src/is/undefined.spec.ts +23 -0
  169. package/src/is/undefined.ts +21 -0
  170. package/src/is/utf8.spec.ts +42 -0
  171. package/src/is/utf8.ts +207 -0
  172. package/src/is/wasm.spec.ts +20 -0
  173. package/src/is/wasm.ts +17 -0
  174. package/src/lazy.spec.ts +71 -0
  175. package/src/lazy.ts +63 -0
  176. package/src/logger.spec.ts +188 -0
  177. package/src/logger.ts +160 -0
  178. package/src/memoize.spec.ts +79 -0
  179. package/src/memoize.ts +49 -0
  180. package/src/mod.ts +4 -0
  181. package/src/nextTick.ts +26 -0
  182. package/src/noop.ts +16 -0
  183. package/src/number/index.ts +9 -0
  184. package/src/number/toHex.spec.ts +44 -0
  185. package/src/number/toHex.ts +27 -0
  186. package/src/number/toU8a.spec.ts +50 -0
  187. package/src/number/toU8a.ts +25 -0
  188. package/src/object/clear.spec.ts +14 -0
  189. package/src/object/clear.ts +16 -0
  190. package/src/object/copy.spec.ts +17 -0
  191. package/src/object/copy.ts +12 -0
  192. package/src/object/entries.spec.ts +20 -0
  193. package/src/object/entries.ts +12 -0
  194. package/src/object/index.ts +10 -0
  195. package/src/object/keys.spec.ts +19 -0
  196. package/src/object/keys.ts +10 -0
  197. package/src/object/property.spec.ts +149 -0
  198. package/src/object/property.ts +39 -0
  199. package/src/object/spread.spec.ts +36 -0
  200. package/src/object/spread.ts +38 -0
  201. package/src/object/values.spec.ts +19 -0
  202. package/src/object/values.ts +10 -0
  203. package/src/packageDetect.ts +13 -0
  204. package/src/packageInfo.ts +6 -0
  205. package/src/promisify.spec.ts +50 -0
  206. package/src/promisify.ts +30 -0
  207. package/src/string/camelCase.spec.ts +119 -0
  208. package/src/string/camelCase.ts +79 -0
  209. package/src/string/index.ts +12 -0
  210. package/src/string/lowerFirst.spec.ts +41 -0
  211. package/src/string/lowerFirst.ts +46 -0
  212. package/src/string/pascalCase.spec.ts +26 -0
  213. package/src/string/shorten.spec.ts +38 -0
  214. package/src/string/shorten.ts +24 -0
  215. package/src/string/toHex.spec.ts +26 -0
  216. package/src/string/toHex.ts +27 -0
  217. package/src/string/toU8a.spec.ts +31 -0
  218. package/src/string/toU8a.ts +28 -0
  219. package/src/string/upperFirst.spec.ts +41 -0
  220. package/src/stringify.spec.ts +33 -0
  221. package/src/stringify.ts +20 -0
  222. package/src/test/index.ts +4 -0
  223. package/src/test/performance.ts +92 -0
  224. package/src/types.ts +100 -0
  225. package/src/u8a/cmp.spec.ts +62 -0
  226. package/src/u8a/cmp.ts +50 -0
  227. package/src/u8a/concat.spec.ts +42 -0
  228. package/src/u8a/concat.ts +60 -0
  229. package/src/u8a/concatBuffer.ts +34 -0
  230. package/src/u8a/empty.spec.ts +46 -0
  231. package/src/u8a/empty.ts +22 -0
  232. package/src/u8a/eq.spec.ts +113 -0
  233. package/src/u8a/eq.ts +46 -0
  234. package/src/u8a/fixLength.spec.ts +34 -0
  235. package/src/u8a/fixLength.ts +34 -0
  236. package/src/u8a/index.ts +22 -0
  237. package/src/u8a/sorted.spec.ts +20 -0
  238. package/src/u8a/sorted.ts +22 -0
  239. package/src/u8a/toBigInt.spec.ts +106 -0
  240. package/src/u8a/toBigInt.ts +100 -0
  241. package/src/u8a/toBn.spec.ts +106 -0
  242. package/src/u8a/toBn.ts +101 -0
  243. package/src/u8a/toBuffer.spec.ts +20 -0
  244. package/src/u8a/toBuffer.ts +28 -0
  245. package/src/u8a/toFloat.spec.ts +86 -0
  246. package/src/u8a/toFloat.ts +26 -0
  247. package/src/u8a/toHex.spec.ts +94 -0
  248. package/src/u8a/toHex.ts +68 -0
  249. package/src/u8a/toHexBuffer.spec.ts +63 -0
  250. package/src/u8a/toHexBuffer.ts +30 -0
  251. package/src/u8a/toNumber.spec.ts +47 -0
  252. package/src/u8a/toNumber.ts +80 -0
  253. package/src/u8a/toString.spec.ts +36 -0
  254. package/src/u8a/toString.ts +26 -0
  255. package/src/u8a/toU8a.spec.ts +63 -0
  256. package/src/u8a/toU8a.ts +46 -0
  257. package/src/u8a/wrap.spec.ts +139 -0
  258. package/src/u8a/wrap.ts +65 -0
  259. package/tsconfig.build.json +19 -0
  260. package/tsconfig.spec.json +17 -0
@@ -0,0 +1,46 @@
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
+ import { CC_TO_LO, CC_TO_UP } from './camelCase.js';
7
+
8
+ /** @internal */
9
+ function converter (map: readonly string[]): (value?: AnyString | null) => string {
10
+ return (value?: AnyString | null): string =>
11
+ value
12
+ ? map[value.charCodeAt(0)] + value.slice(1)
13
+ : '';
14
+ }
15
+
16
+ /**
17
+ * @name stringLowerFirst
18
+ * @summary Lowercase the first letter of a string
19
+ * @description
20
+ * Lowercase the first letter of a string
21
+ * @example
22
+ * <BR>
23
+ *
24
+ * ```javascript
25
+ * import { stringLowerFirst } from '@pezkuwi/util';
26
+ *
27
+ * stringLowerFirst('ABC'); // => 'aBC'
28
+ * ```
29
+ */
30
+ export const stringLowerFirst = /*#__PURE__*/ converter(CC_TO_LO);
31
+
32
+ /**
33
+ * @name stringUpperFirst
34
+ * @summary Uppercase the first letter of a string
35
+ * @description
36
+ * Lowercase the first letter of a string
37
+ * @example
38
+ * <BR>
39
+ *
40
+ * ```javascript
41
+ * import { stringUpperFirst } from '@pezkuwi/util';
42
+ *
43
+ * stringUpperFirst('abc'); // => 'Abc'
44
+ * ```
45
+ */
46
+ export const stringUpperFirst = /*#__PURE__*/ converter(CC_TO_UP);
@@ -0,0 +1,26 @@
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 { stringPascalCase } from './index.js';
7
+
8
+ describe('stringPascalCase', (): void => {
9
+ it('works correctly', (): void => {
10
+ expect(
11
+ stringPascalCase('Snake_case-something spaced')
12
+ ).toBe('SnakeCaseSomethingSpaced');
13
+ });
14
+
15
+ it('works correctly for String (class)', (): void => {
16
+ expect(
17
+ stringPascalCase(String('foo_bar-- __baz Bob'))
18
+ ).toBe('FooBarBazBob');
19
+ });
20
+
21
+ it('adjusts all-uppercase + digits', (): void => {
22
+ expect(
23
+ stringPascalCase('UUID64')
24
+ ).toEqual('Uuid64');
25
+ });
26
+ });
@@ -0,0 +1,38 @@
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 { stringShorten } from './index.js';
7
+
8
+ describe('stringShorten', (): void => {
9
+ it('returns the value as-is when <= maxLength', (): void => {
10
+ expect(
11
+ stringShorten('0123456789', 4)
12
+ ).toEqual('0123456789');
13
+ });
14
+
15
+ it('returns the shortened value when > maxLength', (): void => {
16
+ expect(
17
+ stringShorten('0123456789', 3)
18
+ ).toEqual('012…789');
19
+ });
20
+
21
+ it('returns the shortened value when > maxLength (String)', (): void => {
22
+ expect(
23
+ stringShorten(String('0123456789'), 3)
24
+ ).toEqual('012…789');
25
+ });
26
+
27
+ it('returns the value as-is when <= maxLength (defaults)', (): void => {
28
+ expect(
29
+ stringShorten('012345', 4)
30
+ ).toEqual('012345');
31
+ });
32
+
33
+ it('returns the shortened value when > maxLength (defaults)', (): void => {
34
+ expect(
35
+ stringShorten('01234567890123456789')
36
+ ).toEqual('012345…456789');
37
+ });
38
+ });
@@ -0,0 +1,24 @@
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
+ /**
7
+ * @name stringShorten
8
+ * @summary Returns a string with maximum length
9
+ * @description
10
+ * Checks the string against the `prefixLength`, if longer than double this, shortens it by placing `..` in the middle of it
11
+ * @example
12
+ * <BR>
13
+ *
14
+ * ```javascript
15
+ * import { stringShorten } from '@pezkuwi/util';
16
+ *
17
+ * stringShorten('1234567890', 2); // => 12..90
18
+ * ```
19
+ */
20
+ export function stringShorten (value: AnyString, prefixLength = 6): string {
21
+ return value.length <= 2 + 2 * prefixLength
22
+ ? value.toString()
23
+ : `${value.substring(0, prefixLength)}…${value.slice(-prefixLength)}`;
24
+ }
@@ -0,0 +1,26 @@
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 { stringToHex } from './index.js';
7
+
8
+ describe('hexToString', (): void => {
9
+ it('converts an empty to ""', (): void => {
10
+ expect(
11
+ stringToHex()
12
+ ).toEqual('0x');
13
+ });
14
+
15
+ it('converts to a hex from string', (): void => {
16
+ expect(
17
+ stringToHex('hello')
18
+ ).toEqual('0x68656c6c6f');
19
+ });
20
+
21
+ it('converts to a hex from String', (): void => {
22
+ expect(
23
+ stringToHex(String('hello'))
24
+ ).toEqual('0x68656c6c6f');
25
+ });
26
+ });
@@ -0,0 +1,27 @@
1
+ // Copyright 2017-2025 @polkadot/util authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import type { AnyString, HexString } from '../types.js';
5
+
6
+ import { u8aToHex } from '../u8a/toHex.js';
7
+ import { stringToU8a } from './toU8a.js';
8
+
9
+ /**
10
+ * @name stringToHex
11
+ * @summary Creates a hex string from a utf-8 string
12
+ * @description
13
+ * String input values return the actual encoded hex value.
14
+ * @example
15
+ * <BR>
16
+ *
17
+ * ```javascript
18
+ * import { stringToHex } from '@pezkuwi/util';
19
+ *
20
+ * stringToU8a('hello'); // 0x68656c6c6f
21
+ * ```
22
+ */
23
+ export function stringToHex (value?: AnyString): HexString {
24
+ return u8aToHex(
25
+ stringToU8a(value)
26
+ );
27
+ }
@@ -0,0 +1,31 @@
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 { stringToU8a } from '../index.js';
7
+
8
+ const RUSS_HELLO = new Uint8Array([208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 44, 32, 208, 188, 208, 184, 209, 128, 33]);
9
+
10
+ describe('stringToU8a', (): void => {
11
+ it('decodes to an empty string for undefined/null', (): void => {
12
+ expect(
13
+ stringToU8a()
14
+ ).toEqual(new Uint8Array());
15
+ expect(
16
+ stringToU8a(null)
17
+ ).toEqual(new Uint8Array());
18
+ });
19
+
20
+ it('encodes the string correctly', (): void => {
21
+ expect(
22
+ stringToU8a('Привет, мир!')
23
+ ).toEqual(RUSS_HELLO);
24
+ });
25
+
26
+ it('encodes the string correctly (String)', (): void => {
27
+ expect(
28
+ stringToU8a(String('Привет, мир!'))
29
+ ).toEqual(RUSS_HELLO);
30
+ });
31
+ });
@@ -0,0 +1,28 @@
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
+ import { TextEncoder } from '@pezkuwi/x-textencoder';
7
+
8
+ const encoder = new TextEncoder();
9
+
10
+ /**
11
+ * @name stringToU8a
12
+ * @summary Creates a Uint8Array object from a utf-8 string.
13
+ * @description
14
+ * String input values return the actual encoded `UInt8Array`. `null` or `undefined` values returns an empty encoded array.
15
+ * @example
16
+ * <BR>
17
+ *
18
+ * ```javascript
19
+ * import { stringToU8a } from '@pezkuwi/util';
20
+ *
21
+ * stringToU8a('hello'); // [0x68, 0x65, 0x6c, 0x6c, 0x6f]
22
+ * ```
23
+ */
24
+ export function stringToU8a (value?: AnyString | null): Uint8Array {
25
+ return value
26
+ ? encoder.encode(value.toString())
27
+ : new Uint8Array();
28
+ }
@@ -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 { stringUpperFirst } from './index.js';
8
+
9
+ describe('stringUpperFirst', (): void => {
10
+ it("uppers the first letter if it's a capital letter", (): void => {
11
+ expect(
12
+ stringUpperFirst('ABC')
13
+ ).toBe('ABC');
14
+ });
15
+
16
+ it("uppers the first letter if it's a lowercase letter", (): void => {
17
+ expect(
18
+ stringUpperFirst('abc')
19
+ ).toBe('Abc');
20
+ });
21
+
22
+ it("uppers the first letter if it's a lowercase letter (String)", (): void => {
23
+ expect(
24
+ stringUpperFirst(String('abc'))
25
+ ).toBe('Abc');
26
+ });
27
+
28
+ it('returns undefined as empty', (): void => {
29
+ expect(
30
+ stringUpperFirst()
31
+ ).toBe('');
32
+ });
33
+
34
+ it('returns null as empty', (): void => {
35
+ expect(
36
+ stringUpperFirst(null)
37
+ ).toBe('');
38
+ });
39
+
40
+ perf('stringUpperFirst', 1_000_000, [['helloWorldSomething']], stringUpperFirst);
41
+ });
@@ -0,0 +1,33 @@
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 { BN } from './bn/index.js';
7
+ import { stringify } from './stringify.js';
8
+
9
+ describe('stringify', (): void => {
10
+ it('stringifies a BigInt', (): void => {
11
+ expect(
12
+ stringify(1234n)
13
+ ).toEqual('"1234"');
14
+ });
15
+
16
+ it('stringifies an array of values', (): void => {
17
+ expect(
18
+ stringify(['a', 1, 2n, new BN(69)])
19
+ ).toEqual('["a",1,"2","45"]');
20
+ });
21
+
22
+ it('stringifies an array of values (with spaces)', (): void => {
23
+ expect(
24
+ stringify(['a', 1, 2n, new BN(3)], 2)
25
+ ).toEqual('[\n "a",\n 1,\n "2",\n "03"\n]');
26
+ });
27
+
28
+ it('stringifies a nested object', (): void => {
29
+ expect(
30
+ stringify({ a: 'a', b: 1, c: { d: 2n, e: new BN(3) } })
31
+ ).toEqual('{"a":"a","b":1,"c":{"d":"2","e":"03"}}');
32
+ });
33
+ });
@@ -0,0 +1,20 @@
1
+ // Copyright 2017-2025 @polkadot/util authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { isBigInt } from './is/bigInt.js';
5
+
6
+ /** @internal */
7
+ function replacer (_: unknown, v: unknown): unknown {
8
+ return isBigInt(v)
9
+ ? v.toString()
10
+ : v;
11
+ }
12
+
13
+ /**
14
+ * @name stringify
15
+ * @summary Performs a JSON.stringify, with BigInt handling
16
+ * @description A wrapper for JSON.stringify that handles BigInt values transparently, converting them to string. No differences from the native JSON.stringify function otherwise.
17
+ */
18
+ export function stringify (value: unknown, space?: string | number): string {
19
+ return JSON.stringify(value, replacer, space);
20
+ }
@@ -0,0 +1,4 @@
1
+ // Copyright 2017-2025 @polkadot/util authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { perf, perfCmp } from './performance.js';
@@ -0,0 +1,92 @@
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
+ /* global it, expect */
7
+
8
+ import { formatDecimal, formatNumber, stringify } from '../index.js';
9
+
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ type ExecFn = (...params: any[]) => unknown;
12
+
13
+ const NUM_PAD = 16;
14
+ const PRE_PAD = 32;
15
+
16
+ function loop (exec: ExecFn, count: number, inputs: readonly unknown[][]): [number, unknown[]] {
17
+ const start = performance.now();
18
+ const results = new Array<unknown>(inputs.length);
19
+
20
+ for (let i = 0; i < count; i++) {
21
+ const result = exec(...inputs[i % inputs.length]);
22
+
23
+ if (i < inputs.length) {
24
+ results[i] = result;
25
+ }
26
+ }
27
+
28
+ return [performance.now() - start, results];
29
+ }
30
+
31
+ export function formatFixed (value: number): string {
32
+ const [a, b] = value.toFixed(2).split('.');
33
+
34
+ return [formatDecimal(a), b].join('.');
35
+ }
36
+
37
+ export function formatOps (count: number, time: number): string {
38
+ const micro = (time * 1000) / count;
39
+ const ops = 1_000_000 / micro;
40
+
41
+ return `
42
+ ${formatFixed(ops).padStart(NUM_PAD + PRE_PAD + 1)} ops/s
43
+ ${formatFixed(micro).padStart(NUM_PAD + PRE_PAD + 1)} μs/op`;
44
+ }
45
+
46
+ export function perf (name: string, count: number, inputs: readonly unknown[][], exec: ExecFn, withLog?: boolean): void {
47
+ const test = process.env['GITHUB_REPOSITORY']
48
+ ? it.skip
49
+ : it;
50
+
51
+ test(`performance: ${name}`, (): void => {
52
+ const [time, results] = loop(exec, count, inputs);
53
+
54
+ console.error(`
55
+ performance run for ${name} completed with ${formatNumber(count)} iterations.
56
+
57
+ ${`${name}:`.padStart(PRE_PAD)} ${time.toFixed(2).padStart(NUM_PAD)} ms${formatOps(count, time)}
58
+ `);
59
+
60
+ if (withLog) {
61
+ console.log(results);
62
+ }
63
+ });
64
+ }
65
+
66
+ export function perfCmp (name: string, [first, second]: [string, string], count: number, inputs: readonly unknown[][], exec: ExecFn): void {
67
+ const test = process.env['GITHUB_REPOSITORY']
68
+ ? it.skip
69
+ : it;
70
+
71
+ test(`performance: ${name}`, (): void => {
72
+ const [[t1, r1], [t2, r2]] = [false, true].map((flag) =>
73
+ loop(exec, count, inputs.map((values) =>
74
+ [...values, flag]
75
+ ))
76
+ );
77
+
78
+ console.error(`
79
+ performance run for ${name} completed with ${formatNumber(count)} iterations.
80
+
81
+ ${`${first}:`.padStart(PRE_PAD)} ${t1.toFixed(2).padStart(NUM_PAD)} ms ${t1 < t2 ? '(fastest)' : `(slowest, ${(t1 / t2).toFixed(2)}x)`}${formatOps(count, t1)}
82
+
83
+ ${`${second}:`.padStart(PRE_PAD)} ${t2.toFixed(2).padStart(NUM_PAD)} ms ${t1 > t2 ? '(fastest)' : `(slowest, ${(t2 / t1).toFixed(2)}x)`}${formatOps(count, t2)}
84
+ `);
85
+
86
+ expect(
87
+ r1.filter((_, i) =>
88
+ stringify(r1[i]) !== stringify(r2[i])
89
+ )
90
+ ).toHaveLength(0);
91
+ });
92
+ }
package/src/types.ts ADDED
@@ -0,0 +1,100 @@
1
+ // Copyright 2017-2025 @polkadot/util authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import type { BN } from './bn/bn.js';
5
+
6
+ /* eslint-disable @typescript-eslint/no-explicit-any */
7
+
8
+ /** An interface that defines an actual JS class */
9
+ export interface Class<T = any, A extends unknown[] = any[]> {
10
+ prototype: T;
11
+
12
+ new (...args: A): T;
13
+
14
+ hasOwnProperty (prop: string): boolean;
15
+ isPrototypeOf (other: unknown): boolean;
16
+ }
17
+
18
+ // @deprecated Use Class<T, A> instead
19
+ export type Constructor<T = any, A extends unknown[] = any[]> = Class<T, A>;
20
+
21
+ export interface ToBigInt {
22
+ toBigInt: () => bigint;
23
+ }
24
+
25
+ export interface ToBn {
26
+ toBn: () => BN;
27
+ }
28
+
29
+ export interface SiDef {
30
+ power: number;
31
+ text: string;
32
+ value: string;
33
+ }
34
+
35
+ export interface Logger {
36
+ debug: (...values: unknown[]) => void;
37
+ error: (...values: unknown[]) => void;
38
+ log: (...values: unknown[]) => void;
39
+ noop: (...values: unknown[]) => void;
40
+ warn: (...values: unknown[]) => void;
41
+ }
42
+
43
+ export interface ToBnOptions {
44
+ /** Convert in LE format */
45
+ isLe?: boolean;
46
+ /** Number is signed, apply two's complement */
47
+ isNegative?: boolean;
48
+ }
49
+
50
+ export interface NumberOptions extends ToBnOptions {
51
+ /** Limit to the specified bitLength, despite input length */
52
+ bitLength?: number;
53
+ }
54
+
55
+ export interface Time {
56
+ days: number;
57
+ hours: number;
58
+ minutes: number;
59
+ seconds: number;
60
+ milliseconds: number;
61
+ }
62
+
63
+ export type Memoized<F> = F & {
64
+ unmemoize: (...args: unknown[]) => void;
65
+ }
66
+
67
+ // eslint-disable-next-line @typescript-eslint/ban-types
68
+ export type AnyString = string | String;
69
+
70
+ export type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
71
+
72
+ // One day when template strings support regex, we can improve this
73
+ export type HexString = `0x${string}`;
74
+
75
+ // BufferObject interface compatible with Buffer since we don't want to require
76
+ // references to the Buffer types from the node typings
77
+ //
78
+ // Caveat: the references still do sneak in in the d.ts files, specifically
79
+ // inside u8a/toBuffer & is/buffer (but not in compiled outputs)
80
+ export interface BufferObject extends Uint8Array {
81
+ // Possibly used externally via type imports
82
+ equals: (otherBuffer: Uint8Array) => boolean;
83
+ // As used in is/buffer
84
+ readDoubleLE: (offset?: number) => number;
85
+ }
86
+
87
+ // We define a scappy low-level interface to mock Buffer
88
+ // (this removes the need for the node typings in built bundles)
89
+ export interface BufferClass extends Class<BufferObject> {
90
+ // As used in u8a/toBuffer
91
+ from: <T = BufferObject>(value: unknown) => T;
92
+ // As used in is/buffer
93
+ isBuffer: (value: unknown) => boolean;
94
+ }
95
+
96
+ export type U8aLike = number[] | Uint8Array | AnyString;
97
+
98
+ export interface Observable {
99
+ next: (...params: unknown[]) => unknown;
100
+ }
@@ -0,0 +1,62 @@
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 { u8aCmp } from './index.js';
8
+
9
+ const ltest = new Uint8Array(32768);
10
+ const stest = new Uint8Array(256);
11
+ const ztest = new Uint8Array(64);
12
+
13
+ for (let i = 0, count = ltest.length; i < count; i++) {
14
+ if (i < ztest.length) {
15
+ ztest[i] = i % 256;
16
+ }
17
+
18
+ if (i < stest.length) {
19
+ stest[i] = i % 256;
20
+ }
21
+
22
+ ltest[i] = i % 256;
23
+ }
24
+
25
+ describe('u8aCmp', (): void => {
26
+ it('has the same result as localCompare (equal length)', (): void => {
27
+ const a = 'test abc';
28
+ const b = 'test def';
29
+
30
+ expect(
31
+ u8aCmp(a, b)
32
+ ).toEqual(a.localeCompare(b));
33
+ expect(
34
+ u8aCmp(b, a)
35
+ ).toEqual(b.localeCompare(a));
36
+ });
37
+
38
+ it('has the same result as localCompare (diff length)', (): void => {
39
+ const a = 'test';
40
+ const b = 'test abc';
41
+
42
+ expect(
43
+ u8aCmp(a, b)
44
+ ).toEqual(a.localeCompare(b));
45
+ expect(
46
+ u8aCmp(b, a)
47
+ ).toEqual(b.localeCompare(a));
48
+ });
49
+
50
+ it('compares between string and Uint8Array', (): void => {
51
+ expect(
52
+ u8aCmp(
53
+ '0x12345678',
54
+ new Uint8Array([0x12, 0x34, 0x56, 0x78])
55
+ )
56
+ ).toEqual(0);
57
+ });
58
+
59
+ perf('u8aCmp (64 cmp)', 100_000, [[ztest, ztest]], u8aCmp);
60
+ perf('u8aCmp (256 cmp)', 50_000, [[stest, stest]], u8aCmp);
61
+ perf('u8aCmp (32k cmp)', 500, [[ltest, ltest]], u8aCmp);
62
+ });
package/src/u8a/cmp.ts ADDED
@@ -0,0 +1,50 @@
1
+ // Copyright 2017-2025 @polkadot/util authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { u8aToU8a } from './toU8a.js';
5
+
6
+ /**
7
+ * @name u8aCmp
8
+ * @summary Compares two Uint8Arrays for sorting.
9
+ * @description
10
+ * For `UInt8Array` (or hex string) input values returning -1, 0 or +1
11
+ * @example
12
+ * <BR>
13
+ *
14
+ * ```javascript
15
+ * import { u8aCmp } from '@pezkuwi/util';
16
+ *
17
+ * u8aCmp(new Uint8Array([0x67, 0x65]), new Uint8Array([0x68, 0x65])); // -1
18
+ * u8aCmp(new Uint8Array([0x68, 0x65]), new Uint8Array([0x68, 0x65])); // 0
19
+ * u8aCmp(new Uint8Array([0x69, 0x65]), new Uint8Array([0x68, 0x65])); // +1
20
+ * ```
21
+ */
22
+ export function u8aCmp (a: string | Uint8Array, b: string | Uint8Array): number {
23
+ const u8aa = u8aToU8a(a);
24
+ const u8ab = u8aToU8a(b);
25
+ let i = 0;
26
+
27
+ while (true) {
28
+ const overA = i >= u8aa.length;
29
+ const overB = i >= u8ab.length;
30
+
31
+ if (overA && overB) {
32
+ // both ends reached
33
+ return 0;
34
+ } else if (overA) {
35
+ // a has no more data, b has data
36
+ return -1;
37
+ } else if (overB) {
38
+ // b has no more data, a has data
39
+ return 1;
40
+ } else if (u8aa[i] !== u8ab[i]) {
41
+ // the number in this index doesn't match
42
+ // (we don't use u8aa[i] - u8ab[i] since that doesn't match with localeCompare)
43
+ return u8aa[i] > u8ab[i]
44
+ ? 1
45
+ : -1;
46
+ }
47
+
48
+ i++;
49
+ }
50
+ }