@gadmin2n/schematics 0.0.135 → 0.0.137
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/Dockerfile.server +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/compose-ctl.sh +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/canvas.prisma +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +14 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/User.ts +4 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.md +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.yml +13 -92
- package/dist/lib/application/files/gadmin2-game-angle-demo/readme.md +105 -7
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/ensure-database.js +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +7 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +9 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/gen-jwt.ts +85 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/notify-dev-servers.js +9 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/wait-for-nest-ready.js +5 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +43 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +9 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +24 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.dto.ts +27 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.service.spec.ts +430 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.service.ts +203 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.ts +36 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.module.ts +2 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +54 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +245 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.service.spec.ts +366 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.service.ts +110 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +15 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +79 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +41 -19
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/start-prod.sh +5 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +37 -573
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/ecosystem.dev.config.cjs +12 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +3 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +39 -26
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +3 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +23 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +66 -10
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +16 -7
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +21 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasApi.ts +30 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ExportModal.tsx +84 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ImportModal.tsx +166 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/hooks/useCanvasHistory.ts +52 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +6 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +17 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +18 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +225 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/lazy-with-reload.ts +31 -0
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-dsl-validate.spec.ts +0 -220
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-dsl-validate.ts +0 -132
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/TODO.md +0 -152
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +0 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +0 -25
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +0 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.dockerignore +0 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +0 -7
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/Dockerfile +0 -79
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/GRACEFUL-DEPLOYMENT.md +0 -270
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +0 -122
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +0 -4285
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +0 -28
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +0 -51
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +0 -85
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +0 -35
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +0 -54
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +0 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +0 -85
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +0 -47
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +0 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +0 -101
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +0 -58
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +0 -184
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +0 -133
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +0 -96
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +0 -77
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/validate.ts +0 -109
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +0 -101
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +0 -382
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/activities/code-execute.test.ts +0 -44
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/activities/http-request.test.ts +0 -87
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/cron-trigger-workflow.test.ts +0 -20
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/helpers.test.ts +0 -225
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/node-type-consistency.test.ts +0 -101
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/validate.test.ts +0 -205
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +0 -499
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +0 -19
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +0 -8
- package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +0 -1905
|
@@ -46,7 +46,7 @@ COPY --from=builder --chown=node:node /app/server/package.json /app/server/yarn.
|
|
|
46
46
|
|
|
47
47
|
# 注意:这里不能用 `yarn install --production`。
|
|
48
48
|
# start-prod.sh 启动时需要:
|
|
49
|
-
# - prisma CLI(运行 `yarn
|
|
49
|
+
# - prisma CLI(运行 `yarn migrate:deploy`)
|
|
50
50
|
# - ts-node + dotenv-cli(运行 `yarn seed`)
|
|
51
51
|
# 这三者在 package.json 中位于 devDependencies,--production 会跳过它们。
|
|
52
52
|
# 故安装全量依赖;产物体积增加约 80MB,换来启动脚本统一可用。
|
|
@@ -74,7 +74,7 @@ RUN chmod +x start-prod.sh
|
|
|
74
74
|
# 复制环境变量配置(作为默认值,K8s 注入的同名变量优先级更高)
|
|
75
75
|
COPY --from=builder --chown=node:node /app/server/.env ./.env
|
|
76
76
|
|
|
77
|
-
# package.json 的
|
|
77
|
+
# package.json 的 migrate:deploy / seed 都走 `dotenv -e .env.local -e .env -- ...`,
|
|
78
78
|
# dotenv-cli v7 在指定文件不存在时会报错;镜像里没有 .env.local,touch 空文件兜底。
|
|
79
79
|
RUN touch .env.local && chown node:node .env.local
|
|
80
80
|
|
|
@@ -190,7 +190,7 @@ print_post_up_guide() {
|
|
|
190
190
|
|
|
191
191
|
提示:
|
|
192
192
|
· 前端开发请用 cd web && yarn dev (本 compose 的 web 是 nginx 静态镜像,无热更新)
|
|
193
|
-
· server-init 是一次性容器,跑完
|
|
193
|
+
· server-init 是一次性容器,跑完 migrate:deploy + seed 后退出 (Exited 0) 是正常的
|
|
194
194
|
EOF
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -99,9 +99,9 @@ model WorkflowInstance {
|
|
|
99
99
|
model WorkflowNodeExecution {
|
|
100
100
|
id BigInt @id @default(autoincrement())
|
|
101
101
|
instanceId BigInt @map("instance_id")
|
|
102
|
-
nodeId String @db.VarChar(64)
|
|
103
|
-
nodeType String @db.VarChar(64)
|
|
104
|
-
nodeLabel String? @db.VarChar(128) // human-readable label
|
|
102
|
+
nodeId String @db.VarChar(64) @map("node_id") // DSL node.id
|
|
103
|
+
nodeType String @db.VarChar(64) @map("node_type") // e.g. "http_request"
|
|
104
|
+
nodeLabel String? @db.VarChar(128) @map("node_label") // human-readable label
|
|
105
105
|
status WorkflowInstanceStatus @default(PENDING)
|
|
106
106
|
input Json?
|
|
107
107
|
output Json?
|
|
@@ -177,3 +177,14 @@ model WorkflowEventOutbox {
|
|
|
177
177
|
// (Prisma schema 不支持 WHERE 子句的 partial index)
|
|
178
178
|
@@map("t_workflow_event_outbox")
|
|
179
179
|
}
|
|
180
|
+
|
|
181
|
+
/// @IgnoreReactCode
|
|
182
|
+
model TemporalTenantConfig {
|
|
183
|
+
adminUrl String @db.VarChar(256) @map("admin_url") // shared temporal admin API URL,e.g. http://localhost:8081
|
|
184
|
+
adminToken String @db.VarChar(128) @map("admin_token") // X-Admin-Token
|
|
185
|
+
namespace String @db.VarChar(64) @map("namespace") // 租户 namespace,需与 TEMPORAL_NAMESPACE 一致
|
|
186
|
+
dbUrl String @db.Text @map("db_url") // shared worker 视角的本项目 DB URL
|
|
187
|
+
displayName String @db.VarChar(128) @map("display_name") // 租户展示名
|
|
188
|
+
|
|
189
|
+
@@map("t_temporal_tenant_config")
|
|
190
|
+
}
|
|
@@ -18,7 +18,7 @@ export const User: ModelConfig = {
|
|
|
18
18
|
{
|
|
19
19
|
action: "EXPORT",
|
|
20
20
|
desc: "export",
|
|
21
|
-
fields: ["*", "!createdAt"],
|
|
21
|
+
fields: ["*", "!createdAt", "!groupMemberships.*", "!groupMemberships"],
|
|
22
22
|
},
|
|
23
23
|
{ action: "INSERT", desc: "Insert" },
|
|
24
24
|
],
|
|
@@ -27,7 +27,7 @@ export const User: ModelConfig = {
|
|
|
27
27
|
filter: ["roles"],
|
|
28
28
|
sorter: ["id", "roles"],
|
|
29
29
|
},
|
|
30
|
-
fields: ["*", "!createdAt"],
|
|
30
|
+
fields: ["*", "!createdAt", "!groupMemberships.*", "!groupMemberships"],
|
|
31
31
|
rowSelection: {
|
|
32
32
|
actions: [
|
|
33
33
|
{ action: "DELETE", desc: "Delete" },
|
|
@@ -50,7 +50,7 @@ export const User: ModelConfig = {
|
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
52
|
form: {
|
|
53
|
-
fields: ["*", "!creator", "!createdAt", "!updatedAt"],
|
|
53
|
+
fields: ["*", "!creator", "!createdAt", "!updatedAt", "!groupMemberships.*", "!groupMemberships"],
|
|
54
54
|
reaction: {
|
|
55
55
|
id: {
|
|
56
56
|
toggle: [],
|
|
@@ -61,6 +61,6 @@ export const User: ModelConfig = {
|
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
show: {
|
|
64
|
-
fields: ["*", "!createdAt"],
|
|
64
|
+
fields: ["*", "!createdAt", "!groupMemberships.*", "!groupMemberships"],
|
|
65
65
|
},
|
|
66
66
|
};
|
|
@@ -135,7 +135,7 @@ lsof -iTCP:8080 -sTCP:LISTEN
|
|
|
135
135
|
docker compose logs server-init
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
如果状态是 `Exited (1)` 或更高,说明
|
|
138
|
+
如果状态是 `Exited (1)` 或更高,说明 migrate:deploy 或 seed 失败了,server / worker 不会启动。看日志排错后用 `docker compose up -d server-init` 重跑(幂等)。
|
|
139
139
|
|
|
140
140
|
### Temporal schema 初始化失败
|
|
141
141
|
|
|
@@ -154,7 +154,7 @@ server 镜像里 `TAIHU_*` 用的是 `server/.env` 默认值,对应太湖测
|
|
|
154
154
|
```bash
|
|
155
155
|
./compose-ctl.sh --reset
|
|
156
156
|
# 等 temporal-server 重新做 schema setup(看日志 `temporal-server` 里出现 "Temporal server started")
|
|
157
|
-
# server-init 会自动重跑
|
|
157
|
+
# server-init 会自动重跑 migrate:deploy + seed,业务库回到种子数据状态
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
## 用到的镜像
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
#
|
|
17
17
|
# 端口分配(已避免冲突):
|
|
18
18
|
# 5432 -> PostgreSQL
|
|
19
|
-
# 7233 -> Temporal gRPC(Server)
|
|
20
19
|
# 8000 -> NestJS Server(API)
|
|
21
|
-
# 8080 -> Temporal Web UI
|
|
22
20
|
# 3000 -> Web 前端(nginx,容器内 80)
|
|
21
|
+
# Phase 3 起 gadmin-test 不再内嵌 temporal — TEMPORAL_ADDRESS 指向共享 temporal-shared
|
|
22
|
+
# 部署,见 docs/superpowers/specs/2026-07-14-shared-temporal-phase3-design.md
|
|
23
23
|
#
|
|
24
24
|
# 镜像构建依赖(与 Jenkinsfile 保持一致的方案 C):
|
|
25
25
|
# server / web 通过 ARG CODEGEN_IMAGE + FROM ${CODEGEN_IMAGE} 引用本地 codegen 镜像,
|
|
@@ -28,12 +28,14 @@
|
|
|
28
28
|
#
|
|
29
29
|
# 首次启动顺序(depends_on + healthcheck 自动编排):
|
|
30
30
|
# 1. postgres 起来 → healthy(pg_isready)
|
|
31
|
-
# 2.
|
|
32
|
-
# 3. server
|
|
31
|
+
# 2. server-init 跑 migrate:deploy + seed → 退出
|
|
32
|
+
# 3. server 起来
|
|
33
33
|
# 4. web 起来
|
|
34
34
|
#
|
|
35
|
+
# 前置:Phase 3 起 server 需要能连到共享 temporal(TEMPORAL_ADDRESS 必填);
|
|
36
|
+
# 首次使用先跑 `bash dev/register-tenant.sh` 注册本项目为租户。
|
|
37
|
+
#
|
|
35
38
|
# 提示:
|
|
36
|
-
# - 仅起 Temporal(不起 web/server/worker)请用 ./temporal/docker-compose.yml
|
|
37
39
|
# - web 是生产 nginx 镜像,不支持热更新;前端开发请直接 `cd web && yarn dev`
|
|
38
40
|
# =============================================================================
|
|
39
41
|
|
|
@@ -81,68 +83,14 @@ services:
|
|
|
81
83
|
retries: 10
|
|
82
84
|
|
|
83
85
|
# ---------------------------------------------------------------------------
|
|
84
|
-
#
|
|
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
|
|
86
|
+
# Server 一次性初始化:migrate:deploy + seed
|
|
139
87
|
# ---------------------------------------------------------------------------
|
|
140
88
|
# 直接复用 codegen 镜像(它已含 server 全量依赖:ts-node / prisma CLI / seed/ 源码)。
|
|
141
89
|
# 业务 server 镜像走 `--production` 安装、且不复制 seed/,因此 seed 不能在 server
|
|
142
90
|
# 容器里跑;这里独立成 init 容器,跑完即退出。
|
|
143
91
|
#
|
|
144
92
|
# 幂等:
|
|
145
|
-
# -
|
|
93
|
+
# - migrate:deploy 多次执行无害(只补 schema 差异)
|
|
146
94
|
# - seed 全部用 createMany skipDuplicates / upsert 风格,重复跑不会重复插
|
|
147
95
|
#
|
|
148
96
|
# 依赖:
|
|
@@ -167,8 +115,8 @@ services:
|
|
|
167
115
|
- -c
|
|
168
116
|
- |
|
|
169
117
|
set -e
|
|
170
|
-
echo "[server-init]
|
|
171
|
-
yarn
|
|
118
|
+
echo "[server-init] migrate deploy ..."
|
|
119
|
+
yarn migrate:deploy
|
|
172
120
|
echo "[server-init] seed ..."
|
|
173
121
|
yarn seed
|
|
174
122
|
echo "[server-init] done."
|
|
@@ -193,42 +141,15 @@ services:
|
|
|
193
141
|
condition: service_healthy
|
|
194
142
|
server-init:
|
|
195
143
|
condition: service_completed_successfully
|
|
196
|
-
# 不等 temporal-server healthy:server 启动不强依赖 Temporal
|
|
197
|
-
temporal-server:
|
|
198
|
-
condition: service_started
|
|
199
144
|
environment:
|
|
200
145
|
DATABASE_URL: postgresql://${POSTGRES_USER:-kavenma}:${POSTGRES_PASSWORD:-kavenma}@postgres:5432/gadmin_demo?schema=public
|
|
201
|
-
TEMPORAL_ADDRESS:
|
|
202
|
-
TEMPORAL_NAMESPACE: ${TEMPORAL_NAMESPACE:-
|
|
146
|
+
TEMPORAL_ADDRESS: ${TEMPORAL_ADDRESS:?TEMPORAL_ADDRESS not set — see server/.env}
|
|
147
|
+
TEMPORAL_NAMESPACE: ${TEMPORAL_NAMESPACE:-gadmin-test}
|
|
203
148
|
TEMPORAL_TASK_QUEUE: ${TEMPORAL_TASK_QUEUE:-workflow-execution}
|
|
204
149
|
NODE_ENV: ${NODE_ENV:-development}
|
|
205
150
|
ports:
|
|
206
151
|
- "8000:8000"
|
|
207
152
|
|
|
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
153
|
# ---------------------------------------------------------------------------
|
|
233
154
|
# Web 前端(生产 nginx 镜像;本地仅用于完整集成验证)
|
|
234
155
|
# 镜像构建依赖 codegen:先 `docker compose --profile codegen build codegen`
|
|
@@ -27,7 +27,7 @@ $ vi config/ui/{ModelName}.ts
|
|
|
27
27
|
|
|
28
28
|
### Generate code after edit config/schema.prisma or config/ui.config.ts
|
|
29
29
|
```
|
|
30
|
-
$ gadmin2 g prisma:dev #
|
|
30
|
+
$ gadmin2 g prisma:dev # 生成 CRUD 代码 + 创建并应用迁移(内部调 migrate:dev);gadmin2 g prisma 只生成代码、不碰数据库
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
### Start web DevServer
|
|
@@ -45,6 +45,104 @@ $ yarn start:dev
|
|
|
45
45
|
```
|
|
46
46
|
About nestjs server [read more](https://ptc.coding.intlgame.com/p/gadmin2/d/schematics/git/tree/master/src/lib/application/files/server/nest/README.md)
|
|
47
47
|
|
|
48
|
+
## 数据库迁移(Prisma Migrations)
|
|
49
|
+
|
|
50
|
+
> Schema 的唯一手写真源是 `config/prisma/*.prisma`。`gadmin2 g prisma:dev` 会据此聚合出 `server/prisma/schema.prisma`、生成后端 CRUD 代码,并调用 `migrate:dev` 创建并应用迁移。
|
|
51
|
+
|
|
52
|
+
### Git 追踪边界
|
|
53
|
+
|
|
54
|
+
| 类别 | 路径 | 是否入库 | 谁生成 |
|
|
55
|
+
|------|------|:---:|------|
|
|
56
|
+
| Schema 真源(手改) | `config/prisma/*.prisma` | ✅ | 人 |
|
|
57
|
+
| 迁移文件 | `server/prisma/migrations/` | ✅ | `prisma migrate` |
|
|
58
|
+
| 前端页面 | `web/src/routes/` | ✅ | react 生成器 |
|
|
59
|
+
| 聚合 schema | `server/prisma/schema.prisma` | ❌ | gadmin 聚合 |
|
|
60
|
+
| 后端 CRUD | `server/src/generated/` | ❌ | nestjs 生成器 |
|
|
61
|
+
|
|
62
|
+
因为 `schema.prisma` 与 `generated/` 不入库,**每次拉取到 schema/迁移变更后都要本地重新生成**(见下方 git hook)。
|
|
63
|
+
|
|
64
|
+
### 环境规则(重要)
|
|
65
|
+
|
|
66
|
+
`gadmin2 g prisma:dev` 在检测到漂移时会提示重置数据库,**只能在各自本地库运行**;共享库(测试/生产)一律用 `migrate deploy`(只回放迁移、从不删数据)。
|
|
67
|
+
|
|
68
|
+
| 环境 | 允许的迁移命令 |
|
|
69
|
+
|------|------|
|
|
70
|
+
| 本地开发(各自本地库) | `gadmin2 g prisma:dev` |
|
|
71
|
+
| 共享测试 / 生产库 | 仅 `yarn migrate:deploy` |
|
|
72
|
+
|
|
73
|
+
### 命令详解:`gadmin2 g prisma:dev` vs `yarn migrate:deploy`
|
|
74
|
+
|
|
75
|
+
**`gadmin2 g prisma:dev`(内部调 `migrate:dev` = `prisma migrate dev --name auto`)**
|
|
76
|
+
|
|
77
|
+
一条命令做四件事,按顺序:
|
|
78
|
+
|
|
79
|
+
1. 据 `config/prisma/*.prisma` 聚合出 `server/prisma/schema.prisma`,并生成后端 CRUD 代码
|
|
80
|
+
2. 对比迁移目录与数据库 `_prisma_migrations` 表,**按顺序应用所有 pending 迁移**(含刚拉下来的别人的迁移)
|
|
81
|
+
3. 再对比 `schema.prisma` 与迁移历史,**若本地还有未捕获的 schema 改动,则生成一个新迁移并应用**(`--name auto` 自动命名)
|
|
82
|
+
4. 重新生成 Prisma Client
|
|
83
|
+
|
|
84
|
+
要点:
|
|
85
|
+
- **会生成迁移、会应用、会重新生成代码**——本地开发的主命令。
|
|
86
|
+
- 检测到**漂移(drift)**(本地库和迁移历史对不上,如曾手动 `db push` 改过表)时,会**交互式提示重置数据库(drop 重建)**。纯拉取+应用别人迁移通常不触发;本地库被改脏才会。遇到时看清提示再决定,别盲目回车。
|
|
87
|
+
- 因为会改本地库且交互,**绝不能对共享/生产库运行**。
|
|
88
|
+
|
|
89
|
+
**`yarn migrate:deploy`(= `prisma migrate deploy`)**
|
|
90
|
+
|
|
91
|
+
- **只回放 pending 迁移,从不生成迁移、从不删数据、无交互**,也不会因 drift 提示 reset。
|
|
92
|
+
- **不重新生成后端 CRUD 代码**——若拉下来的变更带了新表/新字段需要 module 代码,还得再跑 `gadmin2 g prisma`(只生成代码、不碰库)。
|
|
93
|
+
- 共享测试库、生产库、CI/部署链路(`start-prod.sh`)专用。
|
|
94
|
+
|
|
95
|
+
**如何选(拉取到别人的新迁移后)**
|
|
96
|
+
|
|
97
|
+
| 我的情况 | 用哪条 |
|
|
98
|
+
|------|------|
|
|
99
|
+
| 本地开发,且/或自己也改了 schema,要生成代码 | `gadmin2 g prisma:dev` |
|
|
100
|
+
| 本地开发,确定自己没改 schema,只想安全应用别人迁移 | `yarn migrate:deploy`(如需代码再 `gadmin2 g prisma`) |
|
|
101
|
+
| 共享测试 / 生产库 | 只能 `yarn migrate:deploy` |
|
|
102
|
+
|
|
103
|
+
### 日常开发流
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
1. 改 config/prisma/{module}.prisma # 唯一手写处
|
|
107
|
+
2. yarn migrate:create # 只生成迁移文件,不应用
|
|
108
|
+
3. 审查 server/prisma/migrations/xxx/migration.sql # 重点看 DROP / 改列类型 / NOT NULL
|
|
109
|
+
4. gadmin2 g prisma:dev # 生成 CRUD 代码 + 应用迁移到本地库
|
|
110
|
+
5. 提交 config/prisma/* + server/prisma/migrations/* + web/src/routes/*
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> 建议第 2、3 步分开:先 `--create-only` 生成、人工审 SQL,再应用,避免误改把线上表 DROP。急活也可跳过直接跑第 4 步(`migrate:dev` 会交互式要迁移名并一步生成+应用)。
|
|
114
|
+
|
|
115
|
+
### 拉取他人改动后
|
|
116
|
+
|
|
117
|
+
`.husky/post-merge` 与 `.husky/post-rewrite` 会在 `git pull`(merge)/ `git pull --rebase` 后,检测本次是否含 schema/迁移变更并提示:
|
|
118
|
+
|
|
119
|
+
- 含 `config/prisma/*` 或新迁移 → 运行 `gadmin2 g prisma:dev`(应用新迁移 + 重新生成后端代码)
|
|
120
|
+
- 仅含 `config/ui/*` → 运行 `gadmin2 g prisma`(只重新生成前端代码)
|
|
121
|
+
|
|
122
|
+
hook 只提示、不自动执行(`migrate:dev` 会改本地库且交互,不宜静默跑);需先在项目根跑过一次 `yarn`(触发 `husky install`)hook 才生效。
|
|
123
|
+
|
|
124
|
+
### 首次接入迁移(baseline)
|
|
125
|
+
|
|
126
|
+
如果现存库最初由 `db push` 建立、无迁移历史,切换到迁移前需 baseline。`0_init` 为全量基线,已入库。是否要标记「已应用」取决于**本库是否已有表**(这条记录写在数据库 `_prisma_migrations` 表,不随 git 同步,每个库独立):
|
|
127
|
+
|
|
128
|
+
| 场景 | 生成 0_init | `migrate resolve --applied 0_init` | 之后 |
|
|
129
|
+
|------|:---:|:---:|------|
|
|
130
|
+
| 已有本地库(db push 建的) | ❌ 文件已入库 | ✅ 必须一次 | 正常 `gadmin2 g prisma:dev` |
|
|
131
|
+
| 新环境 / 空库 | ❌ | ❌ 不需要 | 直接 `gadmin2 g prisma:dev` 建全表 |
|
|
132
|
+
| 共享测试/生产库(现存非空) | ❌ | ✅ 首次一次 | 之后 `yarn migrate:deploy` |
|
|
133
|
+
|
|
134
|
+
resolve 命令(在 `server/` 下执行,注意用本地 `dotenv-cli` 以避免命中全局 python-dotenv):
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
$ cd server
|
|
138
|
+
$ ./node_modules/.bin/dotenv -e .env.local -e .env -- npx prisma migrate resolve --applied 0_init
|
|
139
|
+
$ ./node_modules/.bin/dotenv -e .env.local -e .env -- npx prisma migrate status # 验证:应显示 up to date、无 pending
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 迁移冲突约定
|
|
143
|
+
|
|
144
|
+
两人各自基于同一父迁移生成迁移,合并后顺序会乱。约定:schema 改动**小步快合**;合并遇到迁移冲突时,**后合并者删掉自己的迁移文件、rebase 后重新 `yarn migrate:create`**,不要手改文件名时间戳。
|
|
145
|
+
|
|
48
146
|
## 构建与部署
|
|
49
147
|
|
|
50
148
|
### 模块划分
|
|
@@ -144,7 +242,7 @@ post.always: 清理本地 codegen 中间镜像
|
|
|
144
242
|
│ • CREATE DATABASE temporal_visibility
|
|
145
243
|
│
|
|
146
244
|
├── server-init(一次性容器,depends_on postgres healthy)
|
|
147
|
-
│ • yarn
|
|
245
|
+
│ • yarn migrate:deploy (prisma 把 schema 推到 gadmin_demo)
|
|
148
246
|
│ • yarn seed (播种 RBAC 等基础数据,跑完即退出 Exited 0)
|
|
149
247
|
│
|
|
150
248
|
└── server / web / temporal-* (正常服务)
|
|
@@ -157,7 +255,7 @@ post.always: 清理本地 codegen 中间镜像
|
|
|
157
255
|
|
|
158
256
|
#### 2. 生产 / 临时环境(K8s + `server/start-prod.sh`)
|
|
159
257
|
|
|
160
|
-
server 镜像的入口是 `start-prod.sh`,比本地 compose 多了「按需
|
|
258
|
+
server 镜像的入口是 `start-prod.sh`,比本地 compose 多了「按需 migrate:deploy」「per-branch schema 隔离」逻辑:
|
|
161
259
|
|
|
162
260
|
```
|
|
163
261
|
container start
|
|
@@ -173,13 +271,13 @@ container start
|
|
|
173
271
|
│ │
|
|
174
272
|
│ ├─ A. 临时环境(feature*/bugfix*/hotfix*):每次启动都重建分支 schema
|
|
175
273
|
│ │ • 改写 DATABASE_URL:schema=<DEPLOY_NAME>(- 与 / 替换为 _)
|
|
176
|
-
│ │ • yarn
|
|
274
|
+
│ │ • yarn migrate:deploy
|
|
177
275
|
│ │ • node migrate-between-pg-schemas.js (从 public schema 拷数据到分支 schema)
|
|
178
276
|
│ │ • yarn seed (幂等,每次启动都跑)
|
|
179
277
|
│ │
|
|
180
278
|
│ └─ B. 非临时环境(默认 / production):按需初始化
|
|
181
279
|
│ • DATABASE_URL 兜底 schema=public
|
|
182
|
-
│ • 探测 t_role:不存在或 count=0 → yarn
|
|
280
|
+
│ • 探测 t_role:不存在或 count=0 → yarn migrate:deploy + yarn seed;否则跳过
|
|
183
281
|
│ • 连接失败等异常 → 保守走初始化路径
|
|
184
282
|
│
|
|
185
283
|
└── exec node dist/src/main ← 启动 NestJS
|
|
@@ -188,7 +286,7 @@ container start
|
|
|
188
286
|
要点:
|
|
189
287
|
- `ensure-database.js` 与本地 compose 的 `init.sql` 是**互补关系**:compose 路径走 init.sql,K8s / 外部托管 PG 走 ensure-database.js。重复执行无副作用。
|
|
190
288
|
- 临时环境「每次启动都 seed」依赖所有 seed 实现都是 upsert / skipDuplicates 风格,重复跑不插重。
|
|
191
|
-
- 非临时环境用 `t_role` 行数判断是否需要初始化(首次部署或被清库),避免每次重启都跑
|
|
289
|
+
- 非临时环境用 `t_role` 行数判断是否需要初始化(首次部署或被清库),避免每次重启都跑 migrate:deploy + seed。
|
|
192
290
|
- 如果部署环境已通过 DBA / 运维流程保证库存在,可设 `SKIP_ENSURE_DATABASE=1` 跳过 ensure-database.js(预留开关,当前实现未消费该变量,按需扩展)。
|
|
193
291
|
|
|
194
292
|
#### 3. 谁在何时建什么 — 总览
|
|
@@ -196,7 +294,7 @@ container start
|
|
|
196
294
|
| 对象 | 本地 compose | 生产 / 临时环境 |
|
|
197
295
|
|---|---|---|
|
|
198
296
|
| 数据库(`gadmin_demo`) | `dev/postgres/init.sql`(pgdata 卷为空时) | `ensure-database.js`(每次启动幂等) |
|
|
199
|
-
| Schema + 表结构 | `server-init` 里 `yarn
|
|
297
|
+
| Schema + 表结构 | `server-init` 里 `yarn migrate:deploy` | `start-prod.sh` 按分支策略 `yarn migrate:deploy` |
|
|
200
298
|
| 基础数据(seed) | `server-init` 里 `yarn seed` | `start-prod.sh` 按分支策略 `yarn seed` |
|
|
201
299
|
| 临时环境 schema 隔离 | — | `start-prod.sh` 改写 DATABASE_URL + `migrate-between-pg-schemas.js` |
|
|
202
300
|
|
|
@@ -22,22 +22,23 @@
|
|
|
22
22
|
"test:cov": "jest --coverage",
|
|
23
23
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
|
24
24
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
|
25
|
-
"migrate:dev": "
|
|
26
|
-
"migrate:
|
|
25
|
+
"migrate:dev": "dotenv -e .env.local -e .env -- prisma migrate dev --name auto",
|
|
26
|
+
"migrate:create": "dotenv -e .env.local -e .env -- prisma migrate dev --create-only",
|
|
27
27
|
"migrate:deploy": "dotenv -e .env.local -e .env -- prisma migrate deploy",
|
|
28
28
|
"migrate:status": "dotenv -e .env.local -e .env -- prisma migrate status",
|
|
29
29
|
"generate": "dotenv -e .env.local -e .env -- npx prisma generate",
|
|
30
|
-
"generate:dev": "npm run migrate:dev
|
|
30
|
+
"generate:dev": "npm run migrate:dev",
|
|
31
31
|
"postgenerate:dev": "dotenv -e .env.local -e .env -- ts-node seed/data-mngt.seed.ts",
|
|
32
32
|
"postgadminGenerate": "node scripts/notify-dev-servers.js",
|
|
33
33
|
"push:db": "dotenv -e .env.local -e .env -- prisma db push --skip-generate",
|
|
34
34
|
"seed": "dotenv -e .env.local -e .env -- ts-node seed/index.ts",
|
|
35
|
-
"prisma:studio": "dotenv -e .env.local -e .env -- prisma studio"
|
|
35
|
+
"prisma:studio": "dotenv -e .env.local -e .env -- prisma studio",
|
|
36
|
+
"gen:jwt": "dotenv -e .env.local -e .env -- ts-node scripts/gen-jwt.ts"
|
|
36
37
|
},
|
|
37
38
|
"dependencies": {
|
|
38
39
|
"@agendajs/postgres-backend": "^3.0.5",
|
|
39
40
|
"@azure/identity": "^4.13.0",
|
|
40
|
-
"@gadmin2n/nest-common": "^0.
|
|
41
|
+
"@gadmin2n/nest-common": "^0.1.3",
|
|
41
42
|
"@nestjs/cache-manager": "^3.0.1",
|
|
42
43
|
"@nestjs/common": "^10.4.15",
|
|
43
44
|
"@nestjs/config": "^3.2.0",
|
|
@@ -90,7 +91,7 @@
|
|
|
90
91
|
"devDependencies": {
|
|
91
92
|
"@faker-js/faker": "^10.4.0",
|
|
92
93
|
"@gadmin2n/prisma-nest-generator": "^0.0.49",
|
|
93
|
-
"@gadmin2n/prisma-react-generator": "^0.0.
|
|
94
|
+
"@gadmin2n/prisma-react-generator": "^0.0.69",
|
|
94
95
|
"@nestjs/cli": "^11.0.21",
|
|
95
96
|
"@nestjs/testing": "^10.4.15",
|
|
96
97
|
"@swc/cli": "^0.8.1",
|
|
@@ -6,6 +6,11 @@ import { defineConfig } from 'prisma/config';
|
|
|
6
6
|
dotenv.config({ path: path.resolve(__dirname, '.env.local') });
|
|
7
7
|
dotenv.config({ path: path.resolve(__dirname, '.env') });
|
|
8
8
|
|
|
9
|
+
// 从连接串的 ?schema= 读取外部表所在 schema,缺省 public
|
|
10
|
+
const schema =
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
12
|
+
new URL(process.env.DATABASE_URL!).searchParams.get('schema') ?? 'public';
|
|
13
|
+
|
|
9
14
|
export default defineConfig({
|
|
10
15
|
engine: 'classic',
|
|
11
16
|
datasource: {
|
|
@@ -18,6 +23,9 @@ export default defineConfig({
|
|
|
18
23
|
tables: {
|
|
19
24
|
// 将要被 Prisma 标记为“外部管理”的表名列表
|
|
20
25
|
// 可以使用 "schema.table" 或仅 "table"(依你 DB/项目设置)
|
|
21
|
-
|
|
26
|
+
// agenda_jobs / agenda_logs 均由 @agendajs/postgres-backend 在服务启动时
|
|
27
|
+
// 通过 CREATE TABLE IF NOT EXISTS 自动创建并维护(含部分索引、唯一索引、触发器),
|
|
28
|
+
// Prisma schema 无法完整表达,故整体交给库管理,迁移不碰。
|
|
29
|
+
external: [`${schema}.agenda_jobs`, `${schema}.agenda_logs`],
|
|
22
30
|
},
|
|
23
31
|
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gen-jwt.ts — 使用 TaiHuId.sign() 为 seed 用户生成 JWT token
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* yarn gen:jwt --userid kavenma
|
|
6
|
+
* yarn gen:jwt --userid kavenma --expiresIn 3600
|
|
7
|
+
*
|
|
8
|
+
* userid 必须在 seed/users.ts 中存在。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import seedUsers from '../seed/users';
|
|
12
|
+
import TaiHuId from '../src/lib/taihu';
|
|
13
|
+
|
|
14
|
+
function parseArgs(): Record<string, string> {
|
|
15
|
+
const argv = process.argv.slice(2);
|
|
16
|
+
const flags: Record<string, string> = {};
|
|
17
|
+
for (let i = 0; i < argv.length; i++) {
|
|
18
|
+
if (argv[i].startsWith('--')) {
|
|
19
|
+
const key = argv[i].slice(2);
|
|
20
|
+
const next = argv[i + 1];
|
|
21
|
+
flags[key] = next && !next.startsWith('--') ? argv[++i] : 'true';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return flags;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function main() {
|
|
28
|
+
const flags = parseArgs();
|
|
29
|
+
const { userid, expiresIn } = flags;
|
|
30
|
+
|
|
31
|
+
if (!userid) {
|
|
32
|
+
console.error('[gen-jwt] --userid is required.');
|
|
33
|
+
console.error(
|
|
34
|
+
`[gen-jwt] Available userids: ${seedUsers
|
|
35
|
+
.map((u) => u.userid)
|
|
36
|
+
.join(', ')}`,
|
|
37
|
+
);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const user = seedUsers.find((u) => u.userid === userid);
|
|
42
|
+
if (!user) {
|
|
43
|
+
console.error(`[gen-jwt] userid "${userid}" not found in seed/users.ts.`);
|
|
44
|
+
console.error(
|
|
45
|
+
`[gen-jwt] Available userids: ${seedUsers
|
|
46
|
+
.map((u) => u.userid)
|
|
47
|
+
.join(', ')}`,
|
|
48
|
+
);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const ttl = expiresIn ? parseInt(expiresIn, 10) : 7 * 24 * 60 * 60; // 默认 7 天
|
|
53
|
+
|
|
54
|
+
const token = await TaiHuId.sign(
|
|
55
|
+
{
|
|
56
|
+
user_id: user.userid,
|
|
57
|
+
sub: user.userid,
|
|
58
|
+
name: user.username,
|
|
59
|
+
email: `${user.userid}@tencent.com`,
|
|
60
|
+
},
|
|
61
|
+
ttl,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
console.log(
|
|
65
|
+
`[gen-jwt] ✅ Generated JWT for userid=${user.userid} (expiresIn=${ttl}s):\n`,
|
|
66
|
+
);
|
|
67
|
+
console.log(token);
|
|
68
|
+
|
|
69
|
+
console.log('\n[gen-jwt] 🍪 如何在浏览器中种入 cookie:');
|
|
70
|
+
console.log(' 1) 打开目标站点(例如 http://localhost:3000),进入 DevTools');
|
|
71
|
+
console.log(' 2) Application → Cookies → 选择当前域名');
|
|
72
|
+
console.log(
|
|
73
|
+
' 新增一条 cookie:Name=gadmin-token Value=<上面的 token> Path=/',
|
|
74
|
+
);
|
|
75
|
+
console.log(' 3) 刷新页面即可以该 userid 身份登录\n');
|
|
76
|
+
console.log(' 或在 DevTools Console 中执行(同域下即时生效):');
|
|
77
|
+
console.log(
|
|
78
|
+
` document.cookie = "gadmin-token=${token}; path=/; max-age=${ttl}"`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main().catch((e) => {
|
|
83
|
+
console.error('[gen-jwt] Fatal error:', e);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
});
|
package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/notify-dev-servers.js
CHANGED
|
@@ -44,7 +44,7 @@ const HEALTH_URL = `http://127.0.0.1:${NEST_PORT}/api/health/live`;
|
|
|
44
44
|
const WEB_SENTINEL = path.resolve(process.cwd(), '..', 'web', '.vite-restart');
|
|
45
45
|
|
|
46
46
|
function log(msg) {
|
|
47
|
-
process.stdout.write(
|
|
47
|
+
process.stdout.write(`\x1b[90m[postgadminGenerate] ${msg}\x1b[0m\n`);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function pingOnce(url) {
|
|
@@ -81,18 +81,19 @@ function touchViteSentinel() {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
(async () => {
|
|
84
|
+
const rawOpts = {
|
|
85
|
+
pollMs: envInt('POSTGEN_POLL_MS'),
|
|
86
|
+
initialStableMs: envInt('POSTGEN_INITIAL_STABLE_MS'),
|
|
87
|
+
maxStableMs: envInt('POSTGEN_MAX_STABLE_MS'),
|
|
88
|
+
observeDownTimeoutMs: envInt('POSTGEN_OBSERVE_DOWN_TIMEOUT_MS'),
|
|
89
|
+
totalTimeoutMs: envInt('POSTGEN_TOTAL_TIMEOUT_MS'),
|
|
90
|
+
};
|
|
84
91
|
await waitForNestReady({
|
|
85
92
|
ping: () => pingOnce(HEALTH_URL),
|
|
86
93
|
sleep,
|
|
87
94
|
now: () => Date.now(),
|
|
88
95
|
log,
|
|
89
|
-
opts:
|
|
90
|
-
pollMs: envInt('POSTGEN_POLL_MS'),
|
|
91
|
-
initialStableMs: envInt('POSTGEN_INITIAL_STABLE_MS'),
|
|
92
|
-
maxStableMs: envInt('POSTGEN_MAX_STABLE_MS'),
|
|
93
|
-
observeDownTimeoutMs: envInt('POSTGEN_OBSERVE_DOWN_TIMEOUT_MS'),
|
|
94
|
-
totalTimeoutMs: envInt('POSTGEN_TOTAL_TIMEOUT_MS'),
|
|
95
|
-
},
|
|
96
|
+
opts: Object.fromEntries(Object.entries(rawOpts).filter(([, v]) => v !== undefined)),
|
|
96
97
|
});
|
|
97
98
|
touchViteSentinel();
|
|
98
99
|
})().catch((e) => {
|