feat: add vite dev containers

This commit is contained in:
熊潇 2024-10-21 01:36:34 +08:00
parent 644539b624
commit c832c0274a
12 changed files with 590 additions and 14 deletions

1
apps/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
container

13
apps/package.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "apps",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

View File

@ -52,6 +52,7 @@
"@kevisual/router": "^0.0.2", "@kevisual/router": "^0.0.2",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"sequelize": "^6.37.4", "sequelize": "^6.37.4",
"sqlite3": "^5.1.7" "sqlite3": "^5.1.7",
"vite": "^5.4.9"
} }
} }

309
pnpm-lock.yaml generated
View File

@ -23,6 +23,9 @@ importers:
sqlite3: sqlite3:
specifier: ^5.1.7 specifier: ^5.1.7
version: 5.1.7 version: 5.1.7
vite:
specifier: ^5.4.9
version: 5.4.9(@types/node@22.5.5)
devDependencies: devDependencies:
'@kevisual/query': '@kevisual/query':
specifier: 0.0.7-alpha.1 specifier: 0.0.7-alpha.1
@ -72,6 +75,144 @@ importers:
packages: packages:
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.21.5':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.21.5':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.21.5':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.21.5':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.21.5':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.21.5':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.21.5':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.21.5':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.21.5':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.21.5':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.21.5':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.21.5':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.21.5':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.21.5':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.21.5':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.21.5':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-x64@0.21.5':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.21.5':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.21.5':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.21.5':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.21.5':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
'@gar/promisify@1.1.3': '@gar/promisify@1.1.3':
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
@ -496,6 +637,11 @@ packages:
err-code@2.0.3: err-code@2.0.3:
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
hasBin: true
estree-walker@2.0.2: estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@ -753,6 +899,11 @@ packages:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0} engines: {node: ^18.17.0 || >=20.5.0}
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
napi-build-utils@1.0.2: napi-build-utils@1.0.2:
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
@ -818,10 +969,17 @@ packages:
resolution: {integrity: sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==} resolution: {integrity: sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==}
engines: {node: '>= 0.8.x'} engines: {node: '>= 0.8.x'}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
picomatch@4.0.2: picomatch@4.0.2:
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
engines: {node: '>=12'} engines: {node: '>=12'}
postcss@8.4.47:
resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
engines: {node: ^10 || ^12 || >=14}
prebuild-install@7.1.2: prebuild-install@7.1.2:
resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -967,6 +1125,10 @@ packages:
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
sprintf-js@1.1.3: sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
@ -1060,6 +1222,37 @@ packages:
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
vite@5.4.9:
resolution: {integrity: sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
less: '*'
lightningcss: ^1.21.0
sass: '*'
sass-embedded: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
peerDependenciesMeta:
'@types/node':
optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
sass-embedded:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
which@2.0.2: which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -1107,6 +1300,75 @@ packages:
snapshots: snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
'@esbuild/android-arm64@0.21.5':
optional: true
'@esbuild/android-arm@0.21.5':
optional: true
'@esbuild/android-x64@0.21.5':
optional: true
'@esbuild/darwin-arm64@0.21.5':
optional: true
'@esbuild/darwin-x64@0.21.5':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
optional: true
'@esbuild/freebsd-x64@0.21.5':
optional: true
'@esbuild/linux-arm64@0.21.5':
optional: true
'@esbuild/linux-arm@0.21.5':
optional: true
'@esbuild/linux-ia32@0.21.5':
optional: true
'@esbuild/linux-loong64@0.21.5':
optional: true
'@esbuild/linux-mips64el@0.21.5':
optional: true
'@esbuild/linux-ppc64@0.21.5':
optional: true
'@esbuild/linux-riscv64@0.21.5':
optional: true
'@esbuild/linux-s390x@0.21.5':
optional: true
'@esbuild/linux-x64@0.21.5':
optional: true
'@esbuild/netbsd-x64@0.21.5':
optional: true
'@esbuild/openbsd-x64@0.21.5':
optional: true
'@esbuild/sunos-x64@0.21.5':
optional: true
'@esbuild/win32-arm64@0.21.5':
optional: true
'@esbuild/win32-ia32@0.21.5':
optional: true
'@esbuild/win32-x64@0.21.5':
optional: true
'@gar/promisify@1.1.3': '@gar/promisify@1.1.3':
optional: true optional: true
@ -1554,6 +1816,32 @@ snapshots:
err-code@2.0.3: err-code@2.0.3:
optional: true optional: true
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
'@esbuild/android-arm': 0.21.5
'@esbuild/android-arm64': 0.21.5
'@esbuild/android-x64': 0.21.5
'@esbuild/darwin-arm64': 0.21.5
'@esbuild/darwin-x64': 0.21.5
'@esbuild/freebsd-arm64': 0.21.5
'@esbuild/freebsd-x64': 0.21.5
'@esbuild/linux-arm': 0.21.5
'@esbuild/linux-arm64': 0.21.5
'@esbuild/linux-ia32': 0.21.5
'@esbuild/linux-loong64': 0.21.5
'@esbuild/linux-mips64el': 0.21.5
'@esbuild/linux-ppc64': 0.21.5
'@esbuild/linux-riscv64': 0.21.5
'@esbuild/linux-s390x': 0.21.5
'@esbuild/linux-x64': 0.21.5
'@esbuild/netbsd-x64': 0.21.5
'@esbuild/openbsd-x64': 0.21.5
'@esbuild/sunos-x64': 0.21.5
'@esbuild/win32-arm64': 0.21.5
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
estree-walker@2.0.2: {} estree-walker@2.0.2: {}
expand-template@2.0.3: {} expand-template@2.0.3: {}
@ -1848,6 +2136,8 @@ snapshots:
mute-stream@2.0.0: {} mute-stream@2.0.0: {}
nanoid@3.3.7: {}
napi-build-utils@1.0.2: {} napi-build-utils@1.0.2: {}
negotiator@0.6.3: negotiator@0.6.3:
@ -1920,8 +2210,16 @@ snapshots:
dependencies: dependencies:
underscore: 1.13.7 underscore: 1.13.7
picocolors@1.1.1: {}
picomatch@4.0.2: {} picomatch@4.0.2: {}
postcss@8.4.47:
dependencies:
nanoid: 3.3.7
picocolors: 1.1.1
source-map-js: 1.2.1
prebuild-install@7.1.2: prebuild-install@7.1.2:
dependencies: dependencies:
detect-libc: 2.0.3 detect-libc: 2.0.3
@ -2085,6 +2383,8 @@ snapshots:
smart-buffer: 4.2.0 smart-buffer: 4.2.0
optional: true optional: true
source-map-js@1.2.1: {}
sprintf-js@1.1.3: sprintf-js@1.1.3:
optional: true optional: true
@ -2193,6 +2493,15 @@ snapshots:
validator@13.12.0: {} validator@13.12.0: {}
vite@5.4.9(@types/node@22.5.5):
dependencies:
esbuild: 0.21.5
postcss: 8.4.47
rollup: 4.24.0
optionalDependencies:
'@types/node': 22.5.5
fsevents: 2.3.3
which@2.0.2: which@2.0.2:
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0

View File

@ -1,6 +1,6 @@
import { App } from '@kevisual/router'; import { App } from '@kevisual/router';
import fs from 'fs'; import fs from 'fs';
import { getConfig, pidFilePath, checkFileExists } from './module/get-config.ts'; import { getConfig, getPidList, pidFilePath, checkFileExists } from './module/get-config.ts';
import { sequelize } from './module/sequelize.ts'; import { sequelize } from './module/sequelize.ts';
export { sequelize }; export { sequelize };
@ -28,11 +28,21 @@ app
// 处理进程退出或中断信号,确保删除 pid 文件 // 处理进程退出或中断信号,确保删除 pid 文件
const cleanUp = () => { const cleanUp = () => {
if (checkFileExists(pidFilePath)) { const pidList = getPidList();
const pid = fs.readFileSync(pidFilePath, 'utf-8'); const findPid = pidList.find((item) => Number(item.pid) === process.pid);
if (Number(pid) === process.pid) { // if (checkFileExists(pidFilePath)) {
fs.unlinkSync(pidFilePath); // const pid = fs.readFileSync(pidFilePath, 'utf-8');
console.log('server id', process.pid, 'is exit'); // if (Number(pid) === process.pid) {
// fs.unlinkSync(pidFilePath);
// console.log('server id', process.pid, 'is exit');
// }
// }
if (findPid) {
console.log('server id', process.pid, 'is exit');
try {
fs.unlinkSync(findPid.file);
} catch (e) {
console.log('unlinkSync error', findPid);
} }
} }
process.exit(0); // 退出进程 process.exit(0); // 退出进程

View File

@ -1,24 +1,51 @@
import { program as app, Command } from '@/program.ts'; import { program as app, Command } from '@/program.ts';
import { getConfig, writeConfig } from '@/module/index.ts'; import { checkFileExists, getConfig, writeConfig } from '@/module/index.ts';
import path from 'path';
import fs from 'fs';
const command = new Command('config') const command = new Command('config')
.description('') .description('')
.option('-d, --dev <dev>', 'Specify dev') .option('-d, --dev <dev>', 'Specify dev')
.option('-l --list', 'list config') .option('-l --list', 'list config')
.option('-w --workdir <path>', 'web config')
.action(async (options) => { .action(async (options) => {
const { dev, list } = options || {}; const { dev, list, workdir } = options || {};
let config = getConfig();
let flag = false;
if (dev === 'true' || dev === 'false') { if (dev === 'true' || dev === 'false') {
flag = true;
const config = getConfig(); const config = getConfig();
if (dev === 'true') { if (dev === 'true') {
writeConfig({ ...config, dev: true }); config.dev = true;
} else { } else {
writeConfig({ ...config, dev: false }); config.dev = false;
} }
} }
if (options.workdir) {
let finalPath: string;
flag = true;
const workdir = options.workdir;
if (workdir.startsWith('/')) {
// 如果以 / 开头,处理为绝对路径
finalPath = workdir;
} else {
// 否则,处理为相对路径
finalPath = path.resolve(workdir);
}
if (!checkFileExists(finalPath)) {
console.log('路径不存在');
fs.mkdirSync(finalPath, { recursive: true });
}
config.workdir = finalPath;
}
if (list) { if (list) {
const config = getConfig(); const config = getConfig();
console.log('config', config); console.log('config', config);
} }
if (flag) {
writeConfig(config);
}
}); });
app.addCommand(command); app.addCommand(command);

View File

@ -53,7 +53,7 @@ const loginCommand = new Command('login')
} else { } else {
console.log('登录失败', res.message || ''); console.log('登录失败', res.message || '');
} }
console.log('u', username, password); console.log('welcome', username);
}); });
app.addCommand(loginCommand); app.addCommand(loginCommand);

