style: 整理代码提交规范 (merge request !2)

Squash merge branch 'feat/code-style' into 'main'
style: 整理代码提交规范
This commit is contained in:
jasonhzhang
2026-03-30 12:53:19 +00:00
parent df334ef4a4
commit be6e864ff5
24 changed files with 2545 additions and 57 deletions
+27
View File
@@ -0,0 +1,27 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in the repository](https://github.com/changesets/changesets).
## Usage
When you make a change that needs to be released:
```bash
pnpm changeset
```
This will prompt you to:
1. Select which packages have changed
2. Choose a semver bump type (major/minor/patch)
3. Provide a summary of the changes
A changeset markdown file will be created in this directory.
When it's time to release:
```bash
pnpm changeset version # Apply version bumps and update changelogs
pnpm changeset publish # Publish to npm
```
+19
View File
@@ -0,0 +1,19 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [
[
"@wecom/cli",
"@wecom/cli-darwin-arm64",
"@wecom/cli-darwin-x64",
"@wecom/cli-linux-x64",
"@wecom/cli-win32-x64"
]
],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
+22
View File
@@ -0,0 +1,22 @@
# EditorConfig - https://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.rs]
indent_size = 4
[*.md]
trim_trailing_whitespace = false
[Cargo.toml]
indent_size = 4
[Cargo.lock]
indent_size = 4
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
npx --no -- commitlint --edit "$1"
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
# Run clippy and fmt check if any Rust files are staged
if git diff --cached --name-only --diff-filter=d | grep -q '\.rs$'; then
cargo fmt --check || exit 1
cargo clippy --all-targets -- -D warnings || exit 1
fi
# Run eslint on staged JS/TS files
JS_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(js|ts)$')
if [ -n "$JS_FILES" ]; then
npx eslint $JS_FILES || exit 1
fi
+20 -1
View File
@@ -1,7 +1,26 @@
# Rust
/target
# Node
node_modules
# Env
.env*
# IDE
.codebuddy
/scripts
.idea/
.vscode/
# OS
.DS_Store
Thumbs.db
# Logs & temp
*.log
*.swp
*.swo
*~
# Platform binary directories (populated during build)
packages/darwin-arm64/bin/
-5
View File
@@ -110,11 +110,6 @@ Options:
wecom-cli init
```
| 参数 | 必填 | 说明 |
| ---------- | ---- | -------------- |
| `--bot-id` | 可选 | 企业微信机器人 Bot ID |
凭证存储位置:`~/.config/wecom/bot.enc`
### 品类调用
+3 -3
View File
@@ -27,7 +27,7 @@ function getPlatformPackage() {
if (!pkg) {
console.error(
`Error: unsupported platform ${platform}-${arch}.\n` +
`Supported platforms: ${Object.keys(platformMap).join(', ')}`
`Supported platforms: ${Object.keys(platformMap).join(', ')}`,
);
process.exit(1);
}
@@ -48,10 +48,10 @@ function getBinaryPath() {
} catch {
console.error(
`Error: cannot find @wecom/cli binary.\n` +
`Please try reinstalling: npm install @wecom/cli\n\n` +
`Please try reinstalling: npm install @wecom/cli\n\n` +
`If the problem persists, check:\n` +
` 1. Your npm config does not disable optional dependencies (--no-optional)\n` +
` 2. Your platform (${os.platform()}-${os.arch()}) is supported`
` 2. Your platform (${os.platform()}-${os.arch()}) is supported`,
);
process.exit(1);
}
+31
View File
@@ -0,0 +1,31 @@
use std::path::Path;
use std::process::Command;
fn main() {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let git_dir = Path::new(&manifest_dir).join(".git");
// Set up git hooks
if git_dir.exists() {
let status = Command::new("git")
.args(["config", "core.hooksPath", ".githooks"])
.current_dir(&manifest_dir)
.status();
match status {
Ok(s) if !s.success() => {
println!(
"cargo:warning=⚠️ Failed to set core.hooksPath. Run `git config core.hooksPath .githooks` manually."
);
}
Err(e) => {
println!(
"cargo:warning=⚠️ Failed to run git: {e}. Run `git config core.hooksPath .githooks` manually."
);
}
_ => {}
}
}
println!("cargo:rerun-if-changed=.githooks");
}
+1
View File
@@ -0,0 +1 @@
msrv = "1.85.0"
+31
View File
@@ -0,0 +1,31 @@
export default {
extends: ['@commitlint/config-conventional'],
rules: {
// type 必须是以下之一
'type-enum': [
2,
'always',
[
'feat', // 新功能
'fix', // 修复 bug
'docs', // 文档变更
'style', // 代码格式(不影响功能)
'refactor', // 重构(不是新功能也不是修复)
'perf', // 性能优化
'test', // 测试
'build', // 构建系统或外部依赖
'ci', // CI 配置
'chore', // 其他杂项
'revert', // 回滚
],
],
// type 不能为空
'type-empty': [2, 'never'],
// subject 不能为空
'subject-empty': [2, 'never'],
// subject 最大长度
'subject-max-length': [2, 'always', 100],
// header 最大长度
'header-max-length': [2, 'always', 120],
},
};
+21
View File
@@ -0,0 +1,21 @@
import eslint from '@eslint/js';
import globals from 'globals';
import prettier from 'eslint-plugin-prettier/recommended';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
prettier,
{
ignores: ['node_modules/', 'packages/*/bin/', 'target/'],
},
{
files: ['**/*.{js,ts}'],
languageOptions: {
globals: {
...globals.node,
},
},
},
);
+18
View File
@@ -23,6 +23,24 @@
"bin",
"README.md"
],
"scripts": {
"prepare": "git config core.hooksPath .githooks"
},
"devDependencies": {
"@changesets/cli": "^2.30.0",
"@commitlint/cli": "^20.5.0",
"@commitlint/config-conventional": "^20.5.0",
"@eslint/js": "^10.0.1",
"@tsconfig/node-lts": "^24.0.0",
"@types/node": "^25.5.0",
"eslint": "^10.1.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"globals": "^17.4.0",
"prettier": "^3.8.1",
"typescript": "^5.8.3",
"typescript-eslint": "^8.57.2"
},
"optionalDependencies": {
"@wecom/cli-darwin-arm64": "0.1.1",
"@wecom/cli-darwin-x64": "0.1.1",
+2275 -1
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,2 +1,3 @@
packages:
- '.'
- 'packages/*'
+6
View File
@@ -0,0 +1,6 @@
/**
* @type {import('prettier').Config}
*/
export default {
singleQuote: true,
};
+5
View File
@@ -0,0 +1,5 @@
edition = "2024"
max_width = 100
tab_spaces = 4
use_field_init_shorthand = true
use_try_shorthand = true
+27 -34
View File
@@ -6,38 +6,31 @@ pub struct CategoryInfo {
/// Return all supported business categories and their tool definitions.
pub fn get_categories() -> Vec<CategoryInfo> {
let mut categories = vec![];
// Insert categories in alphabetical order
categories.push(CategoryInfo {
name: "contact",
description: "通讯录 — 成员查询和搜索",
});
categories.push(CategoryInfo {
name: "doc",
description: "文档 — 文档/智能表格创建和管理",
});
categories.push(CategoryInfo {
name: "meeting",
description: "会议 — 创建/管理/查询视频会议",
});
categories.push(CategoryInfo {
name: "msg",
description: "消息聊天列表、发送/接收消息、媒体下载",
});
categories.push(CategoryInfo {
name: "schedule",
description: "日程 — 日程增删改查和可用性查询",
});
categories.push(CategoryInfo {
name: "todo",
description: "待办事项 — 创建/查询/编辑待办项",
});
categories
// Categories in alphabetical order
vec![
CategoryInfo {
name: "contact",
description: "通讯录 — 成员查询和搜索",
},
CategoryInfo {
name: "doc",
description: "文档 — 文档/智能表格创建和管理",
},
CategoryInfo {
name: "meeting",
description: "会议 — 创建/管理/查询视频会议",
},
CategoryInfo {
name: "msg",
description: "消息 — 聊天列表、发送/接收消息、媒体下载",
},
CategoryInfo {
name: "schedule",
description: "日程日程增删改查和可用性查询",
},
CategoryInfo {
name: "todo",
description: "待办事项 — 创建/查询/编辑待办项",
},
]
}
+4 -3
View File
@@ -78,10 +78,11 @@ pub fn save_key(key: &[u8; 32]) -> Result<()> {
// Always write the file fallback.
let key_path = encryption_key_path();
fs_util::atomic_write(&key_path, &b64.as_bytes(), Some(0o600))?;
fs_util::atomic_write(&key_path, b64.as_bytes(), Some(0o600))?;
if let Err(_) = keyring::Entry::new(KEYRING_SERVICE, KEYRING_USER)
if keyring::Entry::new(KEYRING_SERVICE, KEYRING_USER)
.and_then(|entry| entry.set_password(&b64))
.is_err()
{
tracing::warn!("Keyring unavailable encryption key stored in file only");
}
@@ -97,7 +98,7 @@ pub fn save_key(key: &[u8; 32]) -> Result<()> {
pub fn encrypt_data<T: serde::Serialize + ?Sized>(data: &T, key: &[u8; 32]) -> Result<Vec<u8>> {
let json =
serde_json::to_vec(data).map_err(|e| anyhow::anyhow!("JSON serialize error: {e:#}"))?;
Ok(cipher::encrypt(key, &json)?)
cipher::encrypt(key, &json)
}
/// Decrypt data: AES-256-GCM decrypt → deserialize.
+5 -5
View File
@@ -37,21 +37,21 @@ pub async fn show_category_tools(category: &str) -> Result<()> {
let wecom = env!("CARGO_BIN_NAME");
println!("# {} {}", category, category_description);
println!("");
println!();
println!("使用方式:");
println!(" {} {} <method> [json_args]", wecom, category);
println!("");
println!();
println!("选项:");
println!(" -h, --help 显示详细的工具 schema 信息");
println!("");
println!();
for tool in tools {
let Some(name) = tool.get("name").and_then(|n| n.as_str()) else {
continue;
};
println!("");
println!();
println!("## {}", name);
if let Some(description) = tool.get("description").and_then(|d| d.as_str()) {
println!("");
println!();
println!("{}", description);
}
}
+1 -3
View File
@@ -27,9 +27,7 @@ async fn main() -> Result<()> {
.subcommand_required(true)
.arg_required_else_help(true)
.disable_help_subcommand(true)
.subcommand(
Command::new("init").about("初始化企业微信机器人配置"),
);
.subcommand(Command::new("init").about("初始化企业微信机器人配置"));
for category in categories.iter() {
cmd = cmd.subcommand(cmd::call::CallArgs::augment_args(
+1 -1
View File
@@ -190,7 +190,7 @@ async fn fetch_mcp_config_from_server() -> Result<GetMcpConfigResponse, FetchMcp
let response = reqwest::Client::builder()
.build()
.map_err(|e| FetchMcpConfigError::Other(e.into()))?
.post(&constants::mcp_config_endpoint())
.post(constants::mcp_config_endpoint())
.json(&request)
.send()
.await
+1 -1
View File
@@ -32,7 +32,7 @@ pub fn gen_req_id(prefix: &str) -> String {
/// Generate a random hex string of the specified character length.
fn generate_random_hex(length: usize) -> String {
let byte_len = (length + 1) / 2;
let byte_len = length.div_ceil(2);
let bytes: Vec<u8> = (0..byte_len).map(|_| rand::rng().random::<u8>()).collect();
let hex = hex::encode(bytes);
hex[..length].to_string()
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "@tsconfig/node-lts/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"noEmit": true
},
"include": [
"**/*.js"
]
}