ac-byteconverter 1.0.3
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/.acsemver.js +9 -0
- package/.eslintrc.js +26 -0
- package/CHANGELOG.md +44 -0
- package/Makefile +17 -0
- package/README.md +50 -0
- package/index.js +168 -0
- package/package.json +22 -0
- package/test/test.js +95 -0
package/.acsemver.js
ADDED
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
'env': {
|
|
3
|
+
'commonjs': true,
|
|
4
|
+
'es6': true,
|
|
5
|
+
'node': true
|
|
6
|
+
},
|
|
7
|
+
'extends': 'eslint:recommended',
|
|
8
|
+
"rules": {
|
|
9
|
+
"space-before-function-paren": 0,
|
|
10
|
+
"no-extra-semi": 0,
|
|
11
|
+
"object-curly-spacing": ["error", "always"],
|
|
12
|
+
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
|
|
13
|
+
"no-useless-escape": 0,
|
|
14
|
+
"standard/no-callback-literal": 0,
|
|
15
|
+
"new-cap": 0
|
|
16
|
+
},
|
|
17
|
+
globals: {
|
|
18
|
+
describe: true,
|
|
19
|
+
it: true
|
|
20
|
+
},
|
|
21
|
+
'parserOptions': {
|
|
22
|
+
'ecmaVersion': 2018
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = config
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<a name="1.0.3"></a>
|
|
2
|
+
|
|
3
|
+
## [1.0.3](https://github.com/mmpro/ac-byteconverter/compare/v1.0.2..v1.0.3) (2021-10-09 09:39:20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fix
|
|
7
|
+
|
|
8
|
+
* **App:** Package updates | MP | [05f7221570a83779a9f5ede5afa97eaaad8dd825](https://github.com/mmpro/ac-byteconverter/commit/05f7221570a83779a9f5ede5afa97eaaad8dd825)
|
|
9
|
+
Package updates
|
|
10
|
+
### Chores
|
|
11
|
+
|
|
12
|
+
* **App:** Updated packages | MP | [d0a043433e5cc4fceb3b52dd6d84d4b949eed62f](https://github.com/mmpro/ac-byteconverter/commit/d0a043433e5cc4fceb3b52dd6d84d4b949eed62f)
|
|
13
|
+
Updated packages
|
|
14
|
+
* **App:** Updated packages | MP | [5d75c8f618b0458f70764d5bd3bb29f3d89ac720](https://github.com/mmpro/ac-byteconverter/commit/5d75c8f618b0458f70764d5bd3bb29f3d89ac720)
|
|
15
|
+
Updated packages
|
|
16
|
+
<a name="1.0.2"></a>
|
|
17
|
+
|
|
18
|
+
## [1.0.2](https://github.com/mmpro/ac-byteconverter/compare/v1.0.1..v1.0.2) (2020-08-16 06:12:24)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fix
|
|
22
|
+
|
|
23
|
+
* **App:** Force patch release after version upgrade | MP | [81202a648c5e417d7daecf17e1425c60716218a9](https://github.com/mmpro/ac-byteconverter/commit/81202a648c5e417d7daecf17e1425c60716218a9)
|
|
24
|
+
Force patch release after version upgrade
|
|
25
|
+
<a name="1.0.1"></a>
|
|
26
|
+
|
|
27
|
+
## [1.0.1](https://github.com/mmpro/ac-byteconverter/compare/v1.0.0..v1.0.1) (2020-03-29 14:18:08)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fix
|
|
31
|
+
|
|
32
|
+
* **App:** Prepare repository for AC semantic release | MP | [ba90dac90e87f0fa48adc7cf4664baad530ec76d](https://github.com/mmpro/ac-byteconverter/commit/ba90dac90e87f0fa48adc7cf4664baad530ec76d)
|
|
33
|
+
Cleaned up repository and use ac-semantic-release
|
|
34
|
+
<a name="1.0.0"></a>
|
|
35
|
+
# 1.0.0 (2019-08-04 06:40)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Bug Fixes
|
|
39
|
+
|
|
40
|
+
* **App:** Updated packages and use semver | MP ([79f5264](https://github.com/mmpro/ac-byteconverter/commit/79f5264))
|
|
41
|
+
We now use release management
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
package/Makefile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
MOCHA_OPTS= --slow 0 -A
|
|
2
|
+
REPORTER = spec
|
|
3
|
+
|
|
4
|
+
lint-fix:
|
|
5
|
+
./node_modules/.bin/eslint --fix index.js test/test.js
|
|
6
|
+
|
|
7
|
+
lint-check:
|
|
8
|
+
./node_modules/.bin/eslint index.js test/test.js
|
|
9
|
+
|
|
10
|
+
commit:
|
|
11
|
+
@node ./node_modules/ac-semantic-release/lib/commit.js
|
|
12
|
+
|
|
13
|
+
release:
|
|
14
|
+
@node ./node_modules/ac-semantic-release/lib/release.js
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
.PHONY: check
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# AC ByteConverter
|
|
2
|
+
This tool converts bytes into units like kB (Kilo byte) or KiB (Kibibytes)
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
|
|
6
|
+
***byteConverter.format(value, [unit], [options])***
|
|
7
|
+
|
|
8
|
+
Converts a value in bytes to a human-readable value.
|
|
9
|
+
|
|
10
|
+
+ value -> bytes (NUMBER) to converts
|
|
11
|
+
+ unit -> optional unit (STRING) to convert bytes to (e.g. MB, MiB). If not set, will be auto-detected based on the value (e.g. 10000 will be converted to 10kB)
|
|
12
|
+
+ options -> optional object with options
|
|
13
|
+
+ system -> can be "si" or "iec", defaults to si
|
|
14
|
+
+ decimals -> number of decimals to show, defaults to 2
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
***byteConverter.parse(value, [options])***
|
|
18
|
+
|
|
19
|
+
Converts a human readable value into bytes.
|
|
20
|
+
|
|
21
|
+
+ value -> human readable value (STRING) to convert to bytes
|
|
22
|
+
+ options -> optional object with options
|
|
23
|
+
+ system -> can be "si" or "iec", will be auto-detected
|
|
24
|
+
+ decimals -> number of decimals to show, defaults to 2
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
const byteConverter = require('ac-byteConverter')
|
|
31
|
+
|
|
32
|
+
// convert 1000 to 1kb
|
|
33
|
+
byteConverter.format(1000)
|
|
34
|
+
|
|
35
|
+
// convert 1 MB to 1000000 bytes
|
|
36
|
+
byteConverter.parse('1MB')
|
|
37
|
+
// 1000000
|
|
38
|
+
|
|
39
|
+
// convert 1 Mebibyte to 1048576 bytes
|
|
40
|
+
byteConverter.parse('1MiB')
|
|
41
|
+
// 1048576
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT
|
|
47
|
+
|
|
48
|
+
## Current issues/infos
|
|
49
|
+
2018-07-30
|
|
50
|
+
We are using this fork mmpro/mocha-jenkins-reporter until the packages has been fixed (outdated version is 0.3.12)
|
package/index.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
|
|
3
|
+
const byteConverter = function() {
|
|
4
|
+
const valueMap = [
|
|
5
|
+
{ exp: 0, si: 'B', iec: 'b', iecExp: 1 },
|
|
6
|
+
{ exp: 3, si: 'kB', iec: 'KiB', iecExp: 10 },
|
|
7
|
+
{ exp: 6, si: 'MB', iec: 'MiB', iecExp: 20 },
|
|
8
|
+
{ exp: 9, si: 'GB', iec: 'GiB', iecExp: 30 },
|
|
9
|
+
{ exp: 12, si: 'TB', iec: 'TiB', iecExp: 40 },
|
|
10
|
+
{ exp: 15, si: 'PB', iec: 'PiB', iecExp: 50 },
|
|
11
|
+
{ exp: 18, si: 'EB', iec: 'EiB', iecExp: 60 },
|
|
12
|
+
{ exp: 21, si: 'ZB', iec: 'ZiB', iecExp: 70 },
|
|
13
|
+
{ exp: 24, si: 'YB', iec: 'YiB', iecExp: 80 }
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converts value into unit.
|
|
18
|
+
* If unit is not given, try to determine based on power of ten
|
|
19
|
+
* @param value FLOAT byte value
|
|
20
|
+
*/
|
|
21
|
+
const format = function(value, unit, options) {
|
|
22
|
+
if (_.isNil(value)) {
|
|
23
|
+
return { message: 'valueRequired' }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!_.isNumber(value)) {
|
|
27
|
+
return { message: 'valueMustBeANumber' }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// return 0 value as 0
|
|
31
|
+
if (value === 0) {
|
|
32
|
+
return value.toString()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (_.isObject(unit)) {
|
|
36
|
+
options = unit
|
|
37
|
+
unit = null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// define default options
|
|
41
|
+
options = options || {}
|
|
42
|
+
if (!_.get(options, 'system')) {
|
|
43
|
+
// detect system (check if there is an i)
|
|
44
|
+
if (unit && _.endsWith(unit, 'iB')) {
|
|
45
|
+
_.set(options, 'system', 'iec')
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
_.set(options, 'system', 'si')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let base = 10
|
|
53
|
+
|
|
54
|
+
if (_.get(options, 'system') === 'iec') {
|
|
55
|
+
base = 2
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let map
|
|
59
|
+
|
|
60
|
+
if (!unit) {
|
|
61
|
+
const autoDetectRegex = /(\d.*\+)(\d{1,2})/
|
|
62
|
+
const autoDetect = value.toExponential() // 5.079899957e+9
|
|
63
|
+
const expArray = autoDetect.match(autoDetectRegex)
|
|
64
|
+
const exp = Math.floor(parseInt(_.get(expArray, '[2]')) / 3) * 3
|
|
65
|
+
map = _.find(valueMap, { exp: exp })
|
|
66
|
+
unit = _.get(map, _.get(options, 'system'))
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (_.get(options, 'system') === 'iec') {
|
|
70
|
+
map = _.find(valueMap, { iec: unit })
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
map = _.find(valueMap, { si: unit })
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!map) {
|
|
78
|
+
return { message: 'unitInvalid' }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// convert
|
|
82
|
+
let exp = _.get(map, 'exp')
|
|
83
|
+
|
|
84
|
+
if (_.get(options, 'system') === 'iec') {
|
|
85
|
+
exp = _.get(map, 'iecExp')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const divider = Math.pow(base, exp)
|
|
89
|
+
value = _.round(value / divider, _.get(options, 'decimals', 2))
|
|
90
|
+
|
|
91
|
+
return value + unit
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Ingests a "human readable" value and returns value in bytes
|
|
96
|
+
* If you send a non-string value, the value is just returned
|
|
97
|
+
*/
|
|
98
|
+
const parse = function(value, options) {
|
|
99
|
+
if (_.isNil(value)) {
|
|
100
|
+
return { message: 'valueRequired' }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (_.isNumber(value)) {
|
|
104
|
+
return value
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!_.isString(value)) {
|
|
108
|
+
return { message: 'valueMustBeAString' }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const regex = /([0-9.]*)(\D*)/
|
|
112
|
+
const res = value.match(regex) // 1KiB
|
|
113
|
+
const orgValue = _.trim(res[1])
|
|
114
|
+
const unit = _.trim(res[2])
|
|
115
|
+
|
|
116
|
+
// return zero value ('0' -> 0)
|
|
117
|
+
if (_.parseInt(orgValue) === 0) {
|
|
118
|
+
return _.parseInt(orgValue)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
options = options || {}
|
|
122
|
+
|
|
123
|
+
if (!_.get(options, 'system')) {
|
|
124
|
+
if (_.endsWith(unit, 'iB')) {
|
|
125
|
+
_.set(options, 'system', 'iec')
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
_.set(options, 'system', 'si')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let map
|
|
133
|
+
|
|
134
|
+
if (_.get(options, 'system') === 'iec') {
|
|
135
|
+
map = _.find(valueMap, { iec: unit })
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
map = _.find(valueMap, { si: unit })
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!map) {
|
|
142
|
+
return { message: 'unitInvalid' }
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let exp = _.get(map, 'exp')
|
|
146
|
+
|
|
147
|
+
if (_.get(options, 'system') === 'iec') {
|
|
148
|
+
exp = _.get(map, 'iecExp')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let base = 10
|
|
152
|
+
|
|
153
|
+
if (_.get(options, 'system') === 'iec') {
|
|
154
|
+
base = 2
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const byteValue = orgValue * Math.pow(base, exp)
|
|
158
|
+
|
|
159
|
+
return byteValue
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
format: format,
|
|
164
|
+
parse: parse
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = byteConverter()
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ac-byteconverter",
|
|
3
|
+
"author": "Mark Poepping (https://www.mmpro.de)",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": "mmpro/ac-byteconverter",
|
|
6
|
+
"version": "1.0.3",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"lodash": "^4.17.21"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"ac-semantic-release": "^0.2.6",
|
|
12
|
+
"eslint": "^7.32.0",
|
|
13
|
+
"expect": "^27.2.5",
|
|
14
|
+
"mocha": "^9.1.2"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "mocha --reporter spec"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=10.0.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/test/test.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
const expect = require('expect')
|
|
3
|
+
const byteConverter = require('../index')
|
|
4
|
+
|
|
5
|
+
const formatTests = [
|
|
6
|
+
{ name: '10 bytes', value: 10, expected: '10B' },
|
|
7
|
+
{ name: '1.000 bytes to kb', value: 1000, expected: '1kB' },
|
|
8
|
+
{ name: '1.000.000 bytes to MB', value: 1e6, expected: '1MB' },
|
|
9
|
+
{ name: '1.000.000.000 bytes to GB', value: 1e9, expected: '1GB' },
|
|
10
|
+
{ name: '1.000.000.000.000 bytes to TB', value: 1e12, expected: '1TB' },
|
|
11
|
+
{ name: '1024 bytes to KiB', value: 1024, expected: '1KiB', options: { system: 'iec' } },
|
|
12
|
+
{ name: '2^20 bytes to 1 MiB', value: Math.pow(2, 20), expected: '1MiB', options: { system: 'iec' } },
|
|
13
|
+
{ name: '2^30 bytes to 1 GiB', value: Math.pow(2, 30), expected: '1GiB', options: { system: 'iec' } },
|
|
14
|
+
{ name: '2^40 bytes to 1 TiB', value: Math.pow(2, 40), expected: '1TiB', options: { system: 'iec' } },
|
|
15
|
+
{ name: '1GB as 1000MB', value: 1e9, expected: '1000MB', unit: 'MB' },
|
|
16
|
+
{ name: '1GB as 0.001TB', value: 1e9, expected: '0.001TB', unit: 'TB', options: { decimals: 3 } },
|
|
17
|
+
{ name: '1GB as 0TB with default decimals', value: 1e9, expected: '0TB', unit: 'TB' },
|
|
18
|
+
{ name: '2.5e6 as 2.5MB', value: 2.5e6, expected: '2.5MB' },
|
|
19
|
+
{ name: '53.687.091.200 as 50GiB', value: 53687091200, expected: '50GiB', options: { system: 'iec' } }
|
|
20
|
+
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const parseTests = [
|
|
24
|
+
{ name: '1MB to 1e6 bytes', value: '1MB', expected: 1e6 },
|
|
25
|
+
{ name: '1MB to 1e6 bytes with space', value: '1 MB', expected: 1e6 },
|
|
26
|
+
{ name: '100MB to 1e8 bytes with space', value: '100 MB', expected: 1e8 },
|
|
27
|
+
{ name: '1GB to 1e9 bytes', value: '1GB', expected: 1e9 },
|
|
28
|
+
{ name: '1TB to 1e12 bytes', value: '1TB', expected: 1e12 },
|
|
29
|
+
{ name: '50GiB to 53.687.091.200 bytes', value: '50GiB', expected: 53687091200 },
|
|
30
|
+
{ name: 'Parse float value 1.5MB to 1.5e6', value: '1.5MB', expected: 1.5e6 }
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
const errorFormatTests = [
|
|
34
|
+
{ name: 'no value - error that value is required', value: null, expected: { message: 'valueRequired' } },
|
|
35
|
+
{ name: 'invalid value', value: '1ABB', expected: { message: 'valueMustBeANumber' } },
|
|
36
|
+
{ name: 'non existing unit - try 1000 in ABB', value: 1000, unit: 'ABB', expected: { message: 'unitInvalid' } },
|
|
37
|
+
{ name: 'value as array', value: [1000, '1AABB'], expected: { message: 'valueMustBeANumber' } }
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
const errorParseTests = [
|
|
41
|
+
{ name: 'no value - error that value is required', value: null, expected: { message: 'valueRequired' } },
|
|
42
|
+
{ name: 'invalid value 1ABB', value: '1ABB', expected: { message: 'unitInvalid' } },
|
|
43
|
+
{ name: 'invalid value 1KB', value: '1KB', expected: { message: 'unitInvalid' } },
|
|
44
|
+
{ name: 'invalid value FAIL', value: 'FAIL', expected: { message: 'unitInvalid' } },
|
|
45
|
+
{ name: 'value without unit', value: 1000, expected: 1000 },
|
|
46
|
+
{ name: 'value as array', value: [1000, '1AABB'], expected: { message: 'valueMustBeAString' } }
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
describe('TESTING byteConversion', function () {
|
|
50
|
+
describe('FORMAT Tests', function() {
|
|
51
|
+
_.forEach(formatTests, (test) => {
|
|
52
|
+
it(test.name, function(done) {
|
|
53
|
+
let options = _.get(test, 'options', {})
|
|
54
|
+
let unit = _.get(test, 'unit')
|
|
55
|
+
let r = byteConverter.format(test.value, unit, options)
|
|
56
|
+
expect(r).toEqual(test.expected)
|
|
57
|
+
return done()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
describe('PARSE Tests', function() {
|
|
63
|
+
_.forEach(parseTests, (test) => {
|
|
64
|
+
it(test.name, function(done) {
|
|
65
|
+
let options = _.get(test, 'options', {})
|
|
66
|
+
let r = byteConverter.parse(test.value, options)
|
|
67
|
+
expect(r).toEqual(test.expected)
|
|
68
|
+
return done()
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe('ERROR FORMAT Tests', function() {
|
|
74
|
+
_.forEach(errorFormatTests, (test) => {
|
|
75
|
+
it(test.name, function(done) {
|
|
76
|
+
let options = _.get(test, 'options', {})
|
|
77
|
+
let unit = _.get(test, 'unit')
|
|
78
|
+
let r = byteConverter.format(test.value, unit, options)
|
|
79
|
+
expect(r).toEqual(test.expected)
|
|
80
|
+
return done()
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('ERROR PARSE Tests', function() {
|
|
86
|
+
_.forEach(errorParseTests, (test) => {
|
|
87
|
+
it(test.name, function(done) {
|
|
88
|
+
let options = _.get(test, 'options', {})
|
|
89
|
+
let r = byteConverter.parse(test.value, options)
|
|
90
|
+
expect(r).toEqual(test.expected)
|
|
91
|
+
return done()
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
})
|