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
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
apply plugin: 'com.diffplug.spotless'
|
|
2
|
+
|
|
3
|
+
spotless {
|
|
4
|
+
java {
|
|
5
|
+
target 'src/main/java/**/controller/*.java',
|
|
6
|
+
'src/main/java/**/service/**/*.java',
|
|
7
|
+
'modules/**/src/main/java/**/entity/**/*.java',
|
|
8
|
+
'modules/**/src/main/java/**/dao/*.java'
|
|
9
|
+
|
|
10
|
+
targetExclude 'build/**'
|
|
11
|
+
eclipse('4.31').configFile(rootProject.file('spotless_formatter.xml'))
|
|
12
|
+
removeUnusedImports()
|
|
13
|
+
trimTrailingWhitespace()
|
|
14
|
+
endWithNewline()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
id 'com.diffplug.spotless' version '{{spotlessVersion}}'
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<profiles version="23">
|
|
3
|
+
<profile name="CustomFormatter">
|
|
4
|
+
<!-- ========== Indentation ========== -->
|
|
5
|
+
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
|
6
|
+
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
|
7
|
+
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
|
8
|
+
|
|
9
|
+
<!-- ========== Line Width ========== -->
|
|
10
|
+
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
|
11
|
+
|
|
12
|
+
<!-- ========== Braces (same line) ========== -->
|
|
13
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
|
14
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
|
15
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
|
16
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
|
17
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
|
18
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
|
19
|
+
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
|
20
|
+
|
|
21
|
+
<!-- ========== Single-line control ========== -->
|
|
22
|
+
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
|
|
23
|
+
<setting id="org.eclipse.jdt.core.formatter.keep_simple_if_on_one_line" value="true"/>
|
|
24
|
+
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="true"/>
|
|
25
|
+
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="true"/>
|
|
26
|
+
|
|
27
|
+
<!-- ========== Preserve line breaks in method chains ========== -->
|
|
28
|
+
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
|
29
|
+
|
|
30
|
+
<!-- ========== Annotations on separate line ========== -->
|
|
31
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_type" value="insert"/>
|
|
32
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_method" value="insert"/>
|
|
33
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_field" value="insert"/>
|
|
34
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_local_variable" value="insert"/>
|
|
35
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_parameter" value="do not insert"/>
|
|
36
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_annotation_on_enum_constant" value="do not insert"/>
|
|
37
|
+
|
|
38
|
+
<!-- ========== Annotation content alignment (NO WRAP) ========== -->
|
|
39
|
+
<!-- This is the key setting: keeps @Content(...), @ExampleObject(value = ...) on same line -->
|
|
40
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_in_allocation_expression" value="0"/>
|
|
41
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
|
42
|
+
|
|
43
|
+
<!-- ========== Blank lines ========== -->
|
|
44
|
+
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
|
45
|
+
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
|
46
|
+
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
|
|
47
|
+
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
|
48
|
+
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
|
49
|
+
|
|
50
|
+
<!-- ========== Newlines ========== -->
|
|
51
|
+
<setting id="org.eclipse.jdt.core.formatter.line_terminator" value="LF"/>
|
|
52
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace" value="insert"/>
|
|
53
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch" value="insert"/>
|
|
54
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else" value="insert"/>
|
|
55
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally" value="insert"/>
|
|
56
|
+
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
|
|
57
|
+
|
|
58
|
+
<!-- ========== Import organization ========== -->
|
|
59
|
+
<setting id="org.eclipse.jdt.core.formatter.import_order" value="java;javax;org;com;"/>
|
|
60
|
+
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
|
61
|
+
<setting id="org.eclipse.jdt.core.formatter.remove_unused_imports" value="true"/>
|
|
62
|
+
|
|
63
|
+
<!-- ========== Static imports ========== -->
|
|
64
|
+
<setting id="org.eclipse.jdt.core.formatter.static_import_order" value="org.junit.Assert;org.junit.Assume;org.junit.jupiter.api.Assertions;org.junit.jupiter.api.Assumptions;org.hamcrest.CoreMatchers;org.hamcrest.Matchers;"/>
|
|
65
|
+
|
|
66
|
+
<!-- ========== Alignment ========== -->
|
|
67
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
|
68
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
|
69
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
|
|
70
|
+
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
|
71
|
+
|
|
72
|
+
<!-- ========== Wrapping ========== -->
|
|
73
|
+
<setting id="org.eclipse.jdt.core.formatter.wrapping_strategy_for_method_declaration" value="preserve_existing"/>
|
|
74
|
+
|
|
75
|
+
<!-- ========== Misc ========== -->
|
|
76
|
+
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
|
77
|
+
<setting id="org.eclipse.jdt.core.formatter.remove_trailing_whitespace_on_save" value="true"/>
|
|
78
|
+
|
|
79
|
+
<!-- ========== On/off tags ========== -->
|
|
80
|
+
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
|
81
|
+
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
|
82
|
+
</profile>
|
|
83
|
+
</profiles>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package {{basePackage}}.config;
|
|
2
|
+
|
|
3
|
+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
4
|
+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
5
|
+
import org.springframework.context.annotation.Configuration;
|
|
6
|
+
import {{basePackage}}.security.SsoProperties;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 只有在 application.yml 設 birc.sso.enabled=true 時才會載入。
|
|
10
|
+
* 目前先放設定骨架,實際打 SSO 驗證票根的邏輯(filter / interceptor)
|
|
11
|
+
* 依各專案的 SSO 供應商再補,直接寫在這個專案裡就好。
|
|
12
|
+
*/
|
|
13
|
+
@Configuration
|
|
14
|
+
@ConditionalOnProperty(prefix = "birc.sso", name = "enabled", havingValue = "true")
|
|
15
|
+
@EnableConfigurationProperties(SsoProperties.class)
|
|
16
|
+
public class SsoAutoConfiguration {
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package {{basePackage}}.security;
|
|
2
|
+
|
|
3
|
+
import jakarta.validation.constraints.NotBlank;
|
|
4
|
+
import lombok.Getter;
|
|
5
|
+
import lombok.Setter;
|
|
6
|
+
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
7
|
+
import org.springframework.validation.annotation.Validated;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 校內 SSO 的設定,對應 application.yml 的 birc.sso.*。
|
|
11
|
+
* yml 開 enabled: true 並填 loginUrl / validateUrl 後,SsoAutoConfiguration 才會生效;
|
|
12
|
+
* 沒有 SSO 的專案不用理這段。enabled 時 URL 空白會在啟動失敗,不要拖到打 SSO 才發現。
|
|
13
|
+
*/
|
|
14
|
+
@Getter
|
|
15
|
+
@Setter
|
|
16
|
+
@Validated
|
|
17
|
+
@ConfigurationProperties(prefix = "birc.sso")
|
|
18
|
+
public class SsoProperties {
|
|
19
|
+
|
|
20
|
+
private boolean enabled = false;
|
|
21
|
+
|
|
22
|
+
@NotBlank
|
|
23
|
+
private String loginUrl;
|
|
24
|
+
|
|
25
|
+
@NotBlank
|
|
26
|
+
private String validateUrl;
|
|
27
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package {{basePackage}}.validation;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bean Validation 的 groups。Controller 用 {@code @Validated(ValidGroup.Create.class)},
|
|
5
|
+
* 欄位的 {@code groups} 對同一組,這樣 create 與 update 可以套不同必填規則。
|
|
6
|
+
*/
|
|
7
|
+
public interface ValidGroup {
|
|
8
|
+
|
|
9
|
+
/** 新增時要檢查的欄位。 */
|
|
10
|
+
interface Create {}
|
|
11
|
+
|
|
12
|
+
/** 更新時要檢查的欄位。 */
|
|
13
|
+
interface Update {}
|
|
14
|
+
|
|
15
|
+
/** 刪除還要帶 body 時用:原因、確認碼、樂觀鎖 version。只刪 id 就不用這組。 */
|
|
16
|
+
interface Delete {}
|
|
17
|
+
|
|
18
|
+
/** 送審/提交:比草稿更嚴。草稿走 Create,送審改 @Validated(Submit.class)。 */
|
|
19
|
+
interface Submit {}
|
|
20
|
+
}
|
package/test.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# test
|
|
2
|
+
|
|
3
|
+
實作時測試怎麼寫。流程在 [implement.md](implement.md);規範在 [PROJECT.md](PROJECT.md)。這份只管圍欄。
|
|
4
|
+
|
|
5
|
+
目標不是「讓測試變綠」,是「有問題的碼過不了關」。
|
|
6
|
+
|
|
7
|
+
## 工具
|
|
8
|
+
|
|
9
|
+
沿用 `node --test`(`npm test`)。Given-When-Then 寫在**測試名稱**,例如 `add 第二次不改檔、.bircrc.json.features 只有一個同名 key`。不要另開 `.feature` runner。
|
|
10
|
+
|
|
11
|
+
覆蓋率與變異測試是這份 repo 的硬門檻,不是某一張票順便加的:
|
|
12
|
+
|
|
13
|
+
- `npm run test:coverage`:`c8` 打 `plopfile.js`、`versions.js`、`bin/cli-util.js`,行/函式/陳述 < 80% 或分支 < 65% 就失敗。安裝/更新的 tar 跳脫與自訂 URL 另有定向測試,不拿整份 `home-install.js` 湊門檻。
|
|
14
|
+
- `npm run test:mutation`:Stryker 打 `bin/cli-util.js`(路徑、Gradle wrapper、create 預設),突變分數 < 70 就失敗。`plopfile.js` 的全量突變會重跑 `./gradlew test`,太慢,關鍵路徑改完仍做一次**人工突變**。
|
|
15
|
+
|
|
16
|
+
`.gitlab-ci.yml` 跑這兩道;紅了不能合。過程中跑單一測試;完整 `npm test` 只在 implement 最後一次(裡面會 `create` / `add` / `./gradlew test`)。
|
|
17
|
+
|
|
18
|
+
## 打在哪
|
|
19
|
+
|
|
20
|
+
測試打在使用者拿得到的結果:`create` / `add` / `injectDocs` 之後專案裡的檔、CLI 旗標生出的 dest、產出 Java 的 import。注入文件鎖 dest 的 `AGENTS.md` / `PROJECT.md`,不要讀 generator 裡的 `.hbs`。
|
|
21
|
+
|
|
22
|
+
不斷言 template 排版或 private helper 名稱。預期值來自規格或已知字面,不要用實作自己算一遍再跟自己比。
|
|
23
|
+
|
|
24
|
+
每條關鍵測試要寫得出「這條防住什麼」。
|
|
25
|
+
|
|
26
|
+
## 關鍵路徑 vs 低風險
|
|
27
|
+
|
|
28
|
+
火力只打關鍵路徑。出錯會讓使用者專案壞掉或資料錯的,算關鍵:
|
|
29
|
+
|
|
30
|
+
- `create` / `add` 對同一 feature 生出同一組檔與同一段 yml/gradle;重複 `add` 零變更;anchor 還在。
|
|
31
|
+
- `add` 冪等:已記在 `.bircrc.json.features` 的不再執行;舊專案漏記時既有檔與 fragment 也要跳過。
|
|
32
|
+
- `add` 預檢查:要插 yml / gradle 時 dest 沒有 anchor 就失敗,且不能留下新的 Java 檔。缺 plugin-anchor 時不寫 `spotless_formatter.xml`。
|
|
33
|
+
- 全 feature `create` + `make User` 之後 `./gradlew test` 與 `./gradlew spotlessCheck` 都過。
|
|
34
|
+
- `add --force` / `sync`:覆寫已安裝 feature 的檔,yml / gradle 不重貼。
|
|
35
|
+
- CLI dest:檔落在呼叫者目錄,不是 generator repo。
|
|
36
|
+
- 產出 Java 沒有 `tw.edu.ntub.birc.starter` / `birc-spring-boot-starter`。
|
|
37
|
+
- `make:entity --dto` / `--mapper` 與 `make:mapper` 同一組 Mapper + DTO;預設 `make:entity` 不生它們。
|
|
38
|
+
- `make:model --migration` / `--seed` 的表名跟 Entity `@Table` 一致;migration 與 seed 版本號不重複。
|
|
39
|
+
- `--soft-delete` 的 Entity 用 `deleted_at` + `SoftDeleteType.TIMESTAMP`;沒加 flag 的 Entity / migration 沒有這欄。
|
|
40
|
+
- `--example` 的驗證群組是專案 `ValidGroup.Create` / `Update`,不是 starter `OnCreate`。`Delete` / `Submit` 是空的 marker,給「刪除要帶 body」與送審用,預設 CRUD 不標;不要刪掉。
|
|
41
|
+
- Flyway plugin 版本跟得上 Gradle wrapper;`flywayMigrate` 不能再碰到已刪的 Gradle convention API。
|
|
42
|
+
- 安裝/更新路徑:`detectInstallKind`、自訂 base URL 預設拒絕、tarball 路徑不可逃出目標目錄。
|
|
43
|
+
|
|
44
|
+
低風險:help 用字、banner 日期、純文件潤飾、label 中英對照。最多一條鎖定文案,或零測試。
|
|
45
|
+
|
|
46
|
+
## 原則
|
|
47
|
+
|
|
48
|
+
1. 合法會過,非法被拒(重複 add、壞名稱、不該存在的 starter import)。
|
|
49
|
+
2. 不變量優先:anchor 行還在、features 沒有重複 key、第二次 add 的 snapshot 不變。
|
|
50
|
+
3. 時間敏感邏輯注入可控時間,不用 `sleep`。
|
|
51
|
+
4. 這個 generator 沒有金額/庫存競態,不要為了清單去造假共享狀態。產出 Spring 專案的報名/扣庫存,測在產出專案。
|
|
52
|
+
5. 至少一次**人工突變**:改壞剛寫的關鍵斷言或實作,確認對應測試轉紅,再改回來。這補 Stryker 打不到的 `plopfile.js` / template 路徑。
|
|
53
|
+
|
|
54
|
+
覆蓋率、Stryker、pipeline 都已是硬門檻:`npm test` 綠不夠,還要 `npm run test:coverage` 與 `npm run test:mutation` 過。
|
|
55
|
+
|
|
56
|
+
完成條件:關鍵路徑有正反案例;低風險沒被拿去湊數量;做過一次人工突變。
|
package/uninstall.ps1
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# 用法:
|
|
2
|
+
# irm https://gitlab.ntubimdbirc.tw/lucashsu95/birc-generator/-/raw/main/uninstall.ps1 | iex
|
|
3
|
+
# 或下載後執行: powershell -NoProfile -ExecutionPolicy Bypass -File uninstall.ps1
|
|
4
|
+
# 只拆 curl / PowerShell 裝到 $HOME\.birc-generator 的那份,不會 npm uninstall -g。
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = 'Stop'
|
|
7
|
+
|
|
8
|
+
function Write-Info([string]$Message) {
|
|
9
|
+
Write-Host "[INFO] $Message" -ForegroundColor Green
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function Write-Warn([string]$Message) {
|
|
13
|
+
Write-Host "[WARN] $Message" -ForegroundColor Yellow
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function Remove-Cmd([string]$Target) {
|
|
17
|
+
if (-not (Test-Path $Target)) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
Remove-Item -Force $Target
|
|
22
|
+
Write-Info "已移除 $Target"
|
|
23
|
+
} catch {
|
|
24
|
+
Write-Warn "無法移除 $Target"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function Remove-Shims {
|
|
29
|
+
$candidates = New-Object System.Collections.Generic.List[string]
|
|
30
|
+
$candidates.Add((Join-Path $HOME '.local\bin')) | Out-Null
|
|
31
|
+
try {
|
|
32
|
+
$prefix = (& npm config get prefix 2>$null).Trim()
|
|
33
|
+
if ($prefix) {
|
|
34
|
+
$candidates.Add($prefix) | Out-Null
|
|
35
|
+
$candidates.Add((Join-Path $prefix 'bin')) | Out-Null
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
# npm 不在就算了
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
foreach ($dir in $candidates) {
|
|
42
|
+
Remove-Cmd (Join-Path $dir 'birc')
|
|
43
|
+
Remove-Cmd (Join-Path $dir 'birc.cmd')
|
|
44
|
+
Remove-Cmd (Join-Path $dir 'birc.ps1')
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Write-Info '開始解除安裝 birc-generator...'
|
|
49
|
+
Remove-Shims
|
|
50
|
+
|
|
51
|
+
$installDir = Join-Path $HOME '.birc-generator'
|
|
52
|
+
if (Test-Path $installDir) {
|
|
53
|
+
Write-Info "移除安裝目錄: $installDir"
|
|
54
|
+
Remove-Item -Recurse -Force $installDir
|
|
55
|
+
} else {
|
|
56
|
+
Write-Info "安裝目錄不存在: $installDir"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Write-Info '解除安裝完成。birc 指令與 ~/.birc-generator 已移除。'
|
|
60
|
+
Write-Info '若當初是 npm i -g 裝的,請改跑 npm uninstall -g birc-generator。'
|
package/uninstall.sh
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# birc-generator 解除安裝腳本
|
|
5
|
+
# 用法: bash uninstall.sh
|
|
6
|
+
|
|
7
|
+
# 顏色定義
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
NC='\033[0m' # No Color
|
|
12
|
+
|
|
13
|
+
# 輸出函數
|
|
14
|
+
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
15
|
+
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
16
|
+
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
|
17
|
+
|
|
18
|
+
remove_cmd() {
|
|
19
|
+
local target="$1"
|
|
20
|
+
if [ -e "$target" ] || [ -L "$target" ]; then
|
|
21
|
+
if [ -w "$(dirname "$target")" ]; then
|
|
22
|
+
rm -f "$target"
|
|
23
|
+
info "已移除 $target"
|
|
24
|
+
else
|
|
25
|
+
warn "無法移除 $target(沒有寫入權限)"
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
remove_symlink() {
|
|
31
|
+
local npm_prefix=""
|
|
32
|
+
remove_cmd /usr/local/bin/birc
|
|
33
|
+
remove_cmd "$HOME/.local/bin/birc"
|
|
34
|
+
npm_prefix="$(npm config get prefix 2>/dev/null || true)"
|
|
35
|
+
if [ -n "$npm_prefix" ]; then
|
|
36
|
+
remove_cmd "$npm_prefix/bin/birc"
|
|
37
|
+
remove_cmd "$npm_prefix/bin/birc.cmd"
|
|
38
|
+
remove_cmd "$npm_prefix/birc"
|
|
39
|
+
remove_cmd "$npm_prefix/birc.cmd"
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# 移除安裝目錄
|
|
44
|
+
remove_install_dir() {
|
|
45
|
+
local INSTALL_DIR="$HOME/.birc-generator"
|
|
46
|
+
|
|
47
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
48
|
+
info "移除安裝目錄: $INSTALL_DIR"
|
|
49
|
+
rm -rf "$INSTALL_DIR"
|
|
50
|
+
else
|
|
51
|
+
info "安裝目錄不存在: $INSTALL_DIR"
|
|
52
|
+
fi
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# 清除 npm 全域快取(如果有)
|
|
56
|
+
clear_npm_cache() {
|
|
57
|
+
if command -v npm &> /dev/null; then
|
|
58
|
+
info "清除 npm 快取..."
|
|
59
|
+
npm cache clean --force 2>/dev/null || true
|
|
60
|
+
fi
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# 主函數
|
|
64
|
+
main() {
|
|
65
|
+
info "開始解除安裝 birc-generator..."
|
|
66
|
+
|
|
67
|
+
remove_symlink
|
|
68
|
+
remove_install_dir
|
|
69
|
+
clear_npm_cache
|
|
70
|
+
|
|
71
|
+
info "解除安裝完成!"
|
|
72
|
+
info "birc 指令已移除,安裝目錄已刪除。"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# 執行主函數
|
|
76
|
+
main "$@"
|
package/versions.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module.exports = Object.freeze({
|
|
2
|
+
springBootVersion: '4.0.5',
|
|
3
|
+
dependencyManagementVersion: '1.1.7',
|
|
4
|
+
flywayVersion: '11.14.1',
|
|
5
|
+
sentryVersion: '8.40.0',
|
|
6
|
+
springdocVersion: '3.0.2',
|
|
7
|
+
mapstructVersion: '1.6.3',
|
|
8
|
+
lombokMapstructBindingVersion: '0.2.0',
|
|
9
|
+
spotlessVersion: '6.25.0'
|
|
10
|
+
});
|