birc-generator
v1.9.1
Published
Spring Boot 4 CRUD scaffold generator built on Plop.js
Maintainers
Readme
birc-generator
██████╗ ██╗██████╗ ██████╗ ██████╗ ███████╗███╗ ██╗███████╗██████╗ █████╗ ████████╗ ██████╗ ██████╗
██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝ ██╔════╝████╗ ██║██╔════╝██╔══██╗██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
██████╔╝██║██████╔╝██║ █████╗ ██║ ███╗█████╗ ██╔██╗ ██║█████╗ ██████╔╝███████║ ██║ ██║ ██║██████╔╝
██╔══██╗██║██╔══██╗██║ ╚════╝ ██║ ██║██╔══╝ ██║╚██╗██║██╔══╝ ██╔══██╗██╔══██║ ██║ ██║ ██║██╔══██╗
██████╔╝██║██║ ██║╚██████╗ ╚██████╔╝███████╗██║ ╚████║███████╗██║ ██║██║ ██║ ██║ ╚██████╔╝██║ ██║
╚═════╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝BIRC 後端開新專案,常是把舊專案的 Controller 再抄一份。套件名改到一半、 DAO 繼承寫錯、例外類從 starter 抓來用,之後還要再修。
birc 把這段收成指令。裝一次之後,開專案用 birc create,生一組
CRUD 用 birc make。多模組目錄、BaseDAO、ProjectException 會先寫好。
完整文件在 GitLab wiki (開始使用、add / make / migrate)。這份 README 只留安裝與第一次用。
安裝
需要 Node 18 以上。只走 npm。Win11、WSL、macOS、Linux 都可以。一般只要
裝全域的 birc,不必 clone。改產生器、或要跑還沒發到 npm 的 commit,才
clone。
npm install -g birc-generator裝好後跑 birc --help。之後更新、卸載:
npm update -g birc-generator
npm uninstall -g birc-generatorbirc update 等同 npm install -g birc-generator@latest。使用時若偵測到
新版本,會問要不要更新。說不要的話,同一版本 24 小時內不會再問。不想檢查
就設 BIRC_SKIP_UPDATE_CHECK=1。CI 或不是互動終端也不會問。
以前用 curl | bash 或 PowerShell 裝到 ~/.birc-generator 的,改裝 npm
全域套件,並自行刪掉那個目錄。
第一次用
找一個要放專案的目錄,執行:
birc create它會問專案名稱、base package(預設跟專案名走,例如 campus-activity
→ tw.edu.ntub.birc.campus.activity)、要勾哪些功能(常用 / 登入 / 營運),
以及要不要寫入
AGENTS.md / PROJECT.md / implement.md / test.md。docker、log4j2、
ValidGroup、Spotless、OpenAPI 預設已勾。create 一定是多模組,沒有單模組選項。
做完後會得到同名資料夾,裡面有:
- 根目錄的
Application、build.gradle、application.yml、.bircrc.json - 給人看的
README.md(啟動、birc make、anchor;與injectDocs無關) src/test/java/.../ApplicationTests.java與 H2 測試設定- Gradle wrapper(
gradlew、gradle/wrapper/) modules/<專案名>-configmodules/<專案名>-database-config(BaseDAO、之後的 Entity / DAO 在這裡)
產出的專案是 Spring Boot 4.0.5、Java 25。勾了 docker 的話,會順便把
.env.example 複製成 .env。指令結束後會印啟動、生骨架、打包的下一步。
進到這個資料夾(有 .bircrc.json 的那一層)。先啟動資料庫,再把 .env
載入目前的 shell,最後跑 Spring Boot。
Bash / Git Bash / WSL:
cd campus-activity
docker compose up -d db
set -a && source .env && set +a
./gradlew bootRunPowerShell:
cd campus-activity
docker compose up -d db
Get-Content .env | ForEach-Object {
if ($_ -match '^\s*([^#][^=]*)=(.*)$') {
Set-Item -Path "Env:$($matches[1].Trim())" -Value $matches[2].Trim().Trim('"')
}
}
.\gradlew.bat bootRun再生一組骨架:
birc make輸入 Activity 或 activity,會一次寫出 Entity、DAO、Mapper、DTO、
Service、Controller。小寫會自動收成 PascalCase。只要其中一層,改跑
birc make:entity 或 birc make:controller。預設是初稿,完整範例加
--example,或直接帶 --fields。欄位可寫 --fields title:String,startTime:LocalDateTime,
就不會再問一次。查詢要公開、寫入要登入,加 --public-read(自動帶出完整方法,並產出對應的 XxxSecurityCustomizer)。
只要 SecurityCustomizer 可用 birc make:security 獨立產生。檔已存在時會停下來;要覆寫加 --force。
腳本或課堂示範可 birc create Practice --yes,其餘用預設(docker、log4j2、
ValidGroup、Spotless、OpenAPI、注入 agent 文件),不再問。
create 與 update 可以在任何目錄跑。其餘指令會從目前目錄往上找
.bircrc.json,不必先 cd 回專案根。目前目錄已經是 BIRC 專案、或同名
資料夾已在,create 會停下來。不認得的 -- 選項會失敗並提示接近的名稱。
指令
| 指令 | 做什麼 |
| --- | --- |
| birc create | 開一個多模組 Spring Boot 4 專案。--yes 其餘用預設、不要問 |
| birc update | 更新本機 birc(npm install -g birc-generator@latest) |
| birc add | 往既有專案加模組。沒帶名稱會互動勾選;birc add email sentry 直接加。--force 覆寫已選的已安裝 feature 檔 |
| birc sync | 用目前 template 覆寫全部已安裝 feature 的檔(不動 yml / gradle) |
| birc make | 一次生 Entity + DAO + Mapper + DTO + Service + Controller;加 --migration / --seed。已有 Java 時加這兩個旗標會跳過,只補缺的檔與 SQL / Seeder |
| birc make:entity | Entity、XxxDAO;加 --migration / --seed / --dto、--mapper、--soft-delete。已有檔要覆寫加 --force;只要表或 Seeder 可 --migration / --seed,不會覆寫 Entity |
| birc make:model | 同 make:entity;加 --migration / --seed / --controller / --soft-delete |
| birc make:mapper | Mapper 和 CreateRequest / Response |
| birc make:service | XxxService extends BaseService,CRUD 在 BaseServiceImpl |
| birc make:controller | Controller;加 --public-read 則查詢公開、寫入掛登入檢查並產出 XxxSecurityCustomizer |
| birc make:security | 只產生 XxxSecurityCustomizer,把查詢路徑設為公開(/api/xxx、/api/xxx/**),不生 Controller |
| birc make:exception | 繼承 ProjectException 的例外類 |
| birc make:migration | Flyway SQL。create_book_table / add_author_id_to_book_table / change_price_on_book_table 都讀 Entity 欄位;{ref}_id 會自動帶外鍵。add_deleted_at_to_<table>_table 自動補 @SoftDelete(columnName = "deleted_at", strategy = TIMESTAMP) 到 Entity(冪等、找不到 Entity 也只產 migration) |
| birc make:seeder | Java XxxSeeder(讀 Entity 或 --fields) |
| birc docs | 補 AGENTS.md / PROJECT.md / implement.md / test.md(專案名從 .bircrc.json 讀) |
| birc migrate | 在專案裡跑 Gradle wrapper 的 flywayMigrate(Unix ./gradlew,Windows gradlew.bat) |
| birc migrate:rollback | Flyway Community 做不到 rollback,指令會說明替代作法 |
| birc migrate:reset | flywayClean 後再 flywayMigrate(--force 略過確認) |
| birc seed | 跑 Java Seeder(bootRun --birc.seed,跑完結束) |
| birc db:wipe | 清空資料庫(flywayClean)。沒加 --force 先問一次 |
birc create Practice --yes
birc make:entity User --dto
birc make:entity User --mapper
birc make:entity User --example
birc make:entity User --fields title:String,startTime:LocalDateTime
birc make Book --fields title:String,author:String,isbn:String,price:BigDecimal,publishedAt:LocalDate --migration --seed
birc migrate
birc seed
birc db:wipe
birc make:entity User --force
birc make:model Flight --migration
birc make:model Flight --seed
birc make:model Flight --controller
birc make:model Flight --soft-delete
birc make:model Flight --migration --soft-delete
birc make:security Activity
birc make:entity Book --fields title:String,author:String,isbn:String,price:BigDecimal,publishedAt:LocalDate
birc make:migration create_book_table
birc make:migration add_author_id_to_book_table
birc make:migration change_price_on_book_table
birc make:migration add_deleted_at_to_book_table
birc make:seeder BookSeeder
birc add
birc add email
birc add email sentry
birc add file-upload
birc add file-upload-tika
birc add page
birc add permission-quick --roles=SYS_ADMIN,ADMIN,USER
birc add permission --perms=BOOK_READ,BOOK_WRITE
birc add refresh-token --rotation --device-binding --revoke-on-password-change
birc add --force
birc sync
birc migrate
birc login
birc clockin
birc clockout
birc status中心簽到跟專案無關:birc login 登入(token 寫在 ~/.birc/session.json),
birc clockin 簽到、birc clockout 簽退、birc status 看今日狀態與當月次數。沒帶帳密時會問;也可以
birc login 帳號 密碼。
指令是 make:entity,中間一條冒號,跟 Laravel artisan 一樣。
birc add 沒帶名稱時會問你要加哪些模組;也可以寫 birc add docker、birc add file-upload、birc add page(等於 pagination)或 birc add refresh-token(需先 birc add auth)。
make:migration create_book_table 會讀已有的 Book Entity 把欄位寫進 SQL。birc make Book --fields title:String --migration --seed 同一指令生骨架、CREATE TABLE 與 BookSeeder,再 birc migrate、birc seed。只補 Seeder 用 birc make:seeder BookSeeder。清空資料庫用 birc db:wipe。
add_author_id_to_book_table 會查 Book 的 Entity 決定型別;欄位是 {表}_id 而那張表找得到時,會一併寫 FOREIGN KEY。
change_price_on_book_table 出 MODIFY COLUMN,新型別讀 Entity——所以先改 Entity 的欄位型別,再產生遷移;Entity 上沒有那個欄位時它會直接失敗,不會猜。
各指令的細節見 wiki:make、 add、 migrate、 簽到。
birc add 功能模組詳細對照
執行 birc add 會列出所有可加入的功能模組。每個模組會產生對應的 Java 檔、設定檔片段、Gradle 依賴。下表列出每個模組確切會產出什麼檔案與會改動什麼設定。
| 功能模組 (key) | 模組名稱 | 產出的 Java 檔案 | 設定檔變更 | Gradle 依賴/Plugin | 備註 |
|---|---|---|---|---|---|
| docker | Docker | Dockerfile、docker-compose.yml、docker-compose.prod.yml、.env.example | 無 | 無 | 建立專案時預設勾選,並複製 .env.example → .env |
| email | Email | service/EmailService.java、service/impl/EmailServiceImpl.java、config/EmailAsyncConfig.java、email/sample.html | application.yml 插入 mail 設定 | spring-boot-starter-mail、thymeleaf | 非同步寄信、Thymeleaf 模板 |
| auth | 帳號登入 | config/JwtProperties.java、config/AuthSecurityCustomizer.java、config/JwtSecretEnvironmentPostProcessor.java、entity/AuthUser.java、dao/AuthUserDAO.java、security/JwtService.java、controller/AuthController.java、exception/AuthException.java | application.yml 插入 jwt 設定、JWT_SECRET 寫入 .env | spring-boot-starter-security、jjwt-api/impl/jackson、spring-boot-starter-data-jpa | auth_users 表、POST /api/auth/login 回 X-Auth-Token、JWT filter、GET /api/auth/me |
| sso | SSO | security/SsoProperties.java、config/SsoAutoConfiguration.java | application.yml 插入 sso 設定 | spring-boot-starter-security、spring-boot-starter-oauth2-client | 僅設定骨架,驗票/發證需自行接入 |
| oauth | OAuth2 登入 | config/OAuth2LoginSuccessHandler.java | application.yml 插入 oauth2 設定 | spring-boot-starter-oauth2-client | 範例接 Google,需自行掛 SecurityCustomizer 才生效 |
| scheduling | 排程 | config/SchedulingConfig.java、schedule/SampleSchedule.java | 無 | 無 | @EnableScheduling + 範例 Job |
| aop | AOP 事件記錄 | annotation/OperationLog.java、aspect/OperationLogAspect.java | application.yml 插入 aop 設定 | spring-boot-starter-aop | 自訂 @OperationLog 註解 + Aspect |
| permission-audit | 權限稽核日誌 | audit/AuditLogUtils.java、aspect/PermissionAspect.java (修改) | application.yml 插入 permission.audit.* 設定 | 無 (共用既有依賴) | 記錄授權決策(允許/拒絕/未登入)、敏感參數遮罩、支援 operation-log 共用設定,預設關閉 |
| client | Client | config/ExternalApiProperties.java、config/ExternalApiClientConfig.java、client/ExternalApiClient.java | application.yml 插入 external-api 設定 | spring-boot-starter-web | RestClient 封裝、支援重試/熔斷/日誌 |
| sentry | Sentry | config/SentryConfig.java、config/SentryBeforeSend.java | application.yml 插入 sentry 設定 | sentry-spring-boot-starter | 只收 5xx,4xx/Security 401/403/驗證例外丟掉 |
| openapi | OpenAPI | config/OpenApiConfig.java | application.yml 插入 springdoc 設定 | springdoc-openapi-starter-webmvc-ui | Swagger UI + 全域 Bearer JWT、make --example 產生 @Tag/@Operation |
| fileUpload | 檔案上傳 | config/FileStorageProperties.java、service/FileStorageService.java、service/impl/FileStorageServiceImpl.java、controller/FileUploadController.java、util/file/FileUtils.java、util/file/FileExtensionUtils.java、exception/file/* | application.yml 插入 file-storage 設定 | 無 | 本機磁碟、POST /api/files、POST /api/files/multiple、RFC 5987 中文檔名、多檔 rollback |
| fileUploadTika | 檔案上傳 | 同 fileUpload,但 FileExtensionUtils.java 改用 Tika | 同 fileUpload | org.apache.tika:tika-core:3.2.1 | 互斥 fileUpload,支援百種格式、升級路徑 fileUpload→fileUploadTika |
| pagination | 分頁查詢 | dto/PageRequest.java、dto/PageResponse.java、dto/PageInfo.java、dto/Pager.java、specification/SearchCriteria.java、specification/GenericSpecification.java、specification/SpecificationSupport.java | 無 | 無 | PageRequest/PageResponse/GenericSpecification,動態條件、排序、N+1 提醒 |
| validGroup | 驗證群組 | validation/ValidGroup.java | 無 | 無 | ValidGroup.Create/Update/Delete/Submit,@Validated + 欄位 groups |
| permission-quick | 角色即權限 | annotation/RequirePermission.java、aspect/PermissionAspect.java、security/SecurityUtils.java、seeder/AuthRoleSeeder.java、config/RoleHierarchyConfig.java、entity/AuthRole.java、dao/AuthRoleDAO.java、db/migration/V1__create_auth_roles_table.sql、db/migration/V1__add_role_id_to_auth_users_table.sql (需 auth) | 無 | spring-boot-starter-security、spring-boot-starter-aspectj | auth_roles 表、角色名稱即權限代碼、RoleHierarchy 依順序產出、--roles 參數指定階層 |
| permission | 精細權限 | permission-quick 所有檔 + entity/AuthPermission.java、dao/AuthPermissionDAO.java、entity/AuthRole.java (多對多)、entity/AuthRoleSeeder.java、security/BircUserDetails.java、security/JpaUserDetailsService.java、db/migration/V1__create_auth_permission.sql、db/migration/V1__create_auth_role_permission.sql、db/migration/V1__migrate_quick_to_std.sql (升級用) | 無 | 同 permission-quick | auth_permission + auth_role_permission 多對多、角色變權限容器、BircUserDetails、PermissionProvider 介面、互斥 permission-quick、升級路徑支援 |
| refreshToken | Refresh Token | entity/RefreshToken.java、dao/RefreshTokenDAO.java、security/RefreshTokenService.java、security/RefreshTokenProperties.java、security/RefreshTokenCookieConfig.java、controller/AuthController.java (patch) | application.yml 插入 birc.refresh-token.* 設定 | spring-boot-starter-security、spring-boot-starter-data-jpa、spring-boot-starter-web、spring-boot-starter-validation、spring-session-core | POST /api/auth/refresh、DELETE /api/auth/logout、Token Rotation、裝置綁定、密碼變更撤銷、HttpOnly Cookie 選項,依賴 auth |
| gitlabCi | GitLab CI | .gitlab-ci.yml | 無 | 無 | Harbor build/push + SSH deploy,帳密放 CI/CD Variables |
| spotless | Spotless | spotless_formatter.xml | 無 | com.diffplug.spotless plugin | Eclipse 4.31 格式化、./gradlew spotlessApply |
birc add 行為說明
- 冪等:已記在
.bircrc.json.features的模組不再執行;舊專案漏記也會跳過既有檔與已插入片段 - 預檢查:要插 yml/gradle 的模組會先檢查 anchor 存在,失敗就不寫任何檔
- 互斥:
permissionvspermission-quick、fileUploadvsfileUploadTika不能共存 - 升級:
permission-quick→permission允許(疊加表、種子遷移、既有判斷式不壞)fileUpload→fileUploadTika允許(覆寫驗證邏輯、加 tika-core)- 反向降級皆擋下
- 覆寫:
birc add --force或birc sync覆寫已安裝模組的 Java/資源檔,不重貼 yml/gradle - 錨點:
application.yml用# birc-generator:config-anchor,build.gradle用// birc-generator:dependency-anchor/plugin-anchor/allprojects-anchor,不要刪除
建立專案時可以勾的功能 (同 birc add 完整對照)
勾了就會寫進專案裡。之後也能用 birc add 再補。
birc add 會在 application.yml 的 # birc-generator:config-anchor
後面插入設定,在 build.gradle 的
// birc-generator:dependency-anchor 後面插入依賴,plugin 接
// birc-generator:plugin-anchor,allprojects 接
// birc-generator:allprojects-anchor。這幾行不要刪;缺了
add 會先失敗、不寫任何檔。已加入的模組會記在 .bircrc.json.features;
再次執行 add 時會顯示為已安裝,不會重複生檔或插入設定。template 改了要
覆寫已安裝模組的 Java / 資源檔時,用 birc add --force 或 birc sync
(全部已安裝),不會重貼 yml / gradle。
生出來的程式長什麼樣
多模組的切法是:API 在根專案,共用設定在 *-config,Entity / DAO 在
*-database-config。
DAO 繼承專案裡的 BaseDAO。查不到資料時丟 NotFoundException,它繼承
專案自己的 ProjectException 與 web.Result,不是 starter 的 BusinessException / Result。
Mapper 用 MapStruct。Controller 只轉 DTO,業務寫在 Service。
這些慣例跟 BIRC 現在在跑的後端專案一樣。產出專案給 agent 讀的目錄在
AGENTS.md,規範在 PROJECT.md。產生器自己先讀 AGENTS.md。
這包不會做的事
make 給的是 CRUD 骨架,查詢條件和權限要自己補。create 只出多模組,
沒有單模組選項。K8s 不會一併產生。勾 .gitlab-ci.yml 時會帶 Harbor /
SSH 部署骨架,帳密仍放 GitLab CI/CD Variables,不要寫進 repo。
Flyway Community 沒有 Laravel 的 rollback。birc migrate:rollback 只會
說明替代作法:再寫一筆往前的遷移。birc migrate 會真的跑 Gradle wrapper 的 flywayMigrate,不是只印指令。示範資料用 birc seed;清空資料庫用 birc db:wipe。
改這個產生器
原始碼在 GitLab。npm 上的套件是同一份程式的發佈入口,改完要兩邊一起走。
clone 下來之後,在 repo 裡跑才會吃到你改的 template:
git clone https://gitlab.ntubimdbirc.tw/birc-backend/birc-generator.git
cd birc-generator
npm install
node bin/birc.js --help
npm test
npm run test:coverage
npm run test:mutation改 template、plopfile.js 或 lib/ 之前,先讀 AGENTS.md 的目錄,
規範在 PROJECT.md。wiki 的
改產生器
是給人看的精簡版。
發版順序:先把改動推進 GitLab main,再改 package.json 的 version,
最後 npm publish。只推 GitLab、不 publish 的話,npm install -g 的人
拿不到新版。
接下來
裝好之後可以照這個順序走一次。
- 跑
birc create開一個專案。 cd進專案,docker compose up -d db,載入.env後跑 Spring Boot (Bash / PowerShell 寫法見上面「第一次用」)。- 跑
birc make生第一個實體。 - 打包用
./gradlew build -x test(Windows 用.\gradlew.bat)。
