@lark-apaas/coding-templates 0.1.17 → 0.1.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-templates",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "OpenClaw project templates for mclaw CLI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,54 +1,14 @@
1
- import js from '@eslint/js'
2
- import globals from 'globals'
3
- import reactHooks from 'eslint-plugin-react-hooks'
4
- import reactRefresh from 'eslint-plugin-react-refresh'
5
- import tseslint from 'typescript-eslint'
6
- import { defineConfig, globalIgnores } from 'eslint/config'
1
+ import { eslintPresets } from '@lark-apaas/coding-presets'
7
2
 
8
- export default defineConfig([
9
- globalIgnores(['dist']),
10
- {
3
+ export default [
4
+ // 客户端:React + TypeScript
5
+ ...eslintPresets.client.map(config => config.ignores ? config : {
6
+ ...config,
11
7
  files: ['client/**/*.{ts,tsx}'],
12
- extends: [
13
- js.configs.recommended,
14
- tseslint.configs.recommended,
15
- reactHooks.configs.flat.recommended,
16
- reactRefresh.configs.vite,
17
- ],
18
- languageOptions: {
19
- ecmaVersion: 2020,
20
- globals: globals.browser,
21
- },
22
- rules: {
23
- // 关闭仅语法相关、不影响编译和运行时的规则
24
- 'react-refresh/only-export-components': 'off',
25
- '@typescript-eslint/no-unused-vars': 'off',
26
- '@typescript-eslint/no-explicit-any': 'off',
27
- '@typescript-eslint/no-empty-object-type': 'off',
28
- '@typescript-eslint/no-require-imports': 'off',
29
- 'no-empty': 'off',
30
- 'prefer-const': 'off',
31
- 'no-unused-labels': 'off',
32
- },
33
- },
34
- {
8
+ }),
9
+ // 服务端:Node.js + TypeScript
10
+ ...eslintPresets.server.map(config => config.ignores ? config : {
11
+ ...config,
35
12
  files: ['server/**/*.ts', 'shared/**/*.ts'],
36
- extends: [
37
- js.configs.recommended,
38
- tseslint.configs.recommended,
39
- ],
40
- languageOptions: {
41
- ecmaVersion: 2020,
42
- globals: globals.node,
43
- },
44
- rules: {
45
- '@typescript-eslint/no-unused-vars': 'off',
46
- '@typescript-eslint/no-explicit-any': 'off',
47
- '@typescript-eslint/no-empty-object-type': 'off',
48
- '@typescript-eslint/no-require-imports': 'off',
49
- 'no-empty': 'off',
50
- 'prefer-const': 'off',
51
- 'no-unused-labels': 'off',
52
- },
53
- },
54
- ])
13
+ }),
14
+ ]
@@ -74,19 +74,15 @@
74
74
  "zod": "^4.3.6"
75
75
  },
76
76
  "devDependencies": {
77
- "@eslint/js": "^9",
77
+ "@lark-apaas/coding-presets": "^0.1.0",
78
78
  "@lark-apaas/coding-vite-preset": "^0.1.0",
79
79
  "@types/express": "^5",
80
80
  "@types/node": "^24",
81
81
  "@types/react": "^19",
82
82
  "@types/react-dom": "^19",
83
83
  "eslint": "^9",
84
- "eslint-plugin-react-hooks": "^7",
85
- "eslint-plugin-react-refresh": "^0.5",
86
- "globals": "^17",
87
84
  "tsx": "^4",
88
85
  "typescript": "~5.9",
89
- "typescript-eslint": "^8",
90
86
  "vite": "^8"
91
87
  }
92
88
  }
