@lark-apaas/coding-templates 0.1.23 → 0.1.25
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 +45 -35
- package/package.json +1 -1
- package/template-apex/client/index.html +1 -4
- package/template-apex/client/src/lib/utils.ts +6 -0
- package/template-apex/package.json +17 -6
- package/template-apex/scripts/build.sh +3 -2
- package/template-apex/server/index.ts +31 -16
- package/template-apex/server/routes/index.ts +2 -2
- package/template-apex/tsconfig.server.json +4 -0
- package/template-html/package.json +2 -1
- package/template-vite-react/client/src/lib/utils.ts +3 -3
- package/template-vite-react/package.json +2 -1
- package/template-apex/server/db/index.ts +0 -8
package/README.md
CHANGED
|
@@ -4,39 +4,32 @@ OpenClaw 项目模板包,供 mclaw CLI 使用。
|
|
|
4
4
|
|
|
5
5
|
## 模板列表
|
|
6
6
|
|
|
7
|
-
| 模板 | 目录 | 说明 |
|
|
8
|
-
|
|
9
|
-
| html | `template-html/` | 纯 HTML,零依赖,原型验证 |
|
|
10
|
-
| vite-react | `template-vite-react/` | Vite + React 19 + Tailwind CSS + shadcn/ui |
|
|
7
|
+
| 模板 | 目录 | 类型 | 说明 |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| html | `template-html/` | 纯前端 | 纯 HTML,零依赖,原型验证 |
|
|
10
|
+
| vite-react | `template-vite-react/` | 纯前端 | Vite + React 19 + Tailwind CSS + shadcn/ui |
|
|
11
|
+
| apex | `template-apex/` | 全栈 | Vite + React + Express + Drizzle + PostgreSQL |
|
|
11
12
|
|
|
12
13
|
## 包结构
|
|
13
14
|
|
|
14
15
|
```
|
|
15
16
|
coding-templates/
|
|
16
|
-
├── package.json
|
|
17
|
-
├── meta.json #
|
|
17
|
+
├── package.json
|
|
18
|
+
├── meta.json # 模板元数据
|
|
18
19
|
├── template-html/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
└── template-vite-react/
|
|
23
|
-
├── _gitignore # CLI 复制时重命名为 .gitignore
|
|
24
|
-
├── package.json # mclaw.stack: "vite-react",name 为 {{projectName}}
|
|
25
|
-
├── vite.config.ts
|
|
26
|
-
├── eslint.config.js
|
|
27
|
-
├── components.json
|
|
28
|
-
├── client/
|
|
20
|
+
├── template-vite-react/
|
|
21
|
+
└── template-apex/
|
|
22
|
+
├── client/ # 前端(Vite + React)
|
|
29
23
|
│ ├── index.html
|
|
30
|
-
│ ├── public/
|
|
31
24
|
│ └── src/
|
|
32
|
-
|
|
33
|
-
│
|
|
34
|
-
│
|
|
35
|
-
│
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
├── server/ # 后端(Express + Drizzle)
|
|
26
|
+
│ ├── index.ts
|
|
27
|
+
│ ├── db/
|
|
28
|
+
│ └── routes/
|
|
29
|
+
├── shared/ # 前后端共享类型和 API 契约
|
|
30
|
+
├── scripts/build.sh # 构建脚本
|
|
31
|
+
├── tsconfig.server.json # 服务端 CJS 编译配置
|
|
32
|
+
└── vite.config.ts
|
|
40
33
|
```
|
|
41
34
|
|
|
42
35
|
## 特殊文件命名
|
|
@@ -48,28 +41,45 @@ npm publish 会忽略 `.gitignore` 和 `.env*`,因此模板中使用 `_` 前
|
|
|
48
41
|
| `_gitignore` | `.gitignore` |
|
|
49
42
|
| `_env.local` | `.env.local` |
|
|
50
43
|
|
|
51
|
-
##
|
|
44
|
+
## 模板元数据
|
|
52
45
|
|
|
53
|
-
每个模板的 `package.json` 包含 `mclaw
|
|
46
|
+
每个模板的 `package.json` 包含 `mclaw` 字段:
|
|
54
47
|
|
|
55
48
|
```json
|
|
56
49
|
{
|
|
57
50
|
"mclaw": {
|
|
58
|
-
"stack": "
|
|
59
|
-
"stackVersion": "0.1.0"
|
|
51
|
+
"stack": "apex",
|
|
52
|
+
"stackVersion": "0.1.0",
|
|
53
|
+
"features": ["client", "server"]
|
|
60
54
|
}
|
|
61
55
|
}
|
|
62
56
|
```
|
|
63
57
|
|
|
58
|
+
| 字段 | 说明 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `stack` | 技术栈标识 |
|
|
61
|
+
| `stackVersion` | 模板版本 |
|
|
62
|
+
| `features` | 应用能力,`init` 时自动推导 archType |
|
|
63
|
+
|
|
64
64
|
## 技术栈
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
### apex(全栈)
|
|
67
|
+
|
|
68
|
+
- **前端**: Vite 8 + React 19 + TypeScript 5.9 + Tailwind CSS 4 + shadcn/ui
|
|
69
|
+
- **后端**: Express 5 + Drizzle ORM + PostgreSQL
|
|
70
|
+
- **平台集成**: @lark-apaas/express-core(用户上下文、CSRF、RLS、viewContext)
|
|
71
|
+
- **开发**: Vite middleware mode 集成到 Express,单进程 HMR
|
|
72
|
+
- **构建**: 前端 Vite build,服务端 tsc CJS 输出
|
|
73
|
+
- **部署**: server.zip(服务端 + 裁剪 node_modules + run.sh)→ FaaS
|
|
74
|
+
|
|
75
|
+
### vite-react(纯前端)
|
|
76
|
+
|
|
77
|
+
- Vite 8 + React 19 + TypeScript 5 + Tailwind CSS 4 + shadcn/ui
|
|
78
|
+
- ESLint 9 flat config + react-router-dom
|
|
79
|
+
|
|
80
|
+
### html(纯前端)
|
|
67
81
|
|
|
68
|
-
-
|
|
69
|
-
- **Tailwind CSS 4**(`@tailwindcss/vite`,CSS-first 配置)
|
|
70
|
-
- **shadcn/ui**(new-york 风格,lucide 图标,radix-ui 基础组件)
|
|
71
|
-
- **ESLint 9** flat config
|
|
72
|
-
- **react-router-dom** 客户端路由
|
|
82
|
+
- 纯 HTML + Tailwind CDN,零构建依赖
|
|
73
83
|
|
|
74
84
|
## 发版
|
|
75
85
|
|
package/package.json
CHANGED
|
@@ -9,10 +9,7 @@
|
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<script>
|
|
12
|
-
window.__APP_CONFIG__ = {
|
|
13
|
-
appId: "{{{appId}}}",
|
|
14
|
-
cdnDomain: "{{{cdnDomain}}}"
|
|
15
|
-
};
|
|
12
|
+
window.__APP_CONFIG__ = {{{appConfig}}};
|
|
16
13
|
</script>
|
|
17
14
|
<div id="root"></div>
|
|
18
15
|
<script type="module" src="/src/main.tsx"></script>
|
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"mclaw": {
|
|
7
7
|
"stack": "apex",
|
|
8
|
-
"stackVersion": "0.1.0"
|
|
8
|
+
"stackVersion": "0.1.0",
|
|
9
|
+
"features": [
|
|
10
|
+
"client",
|
|
11
|
+
"server"
|
|
12
|
+
]
|
|
9
13
|
},
|
|
10
14
|
"scripts": {
|
|
11
|
-
"
|
|
12
|
-
"dev
|
|
13
|
-
"dev:client": "vite --host",
|
|
15
|
+
"postinstall": "pnpm rebuild @lark-apaas/express-datapaas",
|
|
16
|
+
"dev": "tsx --watch --watch-path server --watch-path shared server/index.ts",
|
|
14
17
|
"build": "bash scripts/build.sh",
|
|
15
18
|
"lint": "npm run lint:client && npm run lint:server",
|
|
16
19
|
"lint:client": "eslint client/src",
|
|
@@ -45,20 +48,21 @@
|
|
|
45
48
|
"@radix-ui/react-toggle-group": "^1.1.10",
|
|
46
49
|
"@radix-ui/react-tooltip": "^1.1.18",
|
|
47
50
|
"@lark-apaas/client-toolkit-lite": "^0.0.2",
|
|
51
|
+
"@lark-apaas/express-core": "^0.0.5",
|
|
52
|
+
"@lark-apaas/express-datapaas": "^0.0.3",
|
|
48
53
|
"@formkit/auto-animate": "^0.9.0",
|
|
49
54
|
"framer-motion": "^12.38.0",
|
|
50
55
|
"class-variance-authority": "^0.7.1",
|
|
51
56
|
"clsx": "^2.1.1",
|
|
52
57
|
"cmdk": "^1.1.1",
|
|
53
58
|
"date-fns": "^4.1.0",
|
|
54
|
-
"drizzle-orm": "
|
|
59
|
+
"drizzle-orm": "0.44.6",
|
|
55
60
|
"embla-carousel-react": "^8.6.0",
|
|
56
61
|
"express": "^5.1.0",
|
|
57
62
|
"hbs": "^4.2.0",
|
|
58
63
|
"input-otp": "^1.4.2",
|
|
59
64
|
"lucide-react": "^1.7.0",
|
|
60
65
|
"next-themes": "^0.4.6",
|
|
61
|
-
"postgres": "^3.4.8",
|
|
62
66
|
"react": "^19.2.4",
|
|
63
67
|
"react-day-picker": "^9.14.0",
|
|
64
68
|
"react-dom": "^19.2.4",
|
|
@@ -76,6 +80,7 @@
|
|
|
76
80
|
"devDependencies": {
|
|
77
81
|
"@lark-apaas/coding-presets": "^0.2.0",
|
|
78
82
|
"@lark-apaas/coding-vite-preset": "^0.1.0",
|
|
83
|
+
"@vercel/nft": "^0.29.2",
|
|
79
84
|
"@types/express": "^5",
|
|
80
85
|
"@types/node": "^24",
|
|
81
86
|
"@types/react": "^19",
|
|
@@ -84,5 +89,11 @@
|
|
|
84
89
|
"tsx": "^4",
|
|
85
90
|
"typescript": "~5.9",
|
|
86
91
|
"vite": "^8"
|
|
92
|
+
},
|
|
93
|
+
"pnpm": {
|
|
94
|
+
"onlyBuiltDependencies": [
|
|
95
|
+
"@lark-apaas/express-datapaas",
|
|
96
|
+
"esbuild"
|
|
97
|
+
]
|
|
87
98
|
}
|
|
88
99
|
}
|
|
@@ -32,8 +32,9 @@ echo '{ "version": 1, "type": "apex", "fallback": "index.html" }' > "$OUTPUT/rou
|
|
|
32
32
|
# 服务端产物(tsc 输出保留 server/、shared/ 子目录)
|
|
33
33
|
cp -r "$ROOT/dist/server/"* "$OUTPUT/"
|
|
34
34
|
|
|
35
|
-
#
|
|
36
|
-
|
|
35
|
+
# 声明 CJS(服务端 tsc 输出为 commonjs,需要覆盖根 package.json 的 "type": "module")
|
|
36
|
+
# deploy 时 prune 步骤会用精简版覆盖此文件
|
|
37
|
+
echo '{ "private": true }' > "$OUTPUT/package.json"
|
|
37
38
|
|
|
38
39
|
# 4. assets/ → dist/output_resource/(JS/CSS/字体,上传到 CDN)
|
|
39
40
|
if [ -d "$ROOT/dist/client/assets" ]; then
|
|
@@ -1,34 +1,49 @@
|
|
|
1
|
-
import express from "express";
|
|
1
|
+
import express, { type Request, type Response } from "express";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
4
|
import hbs from "hbs";
|
|
5
|
+
import { setup, safeStringify, createViewContextMiddleware } from "@lark-apaas/express-core";
|
|
6
|
+
import * as schema from "./db/schema";
|
|
6
7
|
import { registerRoutes } from "./routes/index";
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
9
|
+
const port = Number(process.env.FORCE_SERVER_PORT) || 3000;
|
|
10
|
+
const host = process.env.FORCE_SERVER_HOST || "localhost";
|
|
11
|
+
const basePath = process.env.CLIENT_BASE_PATH || "/";
|
|
10
12
|
|
|
11
13
|
const app = express();
|
|
12
14
|
|
|
13
|
-
//
|
|
14
|
-
app
|
|
15
|
+
// Platform middleware
|
|
16
|
+
const { close } = setup(app, {
|
|
17
|
+
database: { schema },
|
|
18
|
+
csrf: { enabled: false },
|
|
19
|
+
viewContext: { enabled: false },
|
|
20
|
+
});
|
|
15
21
|
|
|
16
|
-
//
|
|
17
|
-
|
|
22
|
+
// All routes under basePath
|
|
23
|
+
const router = express.Router();
|
|
24
|
+
registerRoutes(router);
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
// Static assets (JS/CSS/images) are served by the deployment platform / CDN
|
|
21
|
-
const templatePath = path.resolve(__dirname, "../public/index.html");
|
|
26
|
+
const templatePath = path.resolve(__dirname, "../index.html");
|
|
22
27
|
const template = hbs.compile(fs.readFileSync(templatePath, "utf-8"));
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
router.get("/{*path}", createViewContextMiddleware(), (_req: Request, res: Response) => {
|
|
25
30
|
const html = template({
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
...res.locals,
|
|
32
|
+
appConfig: safeStringify({
|
|
33
|
+
appId: res.locals.appId || process.env.MCLAW_APP_ID || "",
|
|
34
|
+
cdnDomain: process.env.MCLAW_CDN_DOMAIN || "",
|
|
35
|
+
}),
|
|
28
36
|
});
|
|
29
37
|
res.type("html").send(html);
|
|
30
38
|
});
|
|
31
39
|
|
|
32
|
-
app.
|
|
33
|
-
|
|
40
|
+
app.use(basePath, router);
|
|
41
|
+
|
|
42
|
+
const server = app.listen(port, host, () => {
|
|
43
|
+
console.log(`Server running at http://${host}:${port}${basePath}`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
process.on("SIGTERM", async () => {
|
|
47
|
+
server.close();
|
|
48
|
+
await close();
|
|
34
49
|
});
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"outDir": "./dist/server",
|
|
5
5
|
"rootDir": ".",
|
|
6
|
+
"module": "commonjs",
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"verbatimModuleSyntax": false,
|
|
9
|
+
"esModuleInterop": true,
|
|
6
10
|
"noEmit": false,
|
|
7
11
|
"allowImportingTsExtensions": false,
|
|
8
12
|
"noUnusedParameters": false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { clsx, type ClassValue } from "clsx"
|
|
2
|
-
import { twMerge } from "tailwind-merge"
|
|
1
|
+
import { clsx, type ClassValue } from "clsx"
|
|
2
|
+
import { twMerge } from "tailwind-merge"
|
|
3
3
|
|
|
4
4
|
export function cn(...inputs: ClassValue[]) {
|
|
5
|
-
return twMerge(clsx(inputs))
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
6
6
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { drizzle } from "drizzle-orm/postgres-js";
|
|
2
|
-
import postgres from "postgres";
|
|
3
|
-
import * as schema from "./schema";
|
|
4
|
-
|
|
5
|
-
const connectionString = process.env.DATABASE_URL!;
|
|
6
|
-
const client = postgres(connectionString);
|
|
7
|
-
|
|
8
|
-
export const db = drizzle(client, { schema });
|