style: 整理代码提交规范 (merge request !2)
Squash merge branch 'feat/code-style' into 'main' style: 整理代码提交规范
This commit is contained in:
@@ -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
|
||||
```
|
||||
@@ -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": []
|
||||
}
|
||||
@@ -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
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
npx --no -- commitlint --edit "$1"
|
||||
Executable
+13
@@ -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
@@ -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/
|
||||
|
||||
@@ -110,11 +110,6 @@ Options:
|
||||
wecom-cli init
|
||||
```
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
| ---------- | ---- | -------------- |
|
||||
| `--bot-id` | 可选 | 企业微信机器人 Bot ID |
|
||||
|
||||
|
||||
凭证存储位置:`~/.config/wecom/bot.enc`
|
||||
|
||||
### 品类调用
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
msrv = "1.85.0"
|
||||
@@ -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],
|
||||
},
|
||||
};
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -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",
|
||||
|
||||
Generated
+2275
-1
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,3 @@
|
||||
packages:
|
||||
- '.'
|
||||
- 'packages/*'
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @type {import('prettier').Config}
|
||||
*/
|
||||
export default {
|
||||
singleQuote: true,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
edition = "2024"
|
||||
max_width = 100
|
||||
tab_spaces = 4
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
+27
-34
@@ -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: "待办事项 — 创建/查询/编辑待办项",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "@tsconfig/node-lts/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user