@wneng/create-keel 0.3.6 → 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 (86) hide show
  1. package/dist/index.js +206 -13
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/src/templates/ci-gitee/files/pipeline.yml +62 -0
  5. package/src/templates/ci-github/files/ci.yml +160 -0
  6. package/src/templates/db-go-elasticsearch/files/Makefile +18 -0
  7. package/src/templates/db-go-elasticsearch/files/apply_templates.go +80 -0
  8. package/src/templates/db-go-elasticsearch/files/db-README.md +57 -0
  9. package/src/templates/db-go-elasticsearch/files/go.mod +7 -0
  10. package/src/templates/db-go-elasticsearch/files/index-template-init.json +25 -0
  11. package/src/templates/db-go-elasticsearch/fragment.yaml +22 -0
  12. package/src/templates/db-go-migrate-mysql/files/000001_init.down.sql +3 -0
  13. package/src/templates/db-go-migrate-mysql/files/000001_init.up.sql +35 -0
  14. package/src/templates/db-go-migrate-mysql/files/Makefile +33 -0
  15. package/src/templates/db-go-migrate-mysql/files/db-README.md +77 -0
  16. package/src/templates/db-go-migrate-mysql/files/go.mod +8 -0
  17. package/src/templates/db-go-migrate-mysql/fragment.yaml +22 -0
  18. package/src/templates/db-go-migrate-postgres/files/000001_init.down.sql +3 -0
  19. package/src/templates/db-go-migrate-postgres/files/000001_init.up.sql +32 -0
  20. package/src/templates/db-go-migrate-postgres/files/Makefile +31 -0
  21. package/src/templates/db-go-migrate-postgres/files/db-README.md +71 -0
  22. package/src/templates/db-go-migrate-postgres/files/go.mod +8 -0
  23. package/src/templates/db-go-migrate-postgres/fragment.yaml +22 -0
  24. package/src/templates/db-java-elasticsearch/files/EsTemplateApplier.java +86 -0
  25. package/src/templates/db-java-elasticsearch/files/db-README.md +63 -0
  26. package/src/templates/db-java-elasticsearch/files/index-template-init.json +25 -0
  27. package/src/templates/db-java-elasticsearch/files/pom.xml +134 -0
  28. package/src/templates/db-java-elasticsearch/fragment.yaml +19 -0
  29. package/src/templates/db-java-flyway-mysql/files/V1__init.sql +44 -0
  30. package/src/templates/db-java-flyway-mysql/files/application.yaml +39 -0
  31. package/src/templates/db-java-flyway-mysql/files/db-README.md +102 -0
  32. package/src/templates/db-java-flyway-mysql/files/pom.xml +172 -0
  33. package/src/templates/db-java-flyway-mysql/fragment.yaml +19 -0
  34. package/src/templates/db-java-flyway-postgres/files/V1__init.sql +40 -0
  35. package/src/templates/db-java-flyway-postgres/files/application.yaml +37 -0
  36. package/src/templates/db-java-flyway-postgres/files/db-README.md +75 -0
  37. package/src/templates/db-java-flyway-postgres/files/pom.xml +166 -0
  38. package/src/templates/db-java-flyway-postgres/fragment.yaml +19 -0
  39. package/src/templates/db-node-elasticsearch/files/apply-templates.cjs +60 -0
  40. package/src/templates/db-node-elasticsearch/files/db-README.md +76 -0
  41. package/src/templates/db-node-elasticsearch/files/index-template-init.json +26 -0
  42. package/src/templates/db-node-elasticsearch/files/package.json +26 -0
  43. package/src/templates/db-node-elasticsearch/fragment.yaml +19 -0
  44. package/src/templates/db-node-knex-mysql/files/db-README.md +90 -0
  45. package/src/templates/db-node-knex-mysql/files/knexfile.cjs +72 -0
  46. package/src/templates/db-node-knex-mysql/files/migrations-init.cjs +42 -0
  47. package/src/templates/db-node-knex-mysql/files/package.json +31 -0
  48. package/src/templates/db-node-knex-mysql/files/seeds-dev-fixtures.cjs +38 -0
  49. package/src/templates/db-node-knex-mysql/files/seeds-prod-dictionaries.cjs +25 -0
  50. package/src/templates/db-node-knex-mysql/fragment.yaml +25 -0
  51. package/src/templates/db-node-knex-postgres/files/db-README.md +81 -0
  52. package/src/templates/db-node-knex-postgres/files/knexfile.cjs +67 -0
  53. package/src/templates/db-node-knex-postgres/files/migrations-init.cjs +42 -0
  54. package/src/templates/db-node-knex-postgres/files/package.json +31 -0
  55. package/src/templates/db-node-knex-postgres/files/seeds-dev-fixtures.cjs +36 -0
  56. package/src/templates/db-node-knex-postgres/files/seeds-prod-dictionaries.cjs +26 -0
  57. package/src/templates/db-node-knex-postgres/fragment.yaml +25 -0
  58. package/src/templates/db-python-alembic-mysql/files/0001_init.py +70 -0
  59. package/src/templates/db-python-alembic-mysql/files/alembic.ini +47 -0
  60. package/src/templates/db-python-alembic-mysql/files/db-README.md +87 -0
  61. package/src/templates/db-python-alembic-mysql/files/env.py +71 -0
  62. package/src/templates/db-python-alembic-mysql/files/pyproject.toml +52 -0
  63. package/src/templates/db-python-alembic-mysql/files/script.py.mako +26 -0
  64. package/src/templates/db-python-alembic-mysql/fragment.yaml +25 -0
  65. package/src/templates/db-python-alembic-postgres/files/0001_init.py +62 -0
  66. package/src/templates/db-python-alembic-postgres/files/alembic.ini +45 -0
  67. package/src/templates/db-python-alembic-postgres/files/db-README.md +70 -0
  68. package/src/templates/db-python-alembic-postgres/files/env.py +62 -0
  69. package/src/templates/db-python-alembic-postgres/files/pyproject.toml +52 -0
  70. package/src/templates/db-python-alembic-postgres/files/script.py.mako +25 -0
  71. package/src/templates/db-python-alembic-postgres/fragment.yaml +25 -0
  72. package/src/templates/db-python-elasticsearch/files/apply_templates.py +55 -0
  73. package/src/templates/db-python-elasticsearch/files/db-README.md +57 -0
  74. package/src/templates/db-python-elasticsearch/files/index-template-init.json +25 -0
  75. package/src/templates/db-python-elasticsearch/files/pyproject.toml +50 -0
  76. package/src/templates/db-python-elasticsearch/fragment.yaml +19 -0
  77. package/src/templates/docs-skeleton/files/governance-database.md +150 -0
  78. package/src/templates/docs-skeleton/fragment.yaml +3 -0
  79. package/src/templates/root-files/files/AGENTS.md +6 -2
  80. package/src/templates/server-python/files/README.md +75 -2
  81. package/src/templates/server-python/files/app-init.py +11 -1
  82. package/src/templates/server-python/files/config.py +40 -0
  83. package/src/templates/server-python/files/main.py +62 -0
  84. package/src/templates/server-python/files/pyproject.toml +14 -1
  85. package/src/templates/server-python/files/test_healthz.py +36 -0
  86. package/src/templates/server-python/fragment.yaml +10 -1
