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 ADDED
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ repository: {
3
+ url: 'https://github.com/mmpro/ac-byteconverter'
4
+ },
5
+ changelogFile: __dirname + '/CHANGELOG.md',
6
+ sections: [
7
+ {name: 'App' }
8
+ ],
9
+ }
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
+ })