Matching a string to one of many patterns and extracting data - javascript

I have a problem I want to solve with RegEx, or any other method if there is a better one. I've tried several ways to achieve the goal, but nothing really worked.
I have an array with endpoints:
const endpoints = [
{
id: 1,
url: "/api/items/:itemId"
},
{
id: 2,
url: "/api/users/:userName/delete"
},
{
id: 3,
url: "/api/users/:userName/edit"
}
];
And a request URL:
const url = "/api/users/max/edit";
Now what I want is to have a function which acts like this:
const rewrite = (url, endpoints) => {
// What is the best way to achieve the following return value:
return {
endpointId: 3,
values: {
userName: "max"
}
};
};
Explanation: The function should find the appropriate endpoint for the url. All parts of the endpoint url which start with a colon are not static, but should rather be replaced with values from the request url. In this case :userName should be replaced with max.
I've been in web development for some time now, but to be honest I've almost no clue how to solve such a problem.

const rewrite = (url, endpoints) => {
var doubledArray = Array.prototype.map.call(endpoints, function(el) {
return {
id: el.id,
url: el.url.split('/')
};
});
var parts = url.split('/');
var i = 0;
parts.forEach(function(element) {
doubledArray = doubledArray.filter(el => (element == el.url[i] || el.url[i].startsWith(':')));
i++;
});
return {
endpointId: doubledArray[0].id,
values: {
[`${doubledArray[0].url.filter(el => el.startsWith(':'))[0].substring(1)}`]: parts[doubledArray[0].url.findIndex(function (el) { return el.startsWith(':'); } )],
}
};
};

You can go through the endpoints making each .url into a RegExp to test the url against.
When a matching one is found, it is just a matter of extracting the needed part and making up an Object with the property name:
<script>
const myEndpoints = [
{
id: 1,
url: "/api/items/:itemId"
},
{
id: 2,
url: "/api/users/:userName/delete"
},
{
id: 3,
url: "/api/users/:userName/edit"
}
];
const myUrl = "/api/users/nermal/edit";
const rewrite = (url, endpoints) => {
for (let i = 0; i < endpoints.length; i++) {
var rep = new RegExp(":(\\w+)", "m");
var propName = rep.exec(endpoints[i].url);
var reu = new RegExp(endpoints[i].url.replace(propName[0], "(.*)"));
var a = reu.exec(url);
if (a !== null) {
var x = new Object;
x["endpointId"] = endpoints[i].id;
var y = new Object;
y[propName[1]] = a[1];
x["values"] = y;
return x;
}
}
return null;
};
var q = rewrite(myUrl, myEndpoints);
console.log(q);
console.log(q.values);
</script>
Outputs:
Object { endpointId: 3, values: {…} }
Object { userName: "nermal" }

Related

Append string using regex at the end of URL values inside the nested object on Node.js

