Load data to Snowflake using NodeJS/Express - javascript

I have a simple HTML with single button. JavaScript (being client-side script) captures time of each click. I got stuck on how to pass event/time occurence of a click and display using Node.js to later transfer it intoo Snowflake database.
From what I reviewed it seems that workaround is JSDOM however currently it throws me an error.
Here are the topics I reviewed:
https://stackoverflow.com/questions/13840429/what-is-the-difference-between-client-side-and-server-side-programming
https://stackoverflow.com/questions/38748996/using-document-object-in-nodejs
[UPDATE - November 2020]
After reviewing below I came up with new code splitting the project into 3 files. Still need help with inserting data into Snowflake, not sure how to bind click event to the sql text. Overall goal is to insert datetime of click event into Snowflake's table:
https://gist.github.com/aerrity/fd393e5511106420fba0c9602cc05d35
Work in progress code:
server.js
console.log('Server-side code running');
const express = require('express');
const app = express();
// serve files from the public directory
app.use(express.static('public'));
//connect to snowflake and load data
var snowflake = require('snowflake-sdk');
var connection = snowflake.createConnection( {
account: 'xxxx',
username: 'xxxx',
password: 'xxxx'
}
);
//confirm connection is working
connection.connect(
function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
connection_ID = conn.getId();
}
}
);
// start the express web server listening on 8080
app.listen(8080, () => {
console.log('listening on 8080');
});
// serve the homepage
app.get('/', (req, res) => {
res.sendFile(__dirname + '/countClicks.html');
});
// insert data into snowflake isues, how to bind click event?
connection.execute({
sqlText: 'INSERT INTO DEMO_DB.PUBLIC.INPUT_NODEJS(CLICK_DATETIME)',
binds: [/clicked]
});
countClicks.js
const button = document.getElementById('clicks');
button.addEventListener('click', function(e) {
console.log('button was clicked');
fetch('/clicked', {method: 'POST'})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
countClicks.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Node + Express + Snowflake example</title>
</head>
<body>
<h1>Node + Express + Snowflake example</h1>
<p id="counter">Loading button click data.</p>
<button id="myButton">Click me!</button>
</body>
<script src="countClicks.js"></script>
</html>

Related

Trying to send a string message from javascript server to client using sockets; when pressing HTML button

I am new to this area so forgive me if I fail to explain my question well.
I am essentially trying to send a string "Hello, I connected to the port" to my Javascript client, only when I have pressed a HTML button.
FOR TESTING PURPOSES:
I have been successful in running a client and server Javascript socket connection, and can receive data back and forth. However when trying to link this to my html page I fail to connect them and send data.
CLIENT.JS:
const net = require('net');
const client = net.createConnection({ port: 9898 }, () => {
console.log('CLIENT: I connected');
client.write('CLIENT: Hello this is client!');
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('CLIENT: I disconnected from the server.');
});
SERVER.JS
const net = require('net');
const server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log(data.toString());
});
socket.write('SERVER: Hello! \n');
socket.end('SERVER: Closing connection now \n');
}).on('error', (err) => {
console.error(err);
});
server.listen(9898, () => {
console.log('opened server on', server.address().port);
});
if you save the above code and run them using the lines:
node server.js
node client.js
You will find that they send messages between them quite nicely.
The issue starts when I try to run my html page (which is served using node.JS on port 8083)
(I server my HTML page using npx http-server --cors)
An approach I tried was to place the code in client.js into a function and then call it in my html button:
<input type = "button" onclick = "outputData()" value = "Display">
(outputData being the function that contains the code in client server)
I'm not sure if its even something that can be done, but I'd like to essentially start my server.js from my HTML page, when a button is clicked, so that it can begin sending the data. I'd want to run "node client.js" on terminal and see that messages are coming through as server.js would have been started from my webpage
Any advice would be highly appreciated. Thank you for taking the time.
Information about socket.io library, https://socket.io/docs/v3/client-api/index.html
Sending message index.html
<html>
<body>
<input type="button" onclick="javascript:sendMessage()" value="Click here"/>
<script>
const sendMessage = () => {
var new_message = {message: "this is my message"}
socket.emit('new_message', new_message);
}
</script>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io("http://localhost:8080");
</script>
</body>
</html>
server.js
socket.on('new_message', (data) => {
var New_Details = {
message: data.message
};
socket.broadcast.emit('update_message', New_Details);
console.log(data.username + ' just wrote ' + data.message);
});
I managed to solve this by using Websockets. Where my webserver acted as the client, and I adjusted my server.js to the following:
SERVER.JS
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 9898 });
wss.on("connection", ws => {
console.log("New client connected!");
ws.on("message", data => {
console.log(`Client has sent us: ${data}`);
ws.send(data.toUpperCase());
});
ws.on("close", () => {
console.log("Client has disconnected!");
});
});
HTML
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/dcode.css">
<link rel="shortcut icon" href="/assets/favicon.ico" type="image/x-icon">
<title>WebSockets</title>
</head>
<body>
<script>
const ws = new WebSocket("ws://localhost:9898");
ws.addEventListener("open", () => {
console.log("We are connected!");
ws.send("Hey, how's it going?");
});
ws.addEventListener("message", ({ data }) => {
console.log(data);
});
</script>
</body>
</html>

