diff --git a/package.json b/package.json index c81e560..68e8959 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "license": "MIT", "dependencies": { "antd": "^5.14.1", + "electron-log": "^5.1.1", "electron-squirrel-startup": "^1.0.0", "electron-store": "^8.1.0", - "env-paths": "^3.0.0", "i18next": "^23.10.0", "mysql": "^2.18.1", "react": "^18.2.0", diff --git a/src/configuration/index.test.ts b/src/configuration/index.test.ts index b537c14..d44d5e1 100644 --- a/src/configuration/index.test.ts +++ b/src/configuration/index.test.ts @@ -13,10 +13,6 @@ import { const { getBaseConfig, resetConfiguration } = testables; -vi.mock('env-paths', () => ({ - default: () => ({ config: 'config' }), -})); - vi.mock('node:path', () => ({ resolve: (a: string, b: string) => `${a}/${b}`, })); @@ -46,6 +42,9 @@ vi.mock('electron', () => ({ encryptString: vi.fn((s: string) => Buffer.from(`encrypted-${s}`)), decryptString: vi.fn((b: Buffer) => b.toString().substring(10)), }, + app: { + getPath: vi.fn((s: string) => s), + }, })); function mockExistingConfig( @@ -156,7 +155,7 @@ describe('add connection to config', () => { }); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -212,7 +211,7 @@ describe('add connection to config', () => { }); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -258,7 +257,7 @@ describe('set theme', () => { await changeTheme('test'); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -298,7 +297,7 @@ describe('set theme', () => { await changeTheme('test'); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -354,7 +353,7 @@ describe('set connection appState', async () => { await updateConnectionState('prod', 'isActive', true); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -421,7 +420,7 @@ describe('set connection appState', async () => { await updateConnectionState('prod', 'activeDatabase', 'test'); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -474,7 +473,7 @@ describe('edit', () => { expect(configuration.connections.prod.host).toBe('prod2'); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, @@ -521,7 +520,7 @@ describe('edit', () => { expect(configuration.connections.local2.host).toBe('local2'); expect(mockWriteFile).toHaveBeenCalledWith( - 'config/config.json', + 'userData/config/config.json', JSON.stringify( { version: 1, diff --git a/src/configuration/index.ts b/src/configuration/index.ts index 2155427..8ad5db2 100644 --- a/src/configuration/index.ts +++ b/src/configuration/index.ts @@ -1,8 +1,7 @@ -import { dialog, safeStorage } from 'electron'; +import { app, dialog, safeStorage } from 'electron'; import { existsSync, mkdirSync, readFileSync, writeFile } from 'node:fs'; import { resolve } from 'node:path'; -import envPaths from 'env-paths'; -import { log } from '../log'; +import log from 'electron-log'; import { CONFIGURATION_CHANNEL } from '../preload/configurationChannel'; import { ConnectionObject } from '../sql/types'; import { DEFAULT_THEME } from './themes'; @@ -13,11 +12,10 @@ import { EncryptedConnectionObject, } from './type'; -// TODO use app.getPath('userData') to store the configuration file instead of env-paths -const envPath = envPaths('TianaTables', { suffix: '' }); -const dataFilePath = resolve(envPath.config, 'config.json'); +const configPath = resolve(app.getPath('userData'), 'config'); +const dataFilePath = resolve(configPath, 'config.json'); -log('CONFIG', 'Configuration file path:', dataFilePath); +log.info('Configuration file path:', dataFilePath); function getBaseConfig(): Configuration { return { @@ -92,7 +90,7 @@ function writeConfiguration(config: Configuration): void { ), }; - mkdirSync(envPath.config, { recursive: true }); + mkdirSync(configPath, { recursive: true }); writeFile( dataFilePath, JSON.stringify(encryptedConfig, null, 2), diff --git a/src/log.ts b/src/log.ts deleted file mode 100644 index e93004f..0000000 --- a/src/log.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function log(domain: string, message: string, ...args: unknown[]) { - if (process.env.NODE_ENV !== 'development') { - return; - } - - console.log(`${domain} ${message}`, ...args); -} diff --git a/src/main.ts b/src/main.ts index 606f026..3301b27 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,9 +3,9 @@ import path from 'node:path'; import installExtension, { REACT_DEVELOPER_TOOLS, } from 'electron-devtools-installer'; -import { updateElectronApp } from 'update-electron-app'; +import log from 'electron-log/main'; +import { UpdateSourceType, updateElectronApp } from 'update-electron-app'; import { bindIpcMain as bindIpcMainConfiguration } from './configuration'; -import { log } from './log'; import connectionStackInstance from './sql'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. @@ -13,19 +13,28 @@ if (require('electron-squirrel-startup')) { app.quit(); } -updateElectronApp(); +log.initialize(); + +updateElectronApp({ + updateSource: { + type: UpdateSourceType.ElectronPublicUpdateService, + repo: 'jdeniau/tiana-tables', + }, + logger: log, +}); const isMac = process.platform !== 'darwin'; +const isDev = !app.isPackaged; function installReactDevToolsExtension() { // don't install the extension in production - if (process.env.NODE_ENV === 'development') { + if (!isDev) { return; } installExtension(REACT_DEVELOPER_TOOLS) .then((name) => { - log('DEBUG', `Added Extension: ${name}`); + log.debug(`Added Extension: ${name}`); // once extension is loaded, reload the view after a short period (probably to be sure that the extension is loaded ?) BrowserWindow.getAllWindows().forEach((win) => { @@ -57,7 +66,7 @@ const createWindow = () => { } // Open the DevTools. - if (process.env.NODE_ENV === 'development') { + if (isDev) { mainWindow.webContents.openDevTools(); } }; @@ -85,6 +94,10 @@ app.whenReady().then(() => { bindIpcMainConfiguration(ipcMain); connectionStackInstance.bindIpcMain(ipcMain); + ipcMain.handle('get-is-dev', () => { + return isDev; + }); + // createWindow(); // app.on('activate', function () { // if (BrowserWindow.getAllWindows().length === 0) createWindow(); diff --git a/src/preload.ts b/src/preload.ts index dc1c7ee..deac5e5 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -1,16 +1,21 @@ // See the Electron documentation for details on how to use preload scripts: // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts -import { contextBridge } from 'electron'; +import { contextBridge, ipcRenderer } from 'electron'; import { config } from './preload/config'; import { sql } from './preload/sql'; contextBridge.exposeInMainWorld('config', config); contextBridge.exposeInMainWorld('sql', sql); +ipcRenderer.invoke('get-is-dev').then((isDev) => { + contextBridge.exposeInMainWorld('isDev', isDev); +}); + // Declare window global that have been added declare global { interface Window { + isDev: boolean; config: typeof config; sql: typeof sql; } diff --git a/src/renderer/component/Debug.tsx b/src/renderer/component/Debug.tsx index 474caed..533ef04 100644 --- a/src/renderer/component/Debug.tsx +++ b/src/renderer/component/Debug.tsx @@ -16,7 +16,7 @@ const Url = styled.div` function Debug(): ReactElement | null { const location = useLocation(); - if (process.env.NODE_ENV !== 'development') { + if (!window.isDev) { return null; } diff --git a/src/sql/index.ts b/src/sql/index.ts index 73533bb..5c23078 100644 --- a/src/sql/index.ts +++ b/src/sql/index.ts @@ -1,6 +1,6 @@ +import log from 'electron-log'; import { Connection, createConnection } from 'mysql2/promise'; import { getConfiguration } from '../configuration'; -import { log } from '../log'; import { SQL_CHANNEL } from '../preload/sqlChannel'; import { ConnectionObject, QueryResult } from './types'; @@ -26,13 +26,13 @@ class ConnectionStack { async executeQuery(connectionName: string, query: string): QueryResult { const connection = await this.#getConnection(connectionName); - log('SQL', `Execute query on "${connectionName}": "${query}"`); + log.debug(`Execute query on "${connectionName}": "${query}"`); try { return await connection.query(query); } catch (error) { // retry once - log('SQL', `Error on "${connectionName}"`, error); + log.debug(`Error on "${connectionName}"`, error); this.connections.delete(connectionName); @@ -75,13 +75,13 @@ class ConnectionStack { throw new Error(`Connection already opened on "${name}"`); } - log('SQL', `Open connection to "${name}"`); + log.debug(`Open connection to "${name}"`); // TODO use a connection pool instead ? https://github.com/mysqljs/mysql?tab=readme-ov-file#establishing-connections const connection = await createConnection(rest); connection.on('end', () => { - log('SQL', `Connection to "${name}" ended`); + log.debug(`Connection to "${name}" ended`); this.connections.delete(name); }); diff --git a/yarn.lock b/yarn.lock index daf4866..9d02b8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7646,6 +7646,13 @@ __metadata: languageName: node linkType: hard +"electron-log@npm:^5.1.1": + version: 5.1.1 + resolution: "electron-log@npm:5.1.1" + checksum: 10c0/4ca427404d7a660df69146a4d16fcc266f0fa8d1da665b226cda50b8608f7ef032c43bef1330125b692835582afca4e2123602840b3216735c586dd49c16d03c + languageName: node + linkType: hard + "electron-squirrel-startup@npm:^1.0.0": version: 1.0.0 resolution: "electron-squirrel-startup@npm:1.0.0" @@ -7751,13 +7758,6 @@ __metadata: languageName: node linkType: hard -"env-paths@npm:^3.0.0": - version: 3.0.0 - resolution: "env-paths@npm:3.0.0" - checksum: 10c0/76dec878cee47f841103bacd7fae03283af16f0702dad65102ef0a556f310b98a377885e0f32943831eb08b5ab37842a323d02529f3dfd5d0a40ca71b01b435f - languageName: node - linkType: hard - "envinfo@npm:^7.7.3": version: 7.11.1 resolution: "envinfo@npm:7.11.1" @@ -14934,9 +14934,9 @@ __metadata: chromatic: "npm:^11.0.0" electron: "npm:28.2.3" electron-devtools-installer: "npm:^3.2.0" + electron-log: "npm:^5.1.1" electron-squirrel-startup: "npm:^1.0.0" electron-store: "npm:^8.1.0" - env-paths: "npm:^3.0.0" eslint: "npm:^8.56.0" eslint-plugin-import: "npm:^2.29.1" eslint-plugin-react: "npm:^7.33.2"