Nodejs breeze-sequelize with MySQL - .select() not functioning - mysql

I'm using breeze-sequelize version 0.0.18. I get a bizarre error _.pluck is not a function when I try to use select() on the entityQuery. And if I remove .select(), it'll work just fine.
My breeze query looks like this:
var predicate = Predicate.create('transactionDate', '>=', fromDate);
var entityQuery = EntityQuery.from('Transactions')
.where(predicate)
.select('transactionDate');
var sequelizeQuery = new SequelizeQuery(api.db, entityQuery);
return sequelizeQuery.execute();
And upon return, the error I get is:
TypeError: _.pluck is not a function
at SequelizeQuery.<anonymous> (/Users/shu/Documents/project/node_modules/breeze-sequelize/SequelizeQuery.json.js:143:39)
at Array.map (native)
at SequelizeQuery._processSelect (/Users/shu/Documents/project/node_modules/breeze-sequelize/SequelizeQuery.json.js:136:56)
at SequelizeQuery._processQuery (/Users/shu/Documents/project/node_modules/breeze-sequelize/SequelizeQuery.json.js:72:8)
at new SequelizeQuery (/Users/shu/Documents/project/node_modules/breeze-sequelize/SequelizeQuery.json.js:43:23)
at getTransactions (/Users/shu/Documents/project/src/server/api/admin.controller.js:189:26)
So curiously I took a look at function SequelizeQuery._processSelect in my breeze-sequelize library. The error is coming from return usesNameOnServer ? pp : _.pluck(props, "nameOnServer").join(".");.
SequelizeQuery.prototype._processSelect = function() {
var selectClause = this.entityQuery.selectClause;
var usesNameOnServer = this.entityQuery.usesNameOnServer;
if (selectClause == null) return;
// extract any nest paths and move them onto the include
var navPropertyPaths = [];
this.sqQuery.attributes = selectClause.propertyPaths.map(function(pp) {
var props = this.entityType.getPropertiesOnPath(pp, usesNameOnServer, true);
var isNavPropertyPath = props[0].isNavigationProperty;
if (isNavPropertyPath) {
this._addInclude(this.sqQuery, props);
}
if (isNavPropertyPath) return null;
return usesNameOnServer ? pp : _.pluck(props, "nameOnServer").join(".");
}, this).filter(function(pp) {
return pp != null;
});
}
Can someone help me? Thanks!

The _.pluck function is from lodash, and lodash removed the pluck function in version 4.0
The breeze-sequelize library will eventually be updated to lodash 4, but in the meantime, try using lodash 3.x.

Related

ReferenceError: Window is not defined while importing htmlToDraft from html-to-draftjs on Node.js

I wrote a separate function to convert html to draftjs, there I used htmlToDraft function from
html-to-draftjs.
The Function:
const htmlToDraftBlocks = (html) => {
const blocksFromHTML = htmlToDraft(html);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
const editorState = EditorState.createWithContent(state);
return editorState;
};
when running the server in node.js I get the following error:
ReferenceError : window is not defined
I have tried bellow way as well:
let htmlToDraft = null;
if (typeof window !== 'undefined') {
htmlToDraft = require('html-to-draftjs').default;
}
But in this case htmlToDraft remains null, not getting imported.
Why I am getting this error? Any help is appreciated

Problem assigning 'doJavaScript' return value to a variable (array)

