I have these 2 functions in AssessmentController.js:
/**
* Get all assessments
*
* #param req
* #param res
* #returns {Promise<void>}
*/
static async GetAll(req, res) {
try {
let assessments = await Assessment.GetAll(req.query);
res.json({
msg: 'Assessments were listed successfully.',
assessments //This is marked as unused property
});
} catch (err) {
CustomError.handle(err, res);
}
}
/**
* Get a single assessment
*
* #param req
* #param res
* #returns {Promise<void>}
*/
static async GetAssessment(req, res) {
try {
let assessment = await Assessment.GetAssessment(req.params.id);
res.json({
msg: 'Assessment is retrieved successfully',
assessment //This is NOT marked as unused property
})
} catch (err) {
CustomError.handle(err, res);
}
}
The return types in JSDoc of the functions GetAll and GetAssessment are #returns {Promise<Object[]>} and #returns {Promise<Object>} respectively.
I don't know why passing assessments property to res.json in the first function (GetAll) triggers unused variable although this is not happening in the second function (GetAssessment).
Please let me know in the comments if you need any more information as I don't know where exactly to look for the problem.
Here is a snapshot of what I'm seeing:
NOTE:
Even if I don't use shorthand property (assessments: assessments) I get the warning.
I have also discovered just now that if I rename the variable to assessment (Singular) the warning is gone, how can I trace this problem?
Another example, it happens very randomly and I am showing images to see what I'm facing:
Maybe it is an IDE bug?
This issue is tracked at WEB-38106, please follow it for updates
You can try this:
assessments: assessments
instead of assessments.
Maybe your ide doesn't understand it.
Related
I have a custom excel function that calculates a salt hash and attempts to return the hash and the salt as an array. When I run the function, the values appear to be generated correctly but I get a #VALUE error when trying to display them and I'm not sure why. It appears that the issue is coming from the salt portion of the hash. Excel doesn't seem to like a value starting with "$" so if I add a space before the salt value then it works correctly. Why am I receiving a #VALUE error and how can I resolve it?
Excel AddIn Code
/**
* Returns hash for input text.
* #customfunction SALT_HASH
* #param {string} text
* #param {string} [salt]
* #returns string[][]
*/
export async function saltHash(text: string, salt?: string): Promise<string[][]> {
try {
const saltHash = await api.saltHash(text, salt);
const response = [[saltHash.hash, saltHash.salt]];
Logger.info(response);
return response;
} catch (error) {
Logger.error(new SaltHashErrorLog("Salt hash function call failed", text, salt, error).log());
return [[`Salt hash function call failed: ${buildErrorMessage(error)}`]];
}
}
Example API Response
{
"hash": "1IDvJZuvNSLS3EQl7kD9jLm2qN7Sp5K",
"salt": "$2b$10$BAsip4RJH8MMz0G7Dw5EvO"
}
I'm trying to get the values from two transaction body field using this code below .
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*#param {Record} context.currentRecord
*/
define(['N/record'],
function (msg) {
function beforeSubmit(context) {
try {
var record = context.currentRecord;
var createdDate = record.getValue({
fieldId: 'createddate'
});
var dataNecessidade = record.getValue({
fieldId: 'custbodyek_data_nece_requ_po'
});
console.log(createdDate ,dataNecessidade);
}
catch(ex){
log.error(ex);
}
}
return {
beforeSubmit : beforeSubmit,
};
});
The error raised is "TypeError: Cannot call method "getValue" of undefined"
What I'm doing wrong here?
Thank you!
There is no currentRecord property on the context passed into a user event, hence the error message telling you that record is undefined. Review the docs for the beforeSubmit entry point to find the appropriate values.
On SuiteScript 2 each entry point has different parameters so you need to check those parameters on the Help or if you use an IDE like Eclipse, you will get that information when you create a new script, so for a UserEvent script and the beforeSubmit entry point, you will get something like this:
/**
* Function definition to be triggered before record is loaded.
*
* Task #5060 : calculate PO Spent Amount and Balance in realtime
*
* #param {Object} scriptContext
* #param {Record} scriptContext.newRecord - New record
* #param {Record} scriptContext.oldRecord - Old record
* #param {string} scriptContext.type - Trigger type
* #Since 2015.2
*/
and then you can see that the context parameter doesn't have a currentRecord property, instead, it has two other parameters that you can use newRecord or oldRecord so your code can be like this:
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*#param {Record} context.currentRecord
*/
define(['N/record'],
function (msg) {
// are you aware that you are "injecting" the 'N/record' library into the 'msg' variable ???
function beforeSubmit(context) {
try {
var record = context.newRecord;
var createdDate = record.getValue({
fieldId: 'createddate'
});
var dataNecessidade = record.getValue({
fieldId: 'custbodyek_data_nece_requ_po'
});
console.log(createdDate ,dataNecessidade);
}
catch(ex){
log.error(ex);
}
}
return {
beforeSubmit : beforeSubmit,
};
});
You try to write it like this, I always use this method to get the field value.
const bfRecord= context.newRecord;
const createdDate = bfRecord.getValue('createddate');
I have multiple files that start with comments like:
/*
* #title Force email verification
* #overview Only allow access to users with verified emails.
* #gallery true
* #category access control
*
* This rule will only allow access users that have verified their emails.
*
* > Note: It might be a better UX to make this verification from your application.
*
* If you are using [Lock](https://auth0.com/docs/lock), the default behavior is to log in a user immediately after they have signed up.
* To prevent this from immediately displaying an error to the user, you can pass the following option to `lock.show()` or similar: `loginAfterSignup: false`.
*
* If you are using [auth0.js](https://auth0.com/docs/libraries/auth0js), the equivalent option is `auto_login: false`.
*
*/
//jshint -W025
function (user, context, callback) {
if (!user.email_verified) {
return callback(new UnauthorizedError('Please verify your email before logging in.'));
} else {
return callback(null, user, context);
}
}
All files contains two types of comments i.e /**/ and // Now I am reading this file in my javascript code and want to remove comments and get the actual code in the variable e.g
function (user, context, callback) {
if (!user.email_verified) {
return callback(new UnauthorizedError('Please verify your email before logging in.'));
} else {
return callback(null, user, context);
}
}
I have tried using strip-comments and parse-comments npm but none of these work. Here is the code:
const fs = require('fs');
const path = require('path');
const strip = require('strip-comments');
module.exports = function (ruleFileName, globals, stubs) {
globals = globals || {};
stubs = stubs || {};
const fileName = path.join(__dirname, '../src/rules', ruleFileName + '.js');
const data = fs.readFileSync(fileName, 'utf8');
const code = strip(data);
console.log(code);
return compile(code, globals, stubs);
}
and with parse-comments I tried like:
const parsed = parseComments(data)[0];
const code = data.split('\n').slice(parsed.comment.end).join('\n').trim();
I think strip comment is not working because it takes string as an argument but fs.readFileSync doesn't return string. I have also tried data.toString()but that also didn't work. So how can I strip comments from the content? Is there any other solution?
try use regx to replace /\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm
var Text = `/*
* #title Force email verification
* #overview Only allow access to users with verified emails.
* #gallery true
* #category access control
*
* This rule will only allow access users that have verified their emails.
*
* > Note: It might be a better UX to make this verification from your application.
*
* If you are using [Lock](https://auth0.com/docs/lock), the default behavior is to log in a user immediately after they have signed up.
* To prevent this from immediately displaying an error to the user, you can pass the following option to "lock.show()" or similar: "loginAfterSignup: false".
*
* If you are using [auth0.js](https://auth0.com/docs/libraries/auth0js), the equivalent option is "auto_login: false".
*
*/
//jshint -W025
function (user, context, callback) {
if (!user.email_verified) {
return callback(new UnauthorizedError('Please verify your email before logging in.'));
} else {
return callback(null, user, context);
}
}`
console.log(Text.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm,''))
like this
https://codepen.io/anon/pen/eQKrWP
So I'm trying to use nodejs mysql to access my locally running database that I am using for development. Everything is running correctly and I am able to make successful queries to the server and get the data back.
I have the function I created below which I am module.exports so that it is accessible from within my server where it is invoked and the loadExp() method is called.
var dataStore = function (connection) {
this.con = connection;
this.clientArr = new Map();
/**
* Loads all of the user experiences into the array.
*/
this.loadExp = function () {
var output = 'err';
loadData(this.con, function (err, result) {
console.log(err || result);
output = result.uuid;
});
console.log(output);
};
function loadData(con, callback) {
con.query('SELECT * FROM exp', function (err, rows, fields) {
if (err) throw err;
callback(null, rows);
});
}
/**
* Returns the value of a client from within the hash map.
* #param id
* #returns {*|String}
*/
this.getClient = function (id) {
var value = this.clients.get(id);
if (value != null) {
return value;
} else {
return 'err';
}
};
/**
* Returns a full list of clients.
* #returns {Map}
*/
this.getClientList = function () {
return this.clientArr;
};
/**
* Creates a new instance of a client within the database and also within our datastore.
* #param id
* #param client
*/
this.addClient = function (id, client) {
this.clientArr.set(id, client);
};
};
module.exports = dataStore;
Now I would like to make use of my this.addClient function outlined at the bottom of this function but I can never get my data in scope to make this possible and I'm stuck for how I would get this data in scope so that it is usable.
This is a problem with lexical scoping in JavaScript (ES5). You need to make sure the this is what you think it is when called. this is bound to the object the function was called within.
Look into setting var self = this at the top of your parent function and using that as a reference. Or, even better, using .bind(this).
I am writing a package as part of a small application I am working on and one thing I need to do is fetch json data from an endpoint and populate it to a Server side collection.
I have been receiving error messages telling me I need to put by server side collection update function into a Fiber, or Meteor.bindEnvironment, or Meteor._callAsync.
I am puzzled, because there are no clear and concise explanations telling me what these do exactly, what they are, if and when they are being deprecated or whether or not their use is good practice.
Here is a look at what is important inside my package file
api.addFiles([
'_src/collections.js'
], 'server');
A bit of psuedo code:
1) Set up a list of Mongo.Collection items
2) Populate these using a function I have written called httpFetch() and run this for each collection, returning a resolved promise if the fetch was successful.
3) Call this httpFetch function inside an underscore each() loop, going through each collection I have, fetching the json data, and attempting to insert it to the Server side Mongo DB.
Collections.js looks like what is below. Wrapping the insert function in a Fiber seems to repress the error message but no data is being inserted to the DB.
/**
* Server side component makes requests to a remote
* endpoint to populate server side Mongo Collections.
*
* #class Server
* #static
*/
Server = {
Fiber: Npm.require('fibers'),
/**
* Collections to be populated with content
*
* #property Collections
* #type {Object}
*/
Collections: {
staticContent: new Mongo.Collection('staticContent'),
pages: new Mongo.Collection('pages'),
projects: new Mongo.Collection('projects'),
categories: new Mongo.Collection('categories'),
formations: new Mongo.Collection('formations')
},
/**
* Server side base url for making HTTP calls
*
* #property baseURL
* #type {String}
*/
baseURL: 'http://localhost:3000',
/**
* Function to update all server side collections
*
* #method updateCollections()
* #return {Object} - a resolved or rejected promise
*/
updateCollections: function() {
var deferred = Q.defer(),
self = this,
url = '',
collectionsUpdated = 0;
_.each(self.Collections, function(collection) {
// collection.remove();
url = self.baseURL + '/content/' + collection._name + '.json';
self.httpFetch(url).then(function(result) {
jsonData = EJSON.parse(result.data);
_.each(jsonData.items, function(item) {
console.log('inserting item with id ', item.id);
self.Fiber(function() {
collection.update({testID: "Some random data"}
});
});
deferred.resolve({
status: 'ok',
message: 'Collection updated from url: ' + url
});
}).fail(function(error) {
return deferred.reject({
status: 'error',
message: 'Could not update collection: ' + collection._name,
data: error
});
});
});
return deferred.promise;
},
/**
* Function to load an endpoint from a given url
*
* #method httpFetch()
* #param {String} url
* #return {Object} - A resolved promise if the data was
* received or a rejected promise.
*/
httpFetch: function(url) {
var deferred = Q.defer();
HTTP.call(
'GET',
url,
function(error, result) {
if(error) {
deferred.reject({
status: 'error',
data: error
});
}
else {
deferred.resolve({
status: 'ok',
data: result.content
});
}
}
);
return deferred.promise;
}
};
I am still really stuck on this problem, and from what I have tried before from reading other posts, I still can't seem to figure out the 'best practice' way of getting this working, or getting it working at all.
There are plenty of suggestions from 2011/2012 but I would be reluctant to use them, since Meteor is in constant flux and even a minor update can break quite a lot of things.
Thanks
Good news : the solution is actually much simpler than all the code you've written so far.
From what I've grasped, you wrote an httpFetch function which is using the asynchronous version of HTTP.get decorated with promises. Then you are trying to run your collection update in a new Fiber because async HTTP.get called introduced a callback continued by the use of promise then.
What you need to do in the first place is using the SYNCHRONOUS version of HTTP.get which is available on the server, this will allow you to write this type of code :
updateCollections:function(){
// we are inside a Meteor.method so this code is running inside its own Fiber
_.each(self.Collections, function(collection) {
var url=// whatever
// sync HTTP.get : we get the result right away (from a
// code writing perspective)
var result=HTTP.get(url);
// we got our result and we are still in the method Fiber : we can now
// safely call collection.update without the need to worry about Fiber stuff
});
You should read carefully the docs about the HTTP module : http://docs.meteor.com/#http_call
I now have this working. It appears the problem was with my httpFetch function returning a promise, which was giving rise to the error:
"Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment."
I changed this httpFetch function to run a callback when HTTP.get() had called with success or error.
Inside this callback is the code to parse the fetched data and insert it into my collections, and this is the crucial part that is now working.
Below is the amended Collections.js file with comments to explain everything.
Server = {
/**
* Collections to be populated with content
*
* #property Collections
* #type {Object}
*/
Collections: {
staticContent: new Mongo.Collection('staticContent'),
pages: new Mongo.Collection('pages'),
projects: new Mongo.Collection('projects'),
categories: new Mongo.Collection('categories'),
formations: new Mongo.Collection('formations')
},
/**
* Server side base url for making HTTP calls
*
* #property baseURL
* #type {String}
*/
baseURL: 'http://localhost:3000',
/**
* Function to update all server side collections
*
* #method updateCollections()
* #return {Object} - a resolved or rejected promise
*/
updateCollections: function() {
var deferred = Q.defer(),
self = this,
collectionsUpdated = 0;
/**
* Loop through each collection, fetching its data from the json
* endpoint.
*/
_.each(self.Collections, function(collection) {
/**
* Clear out old collection data
*/
collection.remove({});
/**
* URL endpoint containing json data. Note the name of the collection
* is also the name of the json file. They need to match.
*/
var url = self.baseURL + '/content/' + collection._name + '.json';
/**
* Make Meteor HTTP Get using the function below.
*/
self.httpFetch(url, function(err, res) {
if(err) {
/**
* Reject promise if there was an error
*/
deferred.reject({
status: 'error',
message: 'Error fetching content for url ' + url,
data: err
});
}
else {
/**
* Populate fetched data from json endpoint
*/
var jsonData = res.content;
data = EJSON.parse(res.content);
/**
* Pick out and insert each item into its collection
*/
_.each(data.items, function(item) {
collection.insert(item);
});
collectionsUpdated++;
}
if(collectionsUpdated === _.size(self.Collections)) {
/**
* When we have updated all collections, resovle the promise
*/
deferred.resolve({
status: 'ok',
message: 'All collections updated',
data: {
collections: self.Collections,
count: collectionsUpdated
}
});
}
});
});
/**
* Return the promise
*/
return deferred.promise;
},
/**
* Function to load an endpoint from a given url
*
* #method httpFetch()
* #param {String} url
* #param {Function} cb - Callback in the event of an error
* #return undefined
*/
httpFetch: function(url, cb) {
var res = HTTP.get(
url,
function(error, result) {
cb(error, result);
}
);
}
};