I am trying to open a sqlite3 database encrypted with sqlcipher. I have the password and I could open it successfully using sqlitebrowser.
I started my project using this template. It is based on the electron-forge webpack plugin.
When I type yarn start
, it creates a .webpack folder and all the compiled code goes in it. When I stop the terminal command, this folder disappears.
Then I wanted to use the package @journeyapps/sqlcipher to open my database, but this line is causing an error in the main process: const sqlite3 = require("@journeyapps/sqlcipher")
The error is:
Error: Cannot find module '<<my_path>>/.webpack/main/native_modules/lib/binding/napi-v6-linux-x64/node_sqlite3.node'
The package documentation says two things about using it with electron-forge:
make sure that the folder node_modules/@journeyapps/sqlcipher/lib/binding/napi-v6-linux-x64 exists -> yes it exists
Disable rebuilding of this library using the onlyModules option of electron-rebuild in your package.json "config": { "forge": { "electronRebuildConfig": { "onlyModules": [] // Specify other native modules here if required } }
-> I did it, I added the lines of code
I still have the error, but I feel it can be solved "easily" (with a lot more understanding of webpack than I have). Indeed, a solution would be to move the folder binding/napi-v6-linux-x64 into .webpack each time I launch the app, right?
I tried to do electron-rebuild -f -w sqlite3
, the rebuild succeeded but nothing happens, I still have the same error.
I am stuck here and cannot go further for my app, as it lays on reading this database. Should I start a new project and avoid using webpack? Do you have any example of a project where this package is successfully imported and used?
Thank you in advance for your help!
Well, I finally figured it out. Actually, I tried so much little changes but I managed to make the app work (nearly) as expected.
First: this doesn't have anything to do with the library sqlcipher itself. In fact, it's a webpack configuration problem while dealing with native libraries.
I started a fresh minimal install of electron-forge with Webpack and Typescript template (npx create-electron-app test-electron-forge-github --template=typescript-webpack
) and added sqlite3 and @journeyapps/sqlcipher. It worked so I made a lot of changes in my Webpack configuration to make it closer with the electron-forge one.
The changes I made broke Redux. I chose to sacrifice Redux in order to make sqlcipher work, as today I didn't find a solution for both of them to work.
main.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.js']
},
entry: './electron/main.ts',
module: {
rules: require('./rules.webpack'),
}
}
renderer.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: require('./rules.webpack'),
},
}
rules.webpack.js
module.exports = [
{
test: /\.node$/,
use: 'node-loader',
},
{
test: /\.(m?js|node)$/,
parser: { amd: false },
use: {
loader: '@marshallofsound/webpack-asset-relocator-loader',
options: {
outputAssetBase: 'native_modules',
},
},
resolve: {
fullySpecified: false,
}
},
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
{
test: /\.(sass|less|css)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
]
main.webpack.js
module.exports = {
resolve: {
extensions: ['.ts', '.js']
},
entry: './electron/main.ts',
module: {
rules: [
...require('./rules.webpack'),
{
test: /\.(m?js|node)$/,
parser: { amd: true },
use: {
loader: '@vercel/webpack-asset-relocator-loader',
options: {
outputAssetBase: 'native_modules',
emitDirnameAll: true,
},
}
},
],
}
}
The native modules configuration has been moved from rules.webpack.js to main.webpack.js. This is due to a bug happening in the renderer process if the rule stayed in the rules.wepback.ts file.
The window would open but would stay blank. In the console, there would be an error: __dirname is not defined
. See this Github issue from where I took the solution.
Also note that I changed the loader as the previous one was not doing properly its job.
renderer.webpack.js Unchanged
rules.webpack.js
module.exports = [
{
// We are specifying native_modules in the test because the asset relocator loader generates a
// "fake" .node file which is really a cjs file.
test: /native_modules\/.+\.node$/,
use: 'node-loader',
},
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
{
test: /\.(sass|less|css)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
]
I had to remove this property from rules.webpack.js:
resolve: {
fullySpecified: false,
}
This line was making Redux work.
I don't really know how this works, but it works. I hope it will help you if you are struggling as I was.