I have a Yaml file(layouts.yaml) of this format from which i want to perform crud Operations through REST Api:
Layouts:
-
Name: Default Layout
LayoutId : 1
ConfiguredSegments:
LiveA :
Height : 100
Id : LiveA
Ref1A :
Height : 100
Id : Ref1A
My controller Function to update a layout based on layout Id(I tried 2 ways which wont work):
1st way: //This does not seem to work
const raw = fs.readFileSync("layouts.yaml", 'utf8');
const layoutData = YAML.load(raw);
//function to update specific layout based on LayoutId
export const updateSpecificLayout = (req, res)=>{
const { id } = req.params;
const { ConfiguredSegments } = req.body;
const getLayoutList = JSON.parse(JSON.stringify(layoutData));
getLayoutList.forEach(element => {if(element.LayoutId == id) element.ConfiguredSegments =
ConfiguredSegments
});
let yaml = YAML.dump(getLayoutList);
fs.writeFileSync("layouts.yaml", yaml, function (err,file){
if(err) throw err;
console.log(`Layout with the id:${id} has been updated`);
})
}
2nd way://This does not seem to work as well
const raw = fs.readFileSync("layouts.yaml", 'utf8');
const layoutData = YAML.load(raw);
//function to update specific layout based on LayoutId
export const updateSpecificLayout = (req, res)=>{
const { id } = req.params;
const { ConfiguredSegments } = req.body;
const getLayout = JSON.parse(JSON.stringify(layoutData));
const foundLayout = getLayout.Layouts.find((layout) => layout.LayoutId == id);
if(ConfiguredSegments)foundLayout.ConfiguredSegments = ConfiguredSegments;
console.log(`Layout with the id:${id} has been updated`);
}
Through Postman i am testing my api with patch request with the following body:
{
"ConfiguredSegments": {
"Ref2A": {
"Height": 100,
"Id": "LiveA"
},
"Ref3A": {
"Height": 100,
"Id": "Ref1A"
}
}
}
But the yaml file is not getting updated.Any other ways to achieve this ?
You can try using this method.
Define a function which will be able to find and replace the object you are looking for.
Your controller function:
export const updateSpecificLayout = (req, res)=>{
const { id } = req.params;
const { ConfiguredSegments } = req.body;
const getLayoutList = JSON.parse(JSON.stringify(layoutData));
const layoutToBeUpdated = getLayoutList.Layouts.find((layout) => layout.LayoutId == id );
findAndReplace(getLayoutList.Layouts,layoutToBeUpdated.ConfiguredSegments,ConfiguredSegments)
let yaml = YAML.dump(getLayoutList);
fs.writeFileSync("layouts.yaml", yaml, function (err,file){
if(err) throw err;
console.log(`Layout with the id:${id} has been updated`);
})
}
The helper function which can find and replace the data.
// Helper function to update layout data
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object[x] == value) {
object["ConfiguredSegments"] = replacevalue;
break;
}
}
}
}
Related
I am using full-text search in my API and sorting using the score. The issue is after searching I usually get an item more than once and this is not the behaviour i expected. Please, how can i correct this?
here is how my router is designed
router.get('/place', async (req, res) => {
const match = {
deactivated: false,
}
const sort = {}
if (req.query.search) {
match.$text = {$search: req.query.search}
sort.score = {$meta: "textScore"}
}
const noOnPage = parseInt(req.query.limit) || 20
const pageNo = (parseInt(req.query.page)-1)*parseInt(req.query.limit) || 0
const endIndex = parseInt(req.query.page)*parseInt(req.query.limit)
const next = parseInt(req.query.page)+1
const previous = parseInt(req.query.page)-1
try {
const count = await Place.find(match).countDocuments().exec()
const place = await Place.find(match, sort)
.limit(noOnPage)
.skip(pageNo)
.sort(sort)
const result = {}
// Shows the search result count
result.resultCount = count
// Shows the previous page number
if (parseInt(req.query.page)!=1) {
result.previous = previous
}
// Shows the next page number
if (endIndex < count) {
result.next = next
}
// assigns the search results to variable names results
result.results = place
res.status(200).send(result)
} catch (e) {
res.status(400).send({ "message": "something went wrong please reload page" })
}
})
You could try using the mongoose paginate module.below are the simple changes you would need to make.
Example User model:
import {model, Schema} from 'mongoose';
const mongoosePaginate = require('mongoose-paginate-v2');
const userSchema = new Schema({
firstname: { type: String,trim:true},
lastname: { type: String,trim:true},
isconfirmed:{type:Boolean,default:false},
},
{timestamps:true});
userSchema.plugin(mongoosePaginate);
const appUsers:any = model('appusers', userSchema);
export default appUsers;
Sample get all users method, note the sort can be passed in options. You can play with the options object as you please
getAllUsers(req:Request,res:Response){
const options = {page: req.body.page?req.body.page:1,limit: 10,collation:
{locale: 'en'},sort:{createdAt:-1},select: {_id:1,firstname:1,lastname:1}};
appUsers.paginate({}, options, function(err:any, result:any) {
if(err){
res.status(500).json({status:false,msg:"Failed to fetch All
users",err:err});
}else{
res.status(200).json({status:true,msg:"List populated",data:result});
}
});
}
I have node js server file (index.js) and client file (orderlist.js)
In index.js i am getting promise object , like that
function returnOrderArray() {
var i = 0;
const promise = new Promise((resolve, reject) => {
connection.query('SELECT * FROM orders', function(error, results) {
while (i < results.length) {
order.id[i] = results[i].id;
order.wavetype[i] = results[i].wavetype;
order.color[i] = results[i].color;
order.thick[i] = results[i].thick;
order.readydate[i] = results[i].readydate;
order.createdate[i] = results[i].createdate;
order.manager[i] = results[i].manager;
i++;
}
resolve(order);
// console.log(order);
});
});
return promise;
}
then i want to pass it to other js file.
I tried to do that with module.exports
app.get('/orderlist', checkUserSession, async function(request, response) {
returnOrderArray().catch(error => console.log(error)).then((() => {
module.exports.order = order;
response.render("orderlist.ejs", { username: request.session.username });
})).catch(error => console.log(error));
});
and then import it in orderlist.js
var ind = require('../../index')
function asd() {
alert(ind.order);
}
but it seems not to work.
What am i doing wrong , and what's the best way to pass objects to other files in js?
oh , and file architecture
filearch
You need to export your module like so: module.exports = returnOrderArray
try this,
orderlist.js
const returnOrderArray = () => {...some code..}
module.exports = returnOrderArray
index.js
const returnOrderArray = require('./path/to/orderlist.js')
const run = async() => {
const orderlist = await returnOrderArray() // use await or then as you prefer
}
run()
async_await link if curious!
Hope this will work :)
I am making an API that gets a list of image names, then it has to download them one by one from S3 bucket and then send them all as a response.
The issue is that my images are being uploaded but it seems that when I put them in a list as base64 and then try to send the list then the list just comes up empty.
const getImagesById = async (req, res) => {
const { id } = req.params;
const imagesSet = new Map();
try {
const documentFromDB = await document.findOne({ id });
documentFromDB.devices.forEach((device) => {
const images = new Set();
device.images.forEach(item => images.add(downloadFromS3(item)))
imagesSet.set(device.name, JSON.stringify(mapToObj(images))) // tried adding just images also but neither works
});
res.status(200).json(JSON.stringify(mapToObj(imagesSet)));
} catch (e) {
console.log(`An error occurred : ${e.message}`);
res.status(500)
.send(e.message);
}
};
function mapToObj(inputMap) {
let obj = {};
inputMap.forEach(function(value, key){
obj[key] = value
});
return obj;
}
And this is how I get images from S3:
const downloadFromS3 = async (imageName) => {
try {
const image = await S3Utils.downloadFile(BUCKET_NAME, imageName);
if (image.stack) {
return null;
}
const imageBase64 = image.Body.toString('base64');
return imageBase64;
} catch (e) {
console.log(`An error occurred while downloading : ${e.message}`);
throw e;
}
};
This is the response I am getting at the moment:
"{\"{ name: 'Martin'}\":\"{\\\"[object Promise]\\\":{}}\"}"
What I am trying to do is get a lits of device names, map them in a Map as key with value as the base64 list of images and then send it all in a response to the UI to show the images with the names.
What am I doing wrong here?
You just need to add await before call the downloadFromS3 function, consequently changing all the above functions.
const getImagesById = async (req, res) => {
const { id } = req.params;
const imagesSet = new Map();
try {
const documentFromDB = await document.findOne({ id });
await Promise.all(documentFromDB.devices.map(async (device) => {
const images = new Set();
await Promise.all(device.images.map(async item => images.add(await downloadFromS3(item))))
imagesSet.set(device.name, JSON.stringify(mapToObj(images))) // tried adding just images also but neither works
}));
res.status(200).json(JSON.stringify(mapToObj(imagesSet)));
} catch (e) {
console.log(`An error occurred : ${e.message}`);
res.status(500)
.send(e.message);
}
};
function mapToObj(inputMap) {
let obj = {};
inputMap.forEach(function(value, key){
obj[key] = value
});
return obj;
}
When i call Create Option api it is working fine but when i call list api get error: Cannot read property 'count' of undefined Express (Node + MongoDB) API.here is my Option Controller File code.
i have Log DB.ProductDoption ,getting result but count function not working.
const _ = require('lodash');
const Joi = require('joi');
exports.create = async (req, res, next) => {
try {
const validateSchema = Joi.object().keys({
name: Joi.string().required(),
key: Joi.string().required(),
description: Joi.string().allow(['', null]).optional(),
options: Joi.array().items(Joi.object().keys({
key: Joi.string().required(),
displayText: Joi.string().required()
})).required()
});
const validate = Joi.validate(req.body, validateSchema);
if (validate.error) {
return next(PopulateResponse.validationError(validate.error));
}
const key = Helper.String.createAlias(req.body.key);
console.log(DB.ProductDoption);
const count = await DB.ProductDoption.count({ key });
if (count || validate.value.key === '_custom') {
return next(PopulateResponse.error({
message: 'Please add unique name for key'
}));
}
const option = new DB.ProductDoption(validate.value);
await option.save();
res.locals.option = option;
return next();
} catch (e) {
return next(e);
}
};
exports.list = async (req, res, next) => {
const page = Math.max(0, req.query.page - 1) || 0; // using a zero-based page index for use with skip()
const take = parseInt(req.query.take, 10) || 10;
try {
const query = Helper.App.populateDbQuery(req.query, {
text: ['name', 'key', 'description']
});
const sort = Helper.App.populateDBSort(req.query);
const count = await DB.ProductDoption.count(query);
const items = await DB.ProductDoption.find(query)
.collation({ locale: 'en' })
.sort(sort).skip(page * take)
.limit(take)
.exec();
res.locals.optionList = {
count,
items
};
next();
} catch (e) {
next(e);
}
};
collection.count is deprecated, and will be removed in a future version. Use Collection.countDocuments or Collection.estimatedDocumentCount instead
I am creating a pie chart which shows how much disk space is available/used on my linux box. However, I am unsure how to parse the data onto a microservice url. Help will greatly be appreciated.
Here is what I have at the moment:
Router:
router.route('/linux_disk').get(disk.get_linux_disk)
Controller:
function get_linux_disk(req, res, next) {
try {
var cmd = `df ~`;
exec(cmd)
rows = [];
rows.push({"Command": cmd});
if (rows.length >= 1) {
res.status(200).json(rows);
} else {
res.status(404).end();
}
} catch (err) {
next(err);
}
}
You might try the approach below, we create a row object for each entry that the df
command creates. Once you have this you should be able to create your pie chart from this:
const { exec } = require('child_process');
const { promisify } = require('util');
const execPromise = promisify(exec);
async function get_linux_disk(req, res, next) {
try {
const result = await execPromise(`df ~`)
const lines = result.stdout.split("\n");
const keys = lines[0].split(/\s+/ig);
// Skip the header row when assigning objects..
const rows = lines.slice(1).map(line => {
// Parse each line..
const values = line.split(/\s+/ig);
return keys.reduce((o, k, index) => {
o[k] = values[index];
return o;
}, {})
});
res.status(200).json(rows);
} catch (err) {
res.status(500).send(err.message);
}
}
The resulting JSON will look a bit like so :
[
{
"Filesystem": "/dev/sda1",
"1K-blocks": "10253588",
"Used": "7971516",
"Available": "1741504",
"Use%": "83%",
"Mounted": "/"
}
]