52
src/command/router.ts Normal file
View File

@ -0,0 +1,52 @@
import { program as app, Command } from '@/program.ts';
import { getConfig, writeConfig, checkFileExists } from '@/module/index.ts';
import { createApp } from '@/app.ts';
import fs from 'fs';
import inquirer from 'inquirer';
import { query } from '../module/index.ts';
import chalk from 'chalk';
import util from 'util';
// web 开发模块
const command = new Command('router')
.description('router get')
.option('-p, --path <path>', '退出进程')
.option('-k, --key <key>', '启动进程')
.action(async (options) => {
let { path, key } = options;
// 如果没有传递参数,则通过交互式输入
if (!path || !key) {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'path',
message: 'Enter your path:',
when: () => !path, // 当 username 为空时,提示用户输入
},
{
type: 'input',
name: 'key',
message: 'Enter your key:',
when: () => !key, // 当 password 为空时,提示用户输入
},
]);
path = answers.path || path;
key = answers.key || key;
}
const res = await query.post({ path, key });
if (res?.code === 200) {
const data = res.data.map((item: any) => {
// return `id: ${item.id}, title: ${item.title}`;
return {
id: item.id,
title: item.title,
};
});
console.log(chalk.green(util.inspect(data, { colors: true, depth: 4 })));
} else {
console.log('error', res.message || '');
}
});
app.addCommand(command);