Sample object (the below object is a very large nested object):
const obj = { a: 1, url: "https://someurl.com", b: { c: 1, d: { otherUrl: "https://someotherurl.com"}};
I want to append some query parameter at the end of each URL, like ?d=1234.
I tried to do it, but the URLs are changed:
const convertedObj = JSON.stringify(obj);
let bufferObj;
const fullRegex = /url":"([^"]*)/g;
const fullMatch = convertedObj.match(fullRegex);
if(fullMatch) {
fullMatch.forEach((str, i) => {
bufferObj = convertedObj.replace(/(url|Url)":"([^"]*)/g, `${str}?d=1234`);
});
}
Is there a solution for this in Node.js using regex?
let convertedObj = JSON.stringify(obj);
const fullRegex = /(url|Url)":"([^"]*)/g;
const fullMatch = convertedObj.match(fullRegex);
if(fullMatch) {
fullMatch.forEach((str, i) => {
convertedObj = convertedObj.replace(str, `${str}?d=1234`);
});
}
console.log(convertedObj);

node.js edit variable from another file

Hello i have just started to learn node.js today and i am having a problem getting a variable from another file and editing it.
I'm trying to get the variable bots from server.js and edit it in bots.js.
server.js:
var bots = [
{ botID: '16f11103', userID: '12345' },
{ botID: '5657d5e9', userID: '54321' }
];
setInterval(() => { console.log(bots); }, 5000);
module.exports.bots = bots;
bots.js:
var request = require("../server.js");
var unique_id = '16f11103';
if (request.bots.some(e => e.botID === unique_id)) {
request.bots = request.bots.filter(function(e) {
return e.botID != unique_id;
});
}
One way of doing this is to create a function that sets the variable bots.
Note: Instead of using seperate variables and functions i suggest to use something like a class to group all the functionality surrounding the bots.
server.js
var bots = [
{ botID: "16f11103", userID: "12345" },
{ botID: "5657d5e9", userID: "54321" },
];
var setBots = (newBots) => (bots = newBots);
setInterval(() => {
console.log(bots);
}, 5000);
module.exports = { bots, setBots };
bots.js
var { bots, setBots } = require("./server.js");
var unique_id = "16f11103";
if (bots.some((e) => e.botID === unique_id)) {
var newBots = bots.filter(function (e) {
return e.botID != unique_id;
});
setBots(newBots);
}
It's not working because of how variables are modified in JavaScript (Think copy by reference vs value).
When you first export the bots variable in server.js:
module.exports.bots = bots;
module.exports.bots is pointing to the bots variable by reference. If you modify the array directly like module.exports.bots[0] = 1 it will be reflected in the original bots variable as well since the reference hasn't changed.
However, what you're doing is reassigning the module.exports.bots value completely. The Array.prototype.filter() returns a new array without modifying the original.
When you do:
request.bots = request.bots.filter(function(e) {
return e.botID != unique_id;
});
You're making it so that the module.exports.bots variable points to a new array and no longer points to the original bots array. That's why your console.log call is always printing the same array because the original bots variable is still pointing to that array and it was never modified.
If you don't want to modify the array directly you can try this.
server.js
var request = {};
request.bots = [
{ botID: '16f11103', userID: '12345' },
{ botID: '5657d5e9', userID: '54321' }
];
setInterval(() => { console.log(request.bots); }, 5000);
module.exports = request;
bots.js can now be kept exactly the same
var request = require("../server.js");
var unique_id = '16f11103';
if (request.bots.some(e => e.botID === unique_id)) {
request.bots = request.bots.filter(function(e) {
return e.botID != unique_id;
});
}
You should do
var bots = [
{ botID: '16f11103', userID: '12345' },
{ botID: '5657d5e9', userID: '54321' }
];
setInterval(() => { console.log(bots); }, 5000);
module.exports = bots;
instead of
module.exports.bots = bots;
You can also do
exports.bots = bots;
Then use Like this
var bots = require("./server.js");
var unique_id = '16f11103';
if (bots.some(e => e.botID === unique_id)) {
bots = bots.filter(function(e) {
return e.botID != unique_id;
});
}

How do I set the value of a key in on array as the key in an other array?

I am trying to get the value feature_1 of a key name from the array data and set feature_1 as the key of another array asset which has an array as value.
Example :
//input:
data: {
name: "feature_1",
value_a: 1,
value_b: 2
}
//Output:
asset: {
feature_1:[1,2]
}
You can try:
var asset = {};
if ('name' in data) {
var tmp = [];
for (k in data){
if (k != 'name') tmp.push(data[k]);
}
asset[data['name']] = tmp;
}
and in case your interpreter supports ES6 you can use, for example:
let {name, ...v} = data;
let asset = {[name]: Object.values(v)};
If supports same keys in a JSON object ( It seems not ) You can do it like this:
let data= {
name: "feature_1",
value_a: 1,
value_b: 2,
value_x: 500,
name: "feature_2",
value_a: 17,
value_b: 21,
value_x: 510
}
console.log(
Object.entries(data).reduce((a,[key,value],index)=>{
if (key==='name')
return {index, assets: {...a.assets, [value]:[]}};
return {
index : a.index,
assets : {
...a.assets,
[Object.entries(a.assets)[a.index][0]] : [...Object.entries(a.assets)[a.index][1],value]
}};
},{index:0,assets:{}}).assets
);
But we know the correct way is using separated array rows.
This can be accomplished the following way:
const obj = {
data: {
name: "feature_1",
value_a: 1,
value_b: 2
}
};
const output = {
assets: {
[obj.data.name]: Object.values(obj.data).filter(el => el !== obj.data.name)
}
}
console.log(output);

What is the best way for reducing multiple if statement?

I have a helper function that builds object with appropriate query properties. I use this object as a body in my promise request. What is the most elegant way for refactoring multiple if statements? Here is a function:
getQueryParams = (query, pagination, sorting) => {
let queryParam = {}
if (pagination && pagination.pageNumber) {
queryParam.page = `${pagination.pageNumber}`
}
if (pagination && pagination.rowsOnPage) {
queryParam.size = `${pagination.rowsOnPage}`
}
if (query) {
const updatedQuery = encodeURIComponent(query)
queryParam.q = `${updatedQuery}`
}
if (sorting) {
queryParam.sort = `${sorting.isDescending ? '-' : ''}${sorting.name}`
}
return service.get(`/my-url/`, queryParam).then(result => {
return result
})
}
If service checks its parameters (as it should), you could benefit from the default parameters. Something like this:
const getQueryParams = (
query = '',
pagination = {pageNumber: 0, rowsOnPage: 0},
sorting = {isDescending: '', name: ''}
) => {
const queryParam = {
page: pagination.pageNumber,
size: pagination.rowsOnPage,
q: encodeURIComponent(query),
sort: `${sorting.isDescending}${sorting.name}`
}
return ...;
};
A live example to play with at jsfiddle.
This is an idea how it could looks like, but you need to adopt your params before:
const query = new URLSearchParams();
Object.keys(params).forEach(key => {
if (params[key]) {
query.append(key, params[key]);
}
});

Access var - scope issue

I have a javascript object which is structured like the following:
var object = {
item1: {
name: 'item1',
details: {
name: 'detail1',
warn_lvl: 1
},
check: function(res) {
console.log('Warn lvl of item1 = '+//access var?)
}
}
}
In my console.log() from my check() function, I would like to print the warn_lvl of item1, but I can't figure out how to access it.
I tried several things with this, but nothing which work.
What is the proper way to access this var?
Edit
To be more precise (sorry, my mistake), I call the check function from another Javascript file, like this (only relevant parts):
var fetchMetrics = function (config, metrics) {
Object.keys(metrics).forEach(function(section) {
var metric = metrics[section];
doRequests(metric, section);
};
var doRequests = function(metric, section) {
$.ajax({
dataType: "json",
url: metric.url,
data: metric.params,
var result;
if (!query_result.length) {
result = state_retriever.RESULT_UNKNOWN
} else {
result = metric.check(query_result);
}
};
If you're calling check via object.item1.check("res arg here"), then you can use this.details.warn_lvl:
var object = {
item1: {
name: 'item1',
details: {
name: 'detail1',
warn_lvl: 1
},
check: function(res) {
console.log('Warn lvl of item1 = ' + this.details.warn_lvl)
}
}
};
object.item1.check();
But you've said you're calling check a different way. You can reliably access it via object.item1.details.warn_lvl regardless of how you call check:
var object = {
item1: {
name: 'item1',
details: {
name: 'detail1',
warn_lvl: 1
},
check: function(res) {
console.log('Warn lvl of item1 = ' + object.item1.details.warn_lvl);
}
}
};
var c = object.item1.check;
c();

Categories

Resources