@@ -1,28 +1,8 @@
1
1
  {
2
+ "extends": "@lark-apaas/coding-presets/lib/tsconfig/tsconfig.app.json",
2
3
  "compilerOptions": {
3
4
  "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
- "target": "ES2023",
5
- "useDefineForClassFields": true,
6
- "lib": ["ES2023", "DOM", "DOM.Iterable"],
7
- "module": "ESNext",
8
5
  "types": ["vite/client"],
9
- "skipLibCheck": true,
10
-
11
- /* Bundler mode */
12
- "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
14
- "verbatimModuleSyntax": true,
15
- "moduleDetection": "force",
16
- "noEmit": true,
17
- "jsx": "react-jsx",
18
-
19
- /* Linting */
20
- "strict": true,
21
- "noUnusedLocals": true,
22
- "noUnusedParameters": true,
23
- "erasableSyntaxOnly": true,
24
- "noFallthroughCasesInSwitch": true,
25
- "noUncheckedSideEffectImports": true,
26
6
  "baseUrl": ".",
27
7
  "paths": {
28
8
  "@/*": ["./client/src/*"],
@@ -1,27 +1,7 @@
1
1
  {
2
+ "extends": "@lark-apaas/coding-presets/lib/tsconfig/tsconfig.node.json",
2
3
  "compilerOptions": {
3
4
  "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
- "target": "ES2023",
5
- "lib": ["ES2023"],
6
- "module": "ESNext",
7
- "types": ["node"],
8
- "skipLibCheck": true,
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "verbatimModuleSyntax": true,
14
- "moduleDetection": "force",
15
- "noEmit": true,
16
-
17
- /* Linting */
18
- "strict": true,
19
- "noUnusedLocals": true,
20
- "noUnusedParameters": true,
21
- "erasableSyntaxOnly": true,
22
- "noFallthroughCasesInSwitch": true,
23
- "noUncheckedSideEffectImports": true,
24
-
25
5
  "baseUrl": ".",
26
6
  "paths": {
27
7
  "@shared/*": ["./shared/*"]
@@ -1,15 +1,9 @@
1
1
  {
2
+ "extends": "@lark-apaas/coding-presets/lib/tsconfig/tsconfig.node.json",
2
3
  "compilerOptions": {
3
- "target": "ES2023",
4
- "lib": ["ES2023"],
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "types": ["node"],
8
- "skipLibCheck": true,
9
- "strict": true,
10
- "erasableSyntaxOnly": true,
11
4
  "outDir": "./dist/server",
12
5
  "rootDir": ".",
6
+ "noEmit": false,
13
7
  "baseUrl": ".",
14
8
  "paths": {
15
9
  "@shared/*": ["./shared/*"]
@@ -21,7 +21,7 @@ client/src/
21
21
  ├── components/ # 基础 UI 组件(禁止存放业务组件)
22
22
  │ └── ui/ # shadcn/ui 内置组件(勿手动修改)
23
23
  ├── pages/ # 页面模块(每个页面一个目录)
24
- │ └── HomePage/ # 页面目录使用 PascalCase 命名
24
+ │ └── HomePage/ # 占位示例页,开发时替换为业务首页
25
25
  │ ├── HomePage.tsx # 页面入口文件与目录同名
26
26
  │ └── components/ # 页面专属组件
27
27
  ├── hooks/ # 自定义 Hooks
@@ -35,7 +35,7 @@ client/src/
35
35
  **页面文件只做骨架编排,不包含具体 UI 实现。**
36
36
 
37
37
  ```tsx
38
- // client/src/pages/dashboard/index.tsx
38
+ // client/src/pages/DashboardPage/DashboardPage.tsx
39
39
  import { StatsSection } from "./components/stats-section";
40
40
  import { DataTableSection } from "./components/data-table-section";
41
41
 
@@ -64,7 +64,7 @@ export default function DashboardPage() {
64
64
 
65
65
  **1. 页面文件 = 纯布局组合器**
66
66
 
67
- - `index.tsx` 只做 import + JSX 排列,**禁止包含** `useState`、`useEffect`、数据请求或业务逻辑
67
+ - 页面入口文件(如 `DashboardPage.tsx`)只做 import + JSX 排列,**禁止包含** `useState`、`useEffect`、数据请求或业务逻辑
68
68
  - 页面文件无 props 接口定义,不承担任何数据协调职责
69
69
 
70
70
  **2. Section 自包含原则**
@@ -73,7 +73,7 @@ export default function DashboardPage() {
73
73
  - **数据获取**(API 调用、fetch)— 即使多个 Section 需要同一份数据,各自获取
74
74
  - **状态管理**(useState、useReducer)
75
75
  - **类型定义**(写在同文件或同目录下的 `types.ts`)
76
- - **子组件**(如需拆分,放在同级目录,如 `components/stats-section/` 目录化)
76
+ - **子组件**(如需拆分,平铺在 `components/` 目录下,禁止嵌套子目录)
77
77
 
78
78
  **3. 禁止 Section 间横向依赖**
79
79
 
@@ -85,12 +85,18 @@ export default function DashboardPage() {
85
85
 
86
86
  ## 路由注册
87
87
 
88
- 新增页面在 `client/src/app.tsx` 中注册:
88
+ 新增页面在 `client/src/app.tsx` 中注册。
89
+
90
+ > ⚠️ **首页路由替换(必做)**
91
+ >
92
+ > 模板默认的 `HomePage` 是占位示例页,**不是业务首页**。开发时必须将 `index` 路由替换为真实的业务首页组件(如 `DashboardPage`),并删除 `HomePage` 目录。
93
+
94
+ **替换后的路由示例:**
89
95
 
90
96
  ```tsx
91
97
  import { BrowserRouter, Routes, Route } from "react-router-dom";
92
98
  import { Layout } from "@/components/layout";
93
- import HomePage from "@/pages/HomePage/HomePage";
99
+ import DashboardPage from "@/pages/DashboardPage/DashboardPage";
94
100
  import NotFoundPage from "@/pages/NotFoundPage/NotFoundPage";
95
101
 
96
102
  declare const __APP_BASE_PATH__: string;
@@ -100,7 +106,8 @@ export default function App() {
100
106
  <BrowserRouter basename={__APP_BASE_PATH__}>
101
107
  <Routes>
102
108
  <Route element={<Layout />}>
103
- <Route index element={<HomePage />} />
109
+ {/* index 路由指向真实的业务首页 */}
110
+ <Route index element={<DashboardPage />} />
104
111
  <Route path="*" element={<NotFoundPage />} />
105
112
  </Route>
106
113
  </Routes>
@@ -111,9 +118,8 @@ export default function App() {
111
118
 
112
119
  **新增页面步骤:**
113
120
 
114
- 1. 在 `client/src/pages/` 下新建页面目录(如 `DashboardPage`)和 `DashboardPage.tsx`
121
+ 1. 在 `client/src/pages/` 下新建页面目录(如 `SettingsPage`)和 `SettingsPage.tsx`
115
122
  2. 在 `app.tsx` 的 `<Routes>` 内添加 `<Route>` 配置
116
- 3. **必须调整首页路由**:根据业务需求修改 `index` 路由对应的页面组件(默认的 `HomePage` 仅作为示例,实际开发时需替换为真实的业务首页)
117
123
 
118
124
  **路由跳转必须使用 react-router-dom:**
119
125
 
@@ -204,7 +210,7 @@ export default function App() {
204
210
  |--------|---------|
205
211
  | 页面拆分 | 页面文件只做骨架编排(无 state/effect/逻辑);每个 Section 自包含数据+状态+类型;兄弟 Section 间无互相 import;单文件 ≤150 行 |
206
212
  | 命名规范 | 文件名 kebab-case,组件名 PascalCase |
207
- | 路由注册 | 新页面已在 `app.tsx` 注册;跳转使用 `<Link>` / `useNavigate()`,无 `<a href>` |
213
+ | 路由注册 | 默认 `HomePage` 已替换为业务首页;新页面已在 `app.tsx` 注册;跳转使用 `<Link>` / `useNavigate()`,无 `<a href>` |
208
214
  | 主题色 | 使用语义化变量类(`bg-background`、`text-primary` 等);未硬编码颜色值 |
209
215
  | 主题修改 | 仅增量覆盖变更的变量;新增色同时注册 `:root` 和 `@theme inline` |
210
216
  | 响应式 | 容器 `max-w-*` + `mx-auto`;多列布局窄屏退化单列;flex 有 `min-w-0` |
@@ -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,6 +0,0 @@
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
- }