From 2a8e7b0dcc7fd9b9ff1ed60ef0b3e2d215518432 Mon Sep 17 00:00:00 2001 From: Julien Deniau <1398469+jdeniau@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:39:12 +0100 Subject: [PATCH 1/4] Lint and tests --- .github/workflows/node.js.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/node.js.yml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 0000000..26931bf --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,30 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Lint & Tests +on: + push: + branches: [ "main" ] + pull_request: ~ + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - run: yarn install --frozen-lockfile + - run: yarn lint + - run: yarn test From 597665f3761c75ef77ec9951e10c2183a067cee6 Mon Sep 17 00:00:00 2001 From: Julien Deniau Date: Tue, 20 Feb 2024 17:47:34 +0100 Subject: [PATCH 2/4] Fix eslint errors --- src/Contexts.tsx | 3 +++ src/component/Connection/ConnectionForm.tsx | 5 ++--- src/component/Connection/ConnectionPage.tsx | 2 +- src/component/Connection/ConnectionStack.tsx | 2 +- src/component/Connection/SavedConnections.ts | 2 +- src/component/Connection/{index.d.ts => types.ts} | 14 +++++++------- src/component/DatabaseSelector.tsx | 4 +--- src/component/TableGrid.tsx | 2 -- src/configuration.ts | 2 +- src/preload.ts | 2 +- src/sql/index.ts | 2 +- 11 files changed, 19 insertions(+), 21 deletions(-) rename src/component/Connection/{index.d.ts => types.ts} (94%) diff --git a/src/Contexts.tsx b/src/Contexts.tsx index 8188648..bd64c7e 100644 --- a/src/Contexts.tsx +++ b/src/Contexts.tsx @@ -14,7 +14,9 @@ interface ConnexionContextProps { export const ConnectionContext = createContext({ currentConnectionName: null, connectionNameList: [], + // eslint-disable-next-line @typescript-eslint/no-empty-function connectTo: () => {}, + // eslint-disable-next-line @typescript-eslint/no-empty-function setCurrentConnectionName: () => {}, }); @@ -28,6 +30,7 @@ interface DatabaseContextProps { export const DatabaseContext = createContext({ database: null, + // eslint-disable-next-line @typescript-eslint/no-empty-function setDatabase: () => {}, }); diff --git a/src/component/Connection/ConnectionForm.tsx b/src/component/Connection/ConnectionForm.tsx index 7db62ca..e0cbe93 100644 --- a/src/component/Connection/ConnectionForm.tsx +++ b/src/component/Connection/ConnectionForm.tsx @@ -1,6 +1,6 @@ import { ConnectionContext, ConnectToFunc } from '../../Contexts'; import connections from './SavedConnections'; -import { ConnectionObject } from '.'; +import { ConnectionObject } from './types'; import { ChangeEvent, FormEvent, PureComponent, useContext } from 'react'; interface ConnectionFormProps { @@ -42,8 +42,7 @@ class ConnectionForm extends PureComponent< ); } - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore: name is in state due to previous line + // @ts-expect-error: name is in state due to previous line this.setState({ [name]: value, }); diff --git a/src/component/Connection/ConnectionPage.tsx b/src/component/Connection/ConnectionPage.tsx index 1012943..87b854f 100644 --- a/src/component/Connection/ConnectionPage.tsx +++ b/src/component/Connection/ConnectionPage.tsx @@ -1,6 +1,6 @@ import { Link, Navigate } from 'react-router-dom'; import connections from './SavedConnections'; -import { ConnectionObject } from '.'; +import { ConnectionObject } from './types'; import { ConnectionContext } from '../../Contexts'; import { useContext, useEffect, useState } from 'react'; diff --git a/src/component/Connection/ConnectionStack.tsx b/src/component/Connection/ConnectionStack.tsx index e3878f7..0ea5468 100644 --- a/src/component/Connection/ConnectionStack.tsx +++ b/src/component/Connection/ConnectionStack.tsx @@ -1,7 +1,7 @@ import { NavigateFunction, useNavigate } from 'react-router'; import { ConnectionContext, DatabaseContext } from '../../Contexts'; import { PureComponent, ReactNode } from 'react'; -import { ConnectionObject } from '.'; +import { ConnectionObject } from './types'; interface PropsWithoutHistory { children: ReactNode; diff --git a/src/component/Connection/SavedConnections.ts b/src/component/Connection/SavedConnections.ts index 562090e..c7361fb 100644 --- a/src/component/Connection/SavedConnections.ts +++ b/src/component/Connection/SavedConnections.ts @@ -1,5 +1,5 @@ // import Store from 'electron-store'; -import { ConnectionObject } from '.'; +import { ConnectionObject } from './types'; // import fs from 'node:fs'; // import path from 'node:path'; diff --git a/src/component/Connection/index.d.ts b/src/component/Connection/types.ts similarity index 94% rename from src/component/Connection/index.d.ts rename to src/component/Connection/types.ts index 6ded080..0c75d7a 100644 --- a/src/component/Connection/index.d.ts +++ b/src/component/Connection/types.ts @@ -1,7 +1,7 @@ -export type ConnectionObject = { - name: string; - host: string; - port: number; - user: string; - password: string; -}; +export type ConnectionObject = { + name: string; + host: string; + port: number; + user: string; + password: string; +}; diff --git a/src/component/DatabaseSelector.tsx b/src/component/DatabaseSelector.tsx index 78a88b2..eabdc27 100644 --- a/src/component/DatabaseSelector.tsx +++ b/src/component/DatabaseSelector.tsx @@ -8,9 +8,7 @@ interface DatabaseRow { export default function DatabaseSelector() { const { currentConnectionName } = useContext(ConnectionContext); - const [databaseList, setDatabaseList]: [DatabaseRow[], Function] = useState( - [] - ); + const [databaseList, setDatabaseList] = useState([]); const { database, setDatabase } = useContext(DatabaseContext); diff --git a/src/component/TableGrid.tsx b/src/component/TableGrid.tsx index cb62c5e..f7ce0fa 100644 --- a/src/component/TableGrid.tsx +++ b/src/component/TableGrid.tsx @@ -43,7 +43,6 @@ function TableGrid({ fields, result }: TableGridProps): ReactElement { )} {result && fields && ( - {/* eslint-disable react/jsx-key */} {/* TODO : use the table primary key to make a real key */} {result.map((row: object) => ( @@ -54,7 +53,6 @@ function TableGrid({ fields, result }: TableGridProps): ReactElement { ))} ))} - {/* eslint-enable react/jsx-key */} )} diff --git a/src/configuration.ts b/src/configuration.ts index 7681b31..c724571 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -2,7 +2,7 @@ import { dialog, safeStorage } from 'electron'; import { resolve } from 'node:path'; import { existsSync, mkdirSync, readFileSync, writeFile } from 'node:fs'; import envPaths from 'env-paths'; -import { ConnectionObject } from './component/Connection'; +import { ConnectionObject } from './component/Connection/types'; export type Configuration = { version: 1; diff --git a/src/preload.ts b/src/preload.ts index 93274d4..d207454 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -2,7 +2,7 @@ // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts import { Connection } from 'mysql2/promise'; -import { ConnectionObject } from './component/Connection'; +import { ConnectionObject } from './component/Connection/types'; import { Configuration } from './configuration'; import { contextBridge, ipcRenderer } from 'electron'; diff --git a/src/sql/index.ts b/src/sql/index.ts index 55dfd8f..fb9a0de 100644 --- a/src/sql/index.ts +++ b/src/sql/index.ts @@ -1,5 +1,5 @@ import { Connection, createConnection } from 'mysql2/promise'; -import { ConnectionObject } from 'src/component/Connection'; +import { ConnectionObject } from '../component/Connection/types'; class ConnectionStack { private connections: Map = new Map(); From 1feb9f5f1483affdfadf594640226a39bc3605d6 Mon Sep 17 00:00:00 2001 From: Julien Deniau Date: Tue, 20 Feb 2024 20:48:38 +0100 Subject: [PATCH 3/4] fix linter errors --- .eslintrc.json | 15 ++++++++++++++- .gitignore | 2 ++ package.json | 2 +- src/Contexts.tsx | 2 +- src/component/Query/WhereFilter.tsx | 1 + src/component/TableGrid.tsx | 1 + src/component/TableList.tsx | 2 +- src/error-page.tsx | 1 + src/preload.ts | 2 ++ src/sql/index.ts | 11 +++++++++++ src/styled.d.ts | 9 +++++++++ src/theme/index.ts | 4 ++-- tsconfig.json | 5 ++++- 13 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 src/styled.d.ts diff --git a/.eslintrc.json b/.eslintrc.json index 2d7aa60..af15e45 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,6 +4,11 @@ "es6": true, "node": true }, + "ignorePatterns": [ + "forge.config.ts", + "vite.*.config.*", + "stories/" // exclude stories from linting for now + ], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", @@ -12,5 +17,13 @@ "plugin:import/electron", "plugin:import/typescript" ], - "parser": "@typescript-eslint/parser" + "parser": "@typescript-eslint/parser", + "overrides": [ + { + "files": ["*.js", "*.jsx", "*.ts", "*.tsx"], + "parserOptions": { + "project": "./tsconfig.json" + } + } + ] } diff --git a/.gitignore b/.gitignore index 8296128..8276c4c 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,5 @@ typings/ # Electron-Forge out/ + +.vscode/ \ No newline at end of file diff --git a/package.json b/package.json index 938fe86..2e2c0af 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "package": "electron-forge package", "make": "electron-forge make", "publish": "electron-forge publish", - "lint:eslint": "eslint --ext .ts,.tsx .", + "lint:eslint": "eslint --quiet .", "lint:types": "tsc --noEmit", "test": "vitest" }, diff --git a/src/Contexts.tsx b/src/Contexts.tsx index bd64c7e..2319caf 100644 --- a/src/Contexts.tsx +++ b/src/Contexts.tsx @@ -43,6 +43,7 @@ interface ThemeContextProps { } const ThemeContext = createContext({ themeName: DEFAULT_THEME.name, + // eslint-disable-next-line @typescript-eslint/no-empty-function changeTheme: () => {}, }); @@ -58,7 +59,6 @@ export function ThemeContextProvider({ const [themeName, setThemeName] = useState(DEFAULT_THEME.name); const changeTheme = (newTheme: string) => { - window.config.changeTheme(newTheme); setThemeName(newTheme); }; diff --git a/src/component/Query/WhereFilter.tsx b/src/component/Query/WhereFilter.tsx index 8640427..b5bfee4 100644 --- a/src/component/Query/WhereFilter.tsx +++ b/src/component/Query/WhereFilter.tsx @@ -22,6 +22,7 @@ function WhereFilter({ defaultValue, onSubmit }: Props): ReactElement { onSubmit(where); }} > + {/* @ts-expect-error not present infuture TS verwsion */} setWhere(e.target.value)} /> diff --git a/src/component/TableGrid.tsx b/src/component/TableGrid.tsx index f7ce0fa..2da0eae 100644 --- a/src/component/TableGrid.tsx +++ b/src/component/TableGrid.tsx @@ -48,6 +48,7 @@ function TableGrid({ fields, result }: TableGridProps): ReactElement { {fields.map((field) => ( + {/* @ts-expect-error field name is in object. Need a better type ? */} ))} diff --git a/src/component/TableList.tsx b/src/component/TableList.tsx index c8e03e0..beebcb3 100644 --- a/src/component/TableList.tsx +++ b/src/component/TableList.tsx @@ -40,7 +40,7 @@ function ConnectedTableList({ database }: TableListProps): ReactElement | null {
({ + style={({ isActive }: { isActive: boolean }) => ({ fontWeight: isActive ? 'bold' : undefined, })} > diff --git a/src/error-page.tsx b/src/error-page.tsx index 39ce4b6..08aae54 100644 --- a/src/error-page.tsx +++ b/src/error-page.tsx @@ -11,6 +11,7 @@ export default function ErrorPage() {

Oops!

Sorry, an unexpected error has occurred.

+ {/* @ts-expect-error error might have one of tjose */} {error.statusText || error.message}

diff --git a/src/preload.ts b/src/preload.ts index d207454..7d4361c 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -28,12 +28,14 @@ contextBridge.exposeInMainWorld('config', config); interface Sql { openConnection(params: ConnectionObject): Promise; query(query: string): Promise; + closeAllConnections(): Promise; } // TODO : clone the binder object in sql/index.ts ? const sql: Sql = { openConnection: (params) => ipcRenderer.invoke('sql:connect', params), query: (query) => ipcRenderer.invoke('sql:query', query), + closeAllConnections: () => ipcRenderer.invoke('sql:closeAll'), }; contextBridge.exposeInMainWorld('sql', sql); diff --git a/src/sql/index.ts b/src/sql/index.ts index fb9a0de..c84de10 100644 --- a/src/sql/index.ts +++ b/src/sql/index.ts @@ -8,6 +8,7 @@ class ConnectionStack { #ipcEventBinding = { 'sql:connect': this.connect, 'sql:query': this.query, + 'sql:closeAll': this.closeAllConnections, }; bindIpcMain(ipcMain: Electron.IpcMain): void { @@ -34,6 +35,16 @@ class ConnectionStack { return await connection.query(query); } + async closeAllConnections(): Promise { + await Promise.all( + Array.from(this.connections.values()).map((connection) => + connection.end() + ) + ); + + this.connections.clear(); + } + #getConnection(senderId: number): Connection { const connection = this.connections.get(senderId); diff --git a/src/styled.d.ts b/src/styled.d.ts new file mode 100644 index 0000000..b9bfd9e --- /dev/null +++ b/src/styled.d.ts @@ -0,0 +1,9 @@ +// import original module declarations +import 'styled-components'; +import { TmTheme } from './theme'; + +// and extend them! +declare module 'styled-components' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface DefaultTheme extends TmTheme {} +} diff --git a/src/theme/index.ts b/src/theme/index.ts index 0a497c5..7f78ad3 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -4,7 +4,7 @@ import * as active4d from '../theme/active4d.json'; const THEME_LIST_AS_ARRAY = [dracula, visualStudio, active4d] as const; -type Theme = typeof THEME_LIST_AS_ARRAY[number]; +type Theme = (typeof THEME_LIST_AS_ARRAY)[number]; export const THEME_LIST: Record = {}; THEME_LIST_AS_ARRAY.forEach((t) => { @@ -13,7 +13,7 @@ THEME_LIST_AS_ARRAY.forEach((t) => { export const DEFAULT_THEME = THEME_LIST_AS_ARRAY[0]; -interface TmTheme { +export interface TmTheme { readonly name: string; readonly author?: string; readonly settings: TmThemeSetting[]; diff --git a/tsconfig.json b/tsconfig.json index 0629b90..5b28ed4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,5 +13,8 @@ "resolveJsonModule": true, "jsx": "react-jsx" }, - "include": ["src", "stories"] + "include": [ + "src" + // "stories" /ignore stories for now + ] } From e43c894ce60ee6742c8996f2a851d36d1fa6d6a2 Mon Sep 17 00:00:00 2001 From: Julien Deniau Date: Tue, 20 Feb 2024 20:54:52 +0100 Subject: [PATCH 4/4] add lint command --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2e2c0af..3407839 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "package": "electron-forge package", "make": "electron-forge make", "publish": "electron-forge publish", + "lint": "yarn lint:eslint && yarn lint:types", "lint:eslint": "eslint --quiet .", "lint:types": "tsc --noEmit", "test": "vitest"