@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 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 # npm 包定义(@lark-apaas/coding-templates)
17
- ├── meta.json # 模板元数据(业务侧生成,名称/描述/特性标签)
17
+ ├── package.json
18
+ ├── meta.json # 模板元数据
18
19
  ├── template-html/
19
- ├── _gitignore
20
- │ ├── package.json # mclaw.stack: "html"
21
- │ └── index.html
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
- ├── app.tsx # 路由注册
33
- ├── index.css # 全局样式 + 主题变量
34
- ├── components/ui/ # shadcn/ui 组件(new-york 风格)
35
- ├── pages/
36
- ├── hooks/
37
- │ └── lib/
38
- └── shared/ # 前后端共享代码
39
- └── types.ts
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.stack` 字段,标识模板类型:
46
+ 每个模板的 `package.json` 包含 `mclaw` 字段:
54
47
 
55
48
  ```json
56
49
  {
57
50
  "mclaw": {
58
- "stack": "vite-react",
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
- vite-react 模板技术选型:
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
- - **Vite 8** + React 19 + TypeScript 5
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-templates",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "OpenClaw project templates for mclaw CLI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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>
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -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
- "dev": "npx tsx --watch server/index.ts & npx vite --host",
12
- "dev:server": "tsx --watch server/index.ts",
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": "^0.45.1",
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
- # 复制 package.json(运行时需要依赖信息)
36
- cp "$ROOT/package.json" "$OUTPUT/package.json"
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 __dirname = path.dirname(fileURLToPath(import.meta.url));
9
- const port = Number(process.env.PORT) || 3000;
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
- // JSON body parsing
14
- app.use(express.json());
15
+ // Platform middleware
16
+ const { close } = setup(app, {
17
+ database: { schema },
18
+ csrf: { enabled: false },
19
+ viewContext: { enabled: false },
20
+ });
15
21
 
16
- // Register API routes
17
- registerRoutes(app);
22
+ // All routes under basePath
23
+ const router = express.Router();
24
+ registerRoutes(router);
18
25
 
19
- // Page rendering: compile index.html as hbs template, inject runtime data
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
- app.get("*", (_req, res) => {
29
+ router.get("/{*path}", createViewContextMiddleware(), (_req: Request, res: Response) => {
25
30
  const html = template({
26
- appId: process.env.MCLAW_APP_ID || "",
27
- cdnDomain: process.env.MCLAW_CDN_DOMAIN || "",
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.listen(port, "0.0.0.0", () => {
33
- console.log(`Server running at http://localhost:${port}`);
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
  });
@@ -1,7 +1,7 @@
1
- import type { Express } from "express";
1
+ import type { Router } from "express";
2
2
  // import postsRouter from "./posts";
3
3
 
4
- export function registerRoutes(app: Express) {
4
+ export function registerRoutes(app: Router) {
5
5
  // 在此注册 API 路由
6
6
  //
7
7
  // 使用示例:
@@ -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,
@@ -4,7 +4,8 @@
4
4
  "private": true,
5
5
  "mclaw": {
6
6
  "stack": "html",
7
- "stackVersion": "0.1.0"
7
+ "stackVersion": "0.1.0",
8
+ "features": ["client"]
8
9
  },
9
10
  "scripts": {
10
11
  "build": "bash scripts/build.sh"
@@ -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
  }
@@ -5,7 +5,8 @@
5
5
  "type": "module",
6
6
  "mclaw": {
7
7
  "stack": "vite-react",
8
- "stackVersion": "0.1.0"
8
+ "stackVersion": "0.1.0",
9
+ "features": ["client"]
9
10
  },
10
11
  "scripts": {
11
12
  "dev": "vite",
@@ -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 });