@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,177 @@
|
|
|
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
|
+
import type { SiDef, ToBn } from '../types.js';
|
|
6
|
+
|
|
7
|
+
import { bnToBn } from '../bn/toBn.js';
|
|
8
|
+
import { isBoolean } from '../is/boolean.js';
|
|
9
|
+
import { formatDecimal } from './formatDecimal.js';
|
|
10
|
+
import { getSeparator } from './getSeparator.js';
|
|
11
|
+
import { calcSi, findSi, SI, SI_MID } from './si.js';
|
|
12
|
+
|
|
13
|
+
interface Defaults {
|
|
14
|
+
decimals: number;
|
|
15
|
+
unit: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface SetDefaults {
|
|
19
|
+
decimals?: number[] | number;
|
|
20
|
+
unit?: string[] | string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Options {
|
|
24
|
+
/**
|
|
25
|
+
* @description The number of decimals
|
|
26
|
+
*/
|
|
27
|
+
decimals?: number;
|
|
28
|
+
/**
|
|
29
|
+
* @description Format the number with this specific unit
|
|
30
|
+
*/
|
|
31
|
+
forceUnit?: string;
|
|
32
|
+
/**
|
|
33
|
+
* @description Returns value using all available decimals
|
|
34
|
+
*/
|
|
35
|
+
withAll?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* @description Format with SI, i.e. m/M/etc. (default = true)
|
|
38
|
+
*/
|
|
39
|
+
withSi?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* @description Format with full SI, i.e. mili/Mega/etc.
|
|
42
|
+
*/
|
|
43
|
+
withSiFull?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* @description Add the unit (useful in Balance formats)
|
|
46
|
+
*/
|
|
47
|
+
withUnit?: boolean | string;
|
|
48
|
+
/**
|
|
49
|
+
* @description Returns all trailing zeros, otherwise removes (default = true)
|
|
50
|
+
*/
|
|
51
|
+
withZero?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* @description The locale to use
|
|
54
|
+
*/
|
|
55
|
+
locale?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface BalanceFormatter {
|
|
59
|
+
<ExtToBn extends ToBn> (input?: number | string | BN | bigint | ExtToBn, options?: Options): string;
|
|
60
|
+
calcSi (text: string, decimals?: number): SiDef;
|
|
61
|
+
findSi (type: string): SiDef;
|
|
62
|
+
getDefaults (): Defaults;
|
|
63
|
+
getOptions (decimals?: number): SiDef[];
|
|
64
|
+
setDefaults (defaults: SetDefaults): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const DEFAULT_DECIMALS = 0;
|
|
68
|
+
const DEFAULT_UNIT = SI[SI_MID].text;
|
|
69
|
+
|
|
70
|
+
let defaultDecimals = DEFAULT_DECIMALS;
|
|
71
|
+
let defaultUnit = DEFAULT_UNIT;
|
|
72
|
+
|
|
73
|
+
// Formats a string/number with <prefix>.<postfix><type> notation
|
|
74
|
+
function _formatBalance <ExtToBn extends ToBn> (input?: number | string | BN | bigint | ExtToBn, { decimals = defaultDecimals, forceUnit, locale = 'en', withAll = false, withSi = true, withSiFull = false, withUnit = true, withZero = true }: Options = {}): string {
|
|
75
|
+
// we only work with string inputs here - convert anything
|
|
76
|
+
// into the string-only value
|
|
77
|
+
let text = bnToBn(input).toString();
|
|
78
|
+
|
|
79
|
+
if (text.length === 0 || text === '0') {
|
|
80
|
+
return '0';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// strip the negative sign so we can work with clean groupings, re-add this in the
|
|
84
|
+
// end when we return the result (from here on we work with positive numbers)
|
|
85
|
+
let sign = '';
|
|
86
|
+
|
|
87
|
+
if (text[0].startsWith('-')) {
|
|
88
|
+
sign = '-';
|
|
89
|
+
text = text.substring(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// We start at midpoint (8) minus 1 - this means that values display as
|
|
93
|
+
// 123.4567 instead of 0.1234 k (so we always have the most relevant).
|
|
94
|
+
const si = calcSi(text, decimals, forceUnit);
|
|
95
|
+
const mid = text.length - (decimals + si.power);
|
|
96
|
+
const pre = mid <= 0 ? '0' : text.substring(0, mid);
|
|
97
|
+
|
|
98
|
+
// get the post from the midpoint onward and then first add max decimals
|
|
99
|
+
// before trimming to the correct (calculated) amount of decimals again
|
|
100
|
+
let post = text
|
|
101
|
+
.padStart(mid < 0 ? decimals : 1, '0')
|
|
102
|
+
.substring(mid < 0 ? 0 : mid)
|
|
103
|
+
.padEnd(withAll ? Math.max(decimals, 4) : 4, '0')
|
|
104
|
+
.substring(0, withAll ? Math.max(4, decimals + si.power) : 4);
|
|
105
|
+
|
|
106
|
+
// remove all trailing 0's (if required via flag)
|
|
107
|
+
if (!withZero) {
|
|
108
|
+
let end = post.length - 1;
|
|
109
|
+
|
|
110
|
+
// This looks inefficient, however it is better to do the checks and
|
|
111
|
+
// only make one final slice than it is to do it in multiples
|
|
112
|
+
do {
|
|
113
|
+
if (post[end] === '0') {
|
|
114
|
+
end--;
|
|
115
|
+
}
|
|
116
|
+
} while (post[end] === '0');
|
|
117
|
+
|
|
118
|
+
post = post.substring(0, end + 1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// the display unit
|
|
122
|
+
const unit = isBoolean(withUnit)
|
|
123
|
+
? SI[SI_MID].text
|
|
124
|
+
: withUnit;
|
|
125
|
+
|
|
126
|
+
// format the units for display based on the flags
|
|
127
|
+
const units = withSi || withSiFull
|
|
128
|
+
? si.value === '-'
|
|
129
|
+
? withUnit
|
|
130
|
+
? ` ${unit}`
|
|
131
|
+
: ''
|
|
132
|
+
: ` ${withSiFull ? `${si.text}${withUnit ? ' ' : ''}` : si.value}${withUnit ? unit : ''}`
|
|
133
|
+
: '';
|
|
134
|
+
|
|
135
|
+
const { decimal, thousand } = getSeparator(locale);
|
|
136
|
+
|
|
137
|
+
return `${sign}${formatDecimal(pre, thousand)}${post && `${decimal}${post}`}${units}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const formatBalance = _formatBalance as BalanceFormatter;
|
|
141
|
+
|
|
142
|
+
formatBalance.calcSi = (text: string, decimals: number = defaultDecimals): SiDef =>
|
|
143
|
+
calcSi(text, decimals);
|
|
144
|
+
|
|
145
|
+
formatBalance.findSi = findSi;
|
|
146
|
+
|
|
147
|
+
formatBalance.getDefaults = (): Defaults => {
|
|
148
|
+
return {
|
|
149
|
+
decimals: defaultDecimals,
|
|
150
|
+
unit: defaultUnit
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// get allowable options to display in a dropdown
|
|
155
|
+
formatBalance.getOptions = (decimals: number = defaultDecimals): SiDef[] => {
|
|
156
|
+
return SI.filter(({ power }): boolean =>
|
|
157
|
+
power < 0
|
|
158
|
+
? (decimals + power) >= 0
|
|
159
|
+
: true
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Sets the default decimals to use for formatting (ui-wide)
|
|
164
|
+
formatBalance.setDefaults = ({ decimals, unit }: SetDefaults): void => {
|
|
165
|
+
defaultDecimals = (
|
|
166
|
+
Array.isArray(decimals)
|
|
167
|
+
? decimals[0]
|
|
168
|
+
: decimals
|
|
169
|
+
) ?? defaultDecimals;
|
|
170
|
+
defaultUnit = (
|
|
171
|
+
Array.isArray(unit)
|
|
172
|
+
? unit[0]
|
|
173
|
+
: unit
|
|
174
|
+
) ?? defaultUnit;
|
|
175
|
+
|
|
176
|
+
SI[SI_MID].text = defaultUnit;
|
|
177
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
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 { formatDate } from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('formatDate', (): void => {
|
|
9
|
+
it('formats a known date into the correct format', (): void => {
|
|
10
|
+
const date = new Date(Date.UTC(2020, 1, 15, 11, 14, 34));
|
|
11
|
+
|
|
12
|
+
// make this test-locale agnostic
|
|
13
|
+
date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
|
|
14
|
+
|
|
15
|
+
expect(formatDate(date)).toEqual('2020-02-15 11:14:34');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/** @internal */
|
|
5
|
+
function zeroPad (value: number): string {
|
|
6
|
+
return value.toString().padStart(2, '0');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @name formatDate
|
|
11
|
+
* @description Formats a date in CCYY-MM-DD HH:MM:SS format
|
|
12
|
+
*/
|
|
13
|
+
export function formatDate (date: Date): string {
|
|
14
|
+
const year = date.getFullYear().toString();
|
|
15
|
+
const month = zeroPad((date.getMonth() + 1));
|
|
16
|
+
const day = zeroPad(date.getDate());
|
|
17
|
+
const hour = zeroPad(date.getHours());
|
|
18
|
+
const minute = zeroPad(date.getMinutes());
|
|
19
|
+
const second = zeroPad(date.getSeconds());
|
|
20
|
+
|
|
21
|
+
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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 { formatDecimal } from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('formatDecimal', (): void => {
|
|
9
|
+
it('formats decimals in number groupings', (): void => {
|
|
10
|
+
expect(formatDecimal('12345')).toEqual('12,345');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('formats decimal-only in number groupings', (): void => {
|
|
14
|
+
expect(formatDecimal('test6789')).toEqual('6,789');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('returns input for non-decimal', (): void => {
|
|
18
|
+
expect(formatDecimal('test')).toEqual('test');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('returns non-sensical negative text', (): void => {
|
|
22
|
+
expect(formatDecimal('-test')).toEqual('-test');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('formats negative numbers', (): void => {
|
|
26
|
+
expect(formatDecimal('-123456')).toEqual('-123,456');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line prefer-regex-literals
|
|
5
|
+
const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @name formatDecimal
|
|
9
|
+
* @description Formats a number into string format with thousand separators
|
|
10
|
+
*/
|
|
11
|
+
export function formatDecimal (value: string, separator = ','): string {
|
|
12
|
+
// We can do this by adjusting the regx, however for the sake of clarity
|
|
13
|
+
// we rather strip and re-add the negative sign in the output
|
|
14
|
+
const isNegative = value[0].startsWith('-');
|
|
15
|
+
const matched = isNegative
|
|
16
|
+
? value.substring(1).match(NUMBER_REGEX)
|
|
17
|
+
: value.match(NUMBER_REGEX);
|
|
18
|
+
|
|
19
|
+
return matched
|
|
20
|
+
? `${isNegative ? '-' : ''}${matched.join(separator)}`
|
|
21
|
+
: value;
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
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 { formatElapsed } from './index.js';
|
|
8
|
+
|
|
9
|
+
describe('formatElapsed', (): void => {
|
|
10
|
+
const start = 12345678;
|
|
11
|
+
const now = new Date(12345678);
|
|
12
|
+
|
|
13
|
+
it('formats a Date', (): void => {
|
|
14
|
+
expect(
|
|
15
|
+
formatElapsed(now, new Date(start + 9700))
|
|
16
|
+
).toEqual('9.7s');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('formats a BN', (): void => {
|
|
20
|
+
expect(
|
|
21
|
+
formatElapsed(now, new BN(start + 42700))
|
|
22
|
+
).toEqual('42s');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('formats a Compact', (): void => {
|
|
26
|
+
expect(
|
|
27
|
+
formatElapsed(now, {
|
|
28
|
+
toBn: (): BN => new BN(start + (5.3 * 60000))
|
|
29
|
+
})
|
|
30
|
+
).toEqual('5m');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('formats a number', (): void => {
|
|
34
|
+
expect(
|
|
35
|
+
formatElapsed(now, start + (42 * 60 * 60000))
|
|
36
|
+
).toEqual('42h');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('formats defaults', (): void => {
|
|
40
|
+
expect(
|
|
41
|
+
formatElapsed()
|
|
42
|
+
).toEqual('0.0s');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
import type { ToBn } from '../types.js';
|
|
6
|
+
|
|
7
|
+
import { bnToBn } from '../bn/toBn.js';
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
function formatValue (elapsed: number): string {
|
|
11
|
+
if (elapsed < 15) {
|
|
12
|
+
return `${elapsed.toFixed(1)}s`;
|
|
13
|
+
} else if (elapsed < 60) {
|
|
14
|
+
return `${elapsed | 0}s`;
|
|
15
|
+
} else if (elapsed < 3600) {
|
|
16
|
+
return `${elapsed / 60 | 0}m`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return `${elapsed / 3600 | 0}h`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @name formatElapsed
|
|
24
|
+
* @description Formats an elapsed value into s, m, h or day segments
|
|
25
|
+
*/
|
|
26
|
+
export function formatElapsed <ExtToBn extends ToBn> (now?: Date | null, value?: bigint | BN | ExtToBn | Date | number | null): string {
|
|
27
|
+
const tsNow = now?.getTime() || 0;
|
|
28
|
+
const tsValue = value instanceof Date
|
|
29
|
+
? value.getTime()
|
|
30
|
+
: bnToBn(value).toNumber();
|
|
31
|
+
|
|
32
|
+
return (tsNow && tsValue)
|
|
33
|
+
? formatValue(Math.max(Math.abs(tsNow - tsValue), 0) / 1000)
|
|
34
|
+
: '0.0s';
|
|
35
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
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 { formatNumber } from './index.js';
|
|
8
|
+
|
|
9
|
+
describe('formatNumber', (): void => {
|
|
10
|
+
it('formats empty', (): void => {
|
|
11
|
+
expect(
|
|
12
|
+
formatNumber()
|
|
13
|
+
).toEqual('0');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('formats negative numbers', (): void => {
|
|
17
|
+
expect(
|
|
18
|
+
formatNumber(-123456)
|
|
19
|
+
).toEqual('-123,456');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('formats BN numbers', (): void => {
|
|
23
|
+
expect(
|
|
24
|
+
formatNumber(new BN(12345))
|
|
25
|
+
).toEqual('12,345');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('formats BigInt numbers', (): void => {
|
|
29
|
+
expect(
|
|
30
|
+
formatNumber(123456789n)
|
|
31
|
+
).toEqual('123,456,789');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('formats Compact<BN>', (): void => {
|
|
35
|
+
expect(
|
|
36
|
+
formatNumber({
|
|
37
|
+
toBn: (): BN => new BN(12345),
|
|
38
|
+
unwrap: (): BN => new BN(0)
|
|
39
|
+
})
|
|
40
|
+
).toEqual('12,345');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('formats negative numbers (locale=sl)', (): void => {
|
|
44
|
+
expect(
|
|
45
|
+
formatNumber(-123456, { locale: 'sl' })
|
|
46
|
+
).toEqual('-123.456');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('formats BN numbers (locale=sl)', (): void => {
|
|
50
|
+
expect(
|
|
51
|
+
formatNumber(new BN(12345), { locale: 'sl' })
|
|
52
|
+
).toEqual('12.345');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('formats BigInt numbers (locale=sl)', (): void => {
|
|
56
|
+
expect(
|
|
57
|
+
formatNumber(123456789n, { locale: 'sl' })
|
|
58
|
+
).toEqual('123.456.789');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
import type { ToBn } from '../types.js';
|
|
6
|
+
|
|
7
|
+
import { bnToBn } from '../bn/toBn.js';
|
|
8
|
+
import { formatDecimal } from './formatDecimal.js';
|
|
9
|
+
import { getSeparator } from './getSeparator.js';
|
|
10
|
+
|
|
11
|
+
interface Options {
|
|
12
|
+
/**
|
|
13
|
+
* @description The locale to use
|
|
14
|
+
*/
|
|
15
|
+
locale?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @name formatNumber
|
|
20
|
+
* @description Formats a number into string format with thousand separators
|
|
21
|
+
*/
|
|
22
|
+
export function formatNumber <ExtToBn extends ToBn> (
|
|
23
|
+
value?: ExtToBn | BN | bigint | number | null,
|
|
24
|
+
{ locale = 'en' }: Options = {}
|
|
25
|
+
): string {
|
|
26
|
+
const { thousand } = getSeparator(locale);
|
|
27
|
+
|
|
28
|
+
return formatDecimal(bnToBn(value).toString(), thousand);
|
|
29
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
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 { getSeparator } from './getSeparator.js';
|
|
7
|
+
|
|
8
|
+
describe('getSeparator', (): void => {
|
|
9
|
+
const normalizeSeparator = (separator: string) =>
|
|
10
|
+
separator === '\u202F' ? ' ' : separator;
|
|
11
|
+
|
|
12
|
+
const testLocales = [
|
|
13
|
+
{ decimal: '.', locale: 'en', thousand: ',' },
|
|
14
|
+
{ decimal: '.', locale: 'en-gb', thousand: ',' },
|
|
15
|
+
{ decimal: ',', locale: 'sl', thousand: '.' },
|
|
16
|
+
{ decimal: ',', locale: 'sl-si', thousand: '.' },
|
|
17
|
+
{ decimal: ',', locale: 'it-it', thousand: '.' },
|
|
18
|
+
{ decimal: '.', locale: 'ja-jp', thousand: ',' },
|
|
19
|
+
{ decimal: '.', locale: 'hi-IN', thousand: ',' },
|
|
20
|
+
{ decimal: '.', locale: undefined, thousand: ',' } // Fallback test
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
testLocales.forEach(({ decimal, locale, thousand }) => {
|
|
24
|
+
it(`uses ${locale || 'system default'} locale`, (): void => {
|
|
25
|
+
expect(
|
|
26
|
+
getSeparator(locale)
|
|
27
|
+
).toEqual({ decimal, thousand });
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('falls back for invalid locale', (): void => {
|
|
32
|
+
expect(
|
|
33
|
+
getSeparator('invalid-locale')
|
|
34
|
+
).toEqual({ decimal: '.', thousand: ',' }); // Default fallback
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('matches system locale dynamically', (): void => {
|
|
38
|
+
const n = 1000.1;
|
|
39
|
+
const expected = {
|
|
40
|
+
decimal: n.toLocaleString().substring(5, 6),
|
|
41
|
+
thousand: n.toLocaleString().substring(1, 2)
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
expect(getSeparator()).toEqual(expected);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('handles locales with unique separators', (): void => {
|
|
48
|
+
const result = getSeparator('fr-FR');
|
|
49
|
+
|
|
50
|
+
expect(normalizeSeparator(result.thousand)).toBe(' ');
|
|
51
|
+
expect(result.decimal).toBe(',');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the decimal and thousand separator of a locale
|
|
6
|
+
* @param locale
|
|
7
|
+
* @returns {decimal: string, thousand: string}
|
|
8
|
+
*/
|
|
9
|
+
export function getSeparator (locale?: string):
|
|
10
|
+
{ thousand: string, decimal: string } {
|
|
11
|
+
return {
|
|
12
|
+
decimal: (0.1).toLocaleString(locale, { useGrouping: false }).charAt(1),
|
|
13
|
+
thousand: (1000).toLocaleString(locale, { useGrouping: true }).replace(/\d/g, '').charAt(0)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export { formatBalance } from './formatBalance.js';
|
|
5
|
+
export { formatDate } from './formatDate.js';
|
|
6
|
+
export { formatDecimal } from './formatDecimal.js';
|
|
7
|
+
export { formatElapsed } from './formatElapsed.js';
|
|
8
|
+
export { formatNumber } from './formatNumber.js';
|
|
9
|
+
export { calcSi, findSi } from './si.js';
|
package/src/format/si.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { SiDef } from '../types.js';
|
|
5
|
+
|
|
6
|
+
/** @internal */
|
|
7
|
+
export const SI_MID = 8;
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
export const SI: SiDef[] = [
|
|
11
|
+
{ power: -24, text: 'yocto', value: 'y' },
|
|
12
|
+
{ power: -21, text: 'zepto', value: 'z' },
|
|
13
|
+
{ power: -18, text: 'atto', value: 'a' },
|
|
14
|
+
{ power: -15, text: 'femto', value: 'f' },
|
|
15
|
+
{ power: -12, text: 'pico', value: 'p' },
|
|
16
|
+
{ power: -9, text: 'nano', value: 'n' },
|
|
17
|
+
{ power: -6, text: 'micro', value: 'µ' },
|
|
18
|
+
{ power: -3, text: 'milli', value: 'm' },
|
|
19
|
+
{ power: 0, text: 'Unit', value: '-' }, // position 8
|
|
20
|
+
{ power: 3, text: 'Kilo', value: 'k' },
|
|
21
|
+
{ power: 6, text: 'Mill', value: 'M' }, // Mega, M
|
|
22
|
+
{ power: 9, text: 'Bill', value: 'B' }, // Giga, G
|
|
23
|
+
{ power: 12, text: 'Tril', value: 'T' }, // Tera, T
|
|
24
|
+
{ power: 15, text: 'Peta', value: 'P' },
|
|
25
|
+
{ power: 18, text: 'Exa', value: 'E' },
|
|
26
|
+
{ power: 21, text: 'Zeta', value: 'Z' },
|
|
27
|
+
{ power: 24, text: 'Yotta', value: 'Y' }
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Given a SI type (e.g. k, m, Y) find the SI definition
|
|
31
|
+
/** @internal */
|
|
32
|
+
export function findSi (type: string): SiDef {
|
|
33
|
+
// use a loop here, better RN support (which doesn't have [].find)
|
|
34
|
+
for (let i = 0, count = SI.length; i < count; i++) {
|
|
35
|
+
if (SI[i].value === type) {
|
|
36
|
+
return SI[i];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return SI[SI_MID];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @internal */
|
|
44
|
+
export function calcSi (text: string, decimals: number, forceUnit?: string): SiDef {
|
|
45
|
+
if (forceUnit) {
|
|
46
|
+
return findSi(forceUnit);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const siDefIndex = (SI_MID - 1) + Math.ceil((text.length - decimals) / 3);
|
|
50
|
+
|
|
51
|
+
return SI[siDefIndex] || SI[siDefIndex < 0 ? 0 : SI.length - 1];
|
|
52
|
+
}
|
package/src/has.spec.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
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 { hasBuffer } from './has.js';
|
|
7
|
+
|
|
8
|
+
describe('hasBuffer', (): void => {
|
|
9
|
+
it('has Buffer (Jest + Node.js)', (): void => {
|
|
10
|
+
expect(hasBuffer).toEqual(typeof Buffer !== 'undefined');
|
|
11
|
+
});
|
|
12
|
+
});
|
package/src/has.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/util authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { BufferClass } from './types.js';
|
|
5
|
+
|
|
6
|
+
import { BigInt } from '@pezkuwi/x-bigint';
|
|
7
|
+
import { xglobal } from '@pezkuwi/x-global';
|
|
8
|
+
|
|
9
|
+
// Since we run in very different environments, we have to ensure we have all
|
|
10
|
+
// the types used here for detection (some of these may require Node definitions,
|
|
11
|
+
// which are not available in Deno/browser)
|
|
12
|
+
declare const __dirname: unknown;
|
|
13
|
+
declare const module: unknown;
|
|
14
|
+
declare const require: unknown;
|
|
15
|
+
|
|
16
|
+
/** true if the environment has proper BigInt support */
|
|
17
|
+
export const hasBigInt = typeof BigInt === 'function' && typeof BigInt.asIntN === 'function';
|
|
18
|
+
|
|
19
|
+
/** true if the environment is CJS */
|
|
20
|
+
export const hasCjs = typeof require === 'function' && typeof module !== 'undefined';
|
|
21
|
+
|
|
22
|
+
/** true if the environment has __dirname available */
|
|
23
|
+
export const hasDirname = typeof __dirname !== 'undefined';
|
|
24
|
+
|
|
25
|
+
/** true if the environment is ESM */
|
|
26
|
+
export const hasEsm = !hasCjs;
|
|
27
|
+
|
|
28
|
+
/** true if the environment has WebAssembly available */
|
|
29
|
+
export const hasWasm = typeof WebAssembly !== 'undefined';
|
|
30
|
+
|
|
31
|
+
// NOTE We check the following on globalThis, avoiding specific polyfill detection
|
|
32
|
+
// that some bundlers such as parcel would add (this is a check, not a use)
|
|
33
|
+
|
|
34
|
+
/** true if the environment has support for Buffer (typically Node.js) */
|
|
35
|
+
export const hasBuffer = typeof xglobal.Buffer === 'function' && typeof (xglobal.Buffer as unknown as BufferClass).isBuffer === 'function';
|
|
36
|
+
|
|
37
|
+
/** true if the environment has process available (typically Node.js) */
|
|
38
|
+
export const hasProcess = typeof xglobal.process === 'object';
|
|
@@ -0,0 +1,32 @@
|
|
|
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 { hexAddPrefix } from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('hexAddPrefix', (): void => {
|
|
9
|
+
it('does not add when prefix is available', (): void => {
|
|
10
|
+
expect(
|
|
11
|
+
hexAddPrefix('0x0123')
|
|
12
|
+
).toEqual('0x0123');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('adds the prefix when it is not available', (): void => {
|
|
16
|
+
expect(
|
|
17
|
+
hexAddPrefix('0123')
|
|
18
|
+
).toEqual('0x0123');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('adds extra 0 when length % 2 === 1', (): void => {
|
|
22
|
+
expect(
|
|
23
|
+
hexAddPrefix('123')
|
|
24
|
+
).toEqual('0x0123');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('returns null as 0x', (): void => {
|
|
28
|
+
expect(
|
|
29
|
+
hexAddPrefix(null)
|
|
30
|
+
).toEqual('0x');
|
|
31
|
+
});
|
|
32
|
+
});
|