├── src
├── assets
│ ├── tray.png
│ ├── ico
│ │ ├── icon.ico
│ │ └── icon.png
│ └── logo.svg
├── index.js
├── App.test.js
├── index.html
├── index.css
├── App.css
├── App.js
└── MySql.js
├── .babelrc
├── .gitignore
├── main.js
├── LICENSE
├── gulpfile.js
├── main-tray.js
├── main-tray-two-windows.js
├── package.json
├── package-cert.json
└── README.md
/src/assets/tray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/natancabral/react-js-electron-database/HEAD/src/assets/tray.png
--------------------------------------------------------------------------------
/src/assets/ico/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/natancabral/react-js-electron-database/HEAD/src/assets/ico/icon.ico
--------------------------------------------------------------------------------
/src/assets/ico/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/natancabral/react-js-electron-database/HEAD/src/assets/ico/icon.png
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env", "@babel/preset-react"],
3 | "plugins": ["@babel/plugin-proposal-class-properties"]
4 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | //import './index.css';
4 | import App from './App';
5 |
6 | ReactDOM.render(
7 | ,
8 | document.getElementById('root')
9 | );
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render();
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | React-js + Electron + Sqlite3
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 | /dist
14 | /dist-certificate-win
15 | /release-builds
16 | /app/*
17 |
18 | # misc
19 | .DS_Store
20 | .env.local
21 | .env.development.local
22 | .env.test.local
23 | .env.production.local
24 |
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
29 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, {useEffect, useState} from 'react'
2 | //import logo from './logo.svg';
3 | import MySql from './MySql';
4 | import { ipcRenderer } from 'electron';
5 |
6 | function App() {
7 |
8 | const [version, setVersion] = useState('');
9 |
10 | const getVersion = () => {
11 | ipcRenderer.send('app_version');
12 | ipcRenderer.on('app_version', (event, arg) => {
13 | ipcRenderer.removeAllListeners('app_version');
14 | setVersion(arg.version);
15 | });
16 | }
17 |
18 | useEffect(() => {
19 | getVersion();
20 | },[]);
21 |
22 | return (
23 |
24 |
25 |
26 | React-js + Electron + Database
27 | {version}
28 |
29 |
30 |
31 | );
32 | }
33 |
34 | export default App;
35 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | const { app, ipcMain, BrowserWindow } = require('electron')
2 | const path = require('path')
3 | //const url = require('url')
4 |
5 | function createWindow () {
6 | const win = new BrowserWindow({
7 | width: 800,
8 | height: 600,
9 | webPreferences: {
10 | // webSecurity: false,
11 | // allowRunningInsecureContent: true,
12 | // preload: path.join(__dirname, 'preload.js')
13 | nativeWindowOpen: true,
14 | nodeIntegration: true,
15 | }
16 | })
17 |
18 | win.loadFile('app/index.html')
19 | //win.loadURL('http://127.0.0.1:3000')
20 | //win.webContents.openDevTools()
21 | }
22 |
23 | app.whenReady().then(createWindow)
24 |
25 | app.on('window-all-closed', () => {
26 | if (process.platform !== 'darwin') {
27 | app.quit()
28 | }
29 | })
30 |
31 | app.on('activate', () => {
32 | if (BrowserWindow.getAllWindows().length === 0) {
33 | createWindow()
34 | }
35 | })
36 |
37 | ipcMain.on('app_version', (event) => {
38 | event.sender.send('app_version', { version: app.getVersion() });
39 | console.log('Version', app.getVersion());
40 | });
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Natan Cabral
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const exec = require('child_process').exec;
2 | const gulp = require('gulp');
3 | const babel = require('gulp-babel');
4 | const css = require('gulp-clean-css');
5 | const livereload = require('gulp-livereload');
6 | //1. Compile HTML file and move them to the app folder
7 | gulp.task('html', () => {
8 | return gulp.src('src/index.html')
9 | .pipe(gulp.dest('app/'))
10 | .pipe(livereload());
11 | });
12 |
13 | //2. Compile CSS file and move them to the app folder
14 | gulp.task('css', () => {
15 | return gulp.src('src/**/*.css')
16 | .pipe(css())
17 | .pipe(gulp.dest('app/'))
18 | .pipe(livereload());
19 | });
20 |
21 | //3. Compile JS and JSX files and move them to the app folder
22 | gulp.task('js*', () => {
23 | return gulp.src(['main*.js', 'src/**/*.js*'])
24 | .pipe(babel())
25 | .pipe(gulp.dest('app/'))
26 | .pipe(livereload());
27 | });
28 |
29 | //4. Compile IMAGES file and move them to the app folder
30 | // ------------------------------------------------------------------------------------ All images inside ./assets/
31 | gulp.task('images', () => {
32 | return gulp.src('src/assets/**/*')
33 | .pipe(gulp.dest('app/assets'))
34 | .pipe(livereload());
35 | })
36 |
37 | //5. Watch files
38 | gulp.task('watch', async function() {
39 | livereload.listen();
40 | gulp.watch('src/**/*.html', gulp.series('html'));
41 | gulp.watch('src/**/*.css', gulp.series('css'));
42 | gulp.watch('src/**/*.js*', gulp.series('js*'));
43 | gulp.watch('src/assets/**/*', gulp.series('images'));
44 | });
45 |
46 | //6. Send to app folder
47 | gulp.task('build', gulp.series('html', 'css', 'js*', 'images'));
48 |
49 | //7. Start the electron process.
50 | gulp.task('start', gulp.series('build', () => {
51 | return exec(
52 | __dirname+'/node_modules/.bin/electron .'
53 | ).on('close', () => process.exit());
54 | }));
55 |
56 | //0. Default process.
57 | gulp.task('default', gulp.parallel('start', 'watch'));
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/MySql.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import mysql from "mysql";
3 |
4 | function MySql() {
5 |
6 | // https://github.com/mysqljs/mysql
7 |
8 | // set connection variable
9 | const [conn, setConn] = React.useState(undefined);
10 | const dataConnection = {
11 | //host : '888.88.88.88', //:3306
12 | host: "127.0.0.1",
13 | user: "root",
14 | password: "",
15 | database: "databasename",
16 | }
17 | const [list,setList] = React.useState([]);
18 | const {host, user, password, database} = dataConnection;
19 |
20 | // function connection mysql remote
21 | const connection = () => {
22 | let c = mysql.createConnection(dataConnection);
23 | c.connect((err) => {
24 | // in case of error
25 | if (err) {
26 | alert(err.code);
27 | return console.log(err.code, err.fatal, err.stack);
28 | }
29 | return console.log("Connection successfully established");
30 | });
31 | setConn(c);
32 | };
33 |
34 | // function query/search
35 | const query = () => {
36 | let sql = "SELECT `name`,`id` FROM `tablename` where id > ? limit 0,50 ";
37 | //let value = connection.escape(value);
38 | //let id = connection.escapeId(id);
39 | conn.query(
40 | {
41 | sql: sql,
42 | timeout: 40 * 1000, // 40s
43 | },
44 | [0], // values to replace ?
45 | function (err, results, fields) {
46 | if (err) {
47 | alert(err.code);
48 | console.log(err.code);
49 | } else {
50 | alert(results);
51 | console.log(results);
52 | if (results.length) {
53 | setList(results);
54 | alert(results[0].id + results[0].name);
55 | }
56 | }
57 | });
58 |
59 | // Close the connection
60 | conn.end(function () {
61 | // The connection has been closed
62 | });
63 | };
64 |
65 | const queryPost = () => {
66 | var post = {id: 1, title: 'Hello MySQL'};
67 | var query = conn.query('INSERT INTO posts SET ?', post, function (error, results, fields) {
68 | if (error) throw error;
69 | // Neat!
70 | });
71 | console.log(query.sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
72 | }
73 |
74 | return (
75 |
76 | Click to connect database
77 |
78 |
79 |
80 |
81 |
82 | - Host: {host}
83 | - User: {user}
84 | - Password: {password}
85 | - Database: {database}
86 |
87 |
88 |
89 |
90 | {list.map((dat,idx) => {
91 | return (
92 | - {dat.id} {dat.name}
93 | )
94 | })}
95 |
96 |
97 |
98 | );
99 | }
100 |
101 | export default MySql;
102 |
--------------------------------------------------------------------------------
/main-tray.js:
--------------------------------------------------------------------------------
1 | const {app, BrowserWindow, Tray, nativeImage, screen } = require('electron')
2 | const path = require('path')
3 |
4 | let mainWindow = undefined;;
5 | let tray = undefined;
6 | //app.dock.hide();
7 |
8 | function createWindow () {
9 | // Create the browser window.
10 | mainWindow = new BrowserWindow({
11 | width: 300,
12 | height: 600,
13 | //-----tray----- start
14 | show: true,
15 | frame: false,
16 | fullscreen: false,
17 | resizable: false,
18 | transparent: false,
19 | //-----tray----- end
20 | webPreferences: {
21 | backgroundThrottling: false
22 | }
23 | })
24 |
25 | // mainWindow.loadFile('index.html')
26 | mainWindow.loadFile(path.join(__dirname, 'app', 'index.html'))
27 | // Open the DevTools.
28 | // mainWindow.webContents.openDevTools()
29 |
30 | //-----tray----- start
31 | mainWindow.on('closed',()=>mainWindow = null)
32 | // Hide the window when it loses focus
33 | mainWindow.on('blur', () => {
34 | // if (!mainWindow.webContents.isDevToolsOpened()) {
35 | // mainWindow.hide();
36 | // }
37 | });
38 | //-----tray----- end
39 | }
40 |
41 | //-----tray----- start
42 | const createTray = () => {
43 | const icon = path.join(__dirname, 'assets', 'tray.png')
44 | const nimage = nativeImage.createFromPath(icon)
45 | //tray is a app variable
46 | tray = new Tray(nimage)
47 | tray.on('click', (event)=>toggleWindow())
48 | }
49 |
50 | const toggleWindow = () => {
51 | mainWindow.isVisible() ? mainWindow.hide() : showWindow();
52 | }
53 |
54 | const showWindow = () => {
55 | const position = getWindowPosition();
56 | mainWindow.setPosition(position.x,position.y, false);
57 | mainWindow.show();
58 | }
59 |
60 | const getWindowPosition = () => {
61 |
62 | //console.log(process.platform);
63 | //'aix'
64 | //'darwin'
65 | //'freebsd'
66 | //'linux'
67 | //'openbsd'
68 | //'sunos'
69 | //'win32'
70 |
71 | const { screenWidth, screenHeight } = screen.getPrimaryDisplay().workAreaSize;
72 | const windowBounds = mainWindow.getBounds();
73 | const trayBounds = tray.getBounds();
74 | // Center window horizontally below the tray icon
75 | const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
76 | let y = undefined;
77 | // Position window 4 pixels vertically below the tray icon
78 | if(process.platform == 'win32')
79 | y = Math.round(trayBounds.y - windowBounds.height);
80 | else
81 | y = Math.round(trayBounds.y + trayBounds.height + 4);
82 |
83 | return {x,y}
84 | }
85 | //-----tray----- end
86 |
87 | // This method will be called when Electron has finished
88 | // initialization and is ready to create browser windows.
89 | // Some APIs can only be used after this event occurs.
90 | app.whenReady().then(() => {
91 | //-----tray----- start
92 | createTray()
93 | //-----tray----- end
94 | createWindow()
95 |
96 | app.on('activate', function () {
97 | // On macOS it's common to re-create a window in the app when the
98 | // dock icon is clicked and there are no other windows open.
99 | if (BrowserWindow.getAllWindows().length === 0) createWindow()
100 | })
101 | })
102 |
103 | // Quit when all windows are closed, except on macOS. There, it's common
104 | // for applications and their menu bar to stay active until the user quits
105 | // explicitly with Cmd + Q.
106 | app.on('window-all-closed', function () {
107 | if (process.platform !== 'darwin') app.quit()
108 | })
109 |
110 | // In this file you can include the rest of your app's specific main process
111 | // code. You can also put them in separate files and require them here.
--------------------------------------------------------------------------------
/main-tray-two-windows.js:
--------------------------------------------------------------------------------
1 | const {app, BrowserWindow, Tray, nativeImage, screen } = require('electron')
2 | const path = require('path')
3 |
4 | let mainWindow = undefined;;
5 | let tray = undefined;
6 | //app.dock.hide();
7 |
8 | function createWindow () {
9 | // Create the browser window.
10 | mainWindow = new BrowserWindow({
11 | width: 700,
12 | height: 500,
13 | //-----tray----- end
14 | webPreferences: {
15 | }
16 | })
17 |
18 | // mainWindow.loadFile('index.html')
19 | mainWindow.loadFile(path.join(__dirname, 'app', 'index.html'))
20 | // Open the DevTools.
21 | // mainWindow.webContents.openDevTools()
22 |
23 | //-----tray----- start
24 | mainWindow.on('closed',()=>mainWindow = null)
25 | // Hide the window when it loses focus
26 | mainWindow.on('blur', () => {
27 | // if (!mainWindow.webContents.isDevToolsOpened()) {
28 | // mainWindow.hide();
29 | // }
30 | });
31 | //-----tray----- end
32 | }
33 |
34 | let w = undefined;
35 | function createWindowTray () {
36 | // Create the browser window.
37 | w = new BrowserWindow({
38 | width: 300,
39 | height: 600,
40 | //-----tray----- start
41 | show: false,
42 | frame: false,
43 | fullscreen: false,
44 | resizable: false,
45 | transparent: false,
46 | //-----tray----- end
47 | webPreferences: {
48 | backgroundThrottling: false
49 | }
50 | })
51 |
52 | // w.loadFile('index.html')
53 | w.loadFile(path.join(__dirname, 'app', 'index.html'))
54 | // Open the DevTools.
55 | // w.webContents.openDevTools()
56 |
57 | //-----tray----- start
58 | w.on('closed',()=>w = null)
59 | // Hide the window when it loses focus
60 | w.on('blur', () => {
61 | // if (!w.webContents.isDevToolsOpened()) {
62 | // w.hide();
63 | // }
64 | });
65 | //-----tray----- end
66 | }
67 |
68 | //-----tray----- start
69 | const createTray = () => {
70 | const icon = path.join(__dirname, 'assets', 'tray.png')
71 | const nimage = nativeImage.createFromPath(icon)
72 | //tray is a app variable
73 | tray = new Tray(nimage)
74 | tray.on('click', (event)=>toggleWindow())
75 | }
76 |
77 | const toggleWindow = () => {
78 | // mainWindow.loadFile('index.html')
79 | w.loadFile(path.join(__dirname, 'app', 'index.html'))
80 | //w.show();
81 | w.isVisible() ? w.hide() : showWindow();
82 | }
83 |
84 | const showWindow = () => {
85 | const position = getWindowPosition();
86 | w.setPosition(position.x,position.y, false);
87 | w.show();
88 | }
89 |
90 | const getWindowPosition = () => {
91 |
92 | //console.log(process.platform);
93 | //'aix'
94 | //'darwin'
95 | //'freebsd'
96 | //'linux'
97 | //'openbsd'
98 | //'sunos'
99 | //'win32'
100 |
101 | const { screenWidth, screenHeight } = screen.getPrimaryDisplay().workAreaSize;
102 | const windowBounds = w.getBounds();
103 | const trayBounds = tray.getBounds();
104 | // Center window horizontally below the tray icon
105 | const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
106 | let y = undefined;
107 | // Position window 4 pixels vertically below the tray icon
108 | if(process.platform == 'win32')
109 | y = Math.round(trayBounds.y - windowBounds.height);
110 | else
111 | y = Math.round(trayBounds.y + trayBounds.height + 4);
112 |
113 | return {x,y}
114 | }
115 | //-----tray----- end
116 |
117 | // This method will be called when Electron has finished
118 | // initialization and is ready to create browser windows.
119 | // Some APIs can only be used after this event occurs.
120 | app.whenReady().then(() => {
121 | //-----tray----- start
122 | createTray()
123 | createWindowTray()
124 | //-----tray----- end
125 | createWindow()
126 |
127 |
128 | app.on('activate', function () {
129 | // On macOS it's common to re-create a window in the app when the
130 | // dock icon is clicked and there are no other windows open.
131 | if (BrowserWindow.getAllWindows().length === 0) createWindow()
132 | })
133 | })
134 |
135 | // Quit when all windows are closed, except on macOS. There, it's common
136 | // for applications and their menu bar to stay active until the user quits
137 | // explicitly with Cmd + Q.
138 | app.on('window-all-closed', function () {
139 | if (process.platform !== 'darwin') app.quit()
140 | })
141 |
142 | // In this file you can include the rest of your app's specific main process
143 | // code. You can also put them in separate files and require them here.
144 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-js-electron-database",
3 | "description": "...",
4 | "version": "0.1.0",
5 | "private": true,
6 | "repository": "https://github.com/natancabral/react-js-electron-database.git",
7 | "author": {
8 | "name": "Natan Cabral",
9 | "email": "natancabral@hotmail.com"
10 | },
11 | "dependencies": {
12 | "@babel/plugin-proposal-class-properties": "^7.12.1",
13 | "@testing-library/jest-dom": "^5.11.6",
14 | "@testing-library/react": "^11.2.2",
15 | "@testing-library/user-event": "^12.2.2",
16 | "babel": "^6.23.0",
17 | "fs": "^0.0.1-security",
18 | "gulp-cli": "^1.4.0",
19 | "gulp-livereload": "^4.0.2",
20 | "mysql": "^2.18.1",
21 | "react": "^17.0.1",
22 | "react-dom": "^17.0.1",
23 | "react-script": "^2.0.5",
24 | "react-scripts": "^4.0.3",
25 | "vinyl-fs": "^2.4.1",
26 | "web-vitals": "^0.2.4",
27 | "webpack": "^5.52.1",
28 | "webpack-manifest-plugin": "^4.0.2"
29 | },
30 | "main": "app/main.js",
31 | "scripts": {
32 | "packager:win:1": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds",
33 | "packager:win:2": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/icons/win/app.ico",
34 | "packager:win:3": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/icons/win/icon.ico --prune=true --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"React Electron Sqlite\"",
35 | "build:dist:1": "electron-builder",
36 | "build:dist:2": "electron-builder --dir",
37 | "build:postinstall": "electron-builder install-app-deps",
38 | "electron": "electron .",
39 | "start": "gulp",
40 | "delete:all": "rm -r ./app",
41 | "postinstall": "install-app-deps",
42 | "build": "gulp build",
43 | "test": "gulp test",
44 | "release": "gulp release"
45 | },
46 | "eslintConfig": {
47 | "extends": [
48 | "react-app",
49 | "react-app/jest"
50 | ]
51 | },
52 | "browserslist": {
53 | "production": [
54 | ">0.2%",
55 | "not dead",
56 | "not op_mini all"
57 | ],
58 | "development": [
59 | "last 1 chrome version",
60 | "last 1 firefox version",
61 | "last 1 safari version"
62 | ]
63 | },
64 | "devDependencies": {
65 | "@babel/core": "^7.12.9",
66 | "@babel/preset-env": "^7.12.7",
67 | "@babel/preset-react": "^7.12.7",
68 | "electron": "^11.0.3",
69 | "electron-builder": "^22.9.1",
70 | "electron-packager": "^15.1.0",
71 | "gulp": "^4.0.2",
72 | "gulp-babel": "^8.0.0",
73 | "gulp-clean-css": "^4.3.0",
74 | "gulp-concat": "^2.6.1"
75 | },
76 | "build": {
77 | "asar": true,
78 | "extends": null,
79 | "publish": null,
80 | "appId": "com.natancabral.package",
81 | "compression": "maximum",
82 | "productName": "Package Name",
83 | "win": {
84 | "target": [
85 | "nsis",
86 | "msi"
87 | ],
88 | "icon": "./app/assets/ico/icon.ico"
89 | },
90 | "nsis": {
91 | "shortcutName": "Package Shortcut Name",
92 | "artifactName": "Setup ${productName} v${version}.${ext}",
93 | "installerIcon": "./app/assets/ico/icon.ico",
94 | "oneClick": true,
95 | "perMachine": true,
96 | "allowElevation": true,
97 | "runAfterFinish": true,
98 | "createDesktopShortcut": true,
99 | "createStartMenuShortcut": true,
100 | "deleteAppDataOnUninstall": true,
101 | "allowToChangeInstallationDirectory": false
102 | },
103 | "mac": {
104 | "target": [
105 | "dmg"
106 | ],
107 | "icon": "./app/assets/ico/mac512.icns",
108 | "category": "public.app-category.graphics-design"
109 | },
110 | "dmg": {
111 | "contents": [
112 | {
113 | "x": 110,
114 | "y": 150
115 | },
116 | {
117 | "x": 240,
118 | "y": 150,
119 | "type": "link",
120 | "path": "/Applications"
121 | }
122 | ],
123 | "title": "MAC ${productName} ${version}",
124 | "icon": "./app/assets/ico/mac512.icns"
125 | },
126 | "linux": {
127 | "target": [
128 | "deb",
129 | "AppImage"
130 | ],
131 | "category": "Development"
132 | },
133 | "deb": {},
134 | "directories": {
135 | "buildResources": "./app",
136 | "output": "dist-certificate-win"
137 | },
138 | "files": [
139 | "package.json",
140 | "app/**/*"
141 | ]
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/package-cert.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-js-electron-sqlite3",
3 | "description": "...",
4 | "version": "0.1.0",
5 | "private": true,
6 | "repository": "https://github.com/natancabral/react-js-electron-database.git",
7 | "author": {
8 | "name": "Natan Cabral",
9 | "email": "natancabral@hotmail.com"
10 | },
11 | "homepage": "https://www.gnnc.com.br",
12 | "dependencies": {
13 | "@babel/plugin-proposal-class-properties": "^7.12.1",
14 | "@testing-library/jest-dom": "^5.11.6",
15 | "@testing-library/react": "^11.2.2",
16 | "@testing-library/user-event": "^12.2.2",
17 | "gulp-cli": "^2.3.0",
18 | "gulp-livereload": "^4.0.2",
19 | "react": "^17.0.1",
20 | "react-dom": "^17.0.1",
21 | "react-scripts": "4.0.1",
22 | "web-vitals": "^0.2.4",
23 | "mysql": "^2.18.1"
24 | },
25 | "main": "app/main.js",
26 | "scripts": {
27 | "packager:win:1": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds",
28 | "packager:win:2": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/ico/icon48.png",
29 | "packager:win:3": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/ico/icon48.png --prune=true --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"Cat�logo Valpec\"",
30 | "build:dist:1": "electron-builder",
31 | "build:dist:win": "electron-builder --win",
32 | "build:dist:2": "electron-builder --dir",
33 | "build:dist:all": "electron-builder -mwl",
34 | "build:postinstall": "electron-builder install-app-deps",
35 | "electron": "electron .",
36 | "r": "react-scripts start",
37 | "start": "gulp",
38 | "delete:app": "rm -rf ./app",
39 | "delete:dist": "rm -rf ./dist",
40 | "delete:all": "rm -rf ./app && rm -rf ./dist",
41 | "postinstall": "install-app-deps",
42 | "build": "gulp build",
43 | "test": "gulp test",
44 | "release": "gulp release"
45 | },
46 | "eslintConfig": {
47 | "extends": [
48 | "react-app",
49 | "react-app/jest"
50 | ]
51 | },
52 | "browserslist": {
53 | "production": [
54 | ">0.2%",
55 | "not dead",
56 | "not op_mini all"
57 | ],
58 | "development": [
59 | "last 1 chrome version",
60 | "last 1 firefox version",
61 | "last 1 safari version"
62 | ]
63 | },
64 | "devDependencies": {
65 | "@babel/core": "^7.12.9",
66 | "@babel/preset-env": "^7.12.7",
67 | "@babel/preset-react": "^7.12.7",
68 | "electron": "^11.0.3",
69 | "electron-builder": "^22.9.1",
70 | "electron-packager": "^15.1.0",
71 | "gulp": "^4.0.2",
72 | "gulp-babel": "^8.0.0",
73 | "gulp-clean-css": "^4.3.0",
74 | "gulp-concat": "^2.6.1"
75 | },
76 | "build-no-used": {
77 | "asarUnpack": "**/assets/*"
78 | },
79 | "build": {
80 | "asar": true,
81 | "extends": null,
82 | "publish": null,
83 | "appId": "com.natancabral.package",
84 | "compression": "maximum",
85 | "productName": "Package Name",
86 | "win": {
87 | "target": [
88 | "nsis",
89 | "msi"
90 | ],
91 | "icon": "./app/assets/ico/icon48.ico",
92 | "certificateFile": "./../file.pfx",
93 | "certificatePassword": "password",
94 | "legalTrademarks": "(c) 2020 gnnc.com.br"
95 | },
96 | "nsis": {
97 | "shortcutName": "Package Shortcut Name",
98 | "artifactName": "Setup ${productName} v${version}.${ext}",
99 | "installerIcon": "./app/assets/ico/icon48.ico",
100 | "oneClick": true,
101 | "perMachine": true,
102 | "allowElevation": true,
103 | "runAfterFinish": true,
104 | "createDesktopShortcut": true,
105 | "createStartMenuShortcut": true,
106 | "deleteAppDataOnUninstall": true,
107 | "allowToChangeInstallationDirectory": false
108 | },
109 | "mac": {
110 | "target": [
111 | "dmg"
112 | ],
113 | "icon": "./app/assets/ico/mac512.icns",
114 | "category": "public.app-category.graphics-design"
115 | },
116 | "dmg": {
117 | "contents": [
118 | {
119 | "x": 110,
120 | "y": 150
121 | },
122 | {
123 | "x": 240,
124 | "y": 150,
125 | "type": "link",
126 | "path": "/Applications"
127 | }
128 | ],
129 | "title": "MAC ${productName} ${version}",
130 | "icon": "./app/assets/ico/mac512.icns"
131 | },
132 | "linux": {
133 | "target": [
134 | "deb",
135 | "AppImage"
136 | ],
137 | "category": "Development"
138 | },
139 | "deb": {},
140 | "directories": {
141 | "buildResources": "./app",
142 | "output": "dist-certificate-win"
143 | },
144 | "files": [
145 | "package.json",
146 | "app/**/*"
147 | ]
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-js + Electron + Database
2 | #### Clone this project
3 | ```bash
4 | git clone https://github.com/natancabral/react-js-electron-database.git react-js-electron-database
5 | cd react-js-electron-database
6 | npm install
7 | npm audit fix
8 | npm run start
9 | ```
10 | #### Make yourself
11 | * Create project
12 | * Begin with: [React](#begin-with-react)
13 | * Begin with: [Electron](#begin-with-electron)
14 | * Run React
15 | * Working with: [Babel](#working-with-babel) | read: [css-error](#css-error)
16 | * Working with: [Concurrently + Wait-on](#working-with-wait-on-and-concurrently) (need nodejs installed to run)
17 | * Database
18 | * [MySql](#mysql)
19 | * Sqlite3 (todo)
20 | * [AppTray Window](#apptray-window)
21 | * Tray + NativeImage (todo)
22 | * Packaging App
23 | * [Electron Builder](#electron-builder)
24 | * [Electron Packager](#electron-packager)
25 | * Update (npm audit fix, npm update)
26 | * [Kill Process](#kill-process-port3000)
27 | * [Test](#test)
28 | * [Error](#error)
29 |
30 | ----
31 | # Create Project
32 | ## Begin with: React
33 |
38 | First option begin with React
39 | #### Create project and install React
40 | ```bash
41 | # you need node.js
42 | $ npx create-react-app react-js-electron-sqlite
43 | $ cd react-js-electron-sqlite
44 | ```
45 | #### Install Electron
46 | ```bash
47 | # need sudo
48 | $ npm install electron --save-dev
49 | ```
50 | #### Update package.json file
51 | * en: Open **package.json** file add insert above "scripts"
52 | > "main": "main.js",
53 | * en: Insert inside "scripts"
54 | > "electron": "electron .",
55 |
56 | #### Create main.js file
57 | * en: Copy this script:
58 | ```js
59 | const { app, BrowserWindow } = require('electron')
60 | const path = require('path')
61 | //const url = require('url')
62 |
63 | function createWindow () {
64 | const win = new BrowserWindow({
65 | width: 800,
66 | height: 600,
67 | webPreferences: {
68 | //webSecurity: false,
69 | //allowRunningInsecureContent: true,
70 | //preload: path.join(__dirname, 'preload.js')
71 | nodeIntegration: true
72 | }
73 | })
74 |
75 | win.loadFile('src/index.html')
76 | //win.loadURL('http://127.0.0.1:3000')
77 | //win.webContents.openDevTools()
78 | }
79 |
80 | app.whenReady().then(createWindow)
81 |
82 | app.on('window-all-closed', () => {
83 | if (process.platform !== 'darwin') {
84 | app.quit()
85 | }
86 | })
87 |
88 | app.on('activate', () => {
89 | if (BrowserWindow.getAllWindows().length === 0) {
90 | createWindow()
91 | }
92 | })
93 | ```
94 |
95 | #### /src/index.html file
96 | I will create a **src/** folder and **index.html** file:
97 | ```html
98 |
99 |
100 |
101 |
102 |
103 | React-js + Electron + Sqlite3
104 |
105 |
106 | React-js + Electron + Sqlite3
107 |
108 |
109 |
110 |
111 |
112 |
113 | ```
114 | #### Install react react-dom
115 | ```bash
116 | # need sudo
117 | $ npm install react react-dom
118 | ```
119 | #### Done!
120 | ```bash
121 | $ npm run electron
122 | ```
123 | ## Begin with: Electron
124 | Second option begin with Electron
125 | #### Clone electron-quick-start project
126 | ```bash
127 | # you need node.js
128 | $ git clone https://github.com/electron/electron-quick-start react-js-electron-sqlite
129 | $ cd react-js-electron-sqlite
130 | $ npm install
131 | $ npm start
132 | ```
133 | #### Install react react-dom
134 | ```bash
135 | $ npm install react react-dom
136 | ```
137 | #### Files
138 | * I will create a **src/** folder
139 | * and move to inside **index.html** and **renderer.js**,
140 | * renamed as **renderer.js** to **index.js**.
141 | * I will create an **index.css** and link it to the html. Finally, add an **app** container div.
142 | * Replace **index.html** file:
143 | ```html
144 |
145 |
146 |
147 |
148 |
149 | React-js + Electron + Sqlite3
150 |
151 |
152 | React-js + Electron + Sqlite3
153 |
154 |
155 |
156 |
157 |
158 |
159 | ```
160 | #### Change main.js file
161 | With a small change to **main.js** so that it points to the correct file:
162 | ```js
163 | .loadFile(path.join(__dirname, 'src', 'index.html'))
164 | ```
165 | and **preload.js** to **index.js**
166 | ```js
167 | webPreferences: {
168 | preload: path.join(__dirname, 'src', 'index.js')
169 | }
170 | ```
171 | #### index.js
172 | ```js
173 | import React from 'react';
174 | import ReactDOM from 'react-dom';
175 | //import App from './App.js'; // <-- App / begin React
176 | import App from './app.js'; // <-- app / begin Electron
177 |
178 | window.onload = () => {
179 | ReactDOM.render(, document.getElementById('app'));
180 | };
181 | ```
182 | ----
183 | # Run React
184 |
185 | ## Working with: Babel
186 | Transpiling ES6 with Babel 7.
187 | #### Install Babel + Preset
188 | ```bash
189 | $ npm i @babel/core --save-dev # this will install babel 7.0
190 | $ npm i @babel/preset-env @babel/preset-react --save-dev
191 | $ npm i @babel/plugin-proposal-class-properties
192 | ```
193 | #### Create .babelrc file
194 | When it runs, it looks for its configuration in a file named .babelrc, so create in on the root and add:
195 | ```json
196 | {
197 | "presets": ["@babel/preset-env", "@babel/preset-react"],
198 | "plugins": ["@babel/plugin-proposal-class-properties"]
199 | }
200 | ```
201 | #### Install Gulp
202 | Babel needs to run before any code executes and the best way schedule that is through a build tool
203 | ```bash
204 | $ npm i gulp gulp-babel --save-dev # basic gulp
205 | $ npm i gulp-concat gulp-clean-css --save-dev # plugins
206 | $ npm i gulp-livereload
207 | # need root/admin
208 | $ npm i -g gulp-cli # best sudo
209 | ```
210 | #### Create gulpfile.js file
211 | Create a gulpfile.js at the root of your project and add the tasks
212 | ```js
213 | const exec = require('child_process').exec;
214 | const gulp = require('gulp');
215 | const babel = require('gulp-babel');
216 | const css = require('gulp-clean-css');
217 | const livereload = require('gulp-livereload');
218 | //1. Compile HTML file and move them to the app folder
219 | gulp.task('html', () => {
220 | return gulp.src('src/index.html')
221 | .pipe(gulp.dest('app/'))
222 | .pipe(livereload());
223 | });
224 |
225 | //2. Compile CSS file and move them to the app folder
226 | gulp.task('css', () => {
227 | return gulp.src('src/**/*.css')
228 | .pipe(css())
229 | .pipe(gulp.dest('app/'))
230 | .pipe(livereload());
231 | });
232 |
233 | //3. Compile JS and JSX files and move them to the app folder
234 | gulp.task('js*', () => {
235 | return gulp.src(['main*.js', 'src/**/*.js*'])
236 | .pipe(babel())
237 | .pipe(gulp.dest('app/'))
238 | .pipe(livereload());
239 | });
240 |
241 | //4. Compile IMAGES file and move them to the app folder
242 | // ------------------------------------------------------------------------------------ All images inside ./assets/
243 | gulp.task('images', () => {
244 | return gulp.src('src/assets/**/*')
245 | .pipe(gulp.dest('app/assets'))
246 | .pipe(livereload());
247 | })
248 |
249 | //5. Watch files
250 | gulp.task('watch', async function() {
251 | livereload.listen();
252 | gulp.watch('src/**/*.html', gulp.series('html'));
253 | gulp.watch('src/**/*.css', gulp.series('css'));
254 | gulp.watch('src/**/*.js*', gulp.series('js*'));
255 | gulp.watch('src/assets/**/*', gulp.series('images'));
256 | });
257 |
258 | //6. Send to app folder
259 | gulp.task('build', gulp.series('html', 'css', 'js*', 'images'));
260 |
261 | //7. Start the electron process.
262 | gulp.task('start', gulp.series('build', () => {
263 | return exec(
264 | __dirname+'/node_modules/.bin/electron .'
265 | ).on('close', () => process.exit());
266 | }));
267 |
268 | //0. Default process.
269 | gulp.task('default', gulp.parallel('start', 'watch'));
270 |
271 | ```
272 | #### Edit package.json file
273 | Insert/change this:
274 | ```json
275 | "main": "app/main.js",
276 | ```
277 | And this:
278 | ```json
279 | "scripts": {
280 | "electron": "electron .",
281 | "dev": "react-scripts start",
282 | "start": "gulp",
283 | "delete:all": "rm -r ./app",
284 | "postinstall": "install-app-deps",
285 | "build": "gulp build",
286 | "test": "gulp test",
287 | "release": "gulp release"
288 | }
289 | ```
290 | #### Edit main.js file
291 | Insert/change this:
292 | ```js
293 | // find .loadFile(
294 | // change to
295 | .loadFile(path.join(__dirname, 'app', 'index.html'))
296 | // or
297 | .loadFile('app/index.html')
298 | ```
299 |
300 | #### CSS error
301 | Babel cant import css files in js or jsx.
302 | > **import './style.css'** show error
303 |
304 | You need load css files inside react-context or index.html file.
305 |
306 | #### Run
307 | ```bash
308 | $ npm run-script start
309 | # or
310 | $ npm run start
311 | ```
312 |
313 | ----
314 | ## Working with: Wait-on and Concurrently
315 |
316 | #### Install Wait-on
317 | * en: [Wait-on](https://www.npmjs.com/package/wait-on) is a cross-platform command line utility which will wait for files, ports, sockets, and http(s) resources to become available (or not available using reverse mode). Functionality is also available via a Node.js API. Cross-platform - runs everywhere Node.js runs (linux, unix, mac OS X, windows)
318 | ```node
319 | $ npm install wait-on
320 | ```
321 | #### Install Concurrently
322 | * en: Run multiple commands [concurrently](https://www.npmjs.com/package/concurrently)
323 | ```bash
324 | $ npm install concurrently
325 | ```
326 | #### Run Wait-on + Concurrently
327 | * en: Insert inside "scripts"
328 | ```json
329 | "electron-react": "concurrently \"BROWSER=none npm start\" \"wait-on http://localhost:3000 && electron .\"",
330 | ```
331 | ----
332 | #### main.js
333 | * en: Remember change this: (file)
334 | > .loadFile('index.html')
335 | * en: To this: (url)
336 | > .loadURL('http://127.0.0.1:3000')
337 |
338 | #### Run app
339 | ```bash
340 | $ npm run-script electron-react
341 | ```
342 | #### Done!
343 | Welcome React-Electron project!
344 |
345 | ----
346 | # Database
347 |
348 | ## MySql
349 |
350 | Install package mysql
351 | ```bash
352 | $ npm install mysql
353 | ```
354 |
355 | Import package mysql on component file:
356 | ```js
357 | import mysql from 'mysql';
358 | ```
359 |
360 | inside same component file:
361 | ```js
362 |
363 | // set connection variable
364 | const [conn,setConn] = React.useState(undefined);
365 |
366 | // function connection mysql remote
367 | const connection = () => {
368 | let c = mysql.createConnection({
369 | //host : '888.88.88.88', //:3306
370 | host : 'localhost',
371 | user : 'root',
372 | password : '',
373 | database : 'databasename'
374 | });
375 | c.connect((err) => {
376 | // in case of error
377 | if(err){
378 | alert( err.code );
379 | return console.log(err.code, err.fatal, err.stack);
380 | }
381 | return console.log('Connection successfully established');
382 | });
383 | setConn(c);
384 | }
385 |
386 | // function query/search
387 | const query = () => {
388 | let sql = 'SELECT `name`,`id` FROM `tablename` where id > 0 limit 0,50 ';
389 | conn.query(sql, function (err, results, fields) {
390 | if (err) {
391 | alert(err.code);
392 | console.log(err.code);
393 | }
394 | else {
395 | alert(results);
396 | console.log(results);
397 | if(results.length)
398 | alert(results[0].id + results[0].name);
399 | }
400 | });
401 |
402 | // Close the connection
403 | conn.end(function(){
404 | // The connection has been closed
405 | console.log('Connection successfully closed');
406 | });
407 | }
408 | ```
409 |
410 | Insert call buttons HTML/React/JSX:
411 | ```html
412 |
413 |
414 | ```
415 |
416 |
417 |
418 | ## Sqlite3
419 |
420 |
423 |
487 |
488 | ----
489 | # AppTray Window
490 |
491 | ## Tray + NativeImage
492 | * en: I will create a **main-tray.js** file:
493 | ```js
494 | const {app, BrowserWindow, Tray, nativeImage, screen } = require('electron')
495 | const path = require('path')
496 |
497 | let mainWindow = undefined;;
498 | let tray = undefined;
499 | //app.dock.hide();
500 |
501 | function createWindow () {
502 | // Create the browser window.
503 | mainWindow = new BrowserWindow({
504 | width: 300,
505 | height: 600,
506 | //-----tray----- start
507 | show: true, //set this false
508 | frame: false,
509 | fullscreen: false,
510 | resizable: false,
511 | transparent: false,
512 | //-----tray----- end
513 | webPreferences: {
514 | backgroundThrottling: false
515 | }
516 | })
517 |
518 | // mainWindow.loadFile('index.html')
519 | mainWindow.loadFile(path.join(__dirname, 'index.html'))
520 | // Open the DevTools.
521 | // mainWindow.webContents.openDevTools()
522 |
523 | //-----tray----- start
524 | mainWindow.on('closed',()=>mainWindow = null)
525 | // Hide the window when it loses focus
526 | mainWindow.on('blur', () => {
527 | // if (!mainWindow.webContents.isDevToolsOpened()) {
528 | // mainWindow.hide();
529 | // }
530 | });
531 | //-----tray----- end
532 | }
533 |
534 | //-----tray----- start
535 | const createTray = () => {
536 | const icon = path.join(__dirname, 'app', 'assets', 'tray.png')
537 | const nimage = nativeImage.createFromPath(icon)
538 | //tray is a app variable
539 | tray = new Tray(nimage)
540 | tray.on('click', (event)=>toggleWindow())
541 | }
542 |
543 | const toggleWindow = () => {
544 | mainWindow.isVisible() ? mainWindow.hide() : showWindow();
545 | }
546 |
547 | const showWindow = () => {
548 | const position = getWindowPosition();
549 | mainWindow.setPosition(position.x,position.y, false);
550 | mainWindow.show();
551 | }
552 |
553 | const getWindowPosition = () => {
554 |
555 | //console.log(process.platform);
556 | //'aix'
557 | //'darwin'
558 | //'freebsd'
559 | //'linux'
560 | //'openbsd'
561 | //'sunos'
562 | //'win32'
563 |
564 | const { screenWidth, screenHeight } = screen.getPrimaryDisplay().workAreaSize;
565 | const windowBounds = mainWindow.getBounds();
566 | const trayBounds = tray.getBounds();
567 | // Center window horizontally below the tray icon
568 | const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
569 | let y = undefined;
570 | // Position window 4 pixels vertically below the tray icon
571 | if(process.platform == 'win32')
572 | y = Math.round(trayBounds.y - windowBounds.height);
573 | else
574 | y = Math.round(trayBounds.y + trayBounds.height + 4);
575 |
576 | return {x,y}
577 | }
578 | //-----tray----- end
579 |
580 | // This method will be called when Electron has finished
581 | // initialization and is ready to create browser windows.
582 | // Some APIs can only be used after this event occurs.
583 | app.whenReady().then(() => {
584 | //-----tray----- start
585 | createTray()
586 | //-----tray----- end
587 | createWindow()
588 |
589 | app.on('activate', function () {
590 | // On macOS it's common to re-create a window in the app when the
591 | // dock icon is clicked and there are no other windows open.
592 | if (BrowserWindow.getAllWindows().length === 0) createWindow()
593 | })
594 | })
595 |
596 | // Quit when all windows are closed, except on macOS. There, it's common
597 | // for applications and their menu bar to stay active until the user quits
598 | // explicitly with Cmd + Q.
599 | app.on('window-all-closed', function () {
600 | if (process.platform !== 'darwin') app.quit()
601 | })
602 |
603 | // In this file you can include the rest of your app's specific main process
604 | // code. You can also put them in separate files and require them here.
605 | ```
606 | #### Edit package.json file
607 | Insert/change this:
608 | ```json
609 | "main": "app/main-tray.js",
610 | ```
611 | * [sample1](main-tray.js)
612 | * [sample2](main-tray-two-windows.js)
613 | ----
614 | # Packaging App
615 |
616 | ## Electron Builder
617 | * en: There are mainly two options for packaging an Electron app and we will go with the second, [Electron Builder](https://www.npmjs.com/package/electron-builder/) (the other being Electron Packager).
618 | ```bash
619 | $ npm i electron-builder --save-dev
620 | ```
621 | We need to point the tool to the folder with the code to be compiled through the **package.json** by adding:
622 | ```json
623 | "build": {
624 | "asar": true,
625 | "extends": null,
626 | "publish": null,
627 | "appId": "com.natancabral.react-js-electron-sqlite3",
628 | "compression": "maximum",
629 | "productName": "File Name App",
630 | "nsis": {
631 | "shortcutName": "App Name Shortcut",
632 | "installerIcon": "./app/assets/ico/icon48.ico",
633 | "oneClick": true,
634 | "perMachine": true,
635 | "allowElevation": true,
636 | "runAfterFinish": true,
637 | "createDesktopShortcut": true,
638 | "createStartMenuShortcut": true,
639 | "allowToChangeInstallationDirectory": false
640 | },
641 | "win": {
642 | "target": "nsis",
643 | "icon": "./app/assets/ico/icon48.ico"
644 | },
645 | "directories": {
646 | "buildResources": "./app",
647 | "output": "dist"
648 | },
649 | "files": [
650 | "package.json",
651 | "app/**/*"
652 | ]
653 | }
654 | ```
655 | And inside scritps.
656 | ```json
657 | "scripts": {
658 | ...
659 | "build:dist:1": "electron-builder",
660 | "build:dist:2": "electron-builder --dir",
661 | "build:postinstall": "electron-builder install-app-deps",
662 | }
663 | ```
664 | Plus info.
665 | ```json
666 | "version": "1.0.0"
667 | "author": "",
668 | "description": "",
669 | "license": "",
670 | "private": true,
671 | ```
672 |
673 | ## Electron Packager
674 | * en: Install [electron-packager](https://github.com/electron/electron-packager/)
675 | ```bash
676 | $ npm install electron-packager --save-dev
677 | ```
678 | #### Shotcut to create App
679 | * en: Open **package.json** and insert inside on scripts:
680 | ```json
681 | "scripts": {
682 | ...
683 | "packager:win:1": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds",
684 | "packager:win:2": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/icons/win/app.ico",
685 | "packager:win:3": "electron-packager . --overwrite --platform=win32 --arch=ia32 --out=release-builds --icon=./app/assets/icons/win/icon.ico --prune=true --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"React Electron Sqlite\"",
686 |
687 | "packager:mac:1": "electron-packager . --overwrite --platform=darwin --arch=x64 --out=release-builds",
688 | "packager:mac:2": "electron-packager . --overwrite --platform=darwin --arch=x64 --out=release-builds --icon=./app/assets/icons/mac/icon.icns --prune=true",
689 | "packager:mac:3": "electron-packager . --overwrite --platform=darwin --arch=x64 --out=release-builds --icon=./app/assets/icons/mac/app.icns --osx-sign.identity='React Electron Sqlite' --extend-info=assets/mac/info.plist",
690 |
691 | "packager:linux:1": "electron-packager . --overwrite --platform=linux --arch=x64 --out=release-builds",
692 | "packager:linux:2": "electron-packager . --overwrite --platform=linux --arch=x64 --out=release-builds --icon=./app/assets/icons/png/1024x1024.png --prune=true",
693 |
694 | "packager:sign-exe": "signcode './release-builds/Electron API Demos-win32-ia32/Electron API Demos.exe' --cert ~/electron-api-demos.p12 --prompt --name 'React Electron Sqlite' --url 'http://electron.atom.io'",
695 | "packager:installer": "node ./script/installer.js",
696 | "packager:sign-installer": "signcode './release-builds/windows-installer/ElectronAPIDemosSetup.exe' --cert ~/electron-api-demos.p12 --prompt --name 'React Electron Sqlite' --url 'http://electron.atom.io'",
697 | ...
698 | }
699 | ```
700 | #### Create binary app
701 | ```bash
702 | $ npm run packager:win:1
703 | $ npm run packager:mac:1
704 | $ npm run packager:linux:1
705 | ```
706 | ----
707 | # Others
708 |
709 | ## Kill Process port:3000
710 | #### Install find-process to close server x.x.x.x:3000
711 | * en: Install find-process
712 | ```bash
713 | $ npm install find-process
714 | ```
715 | * en: main.js
716 | ```js
717 | const find = require('find-process');
718 |
719 | app.on('before-quit', (e) => {
720 | find('port', 3000)
721 | .then(function (list) {
722 | if (list[0] != null) {
723 | console.log('---kill---:', list[0].pid);
724 | process.kill(list[0].pid, 'SIGHUP');
725 | }
726 | })
727 | .catch((e) => {
728 | console.log('---error---',e.stack || e);
729 | });
730 | });
731 | ```
732 | ## Test
733 | #### Jest test
734 | ```bash
735 | $ npm i jest
736 | $ npm i babel-jest
737 | ```
738 | #### React test renderer
739 | ```bash
740 | $ npm i react-test-renderer
741 | ```
742 | ## Error
743 | * Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/electron/.electron' [issues](https://github.com/npm/npm/issues/17268)
744 | ```bash
745 | $ sudo npm install -g electron --unsafe-perm=true --allow-root
746 | ```
747 | * Cant remove or update global create-react-app version.
748 | ```bash
749 | $ sudo rm -rf /usr/local/bin/create-react-app
750 | ```
751 | * Update babel
752 | ```bash
753 | $ sudo npm install --save-dev @babel/core @babel/cli
754 | $ sudo npx babel-upgrade --write --install # --install optional
755 | ```
756 | * Danger: Permission denied
757 | ```bash
758 | $ sudo npm install ... --unsafe-perm=true --allow-root # danger
759 | ```
760 | * Gtk-Message: hh:mm:ss.mls: Failed to load module "canberra-gtk-module"
761 | ```bash
762 | $ sudo apt-get install libcanberra-gtk-module
763 | ```
764 |
765 |