Embed RethinkDB into Electron (or NodeJS) app - electron

I'm building an Electron app, specifically a crypto-currency wallet, so I need all the information stored locally on the user's machine and should not be synced to any server.
I like RethinkDB and would like to use it, but I can't find a way to embed it into the app.
I want the database to launch when the app starts, and shutdown when the app closes... in other words have it embedded into the app.
Is this possible with Rethinkdb? There's no relevant info on the page detailing how to start-up the db but perhaps this can be done anyways?

As long as you are storing the user data on their local machine. I believe you should use the embedded database but not the client-server database engine. Of course, we can use any database in our Electron application but in most cases, we don't need any client-server db engine as long as we just need a simple library or script that can store and manage the local db file.
RethinkgDB is a great database library but it's a client-server pattern. Please use SQLite instead. SQLite is not a client-server database engine. Rather, it is embedded into the end program. As the below code snippets show, we just need to set the db file path where all data will be stored.
Query syntax is the same as PostgreSQL.
const sqlite3 = require('sqlite3');
const database = new sqlite3.Database('./public/db.sqlite3', (err) => {
if (err) console.error('Database opening error: ', err);
});
ipcMain.on('asynchronous-message', (event, arg) => {
const sql = arg;
database.all(sql, (err, rows) => {
event.reply('asynchronous-reply', (err && err.message) || rows);
});
});
In addition, I was used to using keytar to keep sensitive data like private keys and credentials of wallet.

Related

Playwright: Failed to Read the localStorage property from Window: Access is denied for this document

I have this script to modify localStorage of my browser instance (assuming all definitions are correct). it returns this Error. I have a feeling that this is because Playwright is launching a browser in incognito mode. Is there a way for me to launch browser in normal mode?
Script:
const rdlocalStorage = fs.readFileSync('localstorage.json','utf8');
const deserializedStorage = JSON.parse(rdlocalStorage);
console.log (deserializedStorage);
await page.evaluate((deserializedStorage)=>{
for (const key in deserializedStorage){
localStorage.setItem(key,deserializedStorage[key]);
}
}, deserializedStorage);
Error Message
enter image description here
I don't know why your error happens, but maybe I do have an alternative.
Playwright has an API to restore cookies and local storage for you, without you having to code it.
context.storageState is the method which allows you to capture the cookies, local storage, etc. You can either await and use the return value as object, or (await and) save the storage state to a file.
Restoring the storage state is done when creating a new browser context, by means of the storageState property on the options parameter of the browser.newContext method. You can either pass it a storageState object or a path to a storage state file.
These same objects and files can also be used in the #playwright/test runner.
The only thing which is not stored in storage state is the session storage (the 'brother' of the local storage). According to the Playwright docs it's not used so often for authentication state, so they don't have a 'native' method for saving and restoring it. But they do describe how to deal with session storage in case it's needed.
Not sure if I am correct but using await page.evaluate might not permit you to do what you're trying to do, thus getting that error. Try instead using the following snippet:
await context.addInitScript((deserializedStorage)=>{
for (const key in deserializedStorage){
localStorage.setItem(key,deserializedStorage[key]);
}
}, deserializedStorage);

Electron: how to close a portable app on pulling out the pendrive

I made a portable app with electron. It works fine. I have it saved in a pendrive, so I don't need to install it and copy into my hard disk to run it. Just executing the app from the pendrive I have it running in my desktop. But what I need, is implement a system that makes that if you pull out the pendrive the app automatically closes. I've been googling something similar and found many ways for using a pendrive as a master key. But that isn't exactly what I need. I don't want to shutdown the PC, I only need to close the app and remove it from memory. There is any way or nodejs library that can help me with that?
You can use node_usbspy module to watch the usb insertion/removal. This module supports only Windows.
If you receive an event with device_status as 0 then you could quit the app with app.quit()
Hope it helps you!
Note: I'm the author of node-usbspy.
I found a practical solution that could work on all platforms:
const basePath = app.getAppPath()
setInterval(() => {
const path = basePath.split('/')
const baseDir = path.slice(0, -1).join('/')
fs.writeFile(baseDir + '/portable.txt', '1', err => {
if(err) {
app.quit()
}
})
}, 1000)
The script above try to save a TXT file every second. If fs.writeFile returns an error, app.quit() is called closing the application.

Using Neo4j with React JS