71
src/command/web.ts Normal file
View File

@ -0,0 +1,71 @@
import { program as app, Command } from '@/program.ts';
import { getConfig, writeConfig, checkFileExists, query } from '@/module/index.ts';
import fs from 'fs';
import path from 'path';
import { startContainerServer } from '@/module/run-vite.ts';
// web 开发模块
const command = new Command('web')
.description('web dev manager')
.option('-e, --exit', '退出进程')
.option('-s, --start', '启动进程')
.action(async (options) => {
const { exit, start } = options || {};
});
app.addCommand(command);
// container 开发模块
const container = new Command('container')
.description('container manager')
.option('-d, --container <id>', '下载镜像')
.option('-f, --force', '下载镜像')
.option('-u, --upload <id>', '上传镜像')
.action(async (options) => {
const { container, upload, force } = options || {};
const config = getConfig();
const workdir = config.workdir;
if (!workdir) {
console.log('请先配置工作目录');
return;
}
if (!config.token) {
console.log('请先登录');
return;
}
// 32210aa6-3d5a-4687-b769-ae4e8137ec1e
if (container) {
console.log('下载镜像', container);
const res = await query.post({ path: 'container', key: 'get', id: container });
if (res.code !== 200) {
console.log('error', res.message || '');
return;
}
await startContainerServer(res.data, force);
}
if (upload) {
console.log('上传镜像', upload);
const directory = path.join(workdir, 'container', upload);
if (!checkFileExists(directory)) {
console.log('文件夹不存在');
return;
}
const code = fs.readFileSync(path.join(directory, 'index.js'), 'utf-8');
if (!code) {
console.log('文件不能为空');
return;
}
const res = await query.post({
path: 'container', //
key: 'update',
data: { id: upload, code },
});
if (res.code !== 200) {
console.log('error', res.message || '');
console.log(res);
return;
}
console.log('上传成功');
}
});
app.addCommand(container);

