Initial commit

This commit is contained in:
2024-03-31 05:53:25 +03:00
commit c689d8783f
34 changed files with 5408 additions and 0 deletions

15
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,15 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @ivuorinen

4
.github/renovate.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>ivuorinen/.github:renovate-config"]
}

31
.github/workflows/compress-images.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
---
# Compress images on demand (workflow_dispatch), and at 11pm every Sunday (schedule).
# Open a Pull Request if any images can be compressed.
name: Compress Images on Demand
on:
workflow_dispatch:
schedule:
- cron: "00 23 * * 0"
jobs:
CompressOnDemandOrSchedule:
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@main
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
compressOnly: true
- name: Create New Pull Request If Needed
if: steps.calibre.outputs.markdown != ''
uses: peter-evans/create-pull-request@v5
with:
title: Compressed Images Nightly
branch-suffix: timestamp
commit-message: Compressed Images
body: ${{ steps.calibre.outputs.markdown }}

26
.github/workflows/dependency-review.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
---
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request,
# surfacing known-vulnerable versions of the packages declared or updated in the PR.
# Once installed, if the workflow run is marked as required, PRs introducing
# known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: "Dependency Review"
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: actions/checkout@v3
- name: "Dependency Review"
uses: actions/dependency-review-action@v3

View File

@@ -0,0 +1,30 @@
---
name: Compress Images
on:
pull_request:
# Run Image Actions when JPG, JPEG, PNG or WebP files are added or changed.
# See https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#onpushpull_requestpaths for reference.
paths:
- "**.jpg"
- "**.jpeg"
- "**.png"
- "**.webp"
jobs:
CompressInPR:
# Only run on Pull Requests within the same repository, and not from forks.
if: github.event.pull_request.head.repo.full_name == github.repository
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Compress Images
uses: calibreapp/image-actions@main
with:
# The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is
# currently running the action. By default, the action cant update Pull Requests initiated from
# forked repositories.
# See https://docs.github.com/en/actions/reference/authentication-in-a-workflow and
# https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions
githubToken: ${{ secrets.GITHUB_TOKEN }}

