refactor: improved typings

This commit is contained in:
Fabio Di Stasio 2023-04-04 17:59:54 +02:00
parent 57c2af2c2b
commit 4e896244d1
7 changed files with 54 additions and 162 deletions

View File

@ -1,100 +0,0 @@
# Contributors Guide
Antares SQL is an application based on [Electron.js](https://www.electronjs.org/) that uses [Vue.js](https://vuejs.org/) and [Spectre.css](https://picturepan2.github.io/spectre/) as frontend frameworks.
For the build process it takes advantage of [electron-builder](https://www.electron.build/).
This application uses [Pinia🍍](https://pinia.vuejs.org/) as application state manager and [electron-store](https://github.com/sindresorhus/electron-store) to save the various settings on disc.
This guide aims to provide useful information and guidelines to everyone wants to contribute with this open-source project.
For every other question related to this project please [contact me](https://github.com/Fabio286).
## Project Structure
The main files of the application are located inside `src` folder and are groupped in three subfolders.
### `common`
This folder contains small libraries, classes and objects. The purpose of `common` folder is to group together utilities used by **renderer** and **main** processes.
Noteworthy is the `customizations` folder that contains clients related customizations. Those settings are merged with `default.js` that lists every option.
Client related customizations are stored on Pinia and can be accessed by `customizations` property of current workspace object, or importing `common/customizations`.
An use case of customizations object can be the following:
```js
computed: {
defaultEngine () {
if (this.workspace.customizations.engines)
return this.workspace.engines.find(engine => engine.isDefault).name;
return '';
}
}
```
In this case the computed property `defaultEngine` returns the default engine for MySQL client, or an empty string with PostgreSQL that doesn't have engines.
Customization properties are also useful **if some features are ready for one client but not others**.
### `main`
Inside this folder are located all files required by main process.
`ipc-handlers` subfolder includes all IPC handlers for events sent from renderer process.
`libs` subfolder includes classes related to clients and **query and connection logics**.
**Everything above client's class level should be "client agnostic"** with a neutral and uniformed api interface
### `renderer`
In this folder is located the structure of Vue frontend application.
## Build
The command to build Antares SQL locally is `npm run build`.
## Conventions
### Electron
- **kebab-case** for IPC event names.
### Vue
- **PascalCase** for file names (with .vue extension) and including components inside others (`<MyComponent/>`).
- "**Base**" prefix for [base component names](https://vuejs.org/v2/style-guide/#Base-component-names-strongly-recommended).
- "**The**" prefix for [single-instance component names](https://vuejs.org/v2/style-guide/#Single-instance-component-names-strongly-recommended).
- [Tightly coupled component names](https://vuejs.org/v2/style-guide/#Tightly-coupled-component-names-strongly-recommended).
- [Order of words in component names](https://vuejs.org/v2/style-guide/#Order-of-words-in-component-names-strongly-recommended).
- **kebab-case** in templates for property and event names.
### Code Style
The project includes [ESlint](https://eslint.org/) and [StyleLint](https://stylelint.io/) config files with style rules. I recommend to set the lint on-save option in your code editor.
Alternatively you can launch following commands to lint the project.
Check if all the style rules have been followed:
```console
npm run lint
```
Apply style rules globally if possible:
```console
npm run lint:fix
```
### Other recommendations
Please, use if possible **template literals** to compose strings and **avoid unnecessary dependencies**.
### Commits
The commit style adopted for this project is [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
Basicly it's important to have **single scoped commits with a prefix** that follows this style because Antares SQL uses [standard-version](https://github.com/conventional-changelog/standard-version) to generate new releases and [CHANGELOG.md](https://github.com/Fabio286/antares/blob/master/CHANGELOG.md) file to track all notable changes.
For Visual Studio Code users may be useful [Conventional Commits](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits) extension.
## Debug
**Debug mode**:
```console
npm run debug
```
After running the debug mode Antares will listen on port 9222 (main process) for a debugger.
On **Visual Studio Code** just launch "*Electron: Main*" configurations after running Antares in debug mode.

View File

@ -87,26 +87,12 @@
"artifactName": "${productName}-${version}-portable.exe"
},
"appx": {
"displayName": "Antares SQL",
"displayName": "Mizar TCP Tester",
"backgroundColor": "transparent",
"showNameOnTiles": true,
"identityName": "62514FabioDiStasio.AntaresSQLClient",
"publisher": "CN=1A2729ED-865C-41D2-9038-39AE2A63AA52",
"applicationId": "FabioDiStasio.AntaresSQLClient"
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
]
}
},
"dependencies": {

View File

@ -3,6 +3,18 @@ import { ClientHost, ClientMessage } from 'common/interfaces';
import * as ElectronStore from 'electron-store';
const persistentStore = new ElectronStore({ name: 'client' });
interface SenderParams {
closeOnEcho: boolean;
persistentConnection: boolean;
nMsgs: number;
tMin: number;
tMax: number;
nClients: number;
trace: boolean;
alertReset: boolean;
loop: boolean;
}
class Sender {
process: NodeJS.Process;
closeOnEcho: boolean;
@ -17,15 +29,14 @@ class Sender {
nConnected: number;
nClosed: number;
nTryConnect: number;
nReceived: any[];
nReceived: number[];
nSent: number;
timeStart: Date;
hosts: ClientHost[];
messages: ClientMessage[];
nHostClients: any[];
nHostBytes: any[];
nHostMsgs: any[];
storagePath: string;
nHostClients: number[];
nHostBytes: number[];
nHostMsgs: number[];
loop: boolean;
/**
@ -55,7 +66,6 @@ class Sender {
this.nHostClients = [];
this.nHostBytes = [];
this.nHostMsgs = [];
this.storagePath = '';
}
/**
@ -74,7 +84,7 @@ class Sender {
* @param {*} params
* @memberof Sender
*/
setParams (params: any) {
setParams (params: SenderParams) {
this.closeOnEcho = params.closeOnEcho;
this.persistentConnection = params.persistentConnection;
this.nMsgs = params.nMsgs;
@ -86,16 +96,6 @@ class Sender {
this.loop = params.loop;
}
/**
* Setta il percorso della cartella storage
*
* @param {string} storagePath
* @memberof Sender
*/
setStoragePath (storagePath: string) {
this.storagePath = storagePath;
}
/**
* Carica i messaggi in memoria
*
@ -188,7 +188,7 @@ class Sender {
const msg = this.randMsg();
client.write(msg, (err: any) => {
client.write(msg, (err: Error) => {
if (err)
this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red');
else {
@ -208,7 +208,7 @@ class Sender {
this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red');
}
client.on('connect', (err: any) => {
client.on('connect', (err: Error) => {
this.nTryConnect++;
if (err)
this.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red');
@ -236,7 +236,7 @@ class Sender {
}
});
client.on('error', (err: any) => {
client.on('error', (err: Error & { code: string }) => {
switch (err.code) {
case 'ECONNRESET':
if (this.alertReset)
@ -281,7 +281,7 @@ class Sender {
this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red');
}
client.on('connect', (err: any) => {
client.on('connect', (err: Error) => {
this.nTryConnect++;
if (err)
this.sendLog(`Errore connessione #${clientId} su ${params.host}:${params.port}:\n${err}`, 'red');
@ -305,7 +305,7 @@ class Sender {
if (this.trace) this.sendLog(`Socket #${clientId} su ${params.host}:${params.port} chiuso`);
});
client.on('error', (err: any) => {
client.on('error', (err: Error & { code: string }) => {
switch (err.code) {
case 'ECONNRESET':
if (this.alertReset)
@ -350,7 +350,7 @@ class Sender {
const msg = this.randMsg();
client.write(msg, (err: any) => {
client.write(msg, (err: Error) => {
if (err)
this.sendLog(`Socket #${clientId} su ${params.host}:${params.port}:\nErrore messaggio: ${err}`, 'red');
else {
@ -417,4 +417,4 @@ class Sender {
}
}
}
export { Sender };
export { Sender, SenderParams };

View File

@ -1,15 +1,21 @@
import { ServerPort } from 'common/interfaces';
import * as net from 'net';
interface ServerParams {
trace: boolean;
echo: boolean;
alertReset: boolean;
}
class Server {
process: NodeJS.Process;
trace: boolean;
echo: boolean;
alertReset: boolean;
ports: ServerPort[];
server: any[];
nBytes: any[];
nMsgs: any[];
server: net.Server[];
nBytes: number[];
nMsgs: number[];
constructor (process: NodeJS.Process) {
this.process = process;
@ -28,7 +34,7 @@ class Server {
* @param {*} ports
* @memberof Server
*/
setPorts (ports: any) {
setPorts (ports: ServerPort[]) {
this.ports = ports;
}
@ -47,7 +53,7 @@ class Server {
this.process.send(log);
}
startServer (params: any) {
startServer (params: ServerParams) {
this.trace = params.trace;
this.echo = params.echo;
this.alertReset = params.alertReset;
@ -59,10 +65,10 @@ class Server {
this.nBytes[i] = 0;
this.nMsgs[i] = 0;
this.server[i].on('connection', (socket: any) => {
this.server[i].on('connection', (socket: net.Socket) => {
if (this.trace) this.sendLog(`Client connesso su porta ${port}`);
socket.on('data', (msg: any) => {
socket.on('data', (msg: Buffer) => {
const msgString = msg.toString();
if (this.echo) socket.write(msg);
this.nBytes[i] += msg.length;
@ -75,7 +81,7 @@ class Server {
if (this.trace) this.sendLog(`Client disconnesso su porta ${port}`);
});
socket.on('error', (err: any) => {
socket.on('error', (err: Error & { code: string }) => {
switch (err.code) {
case 'ECONNRESET':
if (this.alertReset)
@ -89,7 +95,7 @@ class Server {
});
});// <- server
this.server[i].on('error', (err: any) => {
this.server[i].on('error', (err: Error) => {
this.sendLog(`Errore server su porta ${port}: \n${err}`, 'red');
});
@ -102,7 +108,7 @@ class Server {
stopServer (callback: () => void) {
(async () => {
for (let i = 0; i < this.server.length; i++) {
await this.server[i].close(function () {
this.server[i].close(() => {
this.server[i].unref();
});
}
@ -111,16 +117,16 @@ class Server {
}
getReports () {
const reportList: any[] = [];
const reportList: {port: number; sockets: number; data: number; messages: number}[] = [];
for (let i = 0; i < this.server.length; i++) {
const report = {
port: this.server[i].address().port,
sockets: null as any,
port: (this.server[i].address() as net.AddressInfo).port,
sockets: null as number,
data: this.nBytes[i],
messages: this.nMsgs[i]
};
this.server[i].getConnections((err: any, nSockets: any) => {
this.server[i].getConnections((err: Error, nSockets: number) => {
if (err) this.sendLog(`Errore report: \n${err}`, 'red');
report.sockets = nSockets;
reportList.push(report);
@ -143,4 +149,4 @@ class Server {
}
}
}
export { Server };
export { Server, ServerParams };

View File

@ -1,5 +1,5 @@
import { app, BrowserWindow, nativeImage, ipcMain, Menu } from 'electron';
import * as fs from 'fs';
import { app, BrowserWindow, /* nativeImage, */ ipcMain, Menu } from 'electron';
// import * as fs from 'fs';
import * as path from 'path';
import * as Store from 'electron-store';
import { ChildProcess, fork, Serializable } from 'child_process';

View File

@ -1,14 +1,14 @@
import { Sender } from '../libs/Sender';
import { ClientHost } from 'common/interfaces';
import { Sender, SenderParams } from '../libs/Sender';
const Sends = new Sender(process);
let clientTimer: NodeJS.Timer;
process.on('message', (message: any) => {
process.on('message', (message: { event: string; hosts: ClientHost[]; params: SenderParams}) => {
switch (message.event) {
case 'start':
Sends.setHosts(message.hosts);
Sends.setParams(message.params);
Sends.setStoragePath(message.storagePath);
Sends.startFullTest(() => {
const response = {
@ -31,7 +31,6 @@ process.on('message', (message: any) => {
case 'startStep':
Sends.setHosts(message.hosts);
Sends.setParams(message.params);
Sends.setStoragePath(message.storagePath);
Sends.connectClients(() => {
const response = {

View File

@ -1,9 +1,10 @@
import { Server } from '../libs/Server';
import { ServerPort } from 'common/interfaces';
import { Server, ServerParams } from '../libs/Server';
const myServer = new Server(process);
let serverTimer: NodeJS.Timer;
process.on('message', (message: {event: string; ports: string; params: any}) => {
process.on('message', (message: {event: string; ports: ServerPort[]; params: ServerParams}) => {
switch (message.event) {
case 'start':
myServer.setPorts(message.ports);