I'm experimenting with JXA and trying to 'port' a small script, which parses track names from the web page. This script is currently working as Keyboard Maestro macro and is executed in current Safari window:
var trackBlock = document.getElementsByClassName("track tracklist_track_title");
var trackList = [];
for (var a of trackBlock) {
trackList.push(a.innerText);
}
trackList.join("\n");
The problem is that my porting attempt works well in JXA if doJavaScript returns a single string (variable trackName1 contains track title):
var sfr = Application("Safari");
var trackName1 = sfr.doJavaScript('document.getElementsByClassName("track tracklist_track_title")[1].innerText', { in: sfr.windows[0].currentTab });
trackName1 // contains track name
But if I change the code, so that doJavaScript returns an array (as it was in the initial code), the variable is null. Can you, please, explain me: what am I doing wrong?
var sfr = Application("Safari");
var trackBlock = sfr.doJavaScript('document.getElementsByClassName("track tracklist_track_title")', { in: sfr.windows[0].currentTab });
trackBlock[0].innerText; // null
Thank you!
I think the problem is this statement:
trackList.join("\n");
When you put that code in a JXA script, you need to escape the \n:
trackList.join("\\n");
Here's my script that works:
'use strict';
(function myMain() { // function will auto-run when script is executed
var app = Application.currentApplication();
app.includeStandardAdditions = true;
/*
HOW TO USE:
1. Open Safari to this URL:
https://forum.keyboardmaestro.com/
2. Run this script
*/
var jsStr = `
(function myMain2() {
//debugger;
//return 'Just testing';
var elemCol = document.querySelectorAll('div.category-text-title');
var elemArr = Array.from(elemCol);
var titleArr = elemArr.map(e => {return e.innerText});
return titleArr.join('\\n');
})();
`
var safariApp = Application("Safari");
var oTab = safariApp.windows[0].currentTab();
var pageURL = oTab.url();
var pageTitle = oTab.name();
var jsScriptResults = safariApp.doJavaScript(jsStr, {in: oTab})
console.log(jsScriptResults);
return jsScriptResults;
})();
//-->RETURNS:
/* Questions & Suggestions
Macro Library
Plug In Actions
Tips & Tutorials
Wiki
Announcements
Status Menu Icons
Forum Admin
*/
Here is a more clear example of the issue. Here is the code:
var sfr = Application("Safari");
var scr2run = 'document.getElementsByClassName("tracklist_track_title")';
var scr2run1 = 'document.getElementsByClassName("tracklist_track_title")[0]';
var scr2run2 = 'document.getElementsByClassName("tracklist_track_title")[0].innerText';
var trackName = sfr.doJavaScript(scr2run, { in: sfr.windows[0].currentTab });
var trackName1 = sfr.doJavaScript(scr2run1, { in: sfr.windows[0].currentTab });
var trackName2 = sfr.doJavaScript(scr2run2, { in: sfr.windows[0].currentTab });
Here is the output:
app = Application("Safari")
app.doJavaScript("document.getElementsByClassName(\"tracklist_track_title\")", {in:app.windows.at(0).currentTab})
--> null
app.doJavaScript("document.getElementsByClassName(\"tracklist_track_title\")[0]", {in:app.windows.at(0).currentTab})
--> null
app.doJavaScript("document.getElementsByClassName(\"tracklist_track_title\")[0].innerText", {in:app.windows.at(0).currentTab})
--> "From What Is Said To When It's Read"
Why the two first doJavaScript calls return null, but the third one returns expected value?
In answer to your second question:
Why the two first doJavaScript calls return null, but the third one
returns expected value?
var scr2run = 'document.getElementsByClassName("tracklist_track_title")';
var scr2run1 = 'document.getElementsByClassName("tracklist_track_title")[0]';
var scr2run2 = 'document.getElementsByClassName("tracklist_track_title")[0].innerText';
The third JavaScript returns a text value, whereas the first two do not. They return an element collection and an element.

google.script.run.withSuccessHandler() returns Undefined

I created an array in a separate GS file using the code provided below. I tried calling it in my HTML file. My goal is to compare the contents the array to the parameter email. However, the value returned by google.script.run.withSuccessHandler() is undefined
//in GS
function mailGetter()
{
//open sheet
var sheet = SpreadsheetApp.openByUrl("https://sheet.url").getSheetByName("Email Sheet").activate();
//get size of given row range
var row_data_email = sheet.getRange("C2:C").getValues();
var emailArray = row_data_email.join().split(',').filter(Boolean);
Logger.log(emailArray);
return emailArray;
}
//in HTML
function checkEmail(email)
{
var reg1 = /^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$/;
var arraySize = google.script.run.withSuccessHandler(misc).sizeGetter();
console.log(arraySize);
var emailArray = new Array(arraySize);
emailArray = google.script.run.withSuccessHandler(misc).mailGetter();
console.log(emailArray);
if (reg1.test(email) == false)
{
emails.style.border = "1px solid red";
document.getElementById('submitBtn').disabled = true;
}
else if (reg1.test(email) == true)
{
emails.style.border = "1px solid green";
document.getElementById('submitBtn').disabled = false;
}
for (var row = 0; row < arraySize; row++)
{
if (emailArray[row][0] == email)
{
emails.style.border = "1px solid green";
document.getElementById('submitBtn').disabled = false;
break;
}
else if (emailArray[row][0] != email)
{
emails.style.border = "1px solid red";
document.getElementById('submitBtn').disabled = true;
}
}
}
function misc()
{
console.log("Pass");
}
Issue:
Using a asynchronous function's(google.script.run) return value, which will always be undefined.
Solution:
Use successHandler as mentioned in another answer or We can use promises with async/await.
Snippet:
/*Create a promise around old callback api*/
const p = func =>
new Promise(resolve=>
google.script.run.withSuccessHandler(resolve)[func]()
);
async function checkEmail(email) //modified
{
var arraySize = await p('sizeGetter');//Wait to resolve
console.log(arraySize);
//var emailArray = new Array(arraySize);
var emailArray = await p('mailGetter');//Wait to resolve
console.log(emailArray);
//....
}
Note:
It's better to reduce the number of calls to the server. If you can combine both Getters to a single server function, it'll be better.
The above is a snippet showing how to use async/await. But if you wait for each response from the server as shown above, your front end/UI will be slow. Wait only if absolutely necessary. Calls to server should be non-blocking/asynchronous.
References:
Promises
async
await
Issue is in these lines:
emailArray = google.script.run.withSuccessHandler(misc).mailGetter();
console.log(emailArray);
You're trying to execute mailGetter() and expecting it to return value which you're storing in emailArray but this method is asynchronous and does not return directly
Rather you'll get the value in callback which you have defined as SuccessHandler
Suggested solutions :
Calling Apps Script functions from a template : https://developers.google.com/apps-script/guides/html/templates#apps_script_code_in_scriptlets
Calling Apps Script APIs directly : https://developers.google.com/apps-script/guides/html/templates#calling_apps_script_apis_directly
Pushing variables to templates : https://developers.google.com/apps-script/guides/html/templates#pushing_variables_to_templates
Reference : https://developers.google.com/apps-script/guides/html/reference/run#myFunction(...)