68
.github/workflows/pr-lint.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
---
#################################
#################################
## Super Linter GitHub Actions ##
#################################
#################################
name: Lint Code Base
#
# Documentation:
# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions
#
env:
MAIN_BRANCH: main
#############################
# Start the job on all push #
#############################
on:
push:
branches-ignore: [master, main]
# Remove the line above to run when pushing to master
pull_request:
branches: [master, main]
###############
# Set the Job #
###############
jobs:
build:
# Name the Job
name: Lint Code Base
# Set the agent to run on
runs-on: ubuntu-latest
############################################
# Grant status permission for MULTI_STATUS #
############################################
permissions:
contents: read
packages: read
statuses: write
##################
# Load all steps #
##################
steps:
##########################
# Checkout the code base #
##########################
- name: Checkout Code
uses: actions/checkout@v3
with:
# Full git history is needed to get a proper
# list of changed files within `super-linter`
fetch-depth: 0
################################
# Run Linter against code base #
################################
- name: Lint Code Base
uses: github/super-linter@v5
env:
VALIDATE_ALL_CODEBASE: false
# Change to 'master' if your main branch differs
DEFAULT_BRANCH: ${{ env.MAIN_BRANCH }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

16
.github/workflows/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
---
name: Release Drafter
# yamllint disable-line rule:truthy
on:
workflow_call:
jobs:
update_release_draft:
name: ✏️ Draft release
runs-on: ubuntu-latest
steps:
- name: 🚀 Run Release Drafter
uses: release-drafter/release-drafter@v5.24.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

47
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
---
name: Stale
# yamllint disable-line rule:truthy
on:
schedule:
- cron: "0 8 * * *"
workflow_call:
workflow_dispatch:
permissions:
contents: write # only for delete-branch option
issues: write
pull-requests: write
jobs:
stale:
name: 🧹 Clean up stale issues and PRs
runs-on: ubuntu-latest
steps:
- name: 🚀 Run stale
uses: actions/stale@v8.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30
days-before-close: 7
remove-stale-when-updated: true
stale-issue-label: "stale"
exempt-issue-labels: "no-stale,help-wanted"
stale-issue-message: >
There hasn't been any activity on this issue recently, so we
clean up some of the older and inactive issues.
Please make sure to update to the latest version and
check if that solves the issue. Let us know if that works for you
by leaving a comment 👍
This issue has now been marked as stale and will be closed if no
further activity occurs. Thanks!
stale-pr-label: "stale"
exempt-pr-labels: "no-stale"
stale-pr-message: >
There hasn't been any activity on this pull request recently. This
pull request has been automatically marked as stale because of that
and will be closed if no further activity occurs within 7 days.
Thank you for your contributions.

30
.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

8
.prettierrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

7
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"recommendations": [
"Vue.volar",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Ismo Vuorinen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

23
README.md Normal file
View File

@@ -0,0 +1,23 @@
# sysvinit service generator
This Vue 3 app generates templates for sysvinit services.
## Usage
1. Fill in the form with the desired values.
2. Copy the generated template.
3. Paste it into a new file in `/etc/init.d/`.
4. Make the file executable with `chmod +x /etc/init.d/<filename>`.
5. Register the service with `update-rc.d <filename> defaults` on Ubuntu.
6. Start the service with `service <filename> start`.
7. ???
8. Profit!
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- [Vue.js](https://vuejs.org/)
- [yunginnanet/sysvinit-service-generator](https://github.com/yunginnanet/sysvinit-service-generator/)

1
env.d.ts vendored Normal file
View File

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

17
index.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="site.webmanifest">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sysvinit service generator</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

4582
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

35
package.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "sysvinit-service-generator",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"vue": "^3.4.21"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node20": "^20.1.2",
"@types/node": "^20.11.28",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.5.1",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"npm-run-all2": "^6.1.2",
"prettier": "^3.0.3",
"typescript": "~5.4.0",
"vite": "^5.1.6",
"vite-plugin-vue-devtools": "^7.0.18",
"vue-tsc": "^2.0.6"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

6
public/favicon.txt Normal file
View File

@@ -0,0 +1,6 @@
This favicon was generated using the following font:
- Font Title: Inter
- Font Author: Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
- Font Source: https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZhrib2Bg-4.ttf
- Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL))

1
public/site.webmanifest Normal file
View File

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

187
src/App.vue Normal file
View File

@@ -0,0 +1,187 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
let service = defineModel('service', { default: 'my-service' })
let description = defineModel('description', { default: 'This command does something' })
let username = defineModel('username', { default: 'root' })
let command = defineModel('command', { default: '/usr/local/bin/command' })
let servicePath = ref('/etc/init.d/' + service.value )
let logRotatePath = ref('/etc/logrotate.d/' + service.value)
let shellCommands = ref(`sudo chmod +x ${servicePath.value} && sudo update-rc.d ${service.value} defaults`)
let serviceTemplateString = `#!/usr/bin/env sh
### BEGIN INIT INFO
# Provides: <NAME>
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: <DESCRIPTION>
### END INIT INFO
SCRIPT="<COMMAND>"
RUNAS=<USERNAME>
PIDFILE=/var/run/<NAME>.pid
LOGFILE=/var/log/<NAME>.log
start() {
if [ -f $PIDFILE ] && [ -s $PIDFILE ] && kill -0 $(cat $PIDFILE); then
echo "Service already running" >&2
return 1
fi
echo 'Starting service...' >&2
local CMD="$SCRIPT &> \\"$LOGFILE\\" & echo \\$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
# Try with this command instead if above does not work
# su -s /bin/sh $RUNAS -c "$CMD" > "$PIDFILE"
sleep 2
PID=$(cat $PIDFILE)
if pgrep -u $RUNAS -f $NAME > /dev/null
then
echo "$NAME is now running, the PID is $PID"
else
echo ''
echo "Error! Could not start $NAME!"
fi
}
stop() {
if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
echo 'Service not running' >&2
return 1
fi
echo 'Stopping service...' >&2
kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
echo 'Service stopped' >&2
}
uninstall() {
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
local SURE
read SURE
if [ "$SURE" = "yes" ]; then
stop
rm -f "$PIDFILE"
echo "Notice: log file was not removed: $LOGFILE" >&2
update-rc.d -f $NAME remove
rm -fv "$0"
else
echo "Abort!"
fi
}
status() {
printf "%-50s" "Checking <NAME>..."
if [ -f $PIDFILE ] && [ -s $PIDFILE ]; then
PID=$(cat $PIDFILE)
if [ -z "$(ps axf | grep \${PID} | grep -v grep)" ]; then
printf "%s\\n" "The process appears to be dead but pidfile still exists"
else
echo "Running, the PID is $PID"
fi
else
printf "%s\\n" "Service not running"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
uninstall)
uninstall
;;
restart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|status|restart|uninstall}"
esac
`
let logRotateString = `/var/log/<NAME>.log {
rotate 4
weekly
missingok
notifempty
compress
delaycompress
}`
let serviceTemplate = serviceTemplateString
.replace(/<NAME>/g, service.value)
.replace(/<DESCRIPTION>/g, description.value)
.replace(/<USERNAME>/g, username.value)
.replace(/<COMMAND>/g, command.value)
let logRotate = logRotateString.replace(/<NAME>/g, service.value)
watch([service, description, username, command], ([newService, newDescription, newUsername, newCommand]) => {
serviceTemplate = serviceTemplateString
.replace(/<NAME>/g, newService)
.replace(/<DESCRIPTION>/g, newDescription)
.replace(/<USERNAME>/g, newUsername)
.replace(/<COMMAND>/g, newCommand)
servicePath.value = '/etc/init.d/' + newService
logRotate = logRotateString.replace(/<NAME>/g, newService)
logRotatePath.value = '/etc/logrotate.d/' + newService
shellCommands.value = `sudo chmod +x ${servicePath.value} && sudo update-rc.d ${newService} defaults`
})
</script>
<template>
<header>
<h1 class="green">sysvinit service generator</h1>
<label>
Service name:
<input type="text" minlength="1" v-model="service" />
</label>
<label>
Description:
<input type="text" minlength="1" v-model="description" />
</label>
<label>
Run as user:
<input type="text" minlength="1" v-model="username" />
</label>
<label>
Command:
<input type="text" minlength="1" v-model="command" />
</label>
</header>
<main>
<h3>Generated service script:</h3>
<div>Path: <code>{{ servicePath }}</code></div>
<textarea style="height: 400px" v-text="serviceTemplate"></textarea>
<details>
<summary>Logrotate</summary>
<div>Path: <code>{{ logRotatePath }}</code></div>
<textarea class="just-right noresize" v-text="logRotate"></textarea>
</details>
<details>
<summary>Shell commands to run</summary>
<textarea class="just-right noresize" v-text="shellCommands"></textarea>
</details>
</main>
<footer>
<p>Created by <a href="https://github.com/ivuorinen">@ivuorinen</a> from Tampere, Finland</p>
</footer>
</template>

82
src/assets/base.css Normal file
View File

@@ -0,0 +1,82 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
/* semantic color variables for this project */
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family: Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

102
src/assets/main.css Normal file
View File

@@ -0,0 +1,102 @@
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
}
header {
line-height: 1.2;
}
label {
display: block;
margin-bottom: 1rem;
input {
display: block;
margin-top: 1rem;
padding: 0.4rem;
font-size: 1rem;
border: 1px solid var(--color-border);
border-radius: 4px;
}
}
h1 {
font-weight: 500;
font-size: 2.6rem;
margin-bottom: 2rem;
}
h3 {
font-size: 1.2rem;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 2fr;
padding: 0 2rem;
}
footer {
border-top: 1px solid var(--color-border);
padding-top: 1rem;
grid-column: 1 / -1;
}
}
textarea {
width: 100%;
min-width: 100%;
max-width: fit-content;
padding: 1rem;
margin: 1rem 0;
border: 1px solid hsla(160, 100%, 37%, 1);
border-radius: 5px;
background: #222222;
color: #f8f8f8;
font-family: monospace;
&.just-right {
height: fit-content;
min-height: fit-content;
max-height: fit-content;
}
&.noresize {
resize: none;
}
}
summary {
cursor: pointer;
}
footer {
margin-top: 2rem;
text-align: center;
}

6
src/main.ts Normal file
View File

@@ -0,0 +1,6 @@
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

14
tsconfig.app.json Normal file
View File

@@ -0,0 +1,14 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

11
tsconfig.json Normal file
View File

@@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

19
tsconfig.node.json Normal file
View File

@@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node20/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

18
vite.config.ts Normal file
View File

@@ -0,0 +1,18 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueDevTools from 'vite-plugin-vue-devtools'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})