Can we use graph database neo4j with react js? If not so is there any alternate option for including graph database in react JS?
Easily, all you need is neo4j-driver: https://www.npmjs.com/package/neo4j-driver
Here is the most simplistic usage:
neo4j.js
//import { v1 as neo4j } from 'neo4j-driver'
const neo4j = require('neo4j-driver').v1
const driver = neo4j.driver('bolt://localhost', neo4j.auth.basic('username', 'password'))
const session = driver.session()
session
.run(`
MATCH (n:Node)
RETURN n AS someName
`)
.then((results) => {
results.records.forEach((record) => console.log(record.get('someName')))
session.close()
driver.close()
})
It is best practice to close the session always after you get the data. It is inexpensive and lightweight.
It is best practice to only close the driver session once your program is done (like Mongo DB). You will see extreme errors if you close the driver at a bad time, which is incredibly important to note if you are beginner. You will see errors like 'connection to server closed', etc. In async code, for example, if you run a query and close the driver before the results are parsed, you will have a bad time.
You can see in my example that I close the driver after, but only to illustrate proper cleanup. If you run this code in a standalone JS file to test, you will see node.js hangs after the query and you need to press CTRL + C to exit. Adding driver.close() fixes that. Normally, the driver is not closed until the program exits/crashes, which is never in a Backend API, and not until the user logs out in the Frontend.
Knowing this now, you are off to a great start.
Remember, session.close() immediately every time, and be careful with the driver.close().
You could put this code in a React component or action creator easily and render the data.
You will find it no different than hooking up and working with Axios.
You can run statements in a transaction also, which is beneficial for writelocking affected nodes. You should research that thoroughly first, but transaction flow is like this:
const session = driver.session()
const tx = session.beginTransaction()
tx
.run(query)
.then(// same as normal)
.catch(// errors)
// the difference is you can chain multiple transactions:
const tx1 = await tx.run().then()
// use results
const tx2 = await tx.run().then()
// then, once you are ready to commit the changes:
if (results.good !== true) {
tx.rollback()
session.close()
throw error
}
await tx.commit()
session.close()
const finalResults = { tx1, tx2 }
return finalResults
// in my experience, you have to await tx.commit
// in async/await syntax conditions, otherwise it may not commit properly
// that operation is not instant
tl;dr;
Yes, you can!
You are mixing two different technologies together. Neo4j is graph database and React.js is framework for front-end.
You can connect to Neo4j from JavaScript - http://neo4j.com/developer/javascript/
Interesting topic. I am using the driver in a React App and recently experienced some issues. I am closing the session every time a lifecycle hook completes like in your example. When there where more intensive queries I would see a timeout error. Going back to my setup decided to experiment by closing the driver in some more expensive queries and it looks like (still need more testing) the crashes are gone.
If you are deploying a real-world application I would urge you to think about Authentication and Authorization when using a DB-React setup only as you would have to store username/password of the neo4j server in the client. I am looking into options of having the Neo4J server issuing a token and receiving it for Authorization but the best practice is for sure to have a Node.js server in the middle with something like Passport to handle Authentication.
So, all in all, maybe the best scenario is to only use the driver in Node and have the browser always communicating with the Node server using axios...

Equivalence of Rails console for Node.js

I am trying out Node.js Express framework, and looking for plugin that allows me to interact with my models via console, similar to Rails console. Is there such a thing in NodeJS world?
If not, how can I interact with my Node.js models and data, such as manually add/remove objects, test methods on data etc.?
Create your own REPL by making a js file (ie: console.js) with the following lines/components:
Require node's built-in repl: var repl = require("repl");
Load in all your key variables like db, any libraries you swear by, etc.
Load the repl by using var replServer = repl.start({});
Attach the repl to your key variables with replServer.context.<your_variable_names_here> = <your_variable_names_here>. This makes the variable available/usable in the REPL (node console).
For example: If you have the following line in your node app:
var db = require('./models/db')
Add the following lines to your console.js
var db = require('./models/db');
replServer.context.db = db;
Run your console with the command node console.js
Your console.js file should look something like this:
var repl = require("repl");
var epa = require("epa");
var db = require("db");
// connect to database
db.connect(epa.mongo, function(err){
if (err){ throw err; }
// open the repl session
var replServer = repl.start({});
// attach modules to the repl context
replServer.context.epa = epa;
replServer.context.db = db;
});
You can even customize your prompt like this:
var replServer = repl.start({
prompt: "Node Console > ",
});
For the full setup and more details, check out:
http://derickbailey.com/2014/07/02/build-your-own-app-specific-repl-for-your-nodejs-app/
For the full list of options you can pass the repl like prompt, color, etc: https://nodejs.org/api/repl.html#repl_repl_start_options
Thank you to Derick Bailey for this info.
UPDATE:
GavinBelson has a great recommendation for running with sequelize ORM (or anything that requires promise handling in the repl).
I am now running sequelize as well, and for my node console I'm adding the --experimental-repl-await flag.
It's a lot to type in every time, so I highly suggest adding:
"console": "node --experimental-repl-await ./console.js"
to the scripts section in your package.json so you can just run:
npm run console
and not have to type the whole thing out.
Then you can handle promises without getting errors, like this:
const product = await Product.findOne({ where: { id: 1 });
I am not very experienced in using node, but you can enter node in the command line to get to the node console. I then used to require the models manually
Here is the way to do it, with SQL databases:
Install and use Sequelize, it is Node's ORM answer to Active Record in Rails. It even has a CLI for scaffolding models and migrations.
node --experimental-repl-await
> models = require('./models');
> User = models.User; //however you load the model in your actual app this may vary
> await User.findAll(); //use await, then any sequelize calls here
TLDR
This gives you access to all of the models just as you would in Rails active record. Sequelize takes a bit of getting used to, but in many ways it is actually more flexible than Active Record while still having the same features.
Sequelize uses promises, so to run these properly in REPL you will want to use the --experimental-repl-await flag when running node. Otherwise, you can get bluebird promise errors
If you don't want to type out the require('./models') step, you can use console.js - a setup file for REPL at the root of your directory - to preload this. However, I find it easier to just type this one line out in REPL
It's simple: add a REPL to your program
This may not fully answer your question, but to clarify, node.js is much lower-level than Rails, and as such doesn't prescribe tools and data models like Rails. It's more of a platform than a framework.
If you are looking for a more Rails-like experience, you may want to look at a more 'full-featured' framework built on top of node.js, such as Meteor, etc.

Connect to MySQL from Microsoft Data Application Block

lI am using the Data Application block for a majority of my data access, specifically using the SqlHelper class to call the ExecuteReader, ExecuteNonQuery, and like methods. Passing the connection string with each database call.
How can I modify this to enable connection to a MySQL database as well.
If you've got the Enterprise Library installed and already know how to connect to SQL Server databases, connecting to MySQL databases is not any harder.
One way to do it is to use ODBC. This is what I did:
Go to MySQL.com and download the latest MySQL ODBC connector. As I write this it's 5.1.5. I used the 64-bit version, as I have 64-bit Vista.
Install the ODBC Connector. I chose to use the no-installer version. I just unzipped it and ran Install.bat at an administrator's command prompt. The MSI version probably works fine, but I did it this way back when I installed the 3.51 connector.
Verify the installation by opening your ODBC control panel and checking the Drivers tab. You should see the MySQL ODBC 5.1 Driver listed there. It seems to even co-exist peacefully with the older 3.51 version if you already have that. Additionally it coexists peacefully with the .NET connector if that is installed too.
At this point you will be doing what you've done to connect to a SQL Server database. All you need to know is what to use for a connection string.
Here's what mine looks like:
Of course you can set "name" to whatever you want.
If this is your only database, you can set it up as the defaultDatabase like this:
Access your data in your code like you always do! Here's a plain text sql example:
public List<Contact> Contact_SelectAll()
{
List<Contact> contactList = new List<Contact>();
Database db = DatabaseFactory.CreateDatabase("MySqlDatabaseTest");
DbCommand dbCommand = db.GetSqlStringCommand("select * from Contact");
using (IDataReader dataReader = db.ExecuteReader(dbCommand))
{
while (dataReader.Read())
{
Contact contact = new Contact();
contact.ID = (int) dataReader["ContactID"];
client.FirstName = dataReader["ContactFName"].ToString();
client.LastName = dataReader["ContactLName"].ToString();
clientList.Add(client);
}
}
return clientList;
}
Another way to do it is to build and use a MySql provider. This guy did that.
I learned how to do this by adapting these instructions for connecting to Access.
Oh, and here are some more MySql Connection String samples.

Resources