Node.js using socket.io in multiple .js files

I want to be able to write functions in multiple .js files and use the same socket that is create in my main server.js
server.js:
var express = require('express')
var app = express()
var http = require('http')
var server = http.createServer(app)
var io = require('socket.io')(server)
var GOR = require('./gor')
var path = require('path');
app.use(express.static(path.join(__dirname, '/public')));
//handles get request and serves index.html
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
//wait for server to start
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
//setInterval(GOR.send_from_another_js,5000);
//GOR.send_from_another_js(io);
})
function emit_data(){
io.emit( 'update', "webserver.js");
}
As you can see from the code above, I have a function that emits to socket every 5 seconds and that works fine. I have confirmed it already.
All I want to do now, is to create a seperate.js file and keep all my functions there to make the code look cleaner. I name another .js file gor.js:
gor.js:
//I want to call this function in my webserver.js and transmit this socket
function send_from_another_js(io){
console.log("function called");
io.emit( 'update', "another_js");
}
module.exports = {
send_from_another_js
}
When I call this function in my server.js , it does not work:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
What is correct way to use the same .io in other .js files? The above does not work.
EDIT1
In my .html, I wait for a message on socket:
window.addEventListener('DOMContentLoaded', () => {
socket.on('update', function(number_to_set) {
console.log("socket update received");
document.getElementById('number1').innerHTML = number_to_set;
});
var button = document.getElementById("operation_code_button");
button.addEventListener("click", function(event){
var val = document.getElementById("operation_code_input").value;
console.log("socket clicked, emmiting data");
socket.emit('button_click',val);
});
})
And in my .js file I emit to this socket every 5 seconds:
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
})
After 5 seconds, I can see that my webpage update data so everything works!!!
I want to declare the emit_data function inside another .js file and use it in my main .js file.
The function in my secondary .js file ( gor.js):
function send_from_another_js_1(io){
io.emit( 'update', data);
}
I want to call it in my main .js the same way I call emit_data
You need to wait for your server to get initialized. You are calling your function before socket.io is ready. That's why io.emit function is 'undefined'.
server.listen(8080,()=>{
GOR.send_from_another_js(io);
})
Edited:(3)
Trust it is what you are looking for...
"server.js"
const content = require('fs').readFileSync(__dirname + '/index.html', 'utf8');
const httpServer = require('http').createServer((req, res) => {
// serve the index.html file
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(content));
res.end(content);
});
const io = require('socket.io')(httpServer);
const apple = require("./File2.js")
apple.send_from_another_js_1(io);
apple.send_from_another_js_2(io);
var port = 3000; //wamp server
var prompt = 'Open browser at http://localhost:'
httpServer.listen(port, () => {
console.log(prompt, port);
});
"File2.js"
function send_from_another_js_1(io){
io.on('connection', function (socket) {
socket.on('file2_1_EventTrigged', function (data) {
socket.emit('update1', "send_from_another_js_1(io) : "+ data);
console.log("+++ function send_from_another_js_1(io) called");
});
});
}
function send_from_another_js_2(io){
io.on('connection', function (socket) {
socket.on('file2_2_EventTrigged', function (data) {
socket.emit('update2', "send_from_another_js_2(io) : "+ data);
console.log("... function send_from_another_js_2(io) called");
});
});
}
module.exports = {
send_from_another_js_1,
send_from_another_js_2
}
"index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Content-Type" content="text/html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="keywords" content="HTML, CSS, JavaScript">
<meta name="author" content="Dr.Chaiya Tantisukarom">
<meta http-equiv="Cache-Control" content="public, max-age=31536000">
<title>NodeJS socket.io</title>
</head>
<body>
<h1 style="text-align: center;">Hello another world</h1>
<div style="text-align: center;">
<span>
<button onclick="file2_1()">file2_1</button>
</span>
<span>
<button onclick="file2_2()">file2_2</button>
</span>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('connect',()=>{
//alert('Connected');
})
function file2_1(){
socket.emit('file2_1_EventTrigged', "Hello file2_1, how are you today?");
}
socket.on('update1', (data)=>{
alert(data);
})
function file2_2(){
socket.emit('file2_2_EventTrigged', "Hi file2_2, trust you are ok.");
}
socket.on('update2', (data)=>{
alert(data);
})
</script>
</body>
</html>
Cheers !!!
When you call this:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
setInterval() isn't providing a parameter for GOR.send_from_another_js(), so io becomes undefined.
To fix this, I would use a second lambda expression inside of your setInterval() call.
server.listen(8080, () => {
console.log("server started");
setInterval(() => {
GOR.send_from_another_js(io);
}, 5000);
GOR.send_from_another_js(io);
});