@@ -0,0 +1,32 @@
1
+ -- 000001_init.up.sql — 初始化迁移
2
+ --
3
+ -- 命名规则:<NNNNNN>_<description>.up.sql / .down.sql。
4
+ -- 已合入 main 不可修改;改 schema 写新文件 NNNNNN+1。
5
+
6
+ CREATE TABLE IF NOT EXISTS roles (
7
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
8
+ code VARCHAR(64) NOT NULL UNIQUE,
9
+ name VARCHAR(128) NOT NULL,
10
+ description TEXT NULL,
11
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
12
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
13
+ );
14
+
15
+ CREATE TABLE IF NOT EXISTS users (
16
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
17
+ email VARCHAR(255) NOT NULL UNIQUE,
18
+ password_hash VARCHAR(255) NOT NULL,
19
+ display_name VARCHAR(128) NULL,
20
+ role_id BIGINT NOT NULL REFERENCES roles (id),
21
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
22
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
23
+ deleted_at TIMESTAMPTZ NULL
24
+ );
25
+
26
+ CREATE INDEX IF NOT EXISTS idx_users_role_id ON users (role_id);
27
+ CREATE INDEX IF NOT EXISTS idx_users_deleted_at ON users (deleted_at);
28
+
29
+ INSERT INTO roles (code, name, description) VALUES
30
+ ('admin', '系统管理员', '可执行所有管理操作'),
31
+ ('user', '普通用户', '默认注册角色')
32
+ ON CONFLICT (code) DO NOTHING;
@@ -0,0 +1,31 @@
1
+ .PHONY: build test lint run db-up db-down db-status db-create
2
+
3
+ DATABASE_URL ?= postgres://postgres:@127.0.0.1:5432/<%= it.options.projectName %>_dev?sslmode=disable
4
+
5
+ # Install: go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1
6
+ MIGRATE := migrate -path db/migrations -database "$(DATABASE_URL)"
7
+
8
+ build:
9
+ go build -o ./bin/server ./cmd/server
10
+
11
+ run:
12
+ go run ./cmd/server
13
+
14
+ test:
15
+ go test ./...
16
+
17
+ lint:
18
+ golangci-lint run
19
+
20
+ db-up:
21
+ $(MIGRATE) up
22
+
23
+ db-down:
24
+ $(MIGRATE) down 1
25
+
26
+ db-status:
27
+ $(MIGRATE) version
28
+
29
+ # Usage: make db-create name=create_orders
30
+ db-create:
31
+ $(MIGRATE) create -ext sql -dir db/migrations -seq $(name)
@@ -0,0 +1,71 @@
1
+ # server/db/
2
+
3
+ 数据库迁移、种子数据、本地数据库工具的入口。
4
+
5
+ > 跨项目的数据库归属规则见 [`docs/governance/database.md`](../../docs/governance/database.md)。
6
+
7
+ ## 工具与版本
8
+
9
+ | 项 | 值 |
10
+ |---|---|
11
+ | 数据库 | PostgreSQL 14+ |
12
+ | 迁移工具 | [golang-migrate](https://github.com/golang-migrate/migrate) `v4.18.1` |
13
+ | 驱动 | `github.com/jackc/pgx/v5` `v5.7.1` |
14
+
15
+ 需要本地安装 CLI:
16
+ ```bash
17
+ go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@v4.18.1
18
+ ```
19
+
20
+ 工具版本在 `go.mod` 钉死,并镜像到 `docs/03-工程规范与研发基础设施/tech-stack-server.md`。
21
+
22
+ ## 目录布局
23
+
24
+ ```
25
+ server/
26
+ ├── go.mod
27
+ ├── Makefile
28
+ └── db/
29
+ ├── README.md
30
+ └── migrations/
31
+ ├── <NNNNNN>_<description>.up.sql
32
+ └── <NNNNNN>_<description>.down.sql
33
+ ```
34
+
35
+ ## 常用命令
36
+
37
+ ```bash
38
+ make db-create name=create_orders # 新建迁移成对文件
39
+ make db-up # 升到最新
40
+ make db-down # 回滚最近一条
41
+ make db-status # 查看当前版本
42
+ ```
43
+
44
+ 环境变量 `DATABASE_URL`(默认 `postgres://postgres:@127.0.0.1:5432/<project>_dev?sslmode=disable`)。
45
+
46
+ ## prod vs dev seeds
47
+
48
+ | 类型 | 位置 |
49
+ |---|---|
50
+ | 生产字典(必装) | 写进迁移文件的 INSERT ... ON CONFLICT DO NOTHING |
51
+ | 开发样例 | `server/db/seeds/dev/` 下手动执行 |
52
+
53
+ 字典类生产种子真值在 `contracts/dictionaries/enums.yaml`;当前手动同步。
54
+
55
+ ## 改动分级(参见 `docs/governance/change-tiers.md`)
56
+
57
+ | 改动 | Tier |
58
+ |---|---|
59
+ | 新增迁移加表 / 加字段 | 3 |
60
+ | 修改既有迁移 | **不允许** |
61
+ | 删字段 / 改类型(破坏性) | 4 |
62
+ | 改 dev seed | 1/2 |
63
+ | 改字典数据 | 3(同步 contracts/dictionaries/) |
64
+ | 升级 golang-migrate / pgx | 2,但同步改 tech-stack-server.md |
65
+
66
+ ## CI 行为
67
+
68
+ ```bash
69
+ make db-up
70
+ make db-down
71
+ ```
@@ -0,0 +1,8 @@
1
+ module <%= it.options.projectName %>/server
2
+
3
+ go 1.22
4
+
5
+ require (
6
+ github.com/golang-migrate/migrate/v4 v4.18.1
7
+ github.com/jackc/pgx/v5 v5.7.1
8
+ )
@@ -0,0 +1,22 @@
1
+ name: db-go-migrate-postgres
2
+ version: 1.0.0
3
+ appliesWhen:
4
+ backend: go
5
+ database: postgres
6
+ priority: 40
7
+ files:
8
+ - from: files/go.mod
9
+ to: server/go.mod
10
+ render: true
11
+ - from: files/Makefile
12
+ to: server/Makefile
13
+ render: true
14
+ - from: files/000001_init.up.sql
15
+ to: server/db/migrations/000001_init.up.sql
16
+ render: false
17
+ - from: files/000001_init.down.sql
18
+ to: server/db/migrations/000001_init.down.sql
19
+ render: false
20
+ - from: files/db-README.md
21
+ to: server/db/README.md
22
+ render: true
@@ -0,0 +1,86 @@
1
+ package com.example.app;
2
+
3
+ import co.elastic.clients.elasticsearch.ElasticsearchClient;
4
+ import co.elastic.clients.elasticsearch.indices.PutIndexTemplateRequest;
5
+ import co.elastic.clients.json.JsonData;
6
+ import co.elastic.clients.json.JsonpDeserializer;
7
+ import co.elastic.clients.json.JsonpMapper;
8
+
9
+ import org.slf4j.Logger;
10
+ import org.slf4j.LoggerFactory;
11
+ import org.springframework.beans.factory.annotation.Autowired;
12
+ import org.springframework.boot.context.event.ApplicationReadyEvent;
13
+ import org.springframework.context.event.EventListener;
14
+ import org.springframework.core.io.Resource;
15
+ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
16
+ import org.springframework.stereotype.Component;
17
+
18
+ import java.io.ByteArrayInputStream;
19
+ import java.io.InputStream;
20
+ import java.nio.charset.StandardCharsets;
21
+ import java.util.Arrays;
22
+ import java.util.Comparator;
23
+
24
+ /**
25
+ * Idempotent Elasticsearch index-template applier.
26
+ *
27
+ * <p>启动时扫描 {@code classpath:index-templates/*.json},按文件名字典序对每个文件
28
+ * {@code PUT _index_template/<filename-without-ext>}。ES 自身保证 PUT 同名 template
29
+ * 的幂等性。
30
+ *
31
+ * <p>修改既有 template 的 mapping 字段属于 Tier 4 破坏性变更(参见
32
+ * docs/governance/change-tiers.md),因为可能需要 reindex。
33
+ */
34
+ @Component
35
+ public class EsTemplateApplier {
36
+
37
+ private static final Logger LOG = LoggerFactory.getLogger(EsTemplateApplier.class);
38
+
39
+ private final ElasticsearchClient client;
40
+
41
+ @Autowired
42
+ public EsTemplateApplier(ElasticsearchClient client) {
43
+ this.client = client;
44
+ }
45
+
46
+ @EventListener(ApplicationReadyEvent.class)
47
+ public void apply() throws Exception {
48
+ Resource[] resources = new PathMatchingResourcePatternResolver()
49
+ .getResources("classpath:index-templates/*.json");
50
+
51
+ Arrays.stream(resources)
52
+ .sorted(Comparator.comparing(Resource::getFilename))
53
+ .forEach(this::applyOne);
54
+
55
+ LOG.info("ES index templates: {} applied", resources.length);
56
+ }
57
+
58
+ private void applyOne(Resource resource) {
59
+ String filename = resource.getFilename();
60
+ if (filename == null) {
61
+ return;
62
+ }
63
+ String name = filename.substring(0, filename.lastIndexOf('.'));
64
+ try (InputStream in = resource.getInputStream()) {
65
+ byte[] body = in.readAllBytes();
66
+ JsonpMapper mapper = client._transport().jsonpMapper();
67
+ try (var parser = mapper.jsonProvider().createParser(
68
+ new ByteArrayInputStream(body))) {
69
+ PutIndexTemplateRequest req = PutIndexTemplateRequest._DESERIALIZER
70
+ .deserialize(parser, mapper);
71
+ PutIndexTemplateRequest finalReq =
72
+ new PutIndexTemplateRequest.Builder().name(name)
73
+ .indexPatterns(req.indexPatterns())
74
+ .priority(req.priority())
75
+ .template(req.template())
76
+ .meta(req.meta())
77
+ .build();
78
+ client.indices().putIndexTemplate(finalReq);
79
+ LOG.info("✓ applied {}", name);
80
+ }
81
+ } catch (Exception e) {
82
+ LOG.error("✗ failed to apply {}: {}", name, e.getMessage(), e);
83
+ throw new RuntimeException(e);
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,63 @@
1
+ # server/db/
2
+
3
+ Elasticsearch index-template 入口(Java 后端)。
4
+
5
+ > 跨项目的数据库归属规则见 [`docs/governance/database.md`](../../docs/governance/database.md)。
6
+
7
+ ## "Migration" 的语义
8
+
9
+ **Elasticsearch 没有事务性 DDL,本目录里的 JSON 不是迁移文件。**
10
+
11
+ 每个 `src/main/resources/index-templates/*.json` 是一个 [Index Template v2](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-templates.html)。`EsTemplateApplier` 在 Spring Boot 启动 (`ApplicationReadyEvent`) 时遍历目录,按文件名字典序 PUT 每个 template;ES 自身保证幂等。
12
+
13
+ ## 工具与版本
14
+
15
+ | 项 | 值 |
16
+ |---|---|
17
+ | Elasticsearch | 8.15+ |
18
+ | 客户端 | `spring-boot-starter-data-elasticsearch`(spring-data-elasticsearch `5.3.5`,由 Spring Boot 3.3.4 BOM 锁定) |
19
+
20
+ ## 目录布局
21
+
22
+ ```
23
+ server/
24
+ ├── pom.xml # spring-boot-starter-data-elasticsearch
25
+ ├── src/main/java/com/example/app/
26
+ │ └── EsTemplateApplier.java # 启动时调用
27
+ ├── src/main/resources/
28
+ │ └── index-templates/ # ← classpath 扫描
29
+ │ └── <utc-ts>_<description>.json
30
+ └── db/
31
+ └── README.md # 本文件(保留 keel 入口约定)
32
+ ```
33
+
34
+ 注意路径分歧:JSON template 跟 Spring Boot 的 classpath 资源约定走(在 `src/main/resources/`),与 `server/db/` 目录视觉分离;这与 Java + Flyway 的 `src/main/resources/db/migration/` 同因。
35
+
36
+ ## 配置
37
+
38
+ `application.yaml` 加:
39
+
40
+ ```yaml
41
+ spring:
42
+ elasticsearch:
43
+ uris: ${ELASTICSEARCH_URL:http://127.0.0.1:9200}
44
+ username: ${ELASTICSEARCH_USERNAME:}
45
+ password: ${ELASTICSEARCH_PASSWORD:}
46
+ ```
47
+
48
+ ## 改动分级(参见 `docs/governance/change-tiers.md`)
49
+
50
+ | 改动 | Tier |
51
+ |---|---|
52
+ | 新增 template 文件 | 3 |
53
+ | 修改既有 template 的 mapping 字段 | 4(破坏性 - 可能 reindex) |
54
+ | 仅改 priority / settings.refresh_interval | 2 |
55
+ | 删除 template | 4 |
56
+
57
+ ## 与 `contracts/asyncapi/` 的同步
58
+
59
+ 事件 ingest 的 schema 真值在 `contracts/asyncapi/asyncapi.yaml`;index-template 的 mapping 应当与之**对齐**。当前手动同步。
60
+
61
+ ## CI 行为
62
+
63
+ CI 起一个 ES 8 service container;`mvn -B verify` 会启动 Spring Boot test context,触发 `EsTemplateApplier.apply()`。任一 template 应用失败 → CI 红。
@@ -0,0 +1,25 @@
1
+ {
2
+ "index_patterns": ["events-*"],
3
+ "priority": 100,
4
+ "template": {
5
+ "settings": {
6
+ "number_of_shards": 1,
7
+ "number_of_replicas": 1,
8
+ "refresh_interval": "5s"
9
+ },
10
+ "mappings": {
11
+ "properties": {
12
+ "@timestamp": { "type": "date" },
13
+ "tenant_id": { "type": "keyword" },
14
+ "event_type": { "type": "keyword" },
15
+ "user_id": { "type": "keyword" },
16
+ "payload": { "type": "object", "dynamic": true },
17
+ "trace_id": { "type": "keyword" }
18
+ }
19
+ }
20
+ },
21
+ "_meta": {
22
+ "description": "Sample event-stream template. Replace mappings with your domain fields.",
23
+ "managed_by": "@wneng/create-keel"
24
+ }
25
+ }
@@ -0,0 +1,134 @@
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
+ </properties>
28
+
29
+ <dependencies>
30
+ <dependency>
31
+ <groupId>org.springframework.boot</groupId>
32
+ <artifactId>spring-boot-starter-web</artifactId>
33
+ </dependency>
34
+ <dependency>
35
+ <groupId>org.springframework.boot</groupId>
36
+ <artifactId>spring-boot-starter-validation</artifactId>
37
+ </dependency>
38
+ <dependency>
39
+ <groupId>org.springframework.boot</groupId>
40
+ <artifactId>spring-boot-starter-actuator</artifactId>
41
+ </dependency>
42
+ <dependency>
43
+ <groupId>org.springframework.boot</groupId>
44
+ <artifactId>spring-boot-starter-security</artifactId>
45
+ </dependency>
46
+
47
+ <!--
48
+ Spring Data Elasticsearch: Spring 风格的 ES 客户端 + 仓库抽象。
49
+ 版本由 Spring Boot BOM 锁定(3.3.4 -> spring-data-elasticsearch 5.3.5)。
50
+ -->
51
+ <dependency>
52
+ <groupId>org.springframework.boot</groupId>
53
+ <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
54
+ </dependency>
55
+
56
+ <dependency>
57
+ <groupId>io.jsonwebtoken</groupId>
58
+ <artifactId>jjwt-api</artifactId>
59
+ <version>${jjwt.version}</version>
60
+ </dependency>
61
+ <dependency>
62
+ <groupId>io.jsonwebtoken</groupId>
63
+ <artifactId>jjwt-impl</artifactId>
64
+ <version>${jjwt.version}</version>
65
+ <scope>runtime</scope>
66
+ </dependency>
67
+ <dependency>
68
+ <groupId>io.jsonwebtoken</groupId>
69
+ <artifactId>jjwt-jackson</artifactId>
70
+ <version>${jjwt.version}</version>
71
+ <scope>runtime</scope>
72
+ </dependency>
73
+ <dependency>
74
+ <groupId>org.springframework.boot</groupId>
75
+ <artifactId>spring-boot-starter-test</artifactId>
76
+ <scope>test</scope>
77
+ </dependency>
78
+ <dependency>
79
+ <groupId>org.springframework.security</groupId>
80
+ <artifactId>spring-security-test</artifactId>
81
+ <scope>test</scope>
82
+ </dependency>
83
+ </dependencies>
84
+
85
+ <build>
86
+ <plugins>
87
+ <plugin>
88
+ <groupId>org.springframework.boot</groupId>
89
+ <artifactId>spring-boot-maven-plugin</artifactId>
90
+ </plugin>
91
+ <plugin>
92
+ <groupId>org.apache.maven.plugins</groupId>
93
+ <artifactId>maven-checkstyle-plugin</artifactId>
94
+ <version>3.5.0</version>
95
+ <configuration>
96
+ <configLocation>checkstyle.xml</configLocation>
97
+ <consoleOutput>true</consoleOutput>
98
+ <failsOnError>true</failsOnError>
99
+ <linkXRef>false</linkXRef>
100
+ </configuration>
101
+ <executions>
102
+ <execution>
103
+ <id>verify-checkstyle</id>
104
+ <phase>verify</phase>
105
+ <goals><goal>check</goal></goals>
106
+ </execution>
107
+ </executions>
108
+ </plugin>
109
+ <plugin>
110
+ <groupId>com.diffplug.spotless</groupId>
111
+ <artifactId>spotless-maven-plugin</artifactId>
112
+ <version>2.43.0</version>
113
+ <configuration>
114
+ <java>
115
+ <googleJavaFormat>
116
+ <version>1.22.0</version>
117
+ <style>AOSP</style>
118
+ </googleJavaFormat>
119
+ <removeUnusedImports/>
120
+ <trimTrailingWhitespace/>
121
+ <endWithNewline/>
122
+ </java>
123
+ </configuration>
124
+ <executions>
125
+ <execution>
126
+ <id>verify-spotless</id>
127
+ <phase>verify</phase>
128
+ <goals><goal>check</goal></goals>
129
+ </execution>
130
+ </executions>
131
+ </plugin>
132
+ </plugins>
133
+ </build>
134
+ </project>
@@ -0,0 +1,19 @@
1
+ name: db-java-elasticsearch
2
+ version: 1.0.0
3
+ appliesWhen:
4
+ backend: java
5
+ database: elasticsearch
6
+ priority: 40
7
+ files:
8
+ - from: files/pom.xml
9
+ to: server/pom.xml
10
+ render: true
11
+ - from: files/EsTemplateApplier.java
12
+ to: server/src/main/java/com/example/app/EsTemplateApplier.java
13
+ render: false
14
+ - from: files/index-template-init.json
15
+ to: server/src/main/resources/index-templates/20260101000000_init.json
16
+ render: false
17
+ - from: files/db-README.md
18
+ to: server/db/README.md
19
+ render: true
@@ -0,0 +1,44 @@
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
+ -- MySQL 注意:
8
+ -- - charset 用 utf8mb4 避免 emoji 截断
9
+ -- - 主键统一用 BIGINT UNSIGNED + AUTO_INCREMENT
10
+ -- - 时间列用 TIMESTAMP(6) 保留毫秒精度
11
+
12
+ CREATE TABLE IF NOT EXISTS roles (
13
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
14
+ code VARCHAR(64) NOT NULL,
15
+ name VARCHAR(128) NOT NULL,
16
+ description TEXT NULL,
17
+ created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
18
+ updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
19
+ PRIMARY KEY (id),
20
+ UNIQUE KEY uk_roles_code (code)
21
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
22
+
23
+ CREATE TABLE IF NOT EXISTS users (
24
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
25
+ email VARCHAR(255) NOT NULL,
26
+ password_hash VARCHAR(255) NOT NULL,
27
+ display_name VARCHAR(128) NULL,
28
+ role_id BIGINT UNSIGNED NOT NULL,
29
+ created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
30
+ updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
31
+ deleted_at TIMESTAMP(6) NULL,
32
+ PRIMARY KEY (id),
33
+ UNIQUE KEY uk_users_email (email),
34
+ KEY idx_users_role_id (role_id),
35
+ KEY idx_users_deleted_at (deleted_at),
36
+ CONSTRAINT fk_users_role FOREIGN KEY (role_id) REFERENCES roles (id)
37
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
38
+
39
+ -- 字典数据:与 contracts/dictionaries/enums.yaml 对齐。
40
+ -- INSERT IGNORE 让 Flyway repeatable migration 多次跑不报错;
41
+ -- 改字典的 PR 必须同步改这里 + contracts/CHANGELOG.md。
42
+ INSERT IGNORE INTO roles (code, name, description) VALUES
43
+ ('admin', '系统管理员', '可执行所有管理操作'),
44
+ ('user', '普通用户', '默认注册角色');
@@ -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