View File

@ -6,5 +6,7 @@ import './command/me.ts';
import './command/deploy.ts'; import './command/deploy.ts';
import './command/serve.ts'; import './command/serve.ts';
import './command/config.ts'; import './command/config.ts';
import './command/web.ts';
import './command/router.ts';
program.parse(process.argv); program.parse(process.argv);

View File

@ -2,12 +2,23 @@ import os from 'os';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
const envisionPath = path.join(os.homedir(), '.config', 'envision'); export const envisionPath = path.join(os.homedir(), '.config', 'envision');
const configPath = path.join(os.homedir(), '.config', 'envision', 'config.json'); const configPath = path.join(os.homedir(), '.config', 'envision', 'config.json');
export const pidFilePath = path.join(envisionPath, 'app.pid'); export const pidFilePath = path.join(envisionPath, 'app.pid');
export const dbPath = path.join(envisionPath, 'db.sqlite'); export const dbPath = path.join(envisionPath, 'db.sqlite');
const envisionPidDir = path.join(envisionPath);
export const getPidList = () => {
const files = fs.readdirSync(envisionPidDir);
const pidFiles = files.filter((file) => file.endsWith('.pid'));
return pidFiles.map((file) => {
const pid = fs.readFileSync(path.join(envisionPidDir, file), 'utf-8');
return { pid, file: path.join(envisionPidDir, file) };
});
};
export const writeVitePid = (pid: number) => {
fs.writeFileSync(path.join(envisionPath, `vite-${pid}.pid`), pid.toString());
};
export const checkFileExists = (filePath: string) => { export const checkFileExists = (filePath: string) => {
try { try {
fs.accessSync(filePath, fs.constants.F_OK); fs.accessSync(filePath, fs.constants.F_OK);

79
src/module/run-vite.ts Normal file
View File

@ -0,0 +1,79 @@
import fs from 'fs';
import path from 'path';
import { createServer } from 'vite';
import { checkFileExists, getConfig, writeVitePid } from './index.ts';
export const runVite = async (entry: string) => {
const entryDir = path.dirname(entry);
const server = await createServer({
// Vite 配置选项
root: entryDir,
server: {
port: 7101, // 可以根据需要设置端口
host: '0.0.0.0',
},
});
await server.listen();
console.log('Vite server is running at:', server.config.server.port);
};
const template = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="https://envision.xiongxiao.me/resources/root/avatar.png"/>
<title>Container Develop</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
font-size: 16px;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module">
import { ContainerOne } from 'https://kevisual.xiongxiao.me/system/lib/container.js'
import { render, unmount } from './index.js'
const container = new ContainerOne({
root: '#root',
});
container.renderOne({
code: {render, unmount}
});
</script>
</body>
</html>`;
export const startContainerServer = async (container: any, force: boolean) => {
const { id, code } = container;
const config = getConfig();
const workdir = config.workdir;
if (!workdir) {
console.log('请先配置工作目录');
return;
}
if (!config.token) {
console.log('请先登录');
return;
}
const directory = path.join(workdir, 'container', id);
if (!checkFileExists(directory) || force) {
fs.mkdirSync(directory, { recursive: true });
fs.writeFileSync(path.join(directory, 'index.js'), code);
fs.writeFileSync(path.join(directory, 'index.html'), template);
} else {
console.log('文件夹已存在');
}
await runVite(path.join(directory, 'index.html'));
console.log('container server is running at:', 'http://localhost:7101');
console.log('pid:', process.pid);
writeVitePid(process.pid);
};