Button to download a document implemented with Express.js and node.js isn't working properly

In my project, I want the user to be able to download a document when he clicks on a button.
Project Structure:
public/client.js
console.log('Client-side code running');
const button = document.getElementById('myButton');
button.addEventListener('click', function(e) {
console.log('button was clicked');
fetch('/clicked', {method: 'POST'})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
public/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Report Generation</title>
</head>
<body>
<h1>Download your document!</h1>
<button id="myButton">Click me!</button>
</body>
<script src="client.js"></script>
</html>
server.js
console.log('Server-side code running');
const express = require('express');
const createDocumentService =
const app = express();
// serve files from the public directory
app.use(express.static('public'));
// start the express web server listening on 8080
app.listen(8081, () => {
console.log('listening on 8080');
});
// serve the homepage
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
app.get('/download', function(req, res){
setTimeout(() => {
res.download(path.join(__dirname, 'docs/doc1.txt'), function (err) {
console.log(err);
});
}, 500)
});
app.post('/clicked', (req, res) => {
const click = {clickTime: new Date()};
console.log(click);
setTimeout(() => {
res.download(path.join(__dirname, 'docs/doc1.txt'), function (err) {
console.log(err);
});
}, 500)
});
After running the app and clicking the button:
When the user clicks on the button, he should see the report file being downloaded thanks to:
In client.js
button.addEventListener('click', function(e) {
console.log('button was clicked');
fetch('/clicked', {method: 'POST'})
.then(function(response) {
if(response.ok) {
console.log('Click was recorded');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
});
In service.js:
app.post('/clicked', (req, res) => {
const click = {clickTime: new Date()};
console.log(click);
setTimeout(() => {
res.download(path.join(__dirname, 'docs/doc1.txt'), function (err) {
console.log(err);
});
}, 500)
});
But, the document doesn't get downloaded.
However, when I connect to
localhost:5353/download
The same code/logic I wrote for downloading the document and which is written inside the button POST route, works perfectly and the document does get downloaded.
So I don't really see why the same code is working for one "normal" route and isn't working for the other route that depends on the button.
Thank you!
You cannot download file using ajax cause Javascript doesn't have right to write to file. You can just use a href link or use the window.location it will work fine.
HTML:
Click me!
Use a .button class to style the link as a button.
JS:
button.addEventListener('click', function(e) {
console.log('button was clicked');
window.location="./download"
// or window.open(url, '_blank') for new window.
});

How to make a post request to mongo db atlas using node.js and express.js

I am trying to make a simple post request to Mongo Db Atlas using Node.js, Express.js and Mongoose.js. I fill out the form and send the request but it just keeps loading, no erros, nothing. ANyone have any ideas?
//Require assets
const express = require('express');
const app = express();
const mongoose = require('mongoose');
let port = 3000;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const MongoClient = require('mongodb').MongoClient;
const uri = 'mongodb+srv://michael:<PASSWORD-GOES-HERE>#around-town-vsisv.mongodb.net/admin';
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db('around_town_db').collection('events');
// perform actions on the collection object
client.close();
});
mongoose.Promise = global.Promise;
var eventSchema = mongoose.Schema({
eventName: String,
})
var eventData = mongoose.model('Event', eventSchema);
//Load index page using endpoint
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
//Post using endpoint
app.post('/addevent', (req, res) => {
var userData = {
eventName: req.body.eventName
}
new eventData(userData)
.save()
.then(res => {
res.send('item saved to database');
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});
//Listen on port 3000
app.listen(port, () => {
console.log('Server listening on port ' + port);
});
Below is a simple form for submitting the post request. Any ideas on what I am missing?
<!DOCTYPE html>
<html>
<head>
<title>Add a local event</title>
</head>
<body>
<div class="app">
<h1>Add an event</h1>
<form method="post" action="/addevent">
<label>Enter event Name</label><br>
<input type="text" name="eventName" placeholder="Enter event name..." required>
<input type="submit" value="Add Event">
</form>
</div>
</body>
</html>
OK, so it looks like you have two problems. First, you're not letting Mongoose itself connect to your database, and second you're overwriting the response variable. If you note your .then() callback in the userData.save() promise chain, you're calling that result variable 'res' as well as the response variable 'res' from the route callback.
To fix the first problem, somewhere in your app startup, one time call (instead of your current MongoClient code)
mongoose.connect(uri)
You can also use mongoose.createConnection() if you want more fine-grained control over the connection, or need to make multiple connections to different databases.
Second problem, your post handler should look like this:
//Post using endpoint
app.post('/addevent', (req, res) => {
var userData = {
eventName: req.body.eventName
}
new eventData(userData)
.save()
.then(result => { // note the use of a different variable name
res.send(result); // also, you generally want to send *something* down that lets the user know what was saved. Maybe not the whole object, but this is illustrative and the client will at least need to know something (e.g. the id) to refer to the object by in the future.
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});
Unrelated to your problem, but most folks write Express APIs in a RESTful manner. If you want to follow that convention, then your routes should look more like this:
GET /events // list the events
GET /events/:eventId // get a single event by ID
POST /events // add a new event
PUT /events/:eventId // update an existing event
DELETE /events/:eventId // remove an event
Try something like follow:
app.post('/addevent', (req, res) => {
var userData = new eventData({
eventName: req.body.eventName
})
userData.save()
.then(res => {
res.send('item saved to database');
})
.catch(err => {
res.status(400).send('unable to save to database');
});
});

Safari Push Notificatin + permission "denied" and no log found

I am try to integrate safari push notification. I referred following link.
http://samuli.hakoniemi.net/how-to-implement-safari-push-notifications-on-your-website/#resources
My client file is at...
-public_html/push/index.html
Server configuration files are at...
-public_html/push/node_modules/express/index.js
Push packages and log file are at...
-public_html/push/v1/pushPackages/[my push id]/myPackage.zip
-public_html/push/v1/pushPackages/[my push id]/log (file)
My index.js file has following code.
'use strict';
module.exports = require('./lib/express');
//Test code for Safari push notification
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
app.listen(port);
app.get('/', function(req, res) {
res.sendfile('index.html');
});
app.post('/v1/pushPackages/[my push id]', function(req, res) {
alert('hello');
res.sendfile('myPushPackage.zip');
});
app.post('/v1/log', function(req, res) {
});
My client file (index.html) has following code :
!doctype html>
<html>
<head>
<title> Safari Push Notifications</title>
</head>
<body>
<h1>Safari Push Notifications</h1>
Subscribe
<script>
var pushId = [my push id];
document.body.onload = function() {
// Ensure that the user can receive Safari Push Notifications.
if ('safari' in window && 'pushNotification' in window.safari) {
var permissionData = window.safari.pushNotification.permission(pushId);
checkRemotePermission(permissionData);
} else {
alert("Push notifications not supported.");
}
};
var checkRemotePermission = function (permissionData) {
if (permissionData.permission === 'default') {
alert("default.");
// This is a new web service URL and its validity is unknown.
console.log("The user is making a decision");
//alert('The user is making a decision');
var userinfo={};
window.safari.pushNotification.requestPermission(
'https://[mydomain]/push', // The web service URL.
pushId, // The Website Push ID.
userinfo, // Data that you choose to send to your server to help you identify the user.
checkRemotePermission // The callback function.
);
}
else if (permissionData.permission === 'denied') {
alert("denied.");
// The user said no.
console.log('denied');
}
else if (permissionData.permission === 'granted') {
alert("granted.");
// The web service URL is a valid push provider, and the user said yes.
// permissionData.deviceToken is now available to use.
console.log("The user said yes, with token: "+ permissionData.deviceToken);
}
};
</script>
</body>
</html>
It give us the alert of "default" then after "denied" alert.
Please help me.
app.post('/v1/pushPackages/[pushid]', function(req, res) {
console.log('Serving File');
res.sendFile('aa.zip', { root: __dirname });
});
app.post('/v1/log', function(req, res) {
console.log('Received LOG');
console.log(req.body);
});
This Solved my problem having tha aa.zip file on same location of index.js file. For more check your node log as console.log(req.body) show the error.

Categories

Resources