@gadmin2n/schematics 0.0.88 → 0.0.90
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/dist/lib/application/files/gadmin2-game-angle-demo/.dockerignore +16 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile.codegen +40 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile.server +76 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile.web +53 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/Jenkinsfile +219 -33
- package/dist/lib/application/files/gadmin2-game-angle-demo/compose-ctl.sh +250 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +4 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/dev/postgres/init.sql +12 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.md +170 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.yml +254 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +7 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/prismaModels.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/agenda.seed.ts +39 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/audit.seed.ts +40 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/bootstrap.ts +56 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/canvas.seed.ts +39 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/{scripts/sync-data-mngt-pages.ts → seed/data-mngt.seed.ts} +36 -20
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/game.seed.ts +44 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +30 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permission.seed.ts +130 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-event-trigger.ts +60 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +11 -25
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +108 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.spec.ts +41 -57
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.spec.ts +309 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.spec.ts +315 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.spec.ts +312 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.spec.ts +317 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.spec.ts +309 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.spec.ts +299 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.spec.ts +307 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.spec.ts +31 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +309 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +205 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.ts +116 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.spec.ts +158 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +110 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/webhook-signature.util.spec.ts +79 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/webhook-signature.util.ts +54 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +34 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +457 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +241 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +34 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +24 -30
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +34 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +36 -36
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +34 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +48 -24
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +312 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/TODO.md +152 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.dockerignore +12 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/Dockerfile +79 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/GRACEFUL-DEPLOYMENT.md +270 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +23 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +70 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +246 -90
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/cron-trigger-workflow.test.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +96 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/nginx.conf +74 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/ElementInspector.tsx +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/promptGenerator.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/form.tsx +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +3 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +3 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +4 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +156 -139
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +14 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +62 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/PublishModal.tsx +4 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasApi.ts +18 -27
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +32 -11
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +48 -61
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas-page/index.tsx +3 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +16 -16
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +28 -35
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +34 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.css +6 -0
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/.gitattributes +0 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile +0 -63
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/sync-resources.ts +0 -100
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +0 -302
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.spec.ts +0 -20
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +0 -87
- /package/dist/lib/application/files/gadmin2-game-angle-demo/{GRACEFUL-DEPLOYMENT.md → server/GRACEFUL-DEPLOYMENT.md} +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# gadmin2 本地联调环境(完整版)
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# 用途:开发者一行命令起一整套服务(PG + Temporal + Server + Worker + Web)。
|
|
5
|
+
# 生产部署走 K8s(Helm chart);本文件仅用于本地集成验证,不进 CI/CD。
|
|
6
|
+
#
|
|
7
|
+
# 启动流程:
|
|
8
|
+
# 首次 / config/ 有变更后:
|
|
9
|
+
# docker compose --profile codegen build codegen # 构建 codegen 中间镜像
|
|
10
|
+
# docker compose up -d --build # 起全套服务
|
|
11
|
+
# 日常 up(codegen 镜像已存在):
|
|
12
|
+
# docker compose up -d --build
|
|
13
|
+
# 停止: docker compose down
|
|
14
|
+
# 重置: docker compose down -v # 连数据卷一起删,下次首启会重建 schema
|
|
15
|
+
# 查看: docker compose logs -f <service>
|
|
16
|
+
#
|
|
17
|
+
# 端口分配(已避免冲突):
|
|
18
|
+
# 5432 -> PostgreSQL
|
|
19
|
+
# 7233 -> Temporal gRPC(Server)
|
|
20
|
+
# 8000 -> NestJS Server(API)
|
|
21
|
+
# 8080 -> Temporal Web UI
|
|
22
|
+
# 3000 -> Web 前端(nginx,容器内 80)
|
|
23
|
+
#
|
|
24
|
+
# 镜像构建依赖(与 Jenkinsfile 保持一致的方案 C):
|
|
25
|
+
# server / web 通过 ARG CODEGEN_IMAGE + FROM ${CODEGEN_IMAGE} 引用本地 codegen 镜像,
|
|
26
|
+
# compose 不支持 build-time 依赖图,因此 codegen 镜像必须**先于** web/server 构建。
|
|
27
|
+
# 配置变更(config/ui/** 或 config/prisma/**)后需 rebuild codegen,否则用旧产物。
|
|
28
|
+
#
|
|
29
|
+
# 首次启动顺序(depends_on + healthcheck 自动编排):
|
|
30
|
+
# 1. postgres 起来 → healthy(pg_isready)
|
|
31
|
+
# 2. temporal-server auto-setup 跑 schema 初始化(约 30~60s)→ healthy
|
|
32
|
+
# 3. server / temporal-worker / temporal-ui 起来
|
|
33
|
+
# 4. web 起来
|
|
34
|
+
#
|
|
35
|
+
# 提示:
|
|
36
|
+
# - 仅起 Temporal(不起 web/server/worker)请用 ./temporal/docker-compose.yml
|
|
37
|
+
# - web 是生产 nginx 镜像,不支持热更新;前端开发请直接 `cd web && yarn dev`
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
services:
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
# codegen 中间镜像(仅 build,不 run)
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
# 执行 `gadmin2 g prisma`,生成 web/ 与 server/ 的代码并固化到镜像内。
|
|
45
|
+
# web / server 服务通过 ARG CODEGEN_IMAGE 引用本镜像。
|
|
46
|
+
#
|
|
47
|
+
# 用法:
|
|
48
|
+
# docker compose --profile codegen build codegen # 仅构建,不启动
|
|
49
|
+
#
|
|
50
|
+
# 注意:profile 不为空 → 不会被默认的 `docker compose up` 自动启动。
|
|
51
|
+
codegen:
|
|
52
|
+
image: ${COMPOSE_PROJECT_NAME}-codegen:local
|
|
53
|
+
build:
|
|
54
|
+
context: .
|
|
55
|
+
dockerfile: Dockerfile.codegen
|
|
56
|
+
profiles: ["codegen"]
|
|
57
|
+
# 即使被显式启动也立即退出(保险,本服务的存在仅为 build 入口)
|
|
58
|
+
command: ["true"]
|
|
59
|
+
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
# PostgreSQL:业务库 + Temporal 元数据库 + Temporal visibility 库(共用同一实例)
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
postgres:
|
|
64
|
+
image: postgres:15-alpine
|
|
65
|
+
container_name: postgresql
|
|
66
|
+
restart: unless-stopped
|
|
67
|
+
environment:
|
|
68
|
+
POSTGRES_USER: ${POSTGRES_USER:-kavenma}
|
|
69
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-kavenma}
|
|
70
|
+
# POSTGRES_DB 设成 postgres(默认库),实际三个业务库由 init.sql 创建
|
|
71
|
+
POSTGRES_DB: postgres
|
|
72
|
+
ports:
|
|
73
|
+
- "5432:5432"
|
|
74
|
+
volumes:
|
|
75
|
+
- pgdata:/var/lib/postgresql/data
|
|
76
|
+
- ./dev/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
77
|
+
healthcheck:
|
|
78
|
+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-kavenma} -d postgres"]
|
|
79
|
+
interval: 5s
|
|
80
|
+
timeout: 5s
|
|
81
|
+
retries: 10
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# Temporal Server (auto-setup):自动建 schema、起 frontend/history/matching/worker
|
|
85
|
+
# 不开 ENABLE_ES,visibility 走 PG(与本地联调最小依赖一致)
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
temporal-server:
|
|
88
|
+
# 生产 Helm chart 1.2.0 捆绑的 Temporal Server 是 1.31.0(见 docs/temporal-server-argocd.md),
|
|
89
|
+
# 但 Docker Hub 上 temporalio/auto-setup 镜像目前最新只到 1.29.6.1(auto-setup tag 通常滞后于 server)。
|
|
90
|
+
# 本地联调用最接近的 1.29.6.1 即可,schema 与 1.31.0 兼容。
|
|
91
|
+
image: temporalio/auto-setup:1.29.6.1
|
|
92
|
+
container_name: temporal-server
|
|
93
|
+
restart: unless-stopped
|
|
94
|
+
depends_on:
|
|
95
|
+
postgres:
|
|
96
|
+
condition: service_healthy
|
|
97
|
+
environment:
|
|
98
|
+
DB: postgres12
|
|
99
|
+
DB_PORT: 5432
|
|
100
|
+
POSTGRES_SEEDS: postgres
|
|
101
|
+
POSTGRES_USER: ${POSTGRES_USER:-kavenma}
|
|
102
|
+
POSTGRES_PWD: ${POSTGRES_PASSWORD:-kavenma}
|
|
103
|
+
DBNAME: temporal
|
|
104
|
+
VISIBILITY_DBNAME: temporal_visibility
|
|
105
|
+
DYNAMIC_CONFIG_FILE_PATH: config/dynamicconfig/development-sql.yaml
|
|
106
|
+
# 显式绑 0.0.0.0:podman rootless CNI 下 server 默认只绑容器主网卡 IP(如 10.89.x.x),
|
|
107
|
+
# 容器内 127.0.0.1:7233 连不通 → healthcheck 永远 unhealthy → worker 不启动。
|
|
108
|
+
# 设成 0.0.0.0 后 docker / podman 都可达。
|
|
109
|
+
BIND_ON_IP: 0.0.0.0
|
|
110
|
+
volumes:
|
|
111
|
+
- ./temporal/config:/etc/temporal/config/dynamicconfig
|
|
112
|
+
ports:
|
|
113
|
+
- "7233:7233"
|
|
114
|
+
healthcheck:
|
|
115
|
+
# auto-setup 镜像自带 temporal CLI;healthcheck 在容器内执行,地址用 127.0.0.1
|
|
116
|
+
test: ["CMD-SHELL", "temporal operator cluster health --address 127.0.0.1:7233 || exit 1"]
|
|
117
|
+
interval: 10s
|
|
118
|
+
timeout: 5s
|
|
119
|
+
retries: 12
|
|
120
|
+
start_period: 30s
|
|
121
|
+
|
|
122
|
+
# ---------------------------------------------------------------------------
|
|
123
|
+
# Temporal Web UI
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
temporal-ui:
|
|
126
|
+
image: temporalio/ui:latest
|
|
127
|
+
container_name: temporal-ui
|
|
128
|
+
restart: unless-stopped
|
|
129
|
+
depends_on:
|
|
130
|
+
temporal-server:
|
|
131
|
+
condition: service_started
|
|
132
|
+
environment:
|
|
133
|
+
TEMPORAL_ADDRESS: temporal-server:7233
|
|
134
|
+
ports:
|
|
135
|
+
- "8080:8080"
|
|
136
|
+
|
|
137
|
+
# ---------------------------------------------------------------------------
|
|
138
|
+
# Server 一次性初始化:prisma db push + seed
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# 直接复用 codegen 镜像(它已含 server 全量依赖:ts-node / prisma CLI / seed/ 源码)。
|
|
141
|
+
# 业务 server 镜像走 `--production` 安装、且不复制 seed/,因此 seed 不能在 server
|
|
142
|
+
# 容器里跑;这里独立成 init 容器,跑完即退出。
|
|
143
|
+
#
|
|
144
|
+
# 幂等:
|
|
145
|
+
# - prisma db push 多次执行无害(只补 schema 差异)
|
|
146
|
+
# - seed 全部用 createMany skipDuplicates / upsert 风格,重复跑不会重复插
|
|
147
|
+
#
|
|
148
|
+
# 依赖:
|
|
149
|
+
# - 必须先 `docker compose --profile codegen build codegen` 把镜像构出来
|
|
150
|
+
# - postgres 必须 healthy(schema 写入目标)
|
|
151
|
+
#
|
|
152
|
+
# 行为:
|
|
153
|
+
# - restart: "no" —— 一次性
|
|
154
|
+
# - 退出码 0 时 server / temporal-worker 才会启动(service_completed_successfully)
|
|
155
|
+
server-init:
|
|
156
|
+
image: ${COMPOSE_PROJECT_NAME}-codegen:local
|
|
157
|
+
container_name: gadmin2-init
|
|
158
|
+
restart: "no"
|
|
159
|
+
depends_on:
|
|
160
|
+
postgres:
|
|
161
|
+
condition: service_healthy
|
|
162
|
+
working_dir: /app/server
|
|
163
|
+
environment:
|
|
164
|
+
DATABASE_URL: postgresql://${POSTGRES_USER:-kavenma}:${POSTGRES_PASSWORD:-kavenma}@postgres:5432/gadmin_demo?schema=public
|
|
165
|
+
command:
|
|
166
|
+
- sh
|
|
167
|
+
- -c
|
|
168
|
+
- |
|
|
169
|
+
set -e
|
|
170
|
+
echo "[server-init] prisma db push ..."
|
|
171
|
+
yarn push:db
|
|
172
|
+
echo "[server-init] seed ..."
|
|
173
|
+
yarn seed
|
|
174
|
+
echo "[server-init] done."
|
|
175
|
+
|
|
176
|
+
# ---------------------------------------------------------------------------
|
|
177
|
+
# NestJS Server(业务 API)
|
|
178
|
+
# 镜像构建依赖 codegen:先 `docker compose --profile codegen build codegen`
|
|
179
|
+
# 镜像内已 COPY server/.env,TAIHU_* / OTEL_* 等用其默认值;
|
|
180
|
+
# 这里只覆盖 docker 网络相关的连接字符串。
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
server:
|
|
183
|
+
image: ${COMPOSE_PROJECT_NAME}-nest-server:local
|
|
184
|
+
build:
|
|
185
|
+
context: .
|
|
186
|
+
dockerfile: Dockerfile.server
|
|
187
|
+
args:
|
|
188
|
+
CODEGEN_IMAGE: ${COMPOSE_PROJECT_NAME}-codegen:local
|
|
189
|
+
container_name: gadmin2-nest-server
|
|
190
|
+
restart: unless-stopped
|
|
191
|
+
depends_on:
|
|
192
|
+
postgres:
|
|
193
|
+
condition: service_healthy
|
|
194
|
+
server-init:
|
|
195
|
+
condition: service_completed_successfully
|
|
196
|
+
# 不等 temporal-server healthy:server 启动不强依赖 Temporal
|
|
197
|
+
temporal-server:
|
|
198
|
+
condition: service_started
|
|
199
|
+
environment:
|
|
200
|
+
DATABASE_URL: postgresql://${POSTGRES_USER:-kavenma}:${POSTGRES_PASSWORD:-kavenma}@postgres:5432/gadmin_demo?schema=public
|
|
201
|
+
TEMPORAL_ADDRESS: temporal-server:7233
|
|
202
|
+
TEMPORAL_NAMESPACE: ${TEMPORAL_NAMESPACE:-default}
|
|
203
|
+
TEMPORAL_TASK_QUEUE: ${TEMPORAL_TASK_QUEUE:-workflow-execution}
|
|
204
|
+
NODE_ENV: ${NODE_ENV:-development}
|
|
205
|
+
ports:
|
|
206
|
+
- "8000:8000"
|
|
207
|
+
|
|
208
|
+
# ---------------------------------------------------------------------------
|
|
209
|
+
# Temporal Worker(Node.js 长驻进程)
|
|
210
|
+
# ---------------------------------------------------------------------------
|
|
211
|
+
temporal-worker:
|
|
212
|
+
image: ${COMPOSE_PROJECT_NAME}-temporal-worker:local
|
|
213
|
+
build:
|
|
214
|
+
context: ./temporal/worker
|
|
215
|
+
dockerfile: Dockerfile
|
|
216
|
+
container_name: gadmin2-temporal-worker
|
|
217
|
+
restart: on-failure
|
|
218
|
+
depends_on:
|
|
219
|
+
postgres:
|
|
220
|
+
condition: service_healthy
|
|
221
|
+
server-init:
|
|
222
|
+
condition: service_completed_successfully
|
|
223
|
+
temporal-server:
|
|
224
|
+
condition: service_healthy
|
|
225
|
+
environment:
|
|
226
|
+
TEMPORAL_ADDRESS: temporal-server:7233
|
|
227
|
+
TEMPORAL_NAMESPACE: ${TEMPORAL_NAMESPACE:-default}
|
|
228
|
+
TEMPORAL_TASK_QUEUE: ${TEMPORAL_TASK_QUEUE:-workflow-execution}
|
|
229
|
+
DATABASE_URL: postgresql://${POSTGRES_USER:-kavenma}:${POSTGRES_PASSWORD:-kavenma}@postgres:5432/gadmin_demo?schema=public
|
|
230
|
+
# 无对外端口、无 health endpoint
|
|
231
|
+
|
|
232
|
+
# ---------------------------------------------------------------------------
|
|
233
|
+
# Web 前端(生产 nginx 镜像;本地仅用于完整集成验证)
|
|
234
|
+
# 镜像构建依赖 codegen:先 `docker compose --profile codegen build codegen`
|
|
235
|
+
# 开发态请用 `cd web && yarn dev`,热更新更顺手
|
|
236
|
+
# ---------------------------------------------------------------------------
|
|
237
|
+
web:
|
|
238
|
+
image: ${COMPOSE_PROJECT_NAME}-web:local
|
|
239
|
+
build:
|
|
240
|
+
context: .
|
|
241
|
+
dockerfile: Dockerfile.web
|
|
242
|
+
args:
|
|
243
|
+
CODEGEN_IMAGE: ${COMPOSE_PROJECT_NAME}-codegen:local
|
|
244
|
+
NODE_ENV: production
|
|
245
|
+
container_name: gadmin2-web
|
|
246
|
+
restart: unless-stopped
|
|
247
|
+
depends_on:
|
|
248
|
+
server:
|
|
249
|
+
condition: service_started
|
|
250
|
+
ports:
|
|
251
|
+
- "3000:80"
|
|
252
|
+
|
|
253
|
+
volumes:
|
|
254
|
+
pgdata:
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"prebuild": "rimraf dist",
|
|
10
|
-
"build": "
|
|
10
|
+
"build": "nest build -c gadmin-cli.json",
|
|
11
11
|
"format": "prettier --write \"../config/*.ts\" \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
12
12
|
"prepare": "cd .. && husky install",
|
|
13
|
-
"start": "dotenv -e .env.local -e .env --
|
|
14
|
-
"start:dev": "dotenv -e .env.local -e .env --
|
|
15
|
-
"start:debug": "dotenv -e .env.local -e .env --
|
|
13
|
+
"start": "dotenv -e .env.local -e .env -- nest start -c gadmin-cli.json",
|
|
14
|
+
"start:dev": "dotenv -e .env.local -e .env -- nest start -c gadmin-cli.json --watch",
|
|
15
|
+
"start:debug": "dotenv -e .env.local -e .env -- nest start -c gadmin-cli.json --debug --watch",
|
|
16
16
|
"start:prod": "/bin/sh start-prod.sh",
|
|
17
17
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
|
18
18
|
"test": "jest",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"migrate:status": "dotenv -e .env.local -e .env -- prisma migrate status",
|
|
27
27
|
"generate": "dotenv -e .env.local -e .env -- npx prisma generate",
|
|
28
28
|
"generate:dev": "npm run migrate:dev && dotenv -e .env.local -e .env -- npx prisma generate",
|
|
29
|
-
"postgenerate:dev": "dotenv -e .env.local -e .env -- ts-node
|
|
29
|
+
"postgenerate:dev": "dotenv -e .env.local -e .env -- ts-node seed/data-mngt.seed.ts",
|
|
30
30
|
"generate:web": "dotenv -e .env.local -e .env -- npx prisma generate --generator react",
|
|
31
31
|
"generate:server": "dotenv -e .env.local -e .env -- npx prisma generate --generator client --generator nestjs",
|
|
32
32
|
"push:db": "dotenv -e .env.local -e .env -- prisma db push --skip-generate",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"@nestjs/schedule": "^4.0.1",
|
|
47
47
|
"@nestjs/serve-static": "^4.0.1",
|
|
48
48
|
"@nestjs/swagger": "^7.3.0",
|
|
49
|
-
"@temporalio/client": "^1.11.6",
|
|
50
49
|
"@opentelemetry/api": "^1.9.0",
|
|
51
50
|
"@opentelemetry/exporter-trace-otlp-grpc": "^0.211.0",
|
|
52
51
|
"@opentelemetry/instrumentation-express": "^0.47.0",
|
|
@@ -58,6 +57,7 @@
|
|
|
58
57
|
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
59
58
|
"@prisma/client": "^6.19.0",
|
|
60
59
|
"@prisma/instrumentation": "6.19.0",
|
|
60
|
+
"@temporalio/client": "^1.11.6",
|
|
61
61
|
"agenda": "^6.2.5",
|
|
62
62
|
"axios": "^1.13.2",
|
|
63
63
|
"cache-manager": "^6.4.3",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"@faker-js/faker": "^10.4.0",
|
|
91
91
|
"@gadmin2n/prisma-nest-generator": "^0.0.46",
|
|
92
92
|
"@gadmin2n/prisma-react-generator": "^0.0.60",
|
|
93
|
+
"@nestjs/cli": "^11.0.21",
|
|
93
94
|
"@nestjs/testing": "^10.4.15",
|
|
94
95
|
"@types/cookie-parser": "^1.4.3",
|
|
95
96
|
"@types/express": "^4.17.21",
|
package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* page-helpers.ts — 页面与权限管理的共享 DB 操作原语
|
|
3
3
|
*
|
|
4
4
|
* 接受 PrismaClient 作为参数,可被 CLI 脚本(page-manage.ts / permission-manage.ts)
|
|
5
|
-
* 和
|
|
5
|
+
* 和 seed/*.seed.ts(含 data-mngt.seed.ts)共同调用。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { PrismaClient } from '@prisma/client';
|
|
@@ -28,7 +28,7 @@ const PRISMA_CONFIG_DIR = path.resolve(
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Prisma files that define system/permission models and must NOT be scanned.
|
|
31
|
-
* These are already handled by
|
|
31
|
+
* These are already handled by static seed modules (bootstrap + permission/audit/etc.).
|
|
32
32
|
*/
|
|
33
33
|
const EXCLUDED_FILES = new Set(['system.prisma']);
|
|
34
34
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import {
|
|
3
|
+
bindResourceToPage,
|
|
4
|
+
getPageResourceIds,
|
|
5
|
+
grantRoleAccess,
|
|
6
|
+
upsertPage,
|
|
7
|
+
} from '../scripts/lib/page-helpers';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Agenda 模块 seed
|
|
11
|
+
*
|
|
12
|
+
* 职责:agenda page (admin 子节点) + agenda resource + 自家 SYSTEM_ADMIN 授权。
|
|
13
|
+
* 前置:seedBootstrap 已建好 admin 与 SYSTEM_ADMIN。
|
|
14
|
+
*/
|
|
15
|
+
export async function seedAgendaModule(prisma: PrismaClient): Promise<void> {
|
|
16
|
+
const role = await prisma.role.findUniqueOrThrow({
|
|
17
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
18
|
+
});
|
|
19
|
+
const admin = await prisma.page.findUniqueOrThrow({
|
|
20
|
+
where: { code: 'admin' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const page = await upsertPage(prisma, {
|
|
24
|
+
code: 'agenda',
|
|
25
|
+
name: 'agenda',
|
|
26
|
+
zhName: 'Cron Jobs',
|
|
27
|
+
enName: 'Cron Jobs',
|
|
28
|
+
sortOrder: 1020,
|
|
29
|
+
parentId: admin.id,
|
|
30
|
+
});
|
|
31
|
+
console.log(`[agenda] Page: ${page.code} (id=${page.id})`);
|
|
32
|
+
|
|
33
|
+
await bindResourceToPage(prisma, page.id, 'agenda', 'Agenda job management');
|
|
34
|
+
console.log(`[agenda] PageResource: agenda ↔ agenda`);
|
|
35
|
+
|
|
36
|
+
const resourceIds = await getPageResourceIds(prisma, page.id);
|
|
37
|
+
await grantRoleAccess(prisma, role.id, page.id, resourceIds);
|
|
38
|
+
console.log(`[agenda] Grant: SYSTEM_ADMIN → agenda`);
|
|
39
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import {
|
|
3
|
+
bindResourceToPage,
|
|
4
|
+
getPageResourceIds,
|
|
5
|
+
grantRoleAccess,
|
|
6
|
+
upsertPage,
|
|
7
|
+
} from '../scripts/lib/page-helpers';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Audit 模块 seed
|
|
11
|
+
*
|
|
12
|
+
* 职责:audits page (admin 子节点) + audit resource + 自家 SYSTEM_ADMIN 授权。
|
|
13
|
+
* 注意:page.code 是 'audits',但 resource.code 是 'audit'(与 backend module 一致)。
|
|
14
|
+
* 前置:seedBootstrap 已建好 admin 与 SYSTEM_ADMIN。
|
|
15
|
+
*/
|
|
16
|
+
export async function seedAuditModule(prisma: PrismaClient): Promise<void> {
|
|
17
|
+
const role = await prisma.role.findUniqueOrThrow({
|
|
18
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
19
|
+
});
|
|
20
|
+
const admin = await prisma.page.findUniqueOrThrow({
|
|
21
|
+
where: { code: 'admin' },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const page = await upsertPage(prisma, {
|
|
25
|
+
code: 'audits',
|
|
26
|
+
name: 'audits',
|
|
27
|
+
zhName: '审计日志',
|
|
28
|
+
enName: 'Audit Log',
|
|
29
|
+
sortOrder: 1060,
|
|
30
|
+
parentId: admin.id,
|
|
31
|
+
});
|
|
32
|
+
console.log(`[audit] Page: ${page.code} (id=${page.id})`);
|
|
33
|
+
|
|
34
|
+
await bindResourceToPage(prisma, page.id, 'audit', 'Audit logs');
|
|
35
|
+
console.log(`[audit] PageResource: audits ↔ audit`);
|
|
36
|
+
|
|
37
|
+
const resourceIds = await getPageResourceIds(prisma, page.id);
|
|
38
|
+
await grantRoleAccess(prisma, role.id, page.id, resourceIds);
|
|
39
|
+
console.log(`[audit] Grant: SYSTEM_ADMIN → audits`);
|
|
40
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import { grantRoleAccess, upsertPage } from '../scripts/lib/page-helpers';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bootstrap seed — 全模块共享的最小公共集
|
|
6
|
+
*
|
|
7
|
+
* 任何模块 seed 都假设以下 3 个对象已存在:
|
|
8
|
+
* 1. SYSTEM_ADMIN 角色 —— 各模块 grant SYSTEM_ADMIN 时通过 name 查找
|
|
9
|
+
* 2. admin 顶级 page —— 各业务模块 page 的 parentId
|
|
10
|
+
* 3. dataMngt 分组 page —— 自动生成 CRUD 页面(data-mngt.seed.ts)的 parentId
|
|
11
|
+
*
|
|
12
|
+
* 同时把 SYSTEM_ADMIN 对 admin / dataMngt 这两个分组节点的 RolePages 也建好,
|
|
13
|
+
* 否则它们的子菜单父节点不会展开。
|
|
14
|
+
*
|
|
15
|
+
* 必须在所有模块 seed 之前运行(由 seed/index.ts 编排)。
|
|
16
|
+
* 幂等:upsert / skipDuplicates。
|
|
17
|
+
*/
|
|
18
|
+
export async function seedBootstrap(prisma: PrismaClient): Promise<void> {
|
|
19
|
+
// ── SYSTEM_ADMIN 角色 ──────────────────────────────────────────────────────
|
|
20
|
+
const systemAdminRole = await prisma.role.upsert({
|
|
21
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
22
|
+
update: {},
|
|
23
|
+
create: {
|
|
24
|
+
name: 'SYSTEM_ADMIN',
|
|
25
|
+
description: 'System administrator with full access',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
console.log(`[bootstrap] Role: SYSTEM_ADMIN (id=${systemAdminRole.id})`);
|
|
29
|
+
|
|
30
|
+
// ── admin 顶级分组 page ────────────────────────────────────────────────────
|
|
31
|
+
const adminPage = await upsertPage(prisma, {
|
|
32
|
+
code: 'admin',
|
|
33
|
+
name: 'admin',
|
|
34
|
+
zhName: '系统管理',
|
|
35
|
+
enName: 'System Mgnt',
|
|
36
|
+
sortOrder: 1000,
|
|
37
|
+
});
|
|
38
|
+
console.log(`[bootstrap] Page: ${adminPage.code} (id=${adminPage.id})`);
|
|
39
|
+
|
|
40
|
+
// ── dataMngt 分组 page(自动 CRUD 菜单容器) ──────────────────────────────
|
|
41
|
+
const dataMngtPage = await upsertPage(prisma, {
|
|
42
|
+
code: 'dataMngt',
|
|
43
|
+
name: '数据管理',
|
|
44
|
+
zhName: '数据管理',
|
|
45
|
+
enName: 'Data Management',
|
|
46
|
+
sortOrder: 1000,
|
|
47
|
+
parentId: adminPage.id,
|
|
48
|
+
});
|
|
49
|
+
console.log(`[bootstrap] Page: ${dataMngtPage.code} (id=${dataMngtPage.id})`);
|
|
50
|
+
|
|
51
|
+
// ── 分组 page 的 SYSTEM_ADMIN RolePages(无 resource) ──────────────────────
|
|
52
|
+
// 分组节点本身不绑定 resource,只为让侧边栏父节点对 SYSTEM_ADMIN 可见
|
|
53
|
+
await grantRoleAccess(prisma, systemAdminRole.id, adminPage.id, []);
|
|
54
|
+
await grantRoleAccess(prisma, systemAdminRole.id, dataMngtPage.id, []);
|
|
55
|
+
console.log(`[bootstrap] RolePages: SYSTEM_ADMIN → admin, dataMngt`);
|
|
56
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import {
|
|
3
|
+
bindResourceToPage,
|
|
4
|
+
getPageResourceIds,
|
|
5
|
+
grantRoleAccess,
|
|
6
|
+
upsertPage,
|
|
7
|
+
} from '../scripts/lib/page-helpers';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Canvas 模块 seed
|
|
11
|
+
*
|
|
12
|
+
* 职责:canvas page (admin 子节点) + canvas resource + 自家 SYSTEM_ADMIN 授权。
|
|
13
|
+
* 前置:seedBootstrap 已建好 admin 与 SYSTEM_ADMIN。
|
|
14
|
+
*/
|
|
15
|
+
export async function seedCanvasModule(prisma: PrismaClient): Promise<void> {
|
|
16
|
+
const role = await prisma.role.findUniqueOrThrow({
|
|
17
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
18
|
+
});
|
|
19
|
+
const admin = await prisma.page.findUniqueOrThrow({
|
|
20
|
+
where: { code: 'admin' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const page = await upsertPage(prisma, {
|
|
24
|
+
code: 'canvas',
|
|
25
|
+
name: 'canvas',
|
|
26
|
+
zhName: 'Canvas',
|
|
27
|
+
enName: 'Canvas',
|
|
28
|
+
sortOrder: 1010,
|
|
29
|
+
parentId: admin.id,
|
|
30
|
+
});
|
|
31
|
+
console.log(`[canvas] Page: ${page.code} (id=${page.id})`);
|
|
32
|
+
|
|
33
|
+
await bindResourceToPage(prisma, page.id, 'canvas', 'Canvas management');
|
|
34
|
+
console.log(`[canvas] PageResource: canvas ↔ canvas`);
|
|
35
|
+
|
|
36
|
+
const resourceIds = await getPageResourceIds(prisma, page.id);
|
|
37
|
+
await grantRoleAccess(prisma, role.id, page.id, resourceIds);
|
|
38
|
+
console.log(`[canvas] Grant: SYSTEM_ADMIN → canvas`);
|
|
39
|
+
}
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
getPageResourceIds,
|
|
5
5
|
grantRoleAccess,
|
|
6
6
|
upsertPage,
|
|
7
|
-
} from '
|
|
8
|
-
import { readPrismaModels } from '
|
|
7
|
+
} from '../scripts/lib/page-helpers';
|
|
8
|
+
import { readPrismaModels } from '../scripts/prismaModels';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Models whose Page record should be marked `isVirtual = true`,
|
|
@@ -35,7 +35,11 @@ const HIDDEN_FROM_DATA_MNGT_MENU = new Set<string>([
|
|
|
35
35
|
* 5. Upsert a RoleResource record (SYSTEM_ADMIN → resource, full actions)
|
|
36
36
|
*
|
|
37
37
|
* Safe to re-run — every write uses upsert / skipDuplicates.
|
|
38
|
-
*
|
|
38
|
+
*
|
|
39
|
+
* Prerequisites: SYSTEM_ADMIN role and dataMngt page must already exist
|
|
40
|
+
* (created by seedBootstrap). The standalone entry point at the bottom of
|
|
41
|
+
* this file delegates to seed/index.ts main() in case the DB is fresh, so
|
|
42
|
+
* `ts-node seed/data-mngt.seed.ts` always works.
|
|
39
43
|
*/
|
|
40
44
|
export async function seedDataMngtPages(prisma: PrismaClient): Promise<void> {
|
|
41
45
|
const models = readPrismaModels();
|
|
@@ -48,31 +52,25 @@ export async function seedDataMngtPages(prisma: PrismaClient): Promise<void> {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
// ── Anchors ────────────────────────────────────────────────────────────────
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
|
|
55
|
+
// SYSTEM_ADMIN role and dataMngt page are created by seedBootstrap, which
|
|
56
|
+
// seed/index.ts main() always runs before this function. If they're missing,
|
|
57
|
+
// it means this function was called out of order — fail fast with a clear msg.
|
|
58
|
+
const systemAdminRole = await prisma.role.findUnique({
|
|
54
59
|
where: { name: 'SYSTEM_ADMIN' },
|
|
55
60
|
});
|
|
56
|
-
if (!
|
|
57
|
-
|
|
58
|
-
'[seedDataMngtPages] SYSTEM_ADMIN
|
|
61
|
+
if (!systemAdminRole) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
'[seedDataMngtPages] SYSTEM_ADMIN role missing. Run seedBootstrap (via `yarn seed`) first.',
|
|
59
64
|
);
|
|
60
|
-
const { main } = await import('../seed/index');
|
|
61
|
-
await main();
|
|
62
|
-
// main() already calls seedDataMngtPages, so we're done.
|
|
63
|
-
return;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
const systemAdminRole = existingRole;
|
|
67
|
-
|
|
68
67
|
const dataMngtPage = await prisma.page.findUnique({
|
|
69
68
|
where: { code: 'dataMngt' },
|
|
70
69
|
});
|
|
71
70
|
if (!dataMngtPage) {
|
|
72
|
-
|
|
73
|
-
'[seedDataMngtPages] dataMngt page
|
|
71
|
+
throw new Error(
|
|
72
|
+
'[seedDataMngtPages] dataMngt page missing. Run seedBootstrap (via `yarn seed`) first.',
|
|
74
73
|
);
|
|
75
|
-
return;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
// ── Process models ─────────────────────────────────────────────────────────
|
|
@@ -128,12 +126,30 @@ export async function seedDataMngtPages(prisma: PrismaClient): Promise<void> {
|
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
// ─── Standalone Entry Point ───────────────────────────────────────────────────
|
|
131
|
-
// Called directly by `postgenerate:dev` (via ts-node)
|
|
129
|
+
// Called directly by `postgenerate:dev` (via ts-node) for incremental sync
|
|
130
|
+
// after `yarn generate:dev` adds new business models. Also callable manually.
|
|
131
|
+
//
|
|
132
|
+
// Fresh-DB safety: if SYSTEM_ADMIN / dataMngt are missing, we delegate to
|
|
133
|
+
// seed/index.ts main() which runs the full seed pipeline (which itself calls
|
|
134
|
+
// seedDataMngtPages). Otherwise we just run seedDataMngtPages incrementally.
|
|
132
135
|
|
|
133
136
|
if (require.main === module) {
|
|
134
137
|
const prisma = new PrismaClient();
|
|
135
138
|
|
|
136
|
-
|
|
139
|
+
(async () => {
|
|
140
|
+
const adminRole = await prisma.role.findUnique({
|
|
141
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
142
|
+
});
|
|
143
|
+
if (!adminRole) {
|
|
144
|
+
console.log(
|
|
145
|
+
'[seedDataMngtPages] Fresh DB detected — delegating to full seed pipeline…',
|
|
146
|
+
);
|
|
147
|
+
const { main } = await import('./index');
|
|
148
|
+
await main();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
await seedDataMngtPages(prisma);
|
|
152
|
+
})()
|
|
137
153
|
.catch((e) => {
|
|
138
154
|
console.error('[seedDataMngtPages] Fatal error:', e);
|
|
139
155
|
process.exit(1);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import {
|
|
3
|
+
bindResourceToPage,
|
|
4
|
+
getPageResourceIds,
|
|
5
|
+
grantRoleAccess,
|
|
6
|
+
upsertPage,
|
|
7
|
+
} from '../scripts/lib/page-helpers';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Game 模块 seed
|
|
11
|
+
*
|
|
12
|
+
* 职责:game page (admin 子节点) + game resource + 自家 SYSTEM_ADMIN 授权。
|
|
13
|
+
* 前置:seedBootstrap 已建好 admin 与 SYSTEM_ADMIN。
|
|
14
|
+
*/
|
|
15
|
+
export async function seedGameModule(prisma: PrismaClient): Promise<void> {
|
|
16
|
+
const role = await prisma.role.findUniqueOrThrow({
|
|
17
|
+
where: { name: 'SYSTEM_ADMIN' },
|
|
18
|
+
});
|
|
19
|
+
const admin = await prisma.page.findUniqueOrThrow({
|
|
20
|
+
where: { code: 'admin' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const page = await upsertPage(prisma, {
|
|
24
|
+
code: 'game',
|
|
25
|
+
name: 'game',
|
|
26
|
+
zhName: '业务管理',
|
|
27
|
+
enName: 'Business Mgnt',
|
|
28
|
+
sortOrder: 1050,
|
|
29
|
+
parentId: admin.id,
|
|
30
|
+
});
|
|
31
|
+
console.log(`[game] Page: ${page.code} (id=${page.id})`);
|
|
32
|
+
|
|
33
|
+
await bindResourceToPage(
|
|
34
|
+
prisma,
|
|
35
|
+
page.id,
|
|
36
|
+
'game',
|
|
37
|
+
'Business / Game management',
|
|
38
|
+
);
|
|
39
|
+
console.log(`[game] PageResource: game ↔ game`);
|
|
40
|
+
|
|
41
|
+
const resourceIds = await getPageResourceIds(prisma, page.id);
|
|
42
|
+
await grantRoleAccess(prisma, role.id, page.id, resourceIds);
|
|
43
|
+
console.log(`[game] Grant: SYSTEM_ADMIN → game`);
|
|
44
|
+
}
|