So, you've already correctly identified HOW to get the pattern, so your real question is "how can I take a string like 'client.order.time' and get a value for it?"
With a recursive function, it is surprisingly straightforward. Say we have an object like below:
const data = {
client: {
order: {
time: '12:00PM'
}
}
};
We can create a function that takes an object and a string, and recursively loops through each part until it either a) gets through all the parts and finds the value or b) finds an unknown part and returns undefined.
const data = {
client: {
order: {
time: '12:00PM'
}
}
};
const getValueFromPath = (obj, path, delimiter = '.') => {
// path or obj are falsy, just return obj
// you could tweak this bit to do something else if you want
// obj === undefined might be from our recursive call, so keep that in mind if you tweak
if (!path || !obj) return obj;
const parts = path.split(delimiter);
const next = parts.shift(); // get the first part, parts now has all the other parts
// If !parts.length (parts.length === 0), we're on the last part, so we'll return.
if (!parts.length) return obj[next];
// Otherwise, recurse with the rest of the parts.
return getValueFromPath(obj[next], parts.join(delimiter), delimiter);
};
const result = getValueFromPath(data, 'client.order.time');
console.log(result);
const noResult = getValueFromPath(data, 'path.does.not.exist');
console.log(noResult);
If you don't like re-join()-ing the parts every time, you could have a second version of this method which takes an array of parts instead of a path string, but I find the extra code isn't worth the (very minimal) efficiency gains.
Now, circling back to your original question, simply use the replace() method on the string, using a replacer method as the second argument. The 2nd argument of that replacer method is the pattern, so we just feed that to our new method.
const str =
'i need this {client.car.model} exactly at {client.order.time} today';
const data = {
client: {
car: {
model: 'Truck'
},
order: {
time: '12:00PM'
}
}
};
const getValueFromPath = (obj, path, delimiter = '.') => {
// path or obj are falsy, just return obj
// you could tweak this bit to do something else if you want
// obj === undefined might be from our recursive call, so keep that in mind if you tweak
if (!path || !obj) return obj;
const parts = path.split(delimiter);
const next = parts.shift(); // get the first part, parts now has all the other parts
// If !parts.length (parts.length === 0), we're on the last part, so we'll return.
if (!parts.length) return obj[next];
// Otherwise, recurse with the rest of the parts.
return getValueFromPath(obj[next], parts.join(delimiter), delimiter);
};
const result = str.replace(/{(.+?)}/gi, (_, path) => getValueFromPath(data, path));
console.log(result);
{client.car.model}the parser will return:client[car][model]. Regex is probably NOT the right way to go!