/
index.js
107 lines (90 loc) · 2.88 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
const arguguard = require('arguguard')
const forEach = require('lodash.foreach')
const NoPathError = require('./errors/NoPath')
const NoConverterError = require('./errors/NoConverter')
const ConversionError = require('./errors/Conversion')
const Nobject = require('nobject')
function CrossConverter() {
arguguard('CrossConverter', [], arguments)
this.converters = new Nobject
this.paths = new Nobject
this.formsObj = {}
}
CrossConverter.prototype.addConverter = function addConverter(from, to, converter) {
arguguard('crossConverter.addConverter', ['string', 'string', 'function'], arguments)
const forms = [from, to]
forms.forEach((form) => {
if (!this.formsObj[form]) {
this.formsObj[form] = true
}
})
this.paths.set(from, to, [from, to])
this.converters.set(from, to, converter)
}
CrossConverter.prototype.addPath = function addPath(path) {
arguguard('crossConverter.addPath', ['[]string'], arguments)
path.forEach((form, index) => {
if (index === 0) {
return
}
const from = path[index - 1]
const to =form
if (this.converters.get(from, to) === undefined) {
throw new NoConverterError(`No converter from form "${from}" to form "${to}"`)
}
})
const from = path[0]
const to = path[path.length - 1]
this.paths.set(from, to, path)
}
CrossConverter.prototype.addPathUnsafe = function addPathUnsafe(path) {
arguguard('crossConverter.addPathUnsafe', ['[]string'], arguments)
path.forEach((form, index) => {
if (index === 0) {
return
}
const from = path[index - 1]
const to =form
})
const from = path[0]
const to = path[path.length - 1]
this.paths.set(from, to, path)
}
CrossConverter.prototype.convert = function convert(truth, formFrom, formTo) {
arguguard('crossConverter.convert', ['*', 'string', 'string'], arguments)
if (formFrom === formTo) {
return truth
}
if (this.formsObj[formFrom] !== true) {
throw new NoConverterError(`No converter for form "${formFrom}"`)
}
if (this.formsObj[formTo] !== true) {
throw new NoConverterError(`No converter for form "${formTo}"`)
}
const path = this.paths.get(formFrom, formTo)
if (path === undefined) {
throw new NoPathError(`No path from "${formFrom}" to "${formTo}"`)
}
let currentForm = formFrom
let currentTruth = truth
path.forEach((step, index) => {
if (index === 0) {
return
}
const converter = this.converters.get(currentForm, step)
if (converter === undefined) {
throw new NoConverterError(`No converter from form "${currentForm}" to "${step}"`)
}
currentTruth = safeConvert(currentForm, step, converter, currentTruth)
currentForm = step
})
return currentTruth
}
function safeConvert(formFrom, formTo, converter, truth) {
try {
return converter(truth)
} catch (err) {
throw new ConversionError(truth, formFrom, formTo, err.message)
}
}
module.exports = CrossConverter