Node.js環境でブラウザベースのアプリが作成できるElectronですが、結構メジャーなアプリがElectronベースで作られているようでね。そんなElectornで取り扱いが簡単なデータベースのSqlite3が操作できたら、いろいろ便利だろうと思い、サンプルとなるアプリを作成しましのたで、投稿します。自分の知識不足で、結構ハマってしまった個所もありましが、とりあえずはデータの挿入、抽出は確認できています。
動作確認環境
Windows11
node.js v18.18.1
electron v27.0.0
sqlite3 3.43.0
参考になる記事、サイト等
Electronアプリの作成については過去の記事で触れてもらっています。
WindowsにSQLite3をインストールしています。こちらのサイト参考にさせてもらいました。大変丁寧でわかりやすかったです。
データ表示をgrid.jsにさせています。以下参考にどうそ。
準備
Electronアプリを作成できるよう準備しておきます。
また、sqlite3をインストールしておきます。
npm install -S sqlite3
ただし、exeのビルドの際にpakage.jsonのdependenciesにsqlite3が載っていないと実行時にエラーがでてしまいました。手動で修正しました。
"dependencies": {
"electron-squirrel-startup": "^1.0.0",
"sqlite3": "^5.1.6"
}
コードについて
・preload.hs
・index.js
・main.js
の3つのファイルを編集しています。以下コードを掲載しておきます。
preload.js
// レンダラーからNode.jsにアクセスするためのファイル
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('dbOp', {
createDb: async () => ipcRenderer.invoke('createDb'), //データベース作成
selectAll: async () => ipcRenderer.invoke('selectAll'), //SELECT *
insertData: async (memoText) => ipcRenderer.invoke('insertData', memoText), //データを挿入
});
main.js
// main.jsはNode.jsにて動作する requireにてelectronモジュールを読み込んでいる
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const sqlite3 = require('sqlite3');
const db = new sqlite3.Database("./my_database.db");
// ウィンドウの作成準備
const createWindow = () => {
const win = new BrowserWindow({
width: 800, //ウィンドウサイズ
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), //プレローダーの指定
}
});
// 読み込むファイル
win.loadFile('index.html');
// デベロッパーツールを開く 不要ならコメントアウト
// win.webContents.openDevTools();
// メニューバーの非表示
win.setMenuBarVisibility(false);
}
// ウィンドウ初期化時
app.whenReady().then(() => {
// テーブル作成 第2引数asyncでうまく戻り値拾えず。ちゃんとnew Promiseで記述しています。
ipcMain.handle('createDb', (eve) =>
new Promise((resolve, reject) => {
db.run('CREATE TABLE IF NOT EXISTS my_memo ([id] integer primary key autoincrement, [memo] text, [date_time] datetime);', err => {
if (err) reject(err);
resolve();
});
}));
// SELECT文でのデータ取得
ipcMain.handle('selectAll', (eve) =>
new Promise((resolev, reject) => {
db.serialize(() => {
db.all('SELECT * FROM my_memo', (err, rows) => {
if (err) reject(err);
resolev(rows);
});
});
})
);
// データ挿入
ipcMain.handle('insertData', (eve, memoText) =>
new Promise((resolev, reject) => {
db.run('INSERT INTO my_memo (memo, date_time) VALUES (? , datetime("now", "localtime"));', memoText, err => {
if (err) reject(err);
resolev();
});
})
)
// ウィンドウの表示
createWindow();
// macOS用
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
})
})
// ウィンドウのクローズ
app.on('window-all-closed', () => {
db.close();
if (process.platform !== 'darwin') app.quit();
})
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8' />
<title>ElectronでSqlite3</title>
<!-- データ表示にGrid.jsを利用 -->
<link rel='stylesheet' href='https://unpkg.com/gridjs/dist/theme/mermaid.min.css'>
<script src='https://unpkg.com/gridjs/dist/gridjs.umd.js'></script>
</head>
<body>
<h1>ElectronでSqlite</h1>
<p>テキストをSqlite3にて記録するサンプルです</p>
<div>
<input type='text' id="memoInput">
<input type='button' id='insertBtn' value='書込み'>
</div>
<div id='gridTag'></div>
<script>
// テーブル作成 即時関数として呼出し
window.dbOp.createDb()
.catch(err => { console.log(err) });
// 起動時にメモをgridに表示
let grid; // Grid.jsオブジェクト
window.dbOp.selectAll()
.then(ret => {
ret.forEach((elem) => { delete elem.id }); //キー:idを削除
grid = new gridjs.Grid({
data: ret
}).render(document.getElementById('gridTag'));
})
.catch(err => { console.log(err) });
// ボタンクリック時
document.getElementById('insertBtn').onclick = () => {
// メモを書き込む
const memoText = document.getElementById('memoInput').value;
if (memoText) {
window.dbOp.insertData(memoText)
.catch(err => { console.log(err) });
}
document.getElementById('memoInput').value = "";
// メモをgridに表示
window.dbOp.selectAll()
.then(ret => {
ret.forEach((elem) => { delete elem.id }); //キー:idを削除
grid.updateConfig({
data: ret
}).forceRender();
})
.catch(err => { console.log(err) });
}
</script>
</body>
</html>
テキストボックスに記入した文字がデータベースに保存されます。アプリ起動時と、ボタン押下時に、SELECT文を実行して、更新しています。データベースファイルははプロジェクトフォルダまたは、実行ファイルと同じフォルダに自動で作成されますが、絶対パスで指定しておくこともできます。
以上ご参考まで。