Skip to content

插件开发最佳实践

1. 使用 Zod Schemas 校验参数

typescript
// ✅ 好的
parameters: z.object({
  url: z.string().url(),
  timeout: z.number().min(0).optional(),
})

// ❌ 差的
parameters: z.object({
  url: z.any(),
  timeout: z.any(),
})

2. 返回规范的结果

typescript
// ✅ 好的
return ok(data, [`采集到 ${data.length} 条数据`]);

// ❌ 差的
return 'success';

3. 使用存储而非全局变量

typescript
// ✅ 好的
await ctx.storage.set('state', { count: 1 });
const state = await ctx.storage.get('state');

// ❌ 差的
let state = { count: 1 };

4. 提供使用示例

typescript
site.command('search', {
  description: '搜索',
  examples: [
    { cmd: 'search --query "playwright"', description: '搜索 playwright' },
    { cmd: 'search --query "typescript" --limit 10', description: '限制结果数' },
  ],
  handler: async (params) => { /* ... */ },
});

5. 优雅地处理错误

typescript
import { fail } from '@dyyz1993/xcli-core';

site.command('fetch-data', {
  handler: async (params) => {
    try {
      const data = await fetchData(params.url);
      return ok(data, [`获取到 ${data.length} 条数据`]);
    } catch (error) {
      return fail(`请求失败: ${(error as Error).message}`);
    }
  },
});

6. 安全导航

使用 safeGoto 替代裸 page.goto()

typescript
import { safeGoto } from '../_shared';
await safeGoto(ctx.page, site.url);

7. evaluate 内只用标准 DOM API

typescript
// ✅ 正确
const data = await ctx.page.evaluate(() => {
  const el = document.getElementById('case-data') as HTMLScriptElement;
  return JSON.parse(el.textContent || '{}');
});

// ❌ 错误
const data = await ctx.page.evaluate(() => {
  document.querySelector(':has-text("hello")'); // Playwright 语法不支持
});

基于 MIT 许可发布