refactor: move to vite + ts + swc (#2)

This commit is contained in:
2023-07-17 14:51:35 +02:00
committed by GitHub
23 changed files with 627 additions and 7639 deletions

30
.circleci/config.yml Normal file
View File

@@ -0,0 +1,30 @@
version: 2.1
jobs:
build_windows:
docker:
- image: electronuserland/builder:wine
steps:
- checkout
- run: yarn
- run: yarn electron-ci
- run: yarn build-electron-win
build_linux:
docker:
- image: node:lts
steps:
- checkout
- run: yarn
- run: yarn electron-ci
- run: yarn build-electron-linux
workflows:
build:
jobs:
- hold:
type: approval
- build_windows:
requires:
- hold
- build_linux:
requires:
- hold

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',
},
}

View File

@@ -1,31 +0,0 @@
name: Build/release
on: push
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 18
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1
with:
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.github_token }}
# If the commit is tagged with a version (e.g. "v1.0.0"),
# release the app after building
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

43
.gitignore vendored
View File

@@ -1,25 +1,26 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
# Logs
logs
*.log
npm-debug.log*
yarn-debug.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?
build/

View File

@@ -1,7 +1,10 @@
# init-gui
sern init but gui
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/sern-handler/gui)
# why do u use electron!?!?! switch to tauri!! im mad uwu (⌣̀_⌣́)
[answer](https://memz.willysuna.dev/stfu.mp4)
@@ -17,4 +20,4 @@ public/electron.js
# CI builds?
Builds will be set up using a jetbrains teamcity instance when migration to new server is done. ETA still not known. Packaged binaries are built on my host computer for now. If you're skeptical, build the app for yourself.
Builds will be set up using a jetbrains teamcity instance when migration to new server is done. ETA still not known. Packaged binaries are built on my host computer for now. If you're skeptical, build the app for yourself.

View File

@@ -1,9 +1,8 @@
const path = require('path');
const { app, BrowserWindow, dialog, ipcMain } = require('electron');
const isDev = require('electron-is-dev');
const fs = require('fs');
const colorette = require('colorette')
const { exec } = require('node:child_process')
import * as path from 'node:path'
import { app, BrowserWindow, dialog, ipcMain } from 'electron';
import * as isDev from 'electron-is-dev';
import * as colorette from 'colorette';
import { exec } from 'node:child_process';
function createWindow() {
const mainWindow = new BrowserWindow({
@@ -19,7 +18,7 @@ function createWindow() {
title: 'sern',
});
if (isDev) {
mainWindow.loadURL('http://localhost:3000');
mainWindow.loadURL('http://localhost:5173');
} else {
mainWindow.loadFile(path.join(__dirname, '../build/index.html'));
}
@@ -32,7 +31,7 @@ function createWindow() {
e.preventDefault();
});
ipcMain.on('openFolder', (event, arg) => {
ipcMain.on('openFolder', (event, _arg) => {
dialog
.showOpenDialog({
properties: ['openDirectory'],
@@ -52,7 +51,7 @@ function createWindow() {
console.log(data);
console.log(`${colorette.cyan('🛈')} Current OS: ${currentOS}`)
let packageManagerCommand
let packageManagerCommand: string
switch (data.chosenPackageManager) {
case 'npm':
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=npm`
@@ -67,7 +66,7 @@ function createWindow() {
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}"`
break;
}
let commandToRun
let commandToRun: string
switch (currentOS) {
case 'linux':
commandToRun = `cd ${data.selectedPath};${packageManagerCommand}`
@@ -87,11 +86,11 @@ function createWindow() {
console.log(`${colorette.cyan('🛈')} About to execute command: ${commandToRun}`)
const cmd = exec(commandToRun)
cmd.stdout.on('data', (data) => {
cmd.stdout!.on('data', (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}`);
});
@@ -116,7 +115,7 @@ app.on('activate', () => {
}
});
let currentOS
let currentOS: string
switch (process.platform) {
case 'linux':
currentOS = 'linux'
@@ -133,4 +132,21 @@ switch (process.platform) {
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,22 @@
{
"name": "sern-gui",
"productName": "sern-gui",
"version": "0.1.0-alpha",
"main": "./electron/index.js",
"private": true,
"version": "0.1.0-alpha",
"main": "./dist/index.js",
"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 .\"",
"electron-ci": "tsc --outDir \"./dist\" ./electron/index.ts",
"build-electron": "yarn build && electron-builder --linux --windows",
"build-electron-linux": "yarn build && electron-builder --linux",
"build-electron-win": "yarn build && electron-builder --windows",
"build-electron-mac": "yarn build && electron-builder --mac"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
@@ -17,24 +29,30 @@
"colorette": "^2.0.20",
"electron-is-dev": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1"
"react-dom": "^18.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "concurrently -k \"BROWSER=none yarn start\" \"yarn:electron\"",
"electron": "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"
"devDependencies": {
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@vitejs/plugin-react-swc": "^3.3.2",
"concurrently": "^8.2.0",
"electron": "^25.2.0",
"electron-builder": "^24.4.0",
"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": {
"extends": null,
"files": [
"build/**/*"
"./build/**/*",
"./dist/index.js"
],
"directories": {
"buildResources": "assets"
@@ -43,30 +61,5 @@
"icon": "./icons/icon.ico",
"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';
src: local('Classic Console Neue'),
url('https://fonts.srizan.dev/clacon2.ttf') format('truetype');
}
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
} */
.titleHeader {
color: #4af626;

View File

@@ -1,4 +1,3 @@
import * as React from 'react';
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
@@ -6,7 +5,7 @@ import Typography from '@mui/material/Typography';
import InitModal from './InitModal.js';
import PluginsModal from './PluginsModal.js';
function cardChooser(command) {
function cardChooser(command: string) {
switch (command) {
case 'init':
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 (
<Card sx={{ width: window.innerWidth / 2 }} variant='outlined'>
<CardContent>
@@ -34,4 +34,9 @@ export default function FunctionalityCard({ command, description }) {
</CardActions>
</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 MenuItem from '@mui/material/MenuItem';
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 Checkbox from '@mui/material/Checkbox';
import FormGroup from '@mui/material/FormGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import type { IpcRendererEvent } from 'electron'
import './InitModal.css';
const { ipcRenderer } = window.require('electron');
// eslint-disable-next-line no-unused-vars
const style = {
/* const style = {
position: 'absolute',
top: '50%',
left: '50%',
@@ -26,7 +26,7 @@ const style = {
boxShadow: 24,
padding: '20px',
color: 'white',
};
}; */
export default function InitModal() {
const [open, setOpen] = React.useState(false);
@@ -34,21 +34,21 @@ export default function InitModal() {
const handleClose = () => setOpen(false);
const [chosenTemplate, setChosenTemplate] = React.useState('');
const handleTemplateChange = (event) => {
const handleTemplateChange = (event: SelectChangeEvent) => {
setChosenTemplate(event.target.value);
};
const [installPackages, setInstallPackages] = React.useState(true);
const handlePackagesChange = (event) => {
const handlePackagesChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInstallPackages(event.target.checked);
};
const [chosenPackageManager, setChosenPackageManager] = React.useState('');
const handlePackageManagerChange = (event) => {
const handlePackageManagerChange = (event: SelectChangeEvent<string>) => {
setChosenPackageManager(event.target.value);
};
const [templates, setTemplates] = React.useState([]);
const [templates, setTemplates] = React.useState<Array<TemplateList>>([]);
React.useEffect(() => {
fetch('https://raw.githubusercontent.com/sern-handler/create-bot/main/metadata/templateChoices.json')
.then((res) => res.json())
@@ -71,7 +71,7 @@ export default function InitModal() {
};
const [projectName, setProjectName] = React.useState('');
const handleProjectNameChange = (event) => {
const handleProjectNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
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] : '';
setSelectedPath(selectedPath);
};
@@ -169,7 +169,6 @@ export default function InitModal() {
onChange={handlePackagesChange}
/>
}
fullWidth
label="Install packages while you're at it"
/>
</FormGroup>
@@ -240,3 +239,8 @@ export default function InitModal() {
</div>
);
}
interface TemplateList {
title: string
value: string
}

View File

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

11
vite.config.ts Normal file
View File

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

7860
yarn.lock

File diff suppressed because it is too large Load Diff