MEAN Nodejs JSON.parse passing data from client to server

I am using MEAN stack and I am sending query parameters dynamically to my Nodejs server endpoints.
My client controller :
$http.get('/api/things',{params:{query:query}}).then(response => {
this.awesomeThings = response.data;
socket.syncUpdates('thing', this.awesomeThings);
});
where query is a value injected into the controller.
This is the server controller function (which works):
export function index(req, res) {
var query = req.query.query && JSON.parse(req.query.query)
Thing.find(query).sort({_id:-1}).limit(20).execAsync()
.then(respondWithResult(res))
.catch(handleError(res));
}
The above works but I am trying to understand the line
var query = req.query.query && JSON.parse(req.query.query)
as I have never seen this before( and I don't come from a programming background). I console.logged query and understand it's an object (which is required by Mongodb) but when I console.logged (JSON.parse(req.query.query)) or JSON.parse(query) to find out the final output, the program stops working with no error messages, very strange..
If someone can explain the above syntax and why it has to be done this way for it work, that would be much appreciated..
PS when I try to console log the JSON.parse like so, it fails to load even though it should have no effect whatsoever:
export function index(req, res) {
var query = req.query.query && JSON.parse(req.query.query)
var que = JSON.parse(req.query.query)
Thing.find(query).sort({_id:-1}).limit(20).execAsync()
.then(respondWithResult(res))
.catch(handleError(res));
console.log("que"+que)
}
function one() {
var x = {};
var res = JSON.parse(x.y);
console.log(res);
}
function two() {
var x = {};
var res = x.y && JSON.parse(x.y);
console.log(res);
}
<button onclick="one()">ERROR</button>
<button onclick="two()">NO ERROR</button>
var x = data && JSON.parse(data);
Since expression is evaluated from left, first data is evaulated.
If it is undefined then, the next part -> JSON.parse() is not performed.
On the other hand, if data is defined parse is tried and the result is returned and stored in x.
Main advantage here is the parse doesn't run if the variable wasn't defined.
it could be equivalent to saying:
if(data) {x = JSON.parse(x);}

Promisify a recursive function in node.js

I'm using bluebird for the control flow in my application, I'm trying to implement promisify to extend my recursive function into a promise, but it seems like the "then" method never got executed
I'm doing a mapping from one JSON object to another, the find function looks recursively into the JSON properties and returns the property based on an specific condition.
var promise = require("bluebird");
var mapToModel = function(res){
// res is a json structure
var processes = res.definitions.process;
var diagrams = res.definitions.BPMNDiagram;
var documents = [];
for(var prop in processes) {
if(processes.hasOwnProperty(prop)){
var propertyNames = Object.getOwnPropertyNames(processes[prop]);
for(var property in processes[prop]){
var mapping ={};
if(property==="$"){
//do something with the process
}else{
//shapes
mapping.hash = hash.hashCode(new Date().toString());
mapping.type = property;
mapping.value = processes[prop][property];
var bpmnItem = findPromise(processes[prop][property], function(x) {return x.$.id;}).then(function(value){
//I'm not reaching this point
var bpmnId = value.$.id;
console.log(value);
if(bpmnId!=undefined){
console.log("return:"+ bpmnId);
}
});
documents.push(mapping);
}
}
}
return documents;
}
}
var findPromise = promise.promisify(find);
function find(items,f) {
for(var key in items) {
var elem = items[key];
if (f(elem)) { return elem;}
if(typeof elem === "object") {
find(elem,f); // call recursively
}
}
}
The Bluebird promisify method works on the accepted callback convention for NodeJS - nodebacks.
Nodebacks are in the specific format of someOp(function(err,result){ that is - the first argument is always an error.
In fact, your find method is not even asynchronous, so there is no reason to promisify it to begin with. You can simply call it as it is.
Generally, you should not promisify synchronous functions, you just call them normally. In fact, you don't seem to have any asynchronous operation in your code - so you should not be using promises at all in it.
You can simply do:
mapping.value = processes[prop][property];
var value = find(processes[prop][property], function(x) {return x.$.id;});
var bpmnId = value.$.id;
console.log(value);
if(bpmnId!=undefined){
console.log("return:"+ bpmnId);
}
Remember, Promises are an abstraction over an eventual result. You keep doing everything synchronous just like you did before.