/
index.js
151 lines (133 loc) · 5.2 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const validator = require('./lib/validator');
const errors = require('./lib/errors')
class InterpolateJson {
constructor(config) {
this.variablesInterface = config.variablesSchema;
this.interpolationTemplate = config.interpolationTemplate ? new RegExp(config.interpolationTemplate, 'g') : /\$\{(.*?)\}/g;
}
interpolate(jsonString, variables, required = true) {
const variablesInJson = this.getJsonVariables(jsonString);
const result = {
error: null,
data: null
};
if (!variables) {
result.error = new Error(`Variables parameter is required.`);
return result;
}
if (required) {
const missedVariables = this.getMissedVariables(variables, variablesInJson);
if (missedVariables.length) {
result.error = new errors.JSONInterpolateAggregateError(
`JSON contain variables that are not passed.`,
missedVariables.map(variable => new errors.MissedVariableError(
`Variable ${variable.name}`,
{
variable: variable.name,
requestedType: this.variablesInterface[variable.name]
}
))
);
return result;
}
};
if (this.variablesInterface) {
const variablesWithoutInterface = this.getVariablesWithoutDeclaredInterface(variablesInJson)
if (variablesWithoutInterface.length) {
result.error = new errors.JSONInterpolateAggregateError(
`JSON contain variables for which interface is not declared.`,
variablesWithoutInterface.map(variable => new errors.VariableDeclarationError(
`Variable: ${variable.name}`,
{
variable: variable.name,
requestedType: null
}
))
);
return result;
}
}
const validationResult = this.getInvalidVariables(variables);
if (validationResult.errors.length) {
result.error = validationResult.errors;
return result;
}
if (validationResult.variables.length) {
result.error = new errors.JSONInterpolateAggregateError(
`The next variables has invalid type.`,
validationResult.variables.map(variable => new errors.VariableTypeError(
`Variable: ${variable}\nRequested type: ${this.variablesInterface[variable].type}`,
{
requestedType: this.variablesInterface[variable].type,
variable
}
))
);
return result;
}
let resultString = jsonString
for (const variableInJson of variablesInJson) {
resultString = resultString.replace(
variableInJson.full,
variables[variableInJson.name]
);
}
result.data = resultString
return result;
}
getMissedVariables(passedVariables, variablesInJson) {
const passedVariablesKeys = Object.keys(passedVariables);
const notPassedVariables = [];
for (const variableInJson of variablesInJson) {
if (!passedVariablesKeys.includes(variableInJson.name)) {
notPassedVariables.push(variableInJson)
}
}
return notPassedVariables;
}
getVariablesWithoutDeclaredInterface(variablesInJson) {
const variablesInterfaceNames = Object.keys(this.variablesInterface);
const notDeclared = [];
for (const variableInJson of variablesInJson) {
if (!variablesInterfaceNames.includes(variableInJson.name)) {
notDeclared.push(variableInJson)
}
}
return notDeclared;
}
getInvalidVariables(variables) {
const result = {
variables: [],
errors: []
};
for (let [variable, value] of Object.entries(variables)) {
const validationResult = this.isVariableValid(variable, value);
if (validationResult instanceof Error) {
result.errors.push(validationResult)
}
if (!validationResult) {
result.variables.push(variable)
}
}
return result;
}
isVariableValid(variable, value) {
if (this.variablesInterface[variable]) {
return validator(this.variablesInterface[variable].type, value)
}
return true
}
getJsonVariables(jsonString) {
const variablesInJson = [];
for (const match of jsonString.matchAll(this.interpolationTemplate)) {
variablesInJson.push({
from: match.index,
to: match.index + match[0].length,
name: match[1],
full: match[0]
});
};
return variablesInJson;
}
}
module.exports = InterpolateJson;