refactor: move to vite + ts + swc

This commit is contained in:
2023-07-15 19:21:07 +00:00
parent 65c64ff540
commit 3440fcf3fe
21 changed files with 612 additions and 7605 deletions

27
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,27 @@
/* eslint-env node */
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:react-hooks/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: true,
tsconfigRootDir: __dirname,
},
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'@typescript-eslint/no-non-null-assertion': 'off',
},
}

44
.gitignore vendored
View File

@@ -1,25 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # Logs
logs
# dependencies *.log
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
dist/ node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# some random thing from electron (it doesnt compile in a dist folder for some reason
./electron/index.js

View File

@@ -1,9 +1,9 @@
const path = require('path'); import * as path from 'node:path'
const { app, BrowserWindow, dialog, ipcMain } = require('electron'); import { app, BrowserWindow, dialog, ipcMain } from 'electron';
const isDev = require('electron-is-dev'); import * as isDev from 'electron-is-dev';
const fs = require('fs'); import * as fs from 'fs';
const colorette = require('colorette') import * as colorette from 'colorette';
const { exec } = require('node:child_process') import { exec } from 'node:child_process';
function createWindow() { function createWindow() {
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
@@ -19,7 +19,7 @@ function createWindow() {
title: 'sern', title: 'sern',
}); });
if (isDev) { if (isDev) {
mainWindow.loadURL('http://localhost:3000'); mainWindow.loadURL('http://localhost:5173');
} else { } else {
mainWindow.loadFile(path.join(__dirname, '../build/index.html')); mainWindow.loadFile(path.join(__dirname, '../build/index.html'));
} }
@@ -32,7 +32,7 @@ function createWindow() {
e.preventDefault(); e.preventDefault();
}); });
ipcMain.on('openFolder', (event, arg) => { ipcMain.on('openFolder', (event, _arg) => {
dialog dialog
.showOpenDialog({ .showOpenDialog({
properties: ['openDirectory'], properties: ['openDirectory'],
@@ -52,7 +52,7 @@ function createWindow() {
console.log(data); console.log(data);
console.log(`${colorette.cyan('🛈')} Current OS: ${currentOS}`) console.log(`${colorette.cyan('🛈')} Current OS: ${currentOS}`)
let packageManagerCommand let packageManagerCommand: string
switch (data.chosenPackageManager) { switch (data.chosenPackageManager) {
case 'npm': case 'npm':
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=npm` packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=npm`
@@ -67,7 +67,7 @@ function createWindow() {
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}"` packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}"`
break; break;
} }
let commandToRun let commandToRun: string
switch (currentOS) { switch (currentOS) {
case 'linux': case 'linux':
commandToRun = `cd ${data.selectedPath};${packageManagerCommand}` commandToRun = `cd ${data.selectedPath};${packageManagerCommand}`
@@ -87,11 +87,11 @@ function createWindow() {
console.log(`${colorette.cyan('🛈')} About to execute command: ${commandToRun}`) console.log(`${colorette.cyan('🛈')} About to execute command: ${commandToRun}`)
const cmd = exec(commandToRun) const cmd = exec(commandToRun)
cmd.stdout.on('data', (data) => { cmd.stdout!.on('data', (data) => {
console.log(`${colorette.cyan('🛈')} Command stdout: ${data}`); console.log(`${colorette.cyan('🛈')} Command stdout: ${data}`);
}); });
cmd.stderr.on('data', (data) => { cmd.stderr!.on('data', (data) => {
console.error(`${colorette.red('×')} Command stderr: ${data}`); console.error(`${colorette.red('×')} Command stderr: ${data}`);
}); });
@@ -116,7 +116,7 @@ app.on('activate', () => {
} }
}); });
let currentOS let currentOS: string
switch (process.platform) { switch (process.platform) {
case 'linux': case 'linux':
currentOS = 'linux' currentOS = 'linux'
@@ -133,4 +133,21 @@ switch (process.platform) {
break; break;
} }
console.log(fs.readFileSync(__dirname + '/ascii.txt', 'utf-8')) const asciiart = ` .:-=-:.
.:=+++++++++=-.
:-=+++++++++++++++++=-:
=++++++++++++++++++++=:.
=+++++++++++++++=-:
=++++++++++++-. ###### ######## ######## ## ## ###### ## ## ####
=++++++++++++*+=:. ## ## ## ## ## ### ## ## ## ## ## ##
=++++++++++++******=-. ## ## ## ## #### ## ## ## ## ##
:=+++++++++++**********+- ###### ###### ######## ## ## ## ## #### ## ## ##
.:-+++++++********###* ## ## ## ## ## #### ## ## ## ## ##
:-=++***########* ## ## ## ## ## ## ### ## ## ## ## ##
.-*###########* ###### ######## ## ## ## ## ###### ####### ####
:=+###############*
.-=*###################*
.:=*#################*=-.
:=+#########+=:
`
console.log(asciiart)

26
electron/tsconfig.json Normal file
View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"outDir": "./dist",
/* Bundler mode */
"moduleResolution": "node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
}

13
index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -1,10 +1,20 @@
{ {
"name": "sern-gui", "name": "sern-gui",
"productName": "sern-gui",
"version": "0.1.0-alpha",
"main": "./electron/index.js",
"private": true, "private": true,
"version": "0.1.0-alpha",
"main": "./dist/index.js",
"homepage": "./", "homepage": "./",
"scripts": {
"start": "vite",
"dev": "concurrently -k \"yarn:start\" \"yarn:electron\"",
"build": "tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"electron": "tsc-watch ./electron/index.ts --outDir \"./dist\" --onSuccess \"electron .\"",
"build-electron": "yarn build && electron-builder --linux --windows",
"build-electron-linux": "yarn build && electron-builder --linux",
"build-electron-win": "yarn build && electron-builder --windows"
},
"dependencies": { "dependencies": {
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
@@ -17,19 +27,24 @@
"colorette": "^2.0.20", "colorette": "^2.0.20",
"electron-is-dev": "^2.0.0", "electron-is-dev": "^2.0.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0"
"react-scripts": "5.0.1"
}, },
"scripts": { "devDependencies": {
"start": "react-scripts start", "@types/react": "^18.2.14",
"build": "react-scripts build", "@types/react-dom": "^18.2.6",
"test": "react-scripts test", "@typescript-eslint/eslint-plugin": "^5.61.0",
"eject": "react-scripts eject", "@typescript-eslint/parser": "^5.61.0",
"dev": "concurrently -k \"BROWSER=none yarn start\" \"yarn:electron\"", "@vitejs/plugin-react-swc": "^3.3.2",
"electron": "electron .", "concurrently": "^8.2.0",
"build-electron": "yarn build && electron-builder --linux --windows", "electron": "^25.2.0",
"build-electron-linux": "yarn build && electron-builder --linux", "electron-builder": "^24.4.0",
"build-electron-win": "yarn build && electron-builder --windows" "eslint": "^8.44.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.1",
"tsc-watch": "^6.0.4",
"typescript": "^5.0.2",
"vite": "^4.4.0",
"wait-on": "^7.0.1"
}, },
"build": { "build": {
"extends": null, "extends": null,
@@ -43,30 +58,5 @@
"icon": "./icons/icon.ico", "icon": "./icons/icon.ico",
"publisherName": "sern" "publisherName": "sern"
} }
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"concurrently": "^8.2.0",
"electron": "^25.2.0",
"electron-builder": "^24.4.0",
"wait-on": "^7.0.1"
} }
} }

View File

@@ -1,10 +1,10 @@
@font-face { @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
/* @font-face {
font-family: 'Classic Console Neue'; font-family: 'Classic Console Neue';
src: local('Classic Console Neue'), src: local('Classic Console Neue'),
url('https://fonts.srizan.dev/clacon2.ttf') format('truetype'); url('https://fonts.srizan.dev/clacon2.ttf') format('truetype');
} } */
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
.titleHeader { .titleHeader {
color: #4af626; color: #4af626;

View File

@@ -1,4 +1,3 @@
import * as React from 'react';
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions'; import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent'; import CardContent from '@mui/material/CardContent';
@@ -6,7 +5,7 @@ import Typography from '@mui/material/Typography';
import InitModal from './InitModal.js'; import InitModal from './InitModal.js';
import PluginsModal from './PluginsModal.js'; import PluginsModal from './PluginsModal.js';
function cardChooser(command) { function cardChooser(command: string) {
switch (command) { switch (command) {
case 'init': case 'init':
return <InitModal /> return <InitModal />
@@ -17,7 +16,8 @@ function cardChooser(command) {
} }
} }
export default function FunctionalityCard({ command, description }) { export default function FunctionalityCard(props: Props) {
const { command, description } = props
return ( return (
<Card sx={{ width: window.innerWidth / 2 }} variant='outlined'> <Card sx={{ width: window.innerWidth / 2 }} variant='outlined'>
<CardContent> <CardContent>
@@ -34,4 +34,9 @@ export default function FunctionalityCard({ command, description }) {
</CardActions> </CardActions>
</Card> </Card>
); );
}
interface Props {
command: string
description: string
} }

View File

@@ -6,16 +6,16 @@ import Modal from '@mui/material/Modal';
import InputLabel from '@mui/material/InputLabel'; import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem'; import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl'; import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select'; import Select, { SelectChangeEvent } from '@mui/material/Select';
import TextField from '@mui/material/TextField'; import TextField from '@mui/material/TextField';
import Checkbox from '@mui/material/Checkbox'; import Checkbox from '@mui/material/Checkbox';
import FormGroup from '@mui/material/FormGroup'; import FormGroup from '@mui/material/FormGroup';
import FormControlLabel from '@mui/material/FormControlLabel'; import FormControlLabel from '@mui/material/FormControlLabel';
import type { IpcRendererEvent } from 'electron'
import './InitModal.css'; import './InitModal.css';
const { ipcRenderer } = window.require('electron'); const { ipcRenderer } = window.require('electron');
// eslint-disable-next-line no-unused-vars /* const style = {
const style = {
position: 'absolute', position: 'absolute',
top: '50%', top: '50%',
left: '50%', left: '50%',
@@ -26,7 +26,7 @@ const style = {
boxShadow: 24, boxShadow: 24,
padding: '20px', padding: '20px',
color: 'white', color: 'white',
}; }; */
export default function InitModal() { export default function InitModal() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
@@ -34,21 +34,21 @@ export default function InitModal() {
const handleClose = () => setOpen(false); const handleClose = () => setOpen(false);
const [chosenTemplate, setChosenTemplate] = React.useState(''); const [chosenTemplate, setChosenTemplate] = React.useState('');
const handleTemplateChange = (event) => { const handleTemplateChange = (event: SelectChangeEvent) => {
setChosenTemplate(event.target.value); setChosenTemplate(event.target.value);
}; };
const [installPackages, setInstallPackages] = React.useState(true); const [installPackages, setInstallPackages] = React.useState(true);
const handlePackagesChange = (event) => { const handlePackagesChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInstallPackages(event.target.checked); setInstallPackages(event.target.checked);
}; };
const [chosenPackageManager, setChosenPackageManager] = React.useState(''); const [chosenPackageManager, setChosenPackageManager] = React.useState('');
const handlePackageManagerChange = (event) => { const handlePackageManagerChange = (event: SelectChangeEvent<string>) => {
setChosenPackageManager(event.target.value); setChosenPackageManager(event.target.value);
}; };
const [templates, setTemplates] = React.useState([]); const [templates, setTemplates] = React.useState<Array<TemplateList>>([]);
React.useEffect(() => { React.useEffect(() => {
fetch('https://raw.githubusercontent.com/sern-handler/create-bot/main/metadata/templateChoices.json') fetch('https://raw.githubusercontent.com/sern-handler/create-bot/main/metadata/templateChoices.json')
.then((res) => res.json()) .then((res) => res.json())
@@ -71,7 +71,7 @@ export default function InitModal() {
}; };
const [projectName, setProjectName] = React.useState(''); const [projectName, setProjectName] = React.useState('');
const handleProjectNameChange = (event) => { const handleProjectNameChange = (event: any) => {
setProjectName(event.target.value); setProjectName(event.target.value);
}; };
@@ -83,7 +83,7 @@ export default function InitModal() {
}; };
}, []); }, []);
const handleFolderData = (event, paths) => { const handleFolderData = (_event: IpcRendererEvent, paths: string[]) => {
const selectedPath = paths && paths.length > 0 ? paths[0] : ''; const selectedPath = paths && paths.length > 0 ? paths[0] : '';
setSelectedPath(selectedPath); setSelectedPath(selectedPath);
}; };
@@ -169,7 +169,6 @@ export default function InitModal() {
onChange={handlePackagesChange} onChange={handlePackagesChange}
/> />
} }
fullWidth
label="Install packages while you're at it" label="Install packages while you're at it"
/> />
</FormGroup> </FormGroup>
@@ -240,3 +239,8 @@ export default function InitModal() {
</div> </div>
); );
} }
interface TemplateList {
title: string
value: string
}

View File

@@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import './index.css'; import './main.css';
import App from './App'; import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root')); const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />

View File

@@ -1,13 +0,0 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

1
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

26
tsconfig.electron.json Normal file
View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"outDir": "./dist",
/* Bundler mode */
"moduleResolution": "node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"allowSyntheticDefaultImports": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["electron"]
}

26
tsconfig.json Normal file
View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"outDir": "./dist",
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

10
tsconfig.node.json Normal file
View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

7
vite.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})

7860
yarn.lock

File diff suppressed because it is too large Load Diff