267 lines
5.7 KiB
Markdown
267 lines
5.7 KiB
Markdown
---
|
||
name: js-runner
|
||
description: Any task that requires Javascript/Typescript processing should use this skill.
|
||
compatibility: Requires Bun runtime (https://bun.sh)
|
||
---
|
||
|
||
# js-runner
|
||
|
||
基于 Bun 的 JavaScript/TypeScript 执行技能,提供隔离的脚本执行和自动依赖管理。
|
||
|
||
## 前置条件
|
||
|
||
### 安装 Bun
|
||
|
||
js-runner 需要安装 Bun。Bun 是一个快速的 JavaScript 运行时,内置包管理器。
|
||
|
||
**macOS/Linux:**
|
||
|
||
```bash
|
||
curl -fsSL https://bun.sh/install | bash
|
||
```
|
||
|
||
**Windows:**
|
||
|
||
```powershell
|
||
powershell -c "irm bun.sh/install.ps1 | iex"
|
||
```
|
||
|
||
**验证安装:**
|
||
|
||
```bash
|
||
bun --version
|
||
```
|
||
|
||
## 使用流程
|
||
|
||
执行 JavaScript/TypeScript 脚本的完整工作流程:
|
||
|
||
1. **检查环境** - 验证 Bun 是否已安装
|
||
2. **生成临时路径** - 调用辅助脚本获取唯一的临时文件路径
|
||
3. **写入脚本** - 将脚本内容保存到临时文件
|
||
4. **执行脚本** - 使用 Bun 运行脚本
|
||
5. **捕获输出** - 从执行结果读取 stdout/stderr
|
||
6. **清理** - 临时文件由系统自动处理
|
||
|
||
### 完整示例
|
||
|
||
```bash
|
||
# 步骤 1: 检查 Bun 是否已安装
|
||
bun --version
|
||
|
||
# 步骤 2: 生成临时文件路径
|
||
TEMP_FILE=$(bun skills/js-runner/scripts/get_temp_path.js js)
|
||
|
||
# 步骤 3: 将脚本内容写入临时文件
|
||
cat <<EOF > "$TEMP_FILE"
|
||
const greeting = "Hello from js-runner!";
|
||
console.log(greeting);
|
||
EOF
|
||
|
||
# 步骤 4: 执行脚本
|
||
bun "$TEMP_FILE"
|
||
|
||
# 步骤 5: 输出已在上面捕获
|
||
# 临时文件将由系统自动清理
|
||
```
|
||
|
||
### 使用依赖
|
||
|
||
```bash
|
||
# 生成临时文件
|
||
TEMP_FILE=$(bun skills/js-runner/scripts/get_temp_path.js js)
|
||
|
||
# 写入包含外部依赖的脚本
|
||
cat <<EOF > "$TEMP_FILE"
|
||
import axios from 'axios';
|
||
|
||
const response = await axios.get('https://api.github.com');
|
||
console.log('GitHub API status:', response.status);
|
||
EOF
|
||
|
||
# 执行 - Bun 首次运行时会自动下载依赖
|
||
bun "$TEMP_FILE"
|
||
```
|
||
|
||
Bun 会自动:
|
||
|
||
- 检测 `import` 语句
|
||
- 下载并缓存依赖(到 `~/.bun/install/cache`)
|
||
- 根据需要处理 TypeScript 编译
|
||
- 无需 `package.json` 或手动安装
|
||
|
||
## JavaScript 与 TypeScript
|
||
|
||
JavaScript 和 TypeScript 使用相同的工作流程:
|
||
|
||
```bash
|
||
# JavaScript
|
||
TEMP_JS=$(bun skills/js-runner/scripts/get_temp_path.js js)
|
||
cat <<EOF > "$TEMP_JS"
|
||
console.log('JavaScript execution');
|
||
EOF
|
||
bun "$TEMP_JS"
|
||
|
||
# TypeScript
|
||
TEMP_TS=$(bun skills/js-runner/scripts/get_temp_path.js ts)
|
||
cat <<EOF > "$TEMP_TS"
|
||
const message: string = 'TypeScript execution';
|
||
console.log(message);
|
||
EOF
|
||
bun "$TEMP_TS"
|
||
```
|
||
|
||
Bun 会自动即时转译 TypeScript。
|
||
|
||
## 依赖管理
|
||
|
||
Bun 提供自动依赖管理,无需手动配置:
|
||
|
||
### 导入外部包
|
||
|
||
```javascript
|
||
// ESM import(推荐)
|
||
import axios from 'axios'
|
||
import lodash from 'lodash'
|
||
|
||
// CommonJS import(也支持)
|
||
const axios = require('axios')
|
||
```
|
||
|
||
首次执行带有外部导入的脚本时,Bun 会:
|
||
|
||
1. 分析导入
|
||
2. 从 npm 下载缺失的依赖
|
||
3. 全局缓存到 `~/.bun/install/cache`
|
||
4. 后续运行使用缓存版本
|
||
|
||
### 不需要 package.json
|
||
|
||
与 Node.js 不同,你无需创建 `package.json` 或单独运行 `bun install`。Bun 在运行时自动处理所有操作。
|
||
|
||
## 辅助函数 API
|
||
|
||
### `get_temp_path.js`
|
||
|
||
为脚本执行生成唯一的临时文件路径。
|
||
|
||
**CLI 使用方式:**
|
||
|
||
```bash
|
||
bun skills/js-runner/scripts/get_temp_path.js <extension>
|
||
```
|
||
|
||
**参数:**
|
||
|
||
- `extension` (可选): 文件扩展名。默认为 `js`。常用值: `js`, `ts`, `mjs`, `mts`
|
||
|
||
**输出:** 返回类似 `/var/folders/.../js-runner-1234567890-abc123.js` 的路径
|
||
|
||
**路径格式:**
|
||
|
||
- 使用操作系统临时目录(Unix 上为 `/tmp`,Windows 上为 `%TEMP%`)
|
||
- 前缀: `js-runner-`
|
||
- 时间戳: 自纪元以来的毫秒数
|
||
- 随机字符串: 7 字符字母数字
|
||
- 扩展名: 参数中提供的值
|
||
|
||
**示例:**
|
||
|
||
```bash
|
||
$ bun skills/js-runner/scripts/get_temp_path.js js
|
||
/var/folders/8m/0hm18pdd7ts2bwp0530drz500000gn/T/js-runner-1770257905333-na6ujx.js
|
||
|
||
$ bun skills/js-runner/scripts/get_temp_path.js ts
|
||
/var/folders/8m/0hm18pdd7ts2bwp0530drz500000gn/T/js-runner-1770257905333-v8yzt.ts
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 未安装 Bun
|
||
|
||
**症状:** `command not found: bun`
|
||
|
||
**解决方案:**
|
||
|
||
提示用户 Bun 没有安装,并说明安装方式,禁止直接自动安装
|
||
|
||
### 脚本语法错误
|
||
|
||
Bun 提供详细的语法错误信息:
|
||
|
||
```bash
|
||
$ bun "$TEMP_FILE"
|
||
error: Unexpected token
|
||
--> /var/folders/.../script.js:2:10
|
||
|
|
||
2 | const = 123;
|
||
| ^
|
||
```
|
||
|
||
错误信息包括:
|
||
|
||
- 文件路径和行号
|
||
- 错误的确切位置
|
||
- 问题描述
|
||
|
||
### 运行时错误
|
||
|
||
运行时错误包含完整的堆栈跟踪:
|
||
|
||
```bash
|
||
$ bun "$TEMP_FILE"
|
||
ReferenceError: foo is not defined
|
||
at script.js:3:5
|
||
at main (script.js:1:1)
|
||
```
|
||
|
||
### 其他错误
|
||
|
||
其他任何形式的错误都原样输出
|
||
|
||
## 输出处理
|
||
|
||
### 标准输出
|
||
|
||
所有 `console.log()`, `console.info()`, `console.warn()` 输出都到 stdout:
|
||
|
||
```bash
|
||
bun "$TEMP_FILE" # stdout 由调用代码捕获
|
||
```
|
||
|
||
### 错误输出
|
||
|
||
`console.error()` 输出到 stderr:
|
||
|
||
```bash
|
||
bun "$TEMP_FILE" 2>error.log # 单独捕获 stderr
|
||
```
|
||
|
||
### 退出码
|
||
|
||
脚本可以设置自定义退出码:
|
||
|
||
```javascript
|
||
process.exit(1) // 错误
|
||
process.exit(0) // 成功
|
||
```
|
||
|
||
调用者接收这些退出码以确定执行状态。
|
||
|
||
## 临时文件管理
|
||
|
||
执行后 **不会主动删除** 临时文件。这是设计使然:
|
||
|
||
- 操作系统自动管理临时目录空间
|
||
- 文件可以保留用于调试目的
|
||
- 大多数操作系统定期清理旧的临时文件
|
||
|
||
## 最佳实践
|
||
|
||
1. **始终检查 Bun 是否已安装**,然后再尝试执行脚本
|
||
2. **使用辅助脚本为每次执行生成唯一的临时路径**
|
||
3. **单独处理 stdout/stderr** 以区分输出和错误
|
||
4. **检查退出码** 以检测脚本失败
|
||
5. **使用 ESM imports** (`import from`) 编写现代 JavaScript
|
||
6. **捕获并显示错误** 以帮助用户调试问题
|