birc-generator 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bircrc.example.json +14 -0
- package/AGENTS.md +20 -0
- package/PROJECT.md +83 -0
- package/README.md +300 -0
- package/bin/birc.js +645 -0
- package/bin/cli-util.js +428 -0
- package/bin/home-install.js +346 -0
- package/bin/update-check.js +153 -0
- package/implement.md +76 -0
- package/install.ps1 +156 -0
- package/install.sh +201 -0
- package/package.json +68 -0
- package/plopfile.js +1358 -0
- package/project-docs/AGENTS.md.hbs +12 -0
- package/project-docs/PROJECT.md.hbs +128 -0
- package/project-docs/implement.hbs +54 -0
- package/project-docs/test.hbs +31 -0
- package/scripts/install-bin.sh +72 -0
- package/scripts/update.sh +11 -0
- package/templates/aop/OperationLog.hbs +18 -0
- package/templates/aop/OperationLogAspect.hbs +95 -0
- package/templates/aop/build-gradle-dep.hbs +1 -0
- package/templates/base/Application.hbs +11 -0
- package/templates/base/ApplicationTests.java.hbs +11 -0
- package/templates/base/BaseService.hbs +15 -0
- package/templates/base/BaseServiceImpl.hbs +53 -0
- package/templates/base/EntityMapper.hbs +12 -0
- package/templates/base/README.md.hbs +56 -0
- package/templates/base/Result.hbs +48 -0
- package/templates/base/application-test.yml.hbs +27 -0
- package/templates/base/application.yml.hbs +18 -0
- package/templates/base/bircrc.hbs +14 -0
- package/templates/base/build.gradle.hbs +33 -0
- package/templates/base/gitignore.hbs +15 -0
- package/templates/client/ExternalApiClient.hbs +28 -0
- package/templates/client/ExternalApiClientConfig.hbs +26 -0
- package/templates/client/ExternalApiProperties.hbs +30 -0
- package/templates/client/application-yml-block.hbs +7 -0
- package/templates/controller.hbs +55 -0
- package/templates/dao.hbs +11 -0
- package/templates/docker/Dockerfile.hbs +29 -0
- package/templates/docker/docker-compose.prod.yml.hbs +65 -0
- package/templates/docker/docker-compose.yml.hbs +52 -0
- package/templates/docker/dockerignore.hbs +6 -0
- package/templates/docker/env.example.hbs +24 -0
- package/templates/dto-request.hbs +19 -0
- package/templates/dto-response.hbs +13 -0
- package/templates/email/EmailAsyncConfig.hbs +28 -0
- package/templates/email/EmailService.hbs +26 -0
- package/templates/email/EmailServiceImpl.hbs +49 -0
- package/templates/email/application-yml-block.hbs +19 -0
- package/templates/email/build-gradle-dep.hbs +2 -0
- package/templates/email/sample-template.hbs +16 -0
- package/templates/entity.hbs +46 -0
- package/templates/exception/ExceptionHandleController.hbs +16 -0
- package/templates/exception/NotFoundException.hbs +28 -0
- package/templates/exception/ProjectException.hbs +20 -0
- package/templates/exception.hbs +30 -0
- package/templates/file-upload/EmptyFileException.hbs +25 -0
- package/templates/file-upload/FileExtensionIllegalException.hbs +21 -0
- package/templates/file-upload/FileExtensionUtils.hbs +20 -0
- package/templates/file-upload/FileStorageProperties.hbs +37 -0
- package/templates/file-upload/FileStorageService.hbs +15 -0
- package/templates/file-upload/FileStorageServiceImpl.hbs +78 -0
- package/templates/file-upload/FileTooLargeException.hbs +21 -0
- package/templates/file-upload/FileUploadController.hbs +57 -0
- package/templates/file-upload/FileUtils.hbs +39 -0
- package/templates/file-upload/InvalidStoredFileException.hbs +21 -0
- package/templates/file-upload/application-yml-block.hbs +12 -0
- package/templates/gitlab-ci/gitlab-ci.hbs +158 -0
- package/templates/gradle-wrapper/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/templates/gradle-wrapper/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/templates/gradle-wrapper/gradlew +248 -0
- package/templates/gradle-wrapper/gradlew.bat +93 -0
- package/templates/log4j2/build-gradle-dep.hbs +6 -0
- package/templates/log4j2/log4j2-spring.xml.hbs +34 -0
- package/templates/mapper-gradle-dep.hbs +3 -0
- package/templates/mapper.hbs +11 -0
- package/templates/migration/add-column.hbs +4 -0
- package/templates/migration/create-table.hbs +9 -0
- package/templates/migration/custom.hbs +2 -0
- package/templates/migration/remove-column.hbs +4 -0
- package/templates/migration/seed.hbs +7 -0
- package/templates/multi-module/build.gradle.hbs +86 -0
- package/templates/multi-module/config/ApplicationConfig.java.hbs +33 -0
- package/templates/multi-module/config/Config.java.hbs +19 -0
- package/templates/multi-module/config/SecurityConfig.java.hbs +48 -0
- package/templates/multi-module/config/build.gradle.hbs +10 -0
- package/templates/multi-module/database-config/BaseDAO.java.hbs +31 -0
- package/templates/multi-module/database-config/BaseViewDAO.java.hbs +48 -0
- package/templates/multi-module/database-config/Config.java.hbs +14 -0
- package/templates/multi-module/database-config/JpaConfig.java.hbs +9 -0
- package/templates/multi-module/database-config/build.gradle.hbs +17 -0
- package/templates/multi-module/settings.gradle.hbs +9 -0
- package/templates/oauth/OAuth2LoginSuccessHandler.hbs +31 -0
- package/templates/oauth/application-yml-block.hbs +11 -0
- package/templates/oauth/build-gradle-dep.hbs +1 -0
- package/templates/openapi/OpenApiConfig.hbs +23 -0
- package/templates/openapi/build-gradle-dep.hbs +1 -0
- package/templates/pagination/GenericSpecification.hbs +76 -0
- package/templates/pagination/PageInfo.hbs +20 -0
- package/templates/pagination/PageRequest.hbs +27 -0
- package/templates/pagination/PageResponse.hbs +24 -0
- package/templates/pagination/Pager.hbs +37 -0
- package/templates/pagination/SearchCriteria.hbs +26 -0
- package/templates/pagination/SpecificationSupport.hbs +34 -0
- package/templates/permission/PermissionAspect.hbs +41 -0
- package/templates/permission/RequirePermission.hbs +18 -0
- package/templates/permission/build-gradle-dep.hbs +2 -0
- package/templates/scheduling/SampleSchedule.hbs +22 -0
- package/templates/scheduling/SchedulingConfig.hbs +13 -0
- package/templates/scheduling/application-yml-block.hbs +5 -0
- package/templates/sentry/SentryConfig.hbs +74 -0
- package/templates/sentry/application-yml-block.hbs +15 -0
- package/templates/sentry/build-gradle-dep.hbs +1 -0
- package/templates/service.hbs +9 -0
- package/templates/serviceImpl.hbs +23 -0
- package/templates/spotless/build-gradle-allprojects.hbs +16 -0
- package/templates/spotless/build-gradle-plugin.hbs +1 -0
- package/templates/spotless/spotless_formatter.xml +83 -0
- package/templates/sso/SsoAutoConfiguration.hbs +17 -0
- package/templates/sso/SsoProperties.hbs +27 -0
- package/templates/sso/application-yml-block.hbs +7 -0
- package/templates/valid-group/ValidGroup.hbs +20 -0
- package/test.md +56 -0
- package/uninstall.ps1 +60 -0
- package/uninstall.sh +76 -0
- package/versions.js +10 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# 用法:
|
|
2
|
+
# irm https://gitlab.ntubimdbirc.tw/lucashsu95/birc-generator/-/raw/main/install.ps1 | iex
|
|
3
|
+
# 或下載後執行: powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1
|
|
4
|
+
# 需要 Node.js 18+ 與 npm。程式會放到 $HOME\.birc-generator,跟 curl | bash 同一處。
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = 'Stop'
|
|
7
|
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
8
|
+
|
|
9
|
+
function Write-Info([string]$Message) {
|
|
10
|
+
Write-Host "[INFO] $Message" -ForegroundColor Green
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function Write-Warn([string]$Message) {
|
|
14
|
+
Write-Host "[WARN] $Message" -ForegroundColor Yellow
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function Write-Err([string]$Message) {
|
|
18
|
+
Write-Host "[ERROR] $Message" -ForegroundColor Red
|
|
19
|
+
exit 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
$BaseUrl = if ($env:BIRC_BASE_URL) { $env:BIRC_BASE_URL.TrimEnd('/') } else { 'https://gitlab.ntubimdbirc.tw/lucashsu95/birc-generator' }
|
|
23
|
+
$InstallDir = Join-Path $HOME '.birc-generator'
|
|
24
|
+
|
|
25
|
+
function Test-NodeAndNpm {
|
|
26
|
+
$node = Get-Command node -ErrorAction SilentlyContinue
|
|
27
|
+
if (-not $node) {
|
|
28
|
+
Write-Err "找不到 Node.js。請先安裝 Node.js 18+:https://nodejs.org/"
|
|
29
|
+
}
|
|
30
|
+
$versionText = (& node -v).Trim()
|
|
31
|
+
if ($versionText -notmatch '^v(\d+)') {
|
|
32
|
+
Write-Err "無法判讀 Node.js 版本($versionText)。"
|
|
33
|
+
}
|
|
34
|
+
$major = [int]$Matches[1]
|
|
35
|
+
if ($major -lt 18) {
|
|
36
|
+
Write-Err "Node.js 版本過低($versionText)。需要 18+ 版本。"
|
|
37
|
+
}
|
|
38
|
+
Write-Info "Node.js 版本: $($versionText.TrimStart('v'))"
|
|
39
|
+
|
|
40
|
+
$npm = Get-Command npm -ErrorAction SilentlyContinue
|
|
41
|
+
if (-not $npm) {
|
|
42
|
+
Write-Err "找不到 npm。請先安裝 npm。"
|
|
43
|
+
}
|
|
44
|
+
Write-Info "npm 版本: $((& npm -v).Trim())"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Show-PkgInfo([string]$Dir, [string]$Label) {
|
|
48
|
+
$pkg = Join-Path $Dir 'package.json'
|
|
49
|
+
if (-not (Test-Path $pkg)) {
|
|
50
|
+
Write-Warn "${Label}:找不到 package.json"
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
$meta = & node -e "const p=require(process.argv[1]); const author=typeof p.author==='string'?p.author:(p.author&&p.author.name?p.author.name:''); process.stdout.write([p.version||'?',author,p.bircUpdatedAt||''].join('\n'));" $pkg
|
|
54
|
+
$parts = @($meta -split "`n")
|
|
55
|
+
Write-Info "$Label 版本 $($parts[0])"
|
|
56
|
+
if ($parts.Count -gt 1 -and $parts[1]) { Write-Info "$Label 作者 $($parts[1])" }
|
|
57
|
+
if ($parts.Count -gt 2 -and $parts[2]) { Write-Info "$Label 更新 $($parts[2])" }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function Ask-Update {
|
|
61
|
+
if ($env:BIRC_AUTO_UPDATE -eq '1') {
|
|
62
|
+
Write-Info 'BIRC_AUTO_UPDATE=1,自動更新'
|
|
63
|
+
return $true
|
|
64
|
+
}
|
|
65
|
+
if (-not [Environment]::UserInteractive) {
|
|
66
|
+
Write-Info '非互動安裝,自動更新'
|
|
67
|
+
return $true
|
|
68
|
+
}
|
|
69
|
+
$reply = Read-Host '是否要更新到最新版?(Y/n)'
|
|
70
|
+
return [string]::IsNullOrWhiteSpace($reply) -or $reply -match '^[Yy]'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function Install-FromArchive {
|
|
74
|
+
if (Test-Path $InstallDir) {
|
|
75
|
+
Write-Warn "安裝目錄已存在: $InstallDir"
|
|
76
|
+
Show-PkgInfo $InstallDir '目前已安裝'
|
|
77
|
+
if (-not (Ask-Update)) {
|
|
78
|
+
Write-Info '跳過下載,沿用現有檔案'
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
Write-Info '更新中...'
|
|
82
|
+
Remove-Item -Recurse -Force $InstallDir
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
$zipUrl = "$BaseUrl/-/archive/main/birc-generator-main.zip"
|
|
86
|
+
$staging = Join-Path $env:TEMP ("birc-install-" + [guid]::NewGuid().ToString('N'))
|
|
87
|
+
New-Item -ItemType Directory -Path $staging | Out-Null
|
|
88
|
+
$zip = Join-Path $staging 'birc-generator-main.zip'
|
|
89
|
+
$extract = Join-Path $staging 'extract'
|
|
90
|
+
try {
|
|
91
|
+
Write-Info '下載專案...'
|
|
92
|
+
Invoke-WebRequest -Uri $zipUrl -OutFile $zip -UseBasicParsing
|
|
93
|
+
Expand-Archive -Path $zip -DestinationPath $extract
|
|
94
|
+
$inner = Get-ChildItem -Path $extract -Directory | Select-Object -First 1
|
|
95
|
+
if (-not $inner) {
|
|
96
|
+
Write-Err '下載的 zip 裡沒有專案資料夾。'
|
|
97
|
+
}
|
|
98
|
+
New-Item -ItemType Directory -Path (Split-Path $InstallDir -Parent) -Force | Out-Null
|
|
99
|
+
Move-Item -Path $inner.FullName -Destination $InstallDir
|
|
100
|
+
Show-PkgInfo $InstallDir '即將安裝'
|
|
101
|
+
} finally {
|
|
102
|
+
Remove-Item -Recurse -Force $staging -ErrorAction SilentlyContinue
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function Install-Dependencies {
|
|
107
|
+
Write-Info '安裝 Node.js 依賴...'
|
|
108
|
+
Push-Location $InstallDir
|
|
109
|
+
try {
|
|
110
|
+
& npm install
|
|
111
|
+
if ($LASTEXITCODE -ne 0) {
|
|
112
|
+
Write-Err 'npm install 失敗。'
|
|
113
|
+
}
|
|
114
|
+
} finally {
|
|
115
|
+
Pop-Location
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function Install-CommandShim {
|
|
120
|
+
$jsPath = Join-Path $InstallDir 'bin\birc.js'
|
|
121
|
+
if (-not (Test-Path $jsPath)) {
|
|
122
|
+
Write-Err "找不到 $jsPath"
|
|
123
|
+
}
|
|
124
|
+
& node (Join-Path $InstallDir 'bin\home-install.js') install-command $jsPath
|
|
125
|
+
if ($LASTEXITCODE -ne 0) {
|
|
126
|
+
Write-Err '寫入 birc 指令失敗。'
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function Warn-IfNpmMixed {
|
|
131
|
+
$existing = Get-Command birc -ErrorAction SilentlyContinue
|
|
132
|
+
if ($existing -and $existing.Source -match 'node_modules') {
|
|
133
|
+
Write-Warn 'PATH 上的 birc 來自 npm 全域安裝。同一台不要混裝;要改走這份安裝,先 npm uninstall -g birc-generator。'
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function Test-Installation {
|
|
138
|
+
$existing = Get-Command birc -ErrorAction SilentlyContinue
|
|
139
|
+
if ($existing) {
|
|
140
|
+
Write-Info '安裝成功。可執行 birc --help'
|
|
141
|
+
} else {
|
|
142
|
+
Write-Warn '目前這個視窗還找不到 birc。關掉終端再開一次,或確認 npm prefix 已在 PATH。'
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
Write-Info '開始安裝 birc-generator...'
|
|
147
|
+
Warn-IfNpmMixed
|
|
148
|
+
Test-NodeAndNpm
|
|
149
|
+
Install-FromArchive
|
|
150
|
+
Install-Dependencies
|
|
151
|
+
Install-CommandShim
|
|
152
|
+
Show-PkgInfo $InstallDir '安裝完成'
|
|
153
|
+
Test-Installation
|
|
154
|
+
Write-Info "常用指令: birc create / birc make:entity User / birc --help"
|
|
155
|
+
Write-Info "之後更新用 birc update。"
|
|
156
|
+
Write-Info "解除安裝: irm $BaseUrl/-/raw/main/uninstall.ps1 | iex"
|
package/install.sh
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# 用法: curl -fsSL https://gitlab.ntubimdbirc.tw/lucashsu95/birc-generator/-/raw/main/install.sh | bash
|
|
5
|
+
# 或下載後執行: bash install.sh
|
|
6
|
+
|
|
7
|
+
RED='\033[0;31m'
|
|
8
|
+
GREEN='\033[0;32m'
|
|
9
|
+
YELLOW='\033[1;33m'
|
|
10
|
+
NC='\033[0m'
|
|
11
|
+
|
|
12
|
+
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
13
|
+
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
14
|
+
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
15
|
+
|
|
16
|
+
INSTALL_DIR="$HOME/.birc-generator"
|
|
17
|
+
DEFAULT_BASE_URL="https://gitlab.ntubimdbirc.tw/lucashsu95/birc-generator"
|
|
18
|
+
BASE_URL="${BIRC_BASE_URL:-$DEFAULT_BASE_URL}"
|
|
19
|
+
BASE_URL="${BASE_URL%/}"
|
|
20
|
+
|
|
21
|
+
# 自訂下載來源等於要從別台機器抓程式回來執行。env 被 .bashrc 或 CI 塞了
|
|
22
|
+
# BIRC_BASE_URL 時,這裡必須大聲問過使用者;非互動環境一律拒絕,
|
|
23
|
+
# 要自動化就明確設 BIRC_ALLOW_CUSTOM_BASE=1。
|
|
24
|
+
confirm_base_url() {
|
|
25
|
+
[ "$BASE_URL" = "$DEFAULT_BASE_URL" ] && return 0
|
|
26
|
+
warn "偵測到自訂下載來源: $BASE_URL"
|
|
27
|
+
warn "會從這個來源下載並執行程式碼,有資安風險。"
|
|
28
|
+
if [ "${BIRC_ALLOW_CUSTOM_BASE:-}" = "1" ]; then
|
|
29
|
+
info "BIRC_ALLOW_CUSTOM_BASE=1,繼續使用自訂來源"
|
|
30
|
+
return 0
|
|
31
|
+
fi
|
|
32
|
+
local reply=""
|
|
33
|
+
if [ -r /dev/tty ]; then
|
|
34
|
+
printf '確定要從自訂來源安裝嗎?(y/N): ' > /dev/tty
|
|
35
|
+
read -r reply < /dev/tty || true
|
|
36
|
+
elif [ -t 0 ]; then
|
|
37
|
+
read -r -p "確定要從自訂來源安裝嗎?(y/N): " reply || true
|
|
38
|
+
else
|
|
39
|
+
error "非互動環境不接受自訂來源。要強制使用請設 BIRC_ALLOW_CUSTOM_BASE=1。"
|
|
40
|
+
fi
|
|
41
|
+
[[ "$reply" =~ ^[Yy] ]] || error "已取消安裝。"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
print_pkg_info() {
|
|
45
|
+
local dir="$1"
|
|
46
|
+
local label="${2:-birc}"
|
|
47
|
+
local pkg="$dir/package.json"
|
|
48
|
+
if [ ! -f "$pkg" ]; then
|
|
49
|
+
warn "${label}:找不到 package.json"
|
|
50
|
+
return 0
|
|
51
|
+
fi
|
|
52
|
+
local meta
|
|
53
|
+
meta="$(node -e '
|
|
54
|
+
const p = require(process.argv[1]);
|
|
55
|
+
const author = typeof p.author === "string"
|
|
56
|
+
? p.author
|
|
57
|
+
: (p.author && p.author.name ? p.author.name : "");
|
|
58
|
+
process.stdout.write([p.version || "?", author, p.bircUpdatedAt || ""].join("\n"));
|
|
59
|
+
' "$pkg")"
|
|
60
|
+
local ver author updated
|
|
61
|
+
ver="$(printf '%s\n' "$meta" | sed -n '1p')"
|
|
62
|
+
author="$(printf '%s\n' "$meta" | sed -n '2p')"
|
|
63
|
+
updated="$(printf '%s\n' "$meta" | sed -n '3p')"
|
|
64
|
+
info "${label} 版本 ${ver}"
|
|
65
|
+
[ -n "$author" ] && info "${label} 作者 ${author}"
|
|
66
|
+
[ -n "$updated" ] && info "${label} 更新 ${updated}"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
check_node() {
|
|
70
|
+
if ! command -v node &> /dev/null; then
|
|
71
|
+
error "找不到 Node.js。請先安裝 Node.js 18+:https://nodejs.org/"
|
|
72
|
+
fi
|
|
73
|
+
local NODE_VERSION MAJOR_VERSION
|
|
74
|
+
NODE_VERSION="$(node -v | sed 's/v//')"
|
|
75
|
+
MAJOR_VERSION="$(echo "$NODE_VERSION" | cut -d. -f1)"
|
|
76
|
+
if [ "$MAJOR_VERSION" -lt 18 ]; then
|
|
77
|
+
error "Node.js 版本過低($NODE_VERSION)。需要 18+ 版本。"
|
|
78
|
+
fi
|
|
79
|
+
info "Node.js 版本: $NODE_VERSION"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
check_npm() {
|
|
83
|
+
if ! command -v npm &> /dev/null; then
|
|
84
|
+
error "找不到 npm。請先安裝 npm。"
|
|
85
|
+
fi
|
|
86
|
+
info "npm 版本: $(npm -v)"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# curl | bash 時 stdin 是腳本本身,read 會讀到 EOF 然後被 set -e 整支杀掉。
|
|
90
|
+
# 改問 /dev/tty;沒有終端機就當成要更新。
|
|
91
|
+
ask_update() {
|
|
92
|
+
if [ "${BIRC_AUTO_UPDATE:-}" = "1" ]; then
|
|
93
|
+
info "BIRC_AUTO_UPDATE=1,自動更新"
|
|
94
|
+
return 0
|
|
95
|
+
fi
|
|
96
|
+
local reply=""
|
|
97
|
+
if [ -r /dev/tty ]; then
|
|
98
|
+
printf '是否要更新到最新版?(Y/n): ' > /dev/tty
|
|
99
|
+
read -r reply < /dev/tty || true
|
|
100
|
+
elif [ -t 0 ]; then
|
|
101
|
+
read -r -p "是否要更新到最新版?(Y/n): " reply || true
|
|
102
|
+
else
|
|
103
|
+
info "非互動安裝,自動更新"
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
106
|
+
[[ -z "$reply" || "$reply" =~ ^[Yy] ]]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# 解壓前先驗壓縮檔清單。curl | tar 直接管線時,壞檔半路斷線或被塞
|
|
110
|
+
# ../ 路徑都攔不到;先落地再檢查才擋得住 tar slip。
|
|
111
|
+
# 任何一段是 .. 都拒絕:第一層若就是 ..,會被 --strip-components=1 剝掉而漏判;
|
|
112
|
+
# strip 只用來抓「剝完變絕對路徑」的名字(如 //x)。
|
|
113
|
+
validate_tar_safety() {
|
|
114
|
+
local archive="$1"
|
|
115
|
+
local links bad
|
|
116
|
+
if ! links="$(tar -tvzf "$archive" | awk '$1 ~ /^[lh]/')"; then
|
|
117
|
+
error "無法讀取下載的壓縮檔內容。"
|
|
118
|
+
fi
|
|
119
|
+
if [ -n "$links" ]; then
|
|
120
|
+
error "壓縮檔內含符號或硬連結項目,拒絕解壓:\n$links"
|
|
121
|
+
fi
|
|
122
|
+
if ! bad="$(tar -tzf "$archive" | awk '
|
|
123
|
+
{
|
|
124
|
+
line = $0
|
|
125
|
+
bad = 0
|
|
126
|
+
n = split(line, seg, "/")
|
|
127
|
+
for (i = 1; i <= n; i++) {
|
|
128
|
+
if (seg[i] == "..") { bad = 1; break }
|
|
129
|
+
}
|
|
130
|
+
if (line ~ /^\//) { bad = 1 }
|
|
131
|
+
stripped = line
|
|
132
|
+
sub(/^[^\/]*\//, "", stripped)
|
|
133
|
+
if (stripped ~ /^\//) { bad = 1 }
|
|
134
|
+
if (bad) { print $0 }
|
|
135
|
+
}
|
|
136
|
+
')"; then
|
|
137
|
+
error "無法讀取下載的壓縮檔內容。"
|
|
138
|
+
fi
|
|
139
|
+
if [ -n "$bad" ]; then
|
|
140
|
+
error "壓縮檔含不安全的路徑(可能為 tar slip 攻擊),拒絕解壓:\n$bad"
|
|
141
|
+
fi
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
download_project() {
|
|
145
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
146
|
+
warn "安裝目錄已存在: $INSTALL_DIR"
|
|
147
|
+
print_pkg_info "$INSTALL_DIR" "目前已安裝"
|
|
148
|
+
if ask_update; then
|
|
149
|
+
info "更新中..."
|
|
150
|
+
rm -rf "$INSTALL_DIR"
|
|
151
|
+
else
|
|
152
|
+
info "跳過下載,沿用現有檔案"
|
|
153
|
+
cd "$INSTALL_DIR"
|
|
154
|
+
return 0
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
info "下載專案..."
|
|
159
|
+
local TAR_URL="${BASE_URL}/-/archive/main/birc-generator-main.tar.gz"
|
|
160
|
+
local tmp_tar
|
|
161
|
+
tmp_tar="$(mktemp)"
|
|
162
|
+
mkdir -p "$INSTALL_DIR"
|
|
163
|
+
curl -fsSL "$TAR_URL" -o "$tmp_tar"
|
|
164
|
+
validate_tar_safety "$tmp_tar"
|
|
165
|
+
tar xzf "$tmp_tar" -C "$INSTALL_DIR" --strip-components=1
|
|
166
|
+
rm -f "$tmp_tar"
|
|
167
|
+
cd "$INSTALL_DIR"
|
|
168
|
+
print_pkg_info "$INSTALL_DIR" "即將安裝"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
install_dependencies() {
|
|
172
|
+
info "安裝 Node.js 依賴..."
|
|
173
|
+
npm install
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
create_symlink() {
|
|
177
|
+
node "$(pwd)/bin/home-install.js" install-command "$(pwd)/bin/birc.js"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
test_installation() {
|
|
181
|
+
if command -v birc &> /dev/null; then
|
|
182
|
+
info "安裝成功。可執行 birc --help"
|
|
183
|
+
else
|
|
184
|
+
warn "目前 shell 還找不到 birc,關掉終端再開一次,或執行 hash -r"
|
|
185
|
+
fi
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
main() {
|
|
189
|
+
info "開始安裝 birc-generator..."
|
|
190
|
+
check_node
|
|
191
|
+
check_npm
|
|
192
|
+
confirm_base_url
|
|
193
|
+
download_project
|
|
194
|
+
install_dependencies
|
|
195
|
+
create_symlink
|
|
196
|
+
print_pkg_info "$(pwd)" "安裝完成"
|
|
197
|
+
test_installation
|
|
198
|
+
info "常用指令: birc create / birc make:entity User / birc --help"
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
main "$@"
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "birc-generator",
|
|
3
|
+
"version": "0.5.5",
|
|
4
|
+
"description": "Spring Boot 4 CRUD scaffold generator built on Plop.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "lucashsu95",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"spring-boot",
|
|
9
|
+
"generator",
|
|
10
|
+
"plop",
|
|
11
|
+
"crud",
|
|
12
|
+
"scaffold"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"birc": "bin/birc.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin",
|
|
22
|
+
"plopfile.js",
|
|
23
|
+
"versions.js",
|
|
24
|
+
"templates",
|
|
25
|
+
"project-docs",
|
|
26
|
+
"scripts",
|
|
27
|
+
"install.sh",
|
|
28
|
+
"install.ps1",
|
|
29
|
+
"uninstall.sh",
|
|
30
|
+
"uninstall.ps1",
|
|
31
|
+
"AGENTS.md",
|
|
32
|
+
"PROJECT.md",
|
|
33
|
+
"implement.md",
|
|
34
|
+
"test.md",
|
|
35
|
+
".bircrc.example.json"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"generate": "plop",
|
|
39
|
+
"test": "node --test test/*.test.js",
|
|
40
|
+
"test:coverage": "c8 npm test",
|
|
41
|
+
"test:mutation": "stryker run"
|
|
42
|
+
},
|
|
43
|
+
"c8": {
|
|
44
|
+
"include": [
|
|
45
|
+
"plopfile.js",
|
|
46
|
+
"versions.js",
|
|
47
|
+
"bin/cli-util.js"
|
|
48
|
+
],
|
|
49
|
+
"reporter": [
|
|
50
|
+
"text",
|
|
51
|
+
"json-summary"
|
|
52
|
+
],
|
|
53
|
+
"check-coverage": true,
|
|
54
|
+
"lines": 80,
|
|
55
|
+
"functions": 80,
|
|
56
|
+
"branches": 65,
|
|
57
|
+
"statements": 80
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@stryker-mutator/core": "^10.0.0",
|
|
61
|
+
"c8": "^12.0.0",
|
|
62
|
+
"plop": "^4.0.1"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"js-yaml": "^5.3.0",
|
|
66
|
+
"node-plop": "^0.32.3"
|
|
67
|
+
}
|
|
68
|
+
}
|