@robsun/create-keystone-app 0.2.13 → 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.
- package/README.md +46 -43
- package/dist/create-keystone-app.js +347 -10
- package/dist/create-module.js +1219 -607
- package/package.json +22 -23
- package/template/.claude/skills/keystone-implement/SKILL.md +113 -0
- package/template/.claude/skills/keystone-implement/references/CHECKLIST.md +91 -0
- package/template/.claude/skills/keystone-implement/references/PATTERNS.md +1088 -0
- package/template/.claude/skills/keystone-implement/references/SCHEMA.md +135 -0
- package/template/.claude/skills/keystone-implement/references/TESTING.md +231 -0
- package/template/.claude/skills/keystone-requirements/SKILL.md +296 -0
- package/template/.claude/skills/keystone-requirements/references/CONFIRM_TEMPLATE.md +170 -0
- package/template/.claude/skills/keystone-requirements/references/SCHEMA.md +135 -0
- package/template/.eslintrc.js +3 -0
- package/template/.github/workflows/ci.yml +30 -0
- package/template/.github/workflows/release.yml +32 -0
- package/template/.golangci.yml +11 -0
- package/template/README.md +81 -73
- package/template/apps/server/README.md +8 -0
- package/template/apps/server/cmd/server/main.go +27 -185
- package/template/apps/server/config.example.yaml +31 -1
- package/template/apps/server/config.yaml +31 -1
- package/template/apps/server/go.mod +60 -18
- package/template/apps/server/go.sum +183 -31
- package/template/apps/server/internal/frontend/embed.go +3 -8
- package/template/apps/server/internal/modules/example/README.md +18 -0
- package/template/apps/server/internal/modules/example/api/handler/handler_test.go +9 -0
- package/template/apps/server/internal/modules/example/api/handler/item_handler.go +468 -165
- package/template/apps/server/internal/modules/example/bootstrap/seeds/item.go +217 -8
- package/template/apps/server/internal/modules/example/domain/models/item.go +40 -7
- package/template/apps/server/internal/modules/example/domain/service/approval_callback.go +68 -0
- package/template/apps/server/internal/modules/example/domain/service/approval_schema.go +41 -0
- package/template/apps/server/internal/modules/example/domain/service/errors.go +20 -22
- package/template/apps/server/internal/modules/example/domain/service/item_service.go +267 -7
- package/template/apps/server/internal/modules/example/domain/service/item_service_test.go +281 -0
- package/template/apps/server/internal/modules/example/i18n/keys.go +32 -20
- package/template/apps/server/internal/modules/example/i18n/locales/en-US.json +30 -18
- package/template/apps/server/internal/modules/example/i18n/locales/zh-CN.json +30 -18
- package/template/apps/server/internal/modules/example/infra/exporter/item_exporter.go +119 -0
- package/template/apps/server/internal/modules/example/infra/importer/item_importer.go +77 -0
- package/template/apps/server/internal/modules/example/infra/repository/item_repository.go +99 -49
- package/template/apps/server/internal/modules/example/module.go +171 -97
- package/template/apps/server/internal/modules/example/tests/integration_test.go +7 -0
- package/template/apps/server/internal/modules/manifest.go +7 -7
- package/template/apps/web/README.md +4 -2
- package/template/apps/web/package.json +1 -1
- package/template/apps/web/src/app.config.ts +8 -6
- package/template/apps/web/src/index.css +7 -3
- package/template/apps/web/src/main.tsx +2 -5
- package/template/apps/web/src/modules/example/help/en-US/faq.md +27 -0
- package/template/apps/web/src/modules/example/help/en-US/items.md +30 -0
- package/template/apps/web/src/modules/example/help/en-US/overview.md +31 -0
- package/template/apps/web/src/modules/example/help/zh-CN/faq.md +27 -0
- package/template/apps/web/src/modules/example/help/zh-CN/items.md +31 -0
- package/template/apps/web/src/modules/example/help/zh-CN/overview.md +32 -0
- package/template/apps/web/src/modules/example/locales/en-US/example.json +99 -32
- package/template/apps/web/src/modules/example/locales/zh-CN/example.json +85 -18
- package/template/apps/web/src/modules/example/pages/ExampleItemsPage.tsx +840 -237
- package/template/apps/web/src/modules/example/services/exampleItems.ts +79 -8
- package/template/apps/web/src/modules/example/types.ts +14 -1
- package/template/apps/web/src/modules/index.ts +1 -0
- package/template/apps/web/vite.config.ts +9 -3
- package/template/docs/CONVENTIONS.md +10 -7
- package/template/package.json +4 -5
- package/template/pnpm-lock.yaml +76 -5
- package/template/scripts/build.bat +15 -3
- package/template/scripts/build.sh +9 -3
- package/template/scripts/check-help.js +249 -0
- package/template/scripts/compress-assets.js +89 -0
- package/template/scripts/test.bat +23 -0
- package/template/scripts/test.sh +16 -0
- package/template/.claude/skills/keystone-dev/SKILL.md +0 -103
- package/template/.claude/skills/keystone-dev/references/APPROVAL.md +0 -121
- package/template/.claude/skills/keystone-dev/references/CAPABILITIES.md +0 -261
- package/template/.claude/skills/keystone-dev/references/TEMPLATES.md +0 -532
- package/template/.claude/skills/keystone-dev/references/TESTING.md +0 -44
- package/template/.codex/skills/keystone-dev/SKILL.md +0 -103
- package/template/.codex/skills/keystone-dev/references/APPROVAL.md +0 -121
- package/template/.codex/skills/keystone-dev/references/CAPABILITIES.md +0 -261
- package/template/.codex/skills/keystone-dev/references/TEMPLATES.md +0 -532
- package/template/.codex/skills/keystone-dev/references/TESTING.md +0 -44
- package/template/apps/server/internal/app/routes/module_routes.go +0 -16
- package/template/apps/server/internal/app/routes/routes.go +0 -226
- package/template/apps/server/internal/app/startup/startup.go +0 -74
- package/template/apps/server/internal/frontend/handler.go +0 -122
- package/template/apps/server/internal/modules/registry.go +0 -145
- package/template/apps/web/src/modules/example/help/faq.md +0 -23
- package/template/apps/web/src/modules/example/help/items.md +0 -26
- package/template/apps/web/src/modules/example/help/overview.md +0 -25
|
@@ -1,19 +1,71 @@
|
|
|
1
|
-
import { api, type ApiResponse } from '@robsun/keystone-web-core'
|
|
2
|
-
import type {
|
|
1
|
+
import { api, type ApiResponse, type PaginatedData } from '@robsun/keystone-web-core'
|
|
2
|
+
import type {
|
|
3
|
+
ExampleApprovalStatus,
|
|
4
|
+
ExampleItem,
|
|
5
|
+
ExampleItemCategory,
|
|
6
|
+
ExampleItemStatus,
|
|
7
|
+
} from '../types'
|
|
3
8
|
|
|
4
|
-
type
|
|
5
|
-
|
|
9
|
+
export type ExampleItemListParams = {
|
|
10
|
+
page?: number
|
|
11
|
+
pageSize?: number
|
|
12
|
+
keyword?: string
|
|
13
|
+
status?: ExampleItemStatus
|
|
14
|
+
approvalStatus?: ExampleApprovalStatus
|
|
15
|
+
category?: ExampleItemCategory
|
|
16
|
+
startDate?: string
|
|
17
|
+
endDate?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ExampleItemExportParams = Omit<ExampleItemListParams, 'page' | 'pageSize'>
|
|
21
|
+
|
|
22
|
+
export const listExampleItems = async (
|
|
23
|
+
params: ExampleItemListParams = {}
|
|
24
|
+
): Promise<PaginatedData<ExampleItem>> => {
|
|
25
|
+
const { data } = await api.get<ApiResponse<PaginatedData<ExampleItem>>>('/example/items', {
|
|
26
|
+
params: {
|
|
27
|
+
page: params.page,
|
|
28
|
+
page_size: params.pageSize,
|
|
29
|
+
keyword: params.keyword,
|
|
30
|
+
status: params.status,
|
|
31
|
+
approval_status: params.approvalStatus,
|
|
32
|
+
category: params.category,
|
|
33
|
+
start_date: params.startDate,
|
|
34
|
+
end_date: params.endDate,
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
return data.data
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const exportExampleItemsPdf = async (
|
|
41
|
+
params: ExampleItemExportParams = {}
|
|
42
|
+
): Promise<Blob> => {
|
|
43
|
+
const { data } = await api.get<Blob>('/example/items/export/pdf', {
|
|
44
|
+
params: {
|
|
45
|
+
keyword: params.keyword,
|
|
46
|
+
status: params.status,
|
|
47
|
+
approval_status: params.approvalStatus,
|
|
48
|
+
category: params.category,
|
|
49
|
+
start_date: params.startDate,
|
|
50
|
+
end_date: params.endDate,
|
|
51
|
+
},
|
|
52
|
+
responseType: 'blob',
|
|
53
|
+
})
|
|
54
|
+
return data
|
|
6
55
|
}
|
|
7
56
|
|
|
8
|
-
export const
|
|
9
|
-
const { data } = await api.get<ApiResponse<
|
|
10
|
-
return data.data
|
|
57
|
+
export const getExampleItem = async (id: number): Promise<ExampleItem> => {
|
|
58
|
+
const { data } = await api.get<ApiResponse<ExampleItem>>(`/example/items/${id}`)
|
|
59
|
+
return data.data
|
|
11
60
|
}
|
|
12
61
|
|
|
13
62
|
export const createExampleItem = async (payload: {
|
|
14
63
|
title: string
|
|
15
64
|
description?: string
|
|
65
|
+
category?: ExampleItemCategory
|
|
66
|
+
amount?: number
|
|
16
67
|
status?: ExampleItemStatus
|
|
68
|
+
attachment?: Record<string, unknown> | null
|
|
17
69
|
}) => {
|
|
18
70
|
const { data } = await api.post<ApiResponse<ExampleItem>>('/example/items', payload)
|
|
19
71
|
return data.data
|
|
@@ -21,7 +73,14 @@ export const createExampleItem = async (payload: {
|
|
|
21
73
|
|
|
22
74
|
export const updateExampleItem = async (
|
|
23
75
|
id: number,
|
|
24
|
-
payload: {
|
|
76
|
+
payload: {
|
|
77
|
+
title?: string
|
|
78
|
+
description?: string
|
|
79
|
+
category?: ExampleItemCategory
|
|
80
|
+
amount?: number
|
|
81
|
+
status?: ExampleItemStatus
|
|
82
|
+
attachment?: Record<string, unknown> | null
|
|
83
|
+
}
|
|
25
84
|
) => {
|
|
26
85
|
const { data } = await api.patch<ApiResponse<ExampleItem>>(`/example/items/${id}`, payload)
|
|
27
86
|
return data.data
|
|
@@ -30,3 +89,15 @@ export const updateExampleItem = async (
|
|
|
30
89
|
export const deleteExampleItem = async (id: number) => {
|
|
31
90
|
await api.delete<ApiResponse<{ id: number }>>(`/example/items/${id}`)
|
|
32
91
|
}
|
|
92
|
+
|
|
93
|
+
export const submitExampleItem = async (id: number) => {
|
|
94
|
+
const { data } = await api.post<ApiResponse<ExampleItem>>(`/example/items/${id}/submit`)
|
|
95
|
+
return data.data
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const cancelExampleItem = async (id: number, reason?: string) => {
|
|
99
|
+
const { data } = await api.post<ApiResponse<ExampleItem>>(`/example/items/${id}/cancel`, {
|
|
100
|
+
reason,
|
|
101
|
+
})
|
|
102
|
+
return data.data
|
|
103
|
+
}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
import type { UploadedFile } from '@robsun/keystone-web-core'
|
|
2
|
+
|
|
3
|
+
export type ExampleItemStatus = 'draft' | 'pending' | 'approved' | 'rejected' | 'cancelled'
|
|
4
|
+
|
|
5
|
+
export type ExampleItemCategory = 'general' | 'operations' | 'finance' | 'growth'
|
|
6
|
+
|
|
7
|
+
export type ExampleApprovalStatus = 'pending' | 'approved' | 'rejected' | 'cancelled'
|
|
2
8
|
|
|
3
9
|
export interface ExampleItem {
|
|
4
10
|
id: number
|
|
11
|
+
number: string
|
|
5
12
|
title: string
|
|
6
13
|
description: string
|
|
14
|
+
category: ExampleItemCategory
|
|
15
|
+
amount: number
|
|
7
16
|
status: ExampleItemStatus
|
|
17
|
+
approval_instance_id?: number
|
|
18
|
+
approval_status?: ExampleApprovalStatus
|
|
19
|
+
reject_reason?: string
|
|
20
|
+
attachment?: UploadedFile | null
|
|
8
21
|
created_at: string
|
|
9
22
|
updated_at: string
|
|
10
23
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Register application modules here.
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
/// <reference types="vitest" />
|
|
2
2
|
import { createKeystoneViteConfig } from '@robsun/keystone-web-core/vite'
|
|
3
3
|
import path from 'path'
|
|
4
|
+
import { fileURLToPath } from 'url'
|
|
5
|
+
|
|
6
|
+
const rootDir = path.dirname(fileURLToPath(import.meta.url))
|
|
4
7
|
|
|
5
8
|
export default createKeystoneViteConfig({
|
|
6
|
-
|
|
9
|
+
root: rootDir,
|
|
10
|
+
helpExtraDirs: [path.resolve(rootDir, './src/modules')],
|
|
11
|
+
helpLocales: ['zh-CN', 'en-US'],
|
|
12
|
+
helpDefaultLocale: 'zh-CN',
|
|
7
13
|
resolve: {
|
|
8
14
|
alias: {
|
|
9
|
-
'@app': path.resolve(
|
|
15
|
+
'@app': path.resolve(rootDir, './src'),
|
|
10
16
|
},
|
|
11
17
|
},
|
|
12
18
|
server: {
|
|
@@ -19,7 +25,7 @@ export default createKeystoneViteConfig({
|
|
|
19
25
|
},
|
|
20
26
|
},
|
|
21
27
|
build: {
|
|
22
|
-
outDir: path.resolve(
|
|
28
|
+
outDir: path.resolve(rootDir, '../server/internal/frontend/dist'),
|
|
23
29
|
emptyOutDir: false,
|
|
24
30
|
sourcemap: true,
|
|
25
31
|
rollupOptions: {
|
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
提示:更细节的入口说明见 `apps/web/README.md` 与 `apps/server/README.md`。
|
|
17
17
|
|
|
18
18
|
## 开发流程
|
|
19
|
+
- 先写/补测试:后端用 `*_test.go`,前端用 `*.test.tsx`/`*.spec.tsx`,覆盖核心逻辑与关键路径。
|
|
19
20
|
- `pnpm dev`:执行 `scripts/dev.*`,检查环境并启动 Air + Vite。
|
|
20
21
|
- `apps/server/.air.toml`:后端热重载配置。
|
|
21
|
-
- `pnpm server:dev` 仅启动后端;`pnpm web
|
|
22
|
+
- `pnpm server:dev` 仅启动后端;`pnpm -C apps/web dev` 仅启动前端。
|
|
23
|
+
- 开发完成运行测试:`pnpm test` 或 `pnpm -C apps/web test` + `go -C apps/server test ./...`。
|
|
22
24
|
|
|
23
25
|
## 配置与环境
|
|
24
26
|
- `apps/server/config.yaml` 为默认配置;`apps/server/config.example.yaml` 用作模板。
|
|
@@ -52,10 +54,10 @@ registerModule({ name: 'orders', routes: orderRoutes })
|
|
|
52
54
|
```
|
|
53
55
|
- 页面放 `pages/`,组件放 `components/`,API 放 `services/`。
|
|
54
56
|
|
|
55
|
-
## Help 文档
|
|
56
|
-
- 文档放在 `apps/web/src/modules/<module>/help
|
|
57
|
-
- `helpKey` 与路由 `handle.helpKey` 保持一致。
|
|
58
|
-
- Vite
|
|
57
|
+
## Help 文档
|
|
58
|
+
- 文档放在 `apps/web/src/modules/<module>/help/<locale>/**`。
|
|
59
|
+
- `helpKey` 与路由 `handle.helpKey` 保持一致。
|
|
60
|
+
- Vite 默认合并 core 帮助与 `src/modules`(`helpExtraDirs`),并按语言目录加载。
|
|
59
61
|
|
|
60
62
|
## 后端模块规范
|
|
61
63
|
推荐结构:
|
|
@@ -77,7 +79,7 @@ type Module interface {
|
|
|
77
79
|
RegisterRoutes(rg *gin.RouterGroup)
|
|
78
80
|
RegisterModels() []interface{}
|
|
79
81
|
RegisterPermissions(reg *permissions.Registry) error
|
|
80
|
-
|
|
82
|
+
RegisterTasks(reg *scheduler.Registry) error
|
|
81
83
|
Migrate(db *gorm.DB) error
|
|
82
84
|
Seed(db *gorm.DB) error
|
|
83
85
|
}
|
|
@@ -138,7 +140,7 @@ RegisterPermissions 负责定义权限种子与后台管理项
|
|
|
138
140
|
|
|
139
141
|
## 任务与队列
|
|
140
142
|
- Worker 在 `cmd/server/main.go` 启动。
|
|
141
|
-
- 模块通过 `
|
|
143
|
+
- 模块通过 `RegisterTasks` 注册任务处理器。
|
|
142
144
|
- 队列配置在 `apps/server/config.yaml` 的 `queue` 部分。
|
|
143
145
|
|
|
144
146
|
## 嵌入式前端
|
|
@@ -222,3 +224,4 @@ return &i18n.I18nError{Key: "order.notFound"}
|
|
|
222
224
|
- Web:`pnpm -C apps/web test`(Vitest)。
|
|
223
225
|
- Server:`go -C apps/server test ./...`。
|
|
224
226
|
- 全量:`pnpm test`。
|
|
227
|
+
- 测试目录:`tests/unit`、`tests/integration`、`tests/perf`(或包内 `*_test.go`)。
|
package/template/package.json
CHANGED
|
@@ -2,18 +2,17 @@
|
|
|
2
2
|
"name": "__APP_NAME__",
|
|
3
3
|
"private": true,
|
|
4
4
|
"version": "0.1.0",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "node scripts/dev.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "node scripts/dev.js",
|
|
7
|
+
"server:dev": "go -C apps/server run ./cmd/server",
|
|
7
8
|
"build": "node scripts/build.js",
|
|
8
9
|
"build:web": "pnpm --filter web build",
|
|
9
|
-
"check-modules": "node scripts/check-modules.js",
|
|
10
|
+
"check-modules": "node scripts/check-modules.js && node scripts/check-help.js",
|
|
10
11
|
"create:module": "pnpm dlx --package @robsun/create-keystone-app create-keystone-module",
|
|
11
12
|
"test": "pnpm check-modules && node scripts/test.js",
|
|
12
13
|
"lint": "pnpm --filter web lint",
|
|
13
14
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"",
|
|
14
15
|
"clean": "node scripts/clean.js",
|
|
15
|
-
"web:dev": "pnpm -C apps/web dev",
|
|
16
|
-
"server:dev": "go -C apps/server run ./cmd/server",
|
|
17
16
|
"generate:i18n-types": "node scripts/generate-i18n-types.js",
|
|
18
17
|
"prepare": "husky"
|
|
19
18
|
},
|
package/template/pnpm-lock.yaml
CHANGED
|
@@ -27,20 +27,26 @@ importers:
|
|
|
27
27
|
specifier: ^6.1.0
|
|
28
28
|
version: 6.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
|
29
29
|
'@robsun/keystone-web-core':
|
|
30
|
-
specifier: 0.
|
|
31
|
-
version: 0.
|
|
30
|
+
specifier: ^0.3.0
|
|
31
|
+
version: 0.3.0(@ant-design/icons@6.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react@19.2.7)(antd@6.1.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router-dom@7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
|
|
32
32
|
antd:
|
|
33
33
|
specifier: ^6.0.1
|
|
34
34
|
version: 6.1.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
|
35
35
|
dayjs:
|
|
36
36
|
specifier: ^1.11.19
|
|
37
37
|
version: 1.11.19
|
|
38
|
+
i18next:
|
|
39
|
+
specifier: ^24.2.3
|
|
40
|
+
version: 24.2.3(typescript@5.9.3)
|
|
38
41
|
react:
|
|
39
42
|
specifier: ^19.2.0
|
|
40
43
|
version: 19.2.3
|
|
41
44
|
react-dom:
|
|
42
45
|
specifier: ^19.2.0
|
|
43
46
|
version: 19.2.3(react@19.2.3)
|
|
47
|
+
react-i18next:
|
|
48
|
+
specifier: ^15.5.1
|
|
49
|
+
version: 15.7.4(i18next@24.2.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
|
|
44
50
|
react-router-dom:
|
|
45
51
|
specifier: ^7.10.1
|
|
46
52
|
version: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
|
@@ -924,8 +930,8 @@ packages:
|
|
|
924
930
|
react: '>=16.9.0'
|
|
925
931
|
react-dom: '>=16.9.0'
|
|
926
932
|
|
|
927
|
-
'@robsun/keystone-web-core@0.
|
|
928
|
-
resolution: {integrity: sha512-
|
|
933
|
+
'@robsun/keystone-web-core@0.3.0':
|
|
934
|
+
resolution: {integrity: sha512-BFJehFDaAv62gtoBEw1BhgeYRbyz/LIOKM5tlIZSR8IxlwxagNBiGywwP+gX+93HQRbM6+3aT4EZkDzi4T7r4g==}
|
|
929
935
|
peerDependencies:
|
|
930
936
|
'@ant-design/icons': ^6.1.0
|
|
931
937
|
antd: ^6.0.1
|
|
@@ -1912,6 +1918,9 @@ packages:
|
|
|
1912
1918
|
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
|
|
1913
1919
|
engines: {node: '>=18'}
|
|
1914
1920
|
|
|
1921
|
+
html-parse-stringify@3.0.1:
|
|
1922
|
+
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
|
|
1923
|
+
|
|
1915
1924
|
html-url-attributes@3.0.1:
|
|
1916
1925
|
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
|
|
1917
1926
|
|
|
@@ -1928,6 +1937,17 @@ packages:
|
|
|
1928
1937
|
engines: {node: '>=18'}
|
|
1929
1938
|
hasBin: true
|
|
1930
1939
|
|
|
1940
|
+
i18next-browser-languagedetector@8.2.0:
|
|
1941
|
+
resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==}
|
|
1942
|
+
|
|
1943
|
+
i18next@24.2.3:
|
|
1944
|
+
resolution: {integrity: sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==}
|
|
1945
|
+
peerDependencies:
|
|
1946
|
+
typescript: ^5
|
|
1947
|
+
peerDependenciesMeta:
|
|
1948
|
+
typescript:
|
|
1949
|
+
optional: true
|
|
1950
|
+
|
|
1931
1951
|
iconv-lite@0.6.3:
|
|
1932
1952
|
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
|
1933
1953
|
engines: {node: '>=0.10.0'}
|
|
@@ -2448,6 +2468,22 @@ packages:
|
|
|
2448
2468
|
peerDependencies:
|
|
2449
2469
|
react: ^19.2.3
|
|
2450
2470
|
|
|
2471
|
+
react-i18next@15.7.4:
|
|
2472
|
+
resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==}
|
|
2473
|
+
peerDependencies:
|
|
2474
|
+
i18next: '>= 23.4.0'
|
|
2475
|
+
react: '>= 16.8.0'
|
|
2476
|
+
react-dom: '*'
|
|
2477
|
+
react-native: '*'
|
|
2478
|
+
typescript: ^5
|
|
2479
|
+
peerDependenciesMeta:
|
|
2480
|
+
react-dom:
|
|
2481
|
+
optional: true
|
|
2482
|
+
react-native:
|
|
2483
|
+
optional: true
|
|
2484
|
+
typescript:
|
|
2485
|
+
optional: true
|
|
2486
|
+
|
|
2451
2487
|
react-is@17.0.2:
|
|
2452
2488
|
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
|
2453
2489
|
|
|
@@ -2862,6 +2898,10 @@ packages:
|
|
|
2862
2898
|
jsdom:
|
|
2863
2899
|
optional: true
|
|
2864
2900
|
|
|
2901
|
+
void-elements@3.1.0:
|
|
2902
|
+
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
|
2903
|
+
engines: {node: '>=0.10.0'}
|
|
2904
|
+
|
|
2865
2905
|
w3c-xmlserializer@5.0.0:
|
|
2866
2906
|
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
|
2867
2907
|
engines: {node: '>=18'}
|
|
@@ -3744,7 +3784,7 @@ snapshots:
|
|
|
3744
3784
|
react: 19.2.3
|
|
3745
3785
|
react-dom: 19.2.3(react@19.2.3)
|
|
3746
3786
|
|
|
3747
|
-
'@robsun/keystone-web-core@0.
|
|
3787
|
+
'@robsun/keystone-web-core@0.3.0(@ant-design/icons@6.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@types/react@19.2.7)(antd@6.1.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react-router-dom@7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))':
|
|
3748
3788
|
dependencies:
|
|
3749
3789
|
'@ant-design/icons': 6.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
|
3750
3790
|
'@vitejs/plugin-react': 5.1.2(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
|
|
@@ -3754,8 +3794,11 @@ snapshots:
|
|
|
3754
3794
|
dayjs: 1.11.19
|
|
3755
3795
|
fuse.js: 7.1.0
|
|
3756
3796
|
gray-matter: 4.0.3
|
|
3797
|
+
i18next: 24.2.3(typescript@5.9.3)
|
|
3798
|
+
i18next-browser-languagedetector: 8.2.0
|
|
3757
3799
|
react: 19.2.3
|
|
3758
3800
|
react-dom: 19.2.3(react@19.2.3)
|
|
3801
|
+
react-i18next: 15.7.4(i18next@24.2.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
|
|
3759
3802
|
react-markdown: 10.1.0(@types/react@19.2.7)(react@19.2.3)
|
|
3760
3803
|
react-router-dom: 7.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
|
3761
3804
|
remark-gfm: 4.0.1
|
|
@@ -3764,7 +3807,9 @@ snapshots:
|
|
|
3764
3807
|
- '@types/react'
|
|
3765
3808
|
- debug
|
|
3766
3809
|
- immer
|
|
3810
|
+
- react-native
|
|
3767
3811
|
- supports-color
|
|
3812
|
+
- typescript
|
|
3768
3813
|
- use-sync-external-store
|
|
3769
3814
|
- vite
|
|
3770
3815
|
|
|
@@ -4830,6 +4875,10 @@ snapshots:
|
|
|
4830
4875
|
dependencies:
|
|
4831
4876
|
whatwg-encoding: 3.1.1
|
|
4832
4877
|
|
|
4878
|
+
html-parse-stringify@3.0.1:
|
|
4879
|
+
dependencies:
|
|
4880
|
+
void-elements: 3.1.0
|
|
4881
|
+
|
|
4833
4882
|
html-url-attributes@3.0.1: {}
|
|
4834
4883
|
|
|
4835
4884
|
http-proxy-agent@7.0.2:
|
|
@@ -4848,6 +4897,16 @@ snapshots:
|
|
|
4848
4897
|
|
|
4849
4898
|
husky@9.1.7: {}
|
|
4850
4899
|
|
|
4900
|
+
i18next-browser-languagedetector@8.2.0:
|
|
4901
|
+
dependencies:
|
|
4902
|
+
'@babel/runtime': 7.28.4
|
|
4903
|
+
|
|
4904
|
+
i18next@24.2.3(typescript@5.9.3):
|
|
4905
|
+
dependencies:
|
|
4906
|
+
'@babel/runtime': 7.28.4
|
|
4907
|
+
optionalDependencies:
|
|
4908
|
+
typescript: 5.9.3
|
|
4909
|
+
|
|
4851
4910
|
iconv-lite@0.6.3:
|
|
4852
4911
|
dependencies:
|
|
4853
4912
|
safer-buffer: 2.1.2
|
|
@@ -5537,6 +5596,16 @@ snapshots:
|
|
|
5537
5596
|
react: 19.2.3
|
|
5538
5597
|
scheduler: 0.27.0
|
|
5539
5598
|
|
|
5599
|
+
react-i18next@15.7.4(i18next@24.2.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3):
|
|
5600
|
+
dependencies:
|
|
5601
|
+
'@babel/runtime': 7.28.4
|
|
5602
|
+
html-parse-stringify: 3.0.1
|
|
5603
|
+
i18next: 24.2.3(typescript@5.9.3)
|
|
5604
|
+
react: 19.2.3
|
|
5605
|
+
optionalDependencies:
|
|
5606
|
+
react-dom: 19.2.3(react@19.2.3)
|
|
5607
|
+
typescript: 5.9.3
|
|
5608
|
+
|
|
5540
5609
|
react-is@17.0.2: {}
|
|
5541
5610
|
|
|
5542
5611
|
react-is@18.3.1: {}
|
|
@@ -5961,6 +6030,8 @@ snapshots:
|
|
|
5961
6030
|
- supports-color
|
|
5962
6031
|
- terser
|
|
5963
6032
|
|
|
6033
|
+
void-elements@3.1.0: {}
|
|
6034
|
+
|
|
5964
6035
|
w3c-xmlserializer@5.0.0:
|
|
5965
6036
|
dependencies:
|
|
5966
6037
|
xml-name-validator: 5.0.0
|
|
@@ -53,7 +53,7 @@ for /d %%i in ("%EMBED_DIR%\*") do rd /s /q "%%i" 2>nul
|
|
|
53
53
|
echo [OK] Embed directory cleaned
|
|
54
54
|
|
|
55
55
|
echo ----------------------------------------
|
|
56
|
-
echo [2/
|
|
56
|
+
echo [2/5] Building Frontend
|
|
57
57
|
echo ----------------------------------------
|
|
58
58
|
cd /d "%FRONTEND_DIR%"
|
|
59
59
|
call pnpm build
|
|
@@ -67,7 +67,19 @@ echo [OK] Frontend build completed
|
|
|
67
67
|
cd /d "%PROJECT_ROOT%"
|
|
68
68
|
|
|
69
69
|
echo ----------------------------------------
|
|
70
|
-
echo [3/
|
|
70
|
+
echo [3/5] Precompressing Frontend Assets
|
|
71
|
+
echo ----------------------------------------
|
|
72
|
+
call node "%PROJECT_ROOT%\scripts\compress-assets.js"
|
|
73
|
+
if errorlevel 1 (
|
|
74
|
+
echo [FAIL] Precompression failed
|
|
75
|
+
set FAILED=1
|
|
76
|
+
cd /d "%PROJECT_ROOT%"
|
|
77
|
+
exit /b 1
|
|
78
|
+
)
|
|
79
|
+
echo [OK] Frontend assets precompressed
|
|
80
|
+
|
|
81
|
+
echo ----------------------------------------
|
|
82
|
+
echo [4/5] Building Backend (with embedded frontend)
|
|
71
83
|
echo ----------------------------------------
|
|
72
84
|
cd /d "%BACKEND_DIR%"
|
|
73
85
|
|
|
@@ -100,7 +112,7 @@ echo [OK] Linux build completed
|
|
|
100
112
|
cd /d "%PROJECT_ROOT%"
|
|
101
113
|
|
|
102
114
|
echo ----------------------------------------
|
|
103
|
-
echo [
|
|
115
|
+
echo [5/5] Copying configuration template
|
|
104
116
|
echo ----------------------------------------
|
|
105
117
|
if exist "%BACKEND_DIR%\config.example.yaml" (
|
|
106
118
|
copy /Y "%BACKEND_DIR%\config.example.yaml" "%OUTPUT_DIR%\config.example.yaml" >nul
|
|
@@ -52,7 +52,7 @@ find "$EMBED_DIR" -mindepth 1 ! -name '.gitkeep' -delete 2>/dev/null || true
|
|
|
52
52
|
echo -e "${GREEN}[OK]${NC} Embed directory cleaned"
|
|
53
53
|
|
|
54
54
|
echo "----------------------------------------"
|
|
55
|
-
echo "[2/
|
|
55
|
+
echo "[2/5] Building Frontend"
|
|
56
56
|
echo "----------------------------------------"
|
|
57
57
|
cd "$FRONTEND_DIR"
|
|
58
58
|
pnpm build
|
|
@@ -60,7 +60,13 @@ echo -e "${GREEN}[OK]${NC} Frontend build completed"
|
|
|
60
60
|
cd "$PROJECT_ROOT"
|
|
61
61
|
|
|
62
62
|
echo "----------------------------------------"
|
|
63
|
-
echo "[3/
|
|
63
|
+
echo "[3/5] Precompressing Frontend Assets"
|
|
64
|
+
echo "----------------------------------------"
|
|
65
|
+
node "$PROJECT_ROOT/scripts/compress-assets.js"
|
|
66
|
+
echo -e "${GREEN}[OK]${NC} Frontend assets precompressed"
|
|
67
|
+
|
|
68
|
+
echo "----------------------------------------"
|
|
69
|
+
echo "[4/5] Building Backend (with embedded frontend)"
|
|
64
70
|
echo "----------------------------------------"
|
|
65
71
|
cd "$BACKEND_DIR"
|
|
66
72
|
|
|
@@ -75,7 +81,7 @@ echo -e "${GREEN}[OK]${NC} Linux build completed"
|
|
|
75
81
|
cd "$PROJECT_ROOT"
|
|
76
82
|
|
|
77
83
|
echo "----------------------------------------"
|
|
78
|
-
echo "[
|
|
84
|
+
echo "[5/5] Copying configuration template"
|
|
79
85
|
echo "----------------------------------------"
|
|
80
86
|
if [ -f "$BACKEND_DIR/config.example.yaml" ]; then
|
|
81
87
|
cp "$BACKEND_DIR/config.example.yaml" "$OUTPUT_DIR/config.example.yaml"
|