@wneng/create-keel 0.3.4 → 0.4.0

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.
Files changed (94) hide show
  1. package/dist/index.js +211 -18
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/src/templates/ci-gitee/files/PULL_REQUEST_TEMPLATE.md +13 -1
  5. package/src/templates/ci-gitee/files/pipeline.yml +71 -0
  6. package/src/templates/ci-github/files/PULL_REQUEST_TEMPLATE.md +13 -1
  7. package/src/templates/ci-github/files/ci.yml +169 -0
  8. package/src/templates/contracts-events/fragment.yaml +1 -1
  9. package/src/templates/contracts-rest-events/fragment.yaml +1 -1
  10. package/src/templates/db-go-elasticsearch/files/Makefile +18 -0
  11. package/src/templates/db-go-elasticsearch/files/apply_templates.go +80 -0
  12. package/src/templates/db-go-elasticsearch/files/db-README.md +57 -0
  13. package/src/templates/db-go-elasticsearch/files/go.mod +7 -0
  14. package/src/templates/db-go-elasticsearch/files/index-template-init.json +25 -0
  15. package/src/templates/db-go-elasticsearch/fragment.yaml +22 -0
  16. package/src/templates/db-go-migrate-mysql/files/000001_init.down.sql +3 -0
  17. package/src/templates/db-go-migrate-mysql/files/000001_init.up.sql +35 -0
  18. package/src/templates/db-go-migrate-mysql/files/Makefile +33 -0
  19. package/src/templates/db-go-migrate-mysql/files/db-README.md +77 -0
  20. package/src/templates/db-go-migrate-mysql/files/go.mod +8 -0
  21. package/src/templates/db-go-migrate-mysql/fragment.yaml +22 -0
  22. package/src/templates/db-go-migrate-postgres/files/000001_init.down.sql +3 -0
  23. package/src/templates/db-go-migrate-postgres/files/000001_init.up.sql +32 -0
  24. package/src/templates/db-go-migrate-postgres/files/Makefile +31 -0
  25. package/src/templates/db-go-migrate-postgres/files/db-README.md +71 -0
  26. package/src/templates/db-go-migrate-postgres/files/go.mod +8 -0
  27. package/src/templates/db-go-migrate-postgres/fragment.yaml +22 -0
  28. package/src/templates/db-java-elasticsearch/files/EsTemplateApplier.java +86 -0
  29. package/src/templates/db-java-elasticsearch/files/db-README.md +63 -0
  30. package/src/templates/db-java-elasticsearch/files/index-template-init.json +25 -0
  31. package/src/templates/db-java-elasticsearch/files/pom.xml +134 -0
  32. package/src/templates/db-java-elasticsearch/fragment.yaml +19 -0
  33. package/src/templates/db-java-flyway-mysql/files/V1__init.sql +44 -0
  34. package/src/templates/db-java-flyway-mysql/files/application.yaml +39 -0
  35. package/src/templates/db-java-flyway-mysql/files/db-README.md +102 -0
  36. package/src/templates/db-java-flyway-mysql/files/pom.xml +172 -0
  37. package/src/templates/db-java-flyway-mysql/fragment.yaml +19 -0
  38. package/src/templates/db-java-flyway-postgres/files/V1__init.sql +40 -0
  39. package/src/templates/db-java-flyway-postgres/files/application.yaml +37 -0
  40. package/src/templates/db-java-flyway-postgres/files/db-README.md +75 -0
  41. package/src/templates/db-java-flyway-postgres/files/pom.xml +166 -0
  42. package/src/templates/db-java-flyway-postgres/fragment.yaml +19 -0
  43. package/src/templates/db-node-elasticsearch/files/apply-templates.cjs +60 -0
  44. package/src/templates/db-node-elasticsearch/files/db-README.md +76 -0
  45. package/src/templates/db-node-elasticsearch/files/index-template-init.json +26 -0
  46. package/src/templates/db-node-elasticsearch/files/package.json +26 -0
  47. package/src/templates/db-node-elasticsearch/fragment.yaml +19 -0
  48. package/src/templates/db-node-knex-mysql/files/db-README.md +90 -0
  49. package/src/templates/db-node-knex-mysql/files/knexfile.cjs +72 -0
  50. package/src/templates/db-node-knex-mysql/files/migrations-init.cjs +42 -0
  51. package/src/templates/db-node-knex-mysql/files/package.json +31 -0
  52. package/src/templates/db-node-knex-mysql/files/seeds-dev-fixtures.cjs +38 -0
  53. package/src/templates/db-node-knex-mysql/files/seeds-prod-dictionaries.cjs +25 -0
  54. package/src/templates/db-node-knex-mysql/fragment.yaml +25 -0
  55. package/src/templates/db-node-knex-postgres/files/db-README.md +81 -0
  56. package/src/templates/db-node-knex-postgres/files/knexfile.cjs +67 -0
  57. package/src/templates/db-node-knex-postgres/files/migrations-init.cjs +42 -0
  58. package/src/templates/db-node-knex-postgres/files/package.json +31 -0
  59. package/src/templates/db-node-knex-postgres/files/seeds-dev-fixtures.cjs +36 -0
  60. package/src/templates/db-node-knex-postgres/files/seeds-prod-dictionaries.cjs +26 -0
  61. package/src/templates/db-node-knex-postgres/fragment.yaml +25 -0
  62. package/src/templates/db-python-alembic-mysql/files/0001_init.py +70 -0
  63. package/src/templates/db-python-alembic-mysql/files/alembic.ini +47 -0
  64. package/src/templates/db-python-alembic-mysql/files/db-README.md +87 -0
  65. package/src/templates/db-python-alembic-mysql/files/env.py +71 -0
  66. package/src/templates/db-python-alembic-mysql/files/pyproject.toml +52 -0
  67. package/src/templates/db-python-alembic-mysql/files/script.py.mako +26 -0
  68. package/src/templates/db-python-alembic-mysql/fragment.yaml +25 -0
  69. package/src/templates/db-python-alembic-postgres/files/0001_init.py +62 -0
  70. package/src/templates/db-python-alembic-postgres/files/alembic.ini +45 -0
  71. package/src/templates/db-python-alembic-postgres/files/db-README.md +70 -0
  72. package/src/templates/db-python-alembic-postgres/files/env.py +62 -0
  73. package/src/templates/db-python-alembic-postgres/files/pyproject.toml +52 -0
  74. package/src/templates/db-python-alembic-postgres/files/script.py.mako +25 -0
  75. package/src/templates/db-python-alembic-postgres/fragment.yaml +25 -0
  76. package/src/templates/db-python-elasticsearch/files/apply_templates.py +55 -0
  77. package/src/templates/db-python-elasticsearch/files/db-README.md +57 -0
  78. package/src/templates/db-python-elasticsearch/files/index-template-init.json +25 -0
  79. package/src/templates/db-python-elasticsearch/files/pyproject.toml +50 -0
  80. package/src/templates/db-python-elasticsearch/fragment.yaml +19 -0
  81. package/src/templates/docs-skeleton/files/governance-change-tiers.md +135 -0
  82. package/src/templates/docs-skeleton/files/governance-database.md +150 -0
  83. package/src/templates/docs-skeleton/fragment.yaml +6 -0
  84. package/src/templates/root-files/files/AGENTS.md +42 -7
  85. package/src/templates/server-node/files/_eslintrc.cjs +5 -1
  86. package/src/templates/server-python/files/README.md +75 -2
  87. package/src/templates/server-python/files/app-init.py +11 -1
  88. package/src/templates/server-python/files/config.py +40 -0
  89. package/src/templates/server-python/files/main.py +62 -0
  90. package/src/templates/server-python/files/pyproject.toml +14 -1
  91. package/src/templates/server-python/files/test_healthz.py +36 -0
  92. package/src/templates/server-python/fragment.yaml +10 -1
  93. package/src/templates/web-react/files/_eslintrc.cjs +5 -1
  94. package/src/templates/web-vue/files/_eslintrc.cjs +5 -1
@@ -0,0 +1,39 @@
1
+ spring:
2
+ application:
3
+ name: <%= it.options.projectName %>-server
4
+ datasource:
5
+ url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/<%= it.options.projectName %>?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useUnicode=true}
6
+ username: ${SPRING_DATASOURCE_USERNAME:root}
7
+ password: ${SPRING_DATASOURCE_PASSWORD:}
8
+ driver-class-name: com.mysql.cj.jdbc.Driver
9
+ jpa:
10
+ # Flyway 接管 schema 演化,关掉 Hibernate 的 ddl-auto 避免双向漂移
11
+ hibernate:
12
+ ddl-auto: validate
13
+ properties:
14
+ hibernate:
15
+ dialect: org.hibernate.dialect.MySQLDialect
16
+ format_sql: true
17
+ show-sql: false
18
+ open-in-view: false
19
+ flyway:
20
+ enabled: true
21
+ locations: classpath:db/migration
22
+ baseline-on-migrate: false
23
+ validate-on-migrate: true
24
+ # 修改既有迁移文件 = 破坏性变更;CI 里 out-of-order=false 会拦截
25
+ out-of-order: false
26
+
27
+ server:
28
+ port: 8080
29
+
30
+ management:
31
+ endpoints:
32
+ web:
33
+ exposure:
34
+ include: health,info,flyway
35
+
36
+ app:
37
+ jwt:
38
+ secret: ${JWT_SECRET:change-me-please-this-is-a-development-secret-only-min-32-chars}
39
+ expiration-minutes: 120
@@ -0,0 +1,102 @@
1
+ # server/db/
2
+
3
+ Spring Boot + Flyway 项目的数据库入口。
4
+
5
+ > 跨项目的数据库归属规则(哪类 SQL 放哪个目录、与 `contracts/` 如何对齐)见 [`docs/governance/database.md`](../../docs/governance/database.md)。本文件只解释**本项目的工具与命令**。
6
+
7
+ ## 工具与版本
8
+
9
+ | 项 | 值 |
10
+ |---|---|
11
+ | 数据库 | MySQL 8 / MariaDB 10.6+ |
12
+ | 迁移工具 | [Flyway](https://flywaydb.org) `10.20.0` |
13
+ | 驱动 | `mysql-connector-j` `9.1.0` |
14
+
15
+ 工具版本在 `pom.xml` 钉死,并镜像到 `docs/03-工程规范与研发基础设施/tech-stack-server.md`。governance-lint 检测两边漂移并阻断 PR;升级时同 PR 改两个文件。
16
+
17
+ ## 路径分歧(重要)
18
+
19
+ Spring Boot + Flyway 的迁移文件**不在** `server/db/migrations/`,而在 Spring Boot 的默认扫描路径:
20
+
21
+ ```
22
+ server/
23
+ ├── src/main/resources/
24
+ │ └── db/migration/ # ← Flyway 扫描这里
25
+ │ ├── V1__init.sql
26
+ │ └── V2__add_orders.sql
27
+ └── db/
28
+ ├── README.md # 本文件(保留作为 keel 框架的入口)
29
+ └── seeds/
30
+ └── dev/ # 仅本地 / 测试用,与 Flyway 无关
31
+ └── 0001_dev_users.sql
32
+ ```
33
+
34
+ 之所以接受这个分歧而不强行统一到 `server/db/migrations/`:Spring Boot 在启动时自动扫描 `classpath:db/migration`,逆这个默认会让用户每次都改 `application.yaml`。`server/db/` 仍是 keel 约定的入口(README + seeds),与其他后端语言保持视觉一致。
35
+
36
+ ## 目录布局
37
+
38
+ ```
39
+ server/src/main/resources/
40
+ ├── application.yaml # spring.flyway.* 配置
41
+ └── db/migration/ # Flyway 迁移文件
42
+ └── V<N>__<description>.sql
43
+ ```
44
+
45
+ ## 文件命名规则
46
+
47
+ - 版本化迁移:`V<N>__<description>.sql`
48
+ - `N` 单调递增整数,不允许跳号
49
+ - 已合入 `main` 的文件**绝对不能修改** —— 改 schema 写 `V<N+1>__*.sql`
50
+ - 可重复迁移:`R__<description>.sql`(每次 schema hash 变化时重跑)
51
+ - 用于视图、存储过程、字典数据 upsert
52
+ - 撤销迁移:Flyway Community 不支持 `down`;回滚靠新写一条 `V<N+1>__revert_*.sql`
53
+
54
+ ## 常用命令
55
+
56
+ ```bash
57
+ # Spring Boot 启动时自动应用所有 pending 迁移(默认行为)
58
+ mvn spring-boot:run
59
+
60
+ # 不启动应用,单独跑迁移
61
+ mvn flyway:migrate
62
+
63
+ # 查看当前迁移状态
64
+ mvn flyway:info
65
+
66
+ # 检查迁移文件 vs DB 历史是否一致(CI 用)
67
+ mvn flyway:validate
68
+ ```
69
+
70
+ 环境变量:`SPRING_DATASOURCE_URL` / `SPRING_DATASOURCE_USERNAME` / `SPRING_DATASOURCE_PASSWORD`。
71
+
72
+ ## prod vs dev seeds
73
+
74
+ Flyway 把"种子数据"分成两类:
75
+
76
+ | 类型 | 位置 | 命名 |
77
+ |---|---|---|
78
+ | 生产字典(必装) | `src/main/resources/db/migration/` | `V<N>__seed_<topic>.sql`(首次)或 `R__<topic>.sql`(每次重跑) |
79
+ | 开发样例 | `server/db/seeds/dev/`(不在 Flyway 路径下) | 任意;用 `mysql -e 'source ...'` 手动加载 |
80
+
81
+ 字典类生产种子的真值在 `contracts/dictionaries/enums.yaml`。改字典的 PR 必须**同步**更新对应 SQL;当前是手动同步(自动派生留给 `contract-derived-seeds` 特性)。
82
+
83
+ ## 改动分级(参见 `docs/governance/change-tiers.md`)
84
+
85
+ | 改动 | Tier |
86
+ |---|---|
87
+ | 新增 `V<N>__*.sql` 加表 / 加字段 | 3(contract 一致性 + CHANGELOG) |
88
+ | 修改既有 `V<N>__*.sql` | **绝不允许**;写新文件 |
89
+ | 删字段 / 改类型(破坏性) | 4(ADR + 迁移预案) |
90
+ | 改 dev seed | 1/2 |
91
+ | 改字典 `R__*.sql` 或 prod 种子 | 3(同步 contracts/dictionaries/) |
92
+ | 升级 Flyway / mysql-connector-j | 2,但同步改 tech-stack-server.md |
93
+
94
+ ## CI 行为
95
+
96
+ 每个 PR 的 backend job 跑:
97
+
98
+ ```bash
99
+ mvn -B verify # 含 mvn flyway:migrate(启动应用时)+ mvn flyway:validate
100
+ ```
101
+
102
+ `spring.flyway.validate-on-migrate=true` 强制每次启动时校验"代码里的迁移文件历史"与"DB 中已应用的版本"完全一致;任何已合入 `main` 的迁移被改动都会让 CI 红。
@@ -0,0 +1,172 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5
+ https://maven.apache.org/xsd/maven-4.0.0.xsd">
6
+ <modelVersion>4.0.0</modelVersion>
7
+
8
+ <parent>
9
+ <groupId>org.springframework.boot</groupId>
10
+ <artifactId>spring-boot-starter-parent</artifactId>
11
+ <version>3.3.4</version>
12
+ <relativePath/>
13
+ </parent>
14
+
15
+ <groupId>com.example</groupId>
16
+ <artifactId><%= it.options.projectName %>-server</artifactId>
17
+ <version>0.1.0</version>
18
+ <packaging>jar</packaging>
19
+ <name><%= it.options.projectName %>-server</name>
20
+
21
+ <properties>
22
+ <java.version>21</java.version>
23
+ <maven.compiler.source>21</maven.compiler.source>
24
+ <maven.compiler.target>21</maven.compiler.target>
25
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26
+ <jjwt.version>0.12.6</jjwt.version>
27
+ <flyway.version>10.20.0</flyway.version>
28
+ </properties>
29
+
30
+ <dependencies>
31
+ <dependency>
32
+ <groupId>org.springframework.boot</groupId>
33
+ <artifactId>spring-boot-starter-web</artifactId>
34
+ </dependency>
35
+ <dependency>
36
+ <groupId>org.springframework.boot</groupId>
37
+ <artifactId>spring-boot-starter-validation</artifactId>
38
+ </dependency>
39
+ <dependency>
40
+ <groupId>org.springframework.boot</groupId>
41
+ <artifactId>spring-boot-starter-actuator</artifactId>
42
+ </dependency>
43
+ <dependency>
44
+ <groupId>org.springframework.boot</groupId>
45
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
46
+ </dependency>
47
+ <dependency>
48
+ <groupId>org.springframework.boot</groupId>
49
+ <artifactId>spring-boot-starter-security</artifactId>
50
+ </dependency>
51
+
52
+ <!--
53
+ Flyway: 数据库迁移工具。
54
+ Spring Boot 启动时自动扫描 src/main/resources/db/migration/V*__*.sql
55
+ 并按版本号顺序应用(一次性);也可通过 `mvn flyway:migrate` 手动执行。
56
+ 版本号一旦合入 main 不允许修改;改 schema 写新文件 V<N+1>__*.sql。
57
+ -->
58
+ <dependency>
59
+ <groupId>org.flywaydb</groupId>
60
+ <artifactId>flyway-core</artifactId>
61
+ <version>${flyway.version}</version>
62
+ </dependency>
63
+ <dependency>
64
+ <groupId>org.flywaydb</groupId>
65
+ <artifactId>flyway-mysql</artifactId>
66
+ <version>${flyway.version}</version>
67
+ </dependency>
68
+
69
+ <dependency>
70
+ <groupId>com.mysql</groupId>
71
+ <artifactId>mysql-connector-j</artifactId>
72
+ <version>9.1.0</version>
73
+ <scope>runtime</scope>
74
+ </dependency>
75
+
76
+ <dependency>
77
+ <groupId>io.jsonwebtoken</groupId>
78
+ <artifactId>jjwt-api</artifactId>
79
+ <version>${jjwt.version}</version>
80
+ </dependency>
81
+ <dependency>
82
+ <groupId>io.jsonwebtoken</groupId>
83
+ <artifactId>jjwt-impl</artifactId>
84
+ <version>${jjwt.version}</version>
85
+ <scope>runtime</scope>
86
+ </dependency>
87
+ <dependency>
88
+ <groupId>io.jsonwebtoken</groupId>
89
+ <artifactId>jjwt-jackson</artifactId>
90
+ <version>${jjwt.version}</version>
91
+ <scope>runtime</scope>
92
+ </dependency>
93
+ <dependency>
94
+ <groupId>org.springframework.boot</groupId>
95
+ <artifactId>spring-boot-starter-test</artifactId>
96
+ <scope>test</scope>
97
+ </dependency>
98
+ <dependency>
99
+ <groupId>org.springframework.security</groupId>
100
+ <artifactId>spring-security-test</artifactId>
101
+ <scope>test</scope>
102
+ </dependency>
103
+ <dependency>
104
+ <groupId>com.h2database</groupId>
105
+ <artifactId>h2</artifactId>
106
+ <scope>test</scope>
107
+ </dependency>
108
+ </dependencies>
109
+
110
+ <build>
111
+ <plugins>
112
+ <plugin>
113
+ <groupId>org.springframework.boot</groupId>
114
+ <artifactId>spring-boot-maven-plugin</artifactId>
115
+ </plugin>
116
+
117
+ <plugin>
118
+ <groupId>org.flywaydb</groupId>
119
+ <artifactId>flyway-maven-plugin</artifactId>
120
+ <version>${flyway.version}</version>
121
+ <configuration>
122
+ <url>${env.SPRING_DATASOURCE_URL}</url>
123
+ <user>${env.SPRING_DATASOURCE_USERNAME}</user>
124
+ <password>${env.SPRING_DATASOURCE_PASSWORD}</password>
125
+ </configuration>
126
+ </plugin>
127
+
128
+ <plugin>
129
+ <groupId>org.apache.maven.plugins</groupId>
130
+ <artifactId>maven-checkstyle-plugin</artifactId>
131
+ <version>3.5.0</version>
132
+ <configuration>
133
+ <configLocation>checkstyle.xml</configLocation>
134
+ <consoleOutput>true</consoleOutput>
135
+ <failsOnError>true</failsOnError>
136
+ <linkXRef>false</linkXRef>
137
+ </configuration>
138
+ <executions>
139
+ <execution>
140
+ <id>verify-checkstyle</id>
141
+ <phase>verify</phase>
142
+ <goals><goal>check</goal></goals>
143
+ </execution>
144
+ </executions>
145
+ </plugin>
146
+
147
+ <plugin>
148
+ <groupId>com.diffplug.spotless</groupId>
149
+ <artifactId>spotless-maven-plugin</artifactId>
150
+ <version>2.43.0</version>
151
+ <configuration>
152
+ <java>
153
+ <googleJavaFormat>
154
+ <version>1.22.0</version>
155
+ <style>AOSP</style>
156
+ </googleJavaFormat>
157
+ <removeUnusedImports/>
158
+ <trimTrailingWhitespace/>
159
+ <endWithNewline/>
160
+ </java>
161
+ </configuration>
162
+ <executions>
163
+ <execution>
164
+ <id>verify-spotless</id>
165
+ <phase>verify</phase>
166
+ <goals><goal>check</goal></goals>
167
+ </execution>
168
+ </executions>
169
+ </plugin>
170
+ </plugins>
171
+ </build>
172
+ </project>
@@ -0,0 +1,19 @@
1
+ name: db-java-flyway-mysql
2
+ version: 1.0.0
3
+ appliesWhen:
4
+ backend: java
5
+ database: mysql
6
+ priority: 40
7
+ files:
8
+ - from: files/pom.xml
9
+ to: server/pom.xml
10
+ render: true
11
+ - from: files/application.yaml
12
+ to: server/src/main/resources/application.yaml
13
+ render: true
14
+ - from: files/V1__init.sql
15
+ to: server/src/main/resources/db/migration/V1__init.sql
16
+ render: false
17
+ - from: files/db-README.md
18
+ to: server/db/README.md
19
+ render: true
@@ -0,0 +1,40 @@
1
+ -- V1__init.sql — 初始化迁移
2
+ --
3
+ -- 命名规则:V<N>__<description>.sql。N 单调递增;不允许跳号。
4
+ -- 已合入 main 的迁移文件**不可修改**——改 schema 写 V<N+1>__*.sql。
5
+ -- 修改既有迁移属于破坏性变更,应升 Tier 4(参见 docs/governance/change-tiers.md)。
6
+ --
7
+ -- PostgreSQL 注意:
8
+ -- - 主键统一用 BIGINT GENERATED ALWAYS AS IDENTITY
9
+ -- - 文本默认用 TEXT,仅在确需限长时用 VARCHAR(n)
10
+ -- - 时间列用 TIMESTAMPTZ,统一存 UTC
11
+
12
+ CREATE TABLE IF NOT EXISTS roles (
13
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
14
+ code VARCHAR(64) NOT NULL UNIQUE,
15
+ name VARCHAR(128) NOT NULL,
16
+ description TEXT NULL,
17
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
18
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
19
+ );
20
+
21
+ CREATE TABLE IF NOT EXISTS users (
22
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
23
+ email VARCHAR(255) NOT NULL UNIQUE,
24
+ password_hash VARCHAR(255) NOT NULL,
25
+ display_name VARCHAR(128) NULL,
26
+ role_id BIGINT NOT NULL REFERENCES roles (id),
27
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
28
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
29
+ deleted_at TIMESTAMPTZ NULL
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_users_role_id ON users (role_id);
33
+ CREATE INDEX IF NOT EXISTS idx_users_deleted_at ON users (deleted_at);
34
+
35
+ -- 字典数据:与 contracts/dictionaries/enums.yaml 对齐。
36
+ -- ON CONFLICT DO NOTHING 保证多次跑幂等;改字典的 PR 必须同步改这里 + contracts/CHANGELOG.md。
37
+ INSERT INTO roles (code, name, description) VALUES
38
+ ('admin', '系统管理员', '可执行所有管理操作'),
39
+ ('user', '普通用户', '默认注册角色')
40
+ ON CONFLICT (code) DO NOTHING;
@@ -0,0 +1,37 @@
1
+ spring:
2
+ application:
3
+ name: <%= it.options.projectName %>-server
4
+ datasource:
5
+ url: ${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/<%= it.options.projectName %>}
6
+ username: ${SPRING_DATASOURCE_USERNAME:postgres}
7
+ password: ${SPRING_DATASOURCE_PASSWORD:}
8
+ driver-class-name: org.postgresql.Driver
9
+ jpa:
10
+ hibernate:
11
+ ddl-auto: validate
12
+ properties:
13
+ hibernate:
14
+ dialect: org.hibernate.dialect.PostgreSQLDialect
15
+ format_sql: true
16
+ show-sql: false
17
+ open-in-view: false
18
+ flyway:
19
+ enabled: true
20
+ locations: classpath:db/migration
21
+ baseline-on-migrate: false
22
+ validate-on-migrate: true
23
+ out-of-order: false
24
+
25
+ server:
26
+ port: 8080
27
+
28
+ management:
29
+ endpoints:
30
+ web:
31
+ exposure:
32
+ include: health,info,flyway
33
+
34
+ app:
35
+ jwt:
36
+ secret: ${JWT_SECRET:change-me-please-this-is-a-development-secret-only-min-32-chars}
37
+ expiration-minutes: 120
@@ -0,0 +1,75 @@
1
+ # server/db/
2
+
3
+ Spring Boot + Flyway 项目的数据库入口。
4
+
5
+ > 跨项目的数据库归属规则(哪类 SQL 放哪个目录、与 `contracts/` 如何对齐)见 [`docs/governance/database.md`](../../docs/governance/database.md)。本文件只解释**本项目的工具与命令**。
6
+
7
+ ## 工具与版本
8
+
9
+ | 项 | 值 |
10
+ |---|---|
11
+ | 数据库 | PostgreSQL 14+ |
12
+ | 迁移工具 | [Flyway](https://flywaydb.org) `10.20.0` |
13
+ | 驱动 | `postgresql` (JDBC) `42.7.4` |
14
+
15
+ 工具版本在 `pom.xml` 钉死,并镜像到 `docs/03-工程规范与研发基础设施/tech-stack-server.md`。governance-lint 检测两边漂移并阻断 PR;升级时同 PR 改两个文件。
16
+
17
+ ## 路径分歧(重要)
18
+
19
+ Spring Boot + Flyway 的迁移文件**不在** `server/db/migrations/`,而在 Spring Boot 的默认扫描路径:
20
+
21
+ ```
22
+ server/
23
+ ├── src/main/resources/
24
+ │ └── db/migration/ # ← Flyway 扫描这里
25
+ │ ├── V1__init.sql
26
+ │ └── V2__add_orders.sql
27
+ └── db/
28
+ ├── README.md # 本文件(保留作为 keel 框架的入口)
29
+ └── seeds/
30
+ └── dev/ # 仅本地 / 测试用
31
+ └── 0001_dev_users.sql
32
+ ```
33
+
34
+ 之所以接受这个分歧而不强行统一到 `server/db/migrations/`:Spring Boot 在启动时自动扫描 `classpath:db/migration`,逆这个默认会让用户每次都改 `application.yaml`。
35
+
36
+ ## 文件命名规则
37
+
38
+ - 版本化迁移:`V<N>__<description>.sql`(N 单调递增,不跳号;已合入 `main` 不可修改)
39
+ - 可重复迁移:`R__<description>.sql`(每次 schema hash 变化时重跑,用于视图、字典 upsert)
40
+ - 撤销迁移:Flyway Community 不支持 `down`;回滚靠新写一条 `V<N+1>__revert_*.sql`
41
+
42
+ ## 常用命令
43
+
44
+ ```bash
45
+ mvn spring-boot:run # 启动应用,自动跑 pending 迁移
46
+ mvn flyway:migrate # 仅跑迁移
47
+ mvn flyway:info # 查看当前状态
48
+ mvn flyway:validate # 校验代码 vs DB 历史一致(CI 用)
49
+ ```
50
+
51
+ 环境变量:`SPRING_DATASOURCE_URL` / `SPRING_DATASOURCE_USERNAME` / `SPRING_DATASOURCE_PASSWORD`。
52
+
53
+ ## prod vs dev seeds
54
+
55
+ | 类型 | 位置 | 命名 |
56
+ |---|---|---|
57
+ | 生产字典(必装) | `src/main/resources/db/migration/` | `V<N>__seed_<topic>.sql` 或 `R__<topic>.sql` |
58
+ | 开发样例 | `server/db/seeds/dev/` | 任意;用 `psql -f <file>` 手动加载 |
59
+
60
+ 字典类生产种子的真值在 `contracts/dictionaries/enums.yaml`。改字典的 PR 必须**同步**更新对应 SQL;当前是手动同步。
61
+
62
+ ## 改动分级(参见 `docs/governance/change-tiers.md`)
63
+
64
+ | 改动 | Tier |
65
+ |---|---|
66
+ | 新增 `V<N>__*.sql` 加表 / 加字段 | 3(contract 一致性 + CHANGELOG) |
67
+ | 修改既有 `V<N>__*.sql` | **绝不允许**;写新文件 |
68
+ | 删字段 / 改类型(破坏性) | 4(ADR + 迁移预案) |
69
+ | 改 dev seed | 1/2 |
70
+ | 改字典 `R__*.sql` 或 prod 种子 | 3(同步 contracts/dictionaries/) |
71
+ | 升级 Flyway / postgresql 驱动 | 2,但同步改 tech-stack-server.md |
72
+
73
+ ## CI 行为
74
+
75
+ 每个 PR 的 backend job 跑 `mvn -B verify`,含 `flyway:migrate` + `flyway:validate`;任何已合入 `main` 的迁移被改动都会让 CI 红。
@@ -0,0 +1,166 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5
+ https://maven.apache.org/xsd/maven-4.0.0.xsd">
6
+ <modelVersion>4.0.0</modelVersion>
7
+
8
+ <parent>
9
+ <groupId>org.springframework.boot</groupId>
10
+ <artifactId>spring-boot-starter-parent</artifactId>
11
+ <version>3.3.4</version>
12
+ <relativePath/>
13
+ </parent>
14
+
15
+ <groupId>com.example</groupId>
16
+ <artifactId><%= it.options.projectName %>-server</artifactId>
17
+ <version>0.1.0</version>
18
+ <packaging>jar</packaging>
19
+ <name><%= it.options.projectName %>-server</name>
20
+
21
+ <properties>
22
+ <java.version>21</java.version>
23
+ <maven.compiler.source>21</maven.compiler.source>
24
+ <maven.compiler.target>21</maven.compiler.target>
25
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26
+ <jjwt.version>0.12.6</jjwt.version>
27
+ <flyway.version>10.20.0</flyway.version>
28
+ </properties>
29
+
30
+ <dependencies>
31
+ <dependency>
32
+ <groupId>org.springframework.boot</groupId>
33
+ <artifactId>spring-boot-starter-web</artifactId>
34
+ </dependency>
35
+ <dependency>
36
+ <groupId>org.springframework.boot</groupId>
37
+ <artifactId>spring-boot-starter-validation</artifactId>
38
+ </dependency>
39
+ <dependency>
40
+ <groupId>org.springframework.boot</groupId>
41
+ <artifactId>spring-boot-starter-actuator</artifactId>
42
+ </dependency>
43
+ <dependency>
44
+ <groupId>org.springframework.boot</groupId>
45
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
46
+ </dependency>
47
+ <dependency>
48
+ <groupId>org.springframework.boot</groupId>
49
+ <artifactId>spring-boot-starter-security</artifactId>
50
+ </dependency>
51
+
52
+ <dependency>
53
+ <groupId>org.flywaydb</groupId>
54
+ <artifactId>flyway-core</artifactId>
55
+ <version>${flyway.version}</version>
56
+ </dependency>
57
+ <dependency>
58
+ <groupId>org.flywaydb</groupId>
59
+ <artifactId>flyway-database-postgresql</artifactId>
60
+ <version>${flyway.version}</version>
61
+ </dependency>
62
+
63
+ <dependency>
64
+ <groupId>org.postgresql</groupId>
65
+ <artifactId>postgresql</artifactId>
66
+ <version>42.7.4</version>
67
+ <scope>runtime</scope>
68
+ </dependency>
69
+
70
+ <dependency>
71
+ <groupId>io.jsonwebtoken</groupId>
72
+ <artifactId>jjwt-api</artifactId>
73
+ <version>${jjwt.version}</version>
74
+ </dependency>
75
+ <dependency>
76
+ <groupId>io.jsonwebtoken</groupId>
77
+ <artifactId>jjwt-impl</artifactId>
78
+ <version>${jjwt.version}</version>
79
+ <scope>runtime</scope>
80
+ </dependency>
81
+ <dependency>
82
+ <groupId>io.jsonwebtoken</groupId>
83
+ <artifactId>jjwt-jackson</artifactId>
84
+ <version>${jjwt.version}</version>
85
+ <scope>runtime</scope>
86
+ </dependency>
87
+ <dependency>
88
+ <groupId>org.springframework.boot</groupId>
89
+ <artifactId>spring-boot-starter-test</artifactId>
90
+ <scope>test</scope>
91
+ </dependency>
92
+ <dependency>
93
+ <groupId>org.springframework.security</groupId>
94
+ <artifactId>spring-security-test</artifactId>
95
+ <scope>test</scope>
96
+ </dependency>
97
+ <dependency>
98
+ <groupId>com.h2database</groupId>
99
+ <artifactId>h2</artifactId>
100
+ <scope>test</scope>
101
+ </dependency>
102
+ </dependencies>
103
+
104
+ <build>
105
+ <plugins>
106
+ <plugin>
107
+ <groupId>org.springframework.boot</groupId>
108
+ <artifactId>spring-boot-maven-plugin</artifactId>
109
+ </plugin>
110
+
111
+ <plugin>
112
+ <groupId>org.flywaydb</groupId>
113
+ <artifactId>flyway-maven-plugin</artifactId>
114
+ <version>${flyway.version}</version>
115
+ <configuration>
116
+ <url>${env.SPRING_DATASOURCE_URL}</url>
117
+ <user>${env.SPRING_DATASOURCE_USERNAME}</user>
118
+ <password>${env.SPRING_DATASOURCE_PASSWORD}</password>
119
+ </configuration>
120
+ </plugin>
121
+
122
+ <plugin>
123
+ <groupId>org.apache.maven.plugins</groupId>
124
+ <artifactId>maven-checkstyle-plugin</artifactId>
125
+ <version>3.5.0</version>
126
+ <configuration>
127
+ <configLocation>checkstyle.xml</configLocation>
128
+ <consoleOutput>true</consoleOutput>
129
+ <failsOnError>true</failsOnError>
130
+ <linkXRef>false</linkXRef>
131
+ </configuration>
132
+ <executions>
133
+ <execution>
134
+ <id>verify-checkstyle</id>
135
+ <phase>verify</phase>
136
+ <goals><goal>check</goal></goals>
137
+ </execution>
138
+ </executions>
139
+ </plugin>
140
+
141
+ <plugin>
142
+ <groupId>com.diffplug.spotless</groupId>
143
+ <artifactId>spotless-maven-plugin</artifactId>
144
+ <version>2.43.0</version>
145
+ <configuration>
146
+ <java>
147
+ <googleJavaFormat>
148
+ <version>1.22.0</version>
149
+ <style>AOSP</style>
150
+ </googleJavaFormat>
151
+ <removeUnusedImports/>
152
+ <trimTrailingWhitespace/>
153
+ <endWithNewline/>
154
+ </java>
155
+ </configuration>
156
+ <executions>
157
+ <execution>
158
+ <id>verify-spotless</id>
159
+ <phase>verify</phase>
160
+ <goals><goal>check</goal></goals>
161
+ </execution>
162
+ </executions>
163
+ </plugin>
164
+ </plugins>
165
+ </build>
166
+ </project>
@@ -0,0 +1,19 @@
1
+ name: db-java-flyway-postgres
2
+ version: 1.0.0
3
+ appliesWhen:
4
+ backend: java
5
+ database: postgres
6
+ priority: 40
7
+ files:
8
+ - from: files/pom.xml
9
+ to: server/pom.xml
10
+ render: true
11
+ - from: files/application.yaml
12
+ to: server/src/main/resources/application.yaml
13
+ render: true
14
+ - from: files/V1__init.sql
15
+ to: server/src/main/resources/db/migration/V1__init.sql
16
+ render: false
17
+ - from: files/db-README.md
18
+ to: server/db/README.md
19
+ render: true