UNPKG

@lark-project/cli

Version:

飞书项目插件开发工具

123 lines (105 loc) 3.36 kB
#!/usr/bin/env node /** * preuninstall 钩子:卸载 CLI 时同步移除已注册的 skills。 * * 解析 `skills` 可执行文件的优先级(无网络最稳 → 最兜底): * 1. optionalDependency 拉到的 node_modules/skills/bin * 2. 全局 PATH 上的 `skills` 命令 * 3. `npx --yes skills`(让 npx 自己读用户的 npm 配置,不强制覆盖) * * 卸载阶段任何失败都静默,不阻断卸载,不给用户添乱。 */ 'use strict'; const { spawn, execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); const TIMEOUT_MS = 30_000; function shouldSkip() { if (process.env.LPM_SKIP_SKILLS) return 'LPM_SKIP_SKILLS 已设置'; if (process.env.CI) return 'CI 环境'; if (process.env.npm_config_ignore_scripts === 'true') return '--ignore-scripts'; const initCwd = process.env.INIT_CWD || process.cwd(); const pkgRoot = path.resolve(__dirname, '..'); if (initCwd === pkgRoot) return 'dev install(CLI 自身 yarn install)'; return null; } function resolveBundledSkills() { try { const pkgJsonPath = require.resolve('skills/package.json', { paths: [path.resolve(__dirname, '..')], }); const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')); const binEntry = pkg.bin; if (!binEntry) return null; const relBin = typeof binEntry === 'string' ? binEntry : binEntry.skills; if (!relBin) return null; const absBin = path.resolve(path.dirname(pkgJsonPath), relBin); return fs.existsSync(absBin) ? absBin : null; } catch { return null; } } function resolveGlobalSkills() { try { const cmd = process.platform === 'win32' ? 'where skills' : 'command -v skills'; const out = execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] }) .toString() .trim() .split(/\r?\n/)[0]; return out || null; } catch { return null; } } function main() { if (shouldSkip()) return; const skillsDir = path.resolve(__dirname, '..', 'skills'); if (!fs.existsSync(skillsDir)) return; console.log('→ unregistering Meegle plugin skills...'); const bundled = resolveBundledSkills(); if (bundled) return runRemove(process.execPath, [bundled, 'remove', skillsDir]); const globalBin = resolveGlobalSkills(); if (globalBin) return runRemove(globalBin, ['remove', skillsDir]); return runRemove('npx', ['--yes', 'skills', 'remove', skillsDir]); } function runRemove(cmd, args) { const child = spawn(cmd, args, { stdio: 'inherit', shell: process.platform === 'win32', detached: process.platform !== 'win32', }); const timer = setTimeout(() => killTree(child), TIMEOUT_MS); child.on('error', () => clearTimeout(timer)); child.on('exit', code => { clearTimeout(timer); try { if (code === 0) console.log('✓ Meegle plugin skills unregistered'); } catch { /* EPIPE 兜底 */ } }); } function killTree(child) { if (!child || !child.pid) return; try { if (process.platform === 'win32') { child.kill(); } else { process.kill(-child.pid, 'SIGTERM'); setTimeout(() => { try { process.kill(-child.pid, 'SIGKILL'); } catch { /* exited */ } }, 2000).unref(); } } catch { /* exited */ } } try { main(); } catch { /* silent on uninstall */ }