Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Electron and sqlite3 issue after packaging app

I've asked quite a few questions on here recently as I'm continually getting stuck with varying parts of node and databases.

Anyhow, a bit of background:

I have an Electron app with an AngularJS frontend. So on the electron side of things, I actually spin up an express server which serves my angular app, which can then of course talk to electron over ipc. I'm also using the express side of things to do the database stuff (sqlite3), defining routes for an api which Angular can hit using $http and have db results returned that way. Everything works absolutely fine when I'm running the app with 'npm start'. The code for the db/server side of things is as follows:

var path = require('path');
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require('body-parser');
var path = require('path');
var sqlite3 = require('sqlite3').verbose();

// Load the db
function createDbFile() {
    // Try to open the db file - if it doesn't exist, create it.
    try {
        var filebuffer = fs.readFileSync(path.join(__dirname, 'app.db'));
    }
    catch (err) {
        if (err.code === 'ENOENT') {
            fs.closeSync(fs.openSync(path.join(__dirname, 'app.db'), 'w'));
        } 
        else {
            throw err;
        }
    }
}

createDbFile();
var db = new sqlite3.Database('app.db');
var check;

db.serialize(function() {
db.run("CREATE TABLE IF NOT EXISTS lorem (info TEXT)");

var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
    stmt.run("Ipsum " + i);
}
stmt.finalize();
});

app.use(express.static(__dirname));
// app.use(bodyParser.json());

app.get('/', function (req, res) {
    res.sendFile(__dirname + 'index.html');
});

app.get('/loading', function (req, res) {
    res.sendFile(__dirname + '/loading.html');
});

app.get('/api/get/all', function (req, res) {    
    db.all("SELECT * FROM lorem", function(err, row) {
    res.json(row);
    });
});

app.post('/api/post/site', function (req, res) {
    // Do stuff here.
});

app.listen(3333);

As well as that, here's my main.js file, which requires this server.js file:

const electron = require('electron');
const server = require("./server");
const ipcMain = require('electron').ipcMain;
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

// Define our global references
let mainWindow,
    loadingScreen,
    windowParams = {
      width: 1000,
      height: 700,
      show: false
    },
    loadingWindowParams = {
      width: 400,
      height: 300,
      show: false,
      frame: false
    };

// Define our loading window whose parent is main
function createLoadingScreen() {
    loadingScreen = new BrowserWindow(Object.assign(loadingWindowParams, {parent: mainWindow}));
    loadingScreen.loadURL('http://localhost:3333/loading');
    loadingScreen.on('closed', () => loadingScreen = null);
    loadingScreen.webContents.on('did-finish-load', () => {
        loadingScreen.show();
    });
}

app.on('ready', () => {
  // Create loading screen
  createLoadingScreen();

  // Create the browser window.
  mainWindow = new BrowserWindow(windowParams);

  // Point to our express server
  mainWindow.loadURL(`http://localhost:3333`);

  // Open the DevTools.
  mainWindow.webContents.openDevTools();

  // Simulate loading to allow angular to initialize, then show main window
  mainWindow.once('ready-to-show', () => {
    if (loadingScreen) {
      setTimeout(function() {
        loadingScreen.close();
        mainWindow.show();
      }, 6000);
    }
  });

  // Close the app after window closed for security purposes
  mainWindow.on('closed', function () {
    mainWindow = null
    app.quit();
  });

  // Handle messages
  ipcMain.on('electron-msg', (event, msg) => {
    switch (msg.type) {
      case 'system':
        mainWindow.webContents.send('electron-msg', 'Message received');
      break;
    }
  });

});

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
});

// Open window again when activated
app.on('activate', function () {
  if (mainWindow === null) {
    // Not currently needed, we quit when window closed
  }
});

// Throw our errors
process.on('uncaughtException', function (err) {
  console.log(err);
});

The issue I'm having is that when I package my app using https://github.com/electron-userland/electron-builder, the app functions, the server is spun up and the Angular components work fine, but I cannot read/write/create a database file like I can before packaging. I'm ultimately clueless now as to where to look!

like image 619
Adam Thomason Avatar asked Sep 27 '16 08:09

Adam Thomason


1 Answers

I've managed to fix this almost accidentally after bashing my head against my desk for a while. I was attempting to implement some logging to see whether there were issues with the node module not being recognised correctly when packaged, when I noticed the log file wasn't being created where I was expecting it to be - it was being created outside of the actual app directory and therefore was not accessible. The same thing happened with my database file.

See fix below:

var db = new sqlite3.Database(__dirname + '/app.db');

The addition of __dirname to the db file definition fixed the issue!

like image 190
Adam Thomason Avatar answered Sep 21 '22 17:09

Adam Thomason