itismyskillmarket 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,7 +43,6 @@ import {
43
43
 
44
44
  import { loadRegistry } from './registry.js';
45
45
 
46
- import { getPlatformFromInput, type Platform } from '../utils/platform.js';
47
46
  import { PLATFORMS, LATEST_LINK } from '../constants.js';
48
47
 
49
48
  // -----------------------------------------------------------------------------
@@ -51,22 +50,18 @@ import { PLATFORMS, LATEST_LINK } from '../constants.js';
51
50
  // -----------------------------------------------------------------------------
52
51
 
53
52
  /**
54
- * 同步平台软链接
53
+ * 同步所有平台的软链接
55
54
  *
56
- * 为每个已安装的 skill 在平台目录下创建软链接,
55
+ * 为每个已安装的 skill 在各平台目录下创建软链接,
57
56
  * 指向 skills 目录中对应的平台特定文件。
58
57
  *
59
- * @param {string | Platform} [targetPlatform] - 目标平台(可选,不指定则同步所有平台)
60
58
  * @returns {Promise<void>}
61
59
  *
62
60
  * @example
63
61
  * // 同步所有平台链接
64
62
  * await syncPlatformLinks();
65
- *
66
- * // 仅同步到 opencode
67
- * await syncPlatformLinks('opencode');
68
63
  */
69
- export async function syncPlatformLinks(targetPlatform?: string): Promise<void> {
64
+ export async function syncPlatformLinks(): Promise<void> {
70
65
  // ==========================================================================
71
66
  // 步骤 1: 准备
72
67
  // ==========================================================================
@@ -81,29 +76,13 @@ export async function syncPlatformLinks(targetPlatform?: string): Promise<void>
81
76
  // 加载注册表获取已安装的 skills
82
77
  const registry = await loadRegistry();
83
78
 
84
- // 确定要同步的平台列表
85
- let platformsToSync: Platform[];
86
-
87
- if (targetPlatform) {
88
- const parsed = getPlatformFromInput(targetPlatform);
89
- if (!parsed) {
90
- console.warn(`Invalid platform: ${targetPlatform}, syncing all platforms`);
91
- platformsToSync = PLATFORMS;
92
- } else {
93
- platformsToSync = [parsed];
94
- }
95
- } else {
96
- platformsToSync = PLATFORMS;
97
- }
98
-
99
- const targetDesc = targetPlatform ? targetPlatform : 'all platforms';
100
- console.log(`Syncing platform links to ${targetDesc}...\n`);
79
+ console.log('Syncing platform links...\n');
101
80
 
102
81
  // ==========================================================================
103
- // 步骤 2: 遍历指定平台
82
+ // 步骤 2: 遍历所有平台
104
83
  // ==========================================================================
105
84
 
106
- for (const platform of platformsToSync) {
85
+ for (const platform of PLATFORMS) {
107
86
  // 创建平台的 skills 目录
108
87
  // 例如: ~/.skillmarket/platform-links/cursor/skills/
109
88
  const platformDir = path.join(platformLinksDir, platform, 'skills');
@@ -7,9 +7,10 @@
7
7
  *
8
8
  * 卸载流程:
9
9
  * 1. 检查 skill 是否已安装
10
- * 2. 删除 skill 主目录(包含所有版本和软链接)
11
- * 3. 删除各平台的软链接
12
- * 4. 从注册表中移除记录
10
+ * 2. 从目标平台卸载
11
+ * 3. 删除 skill 主目录(包含所有版本和软链接)
12
+ * 4. 删除各平台的软链接
13
+ * 5. 从注册表中移除记录
13
14
  *
14
15
  * @module commands/uninstall
15
16
  */
@@ -23,6 +24,18 @@ import path from 'path'; // 路径处理
23
24
  import { loadRegistry, saveRegistry } from './registry.js'; // 注册表操作
24
25
  import { getSkillsDir, getPlatformLinksDir } from '../utils/dirs.js'; // 目录工具
25
26
  import { PLATFORMS } from '../constants.js'; // 平台常量
27
+ import { detectPlatforms, getAdapterByPlatform } from '../adapters/index.js'; // 平台适配器
28
+ import type { Platform } from '../constants.js';
29
+ import type { PlatformAdapter } from '../types.js';
30
+
31
+ // -----------------------------------------------------------------------------
32
+ // 卸载选项接口
33
+ // -----------------------------------------------------------------------------
34
+
35
+ export interface UninstallOptions {
36
+ /** 目标平台列表(留空则卸载所有平台) */
37
+ platforms?: string[];
38
+ }
26
39
 
27
40
  // -----------------------------------------------------------------------------
28
41
  // 卸载函数
@@ -32,13 +45,20 @@ import { PLATFORMS } from '../constants.js'; // 平台常量
32
45
  * 卸载指定的 skill
33
46
  *
34
47
  * @param {string} skillId - Skill 标识符
48
+ * @param {UninstallOptions} [options] - 卸载选项
35
49
  * @returns {Promise<void>}
36
50
  *
37
51
  * @example
38
52
  * // 卸载 brainstorming
39
53
  * await uninstallSkill('brainstorming');
54
+ *
55
+ * // 从特定平台卸载
56
+ * await uninstallSkill('brainstorming', { platforms: ['opencode'] });
40
57
  */
41
- export async function uninstallSkill(skillId: string): Promise<void> {
58
+ export async function uninstallSkill(
59
+ skillId: string,
60
+ options?: UninstallOptions
61
+ ): Promise<void> {
42
62
  // ==========================================================================
43
63
  // 步骤 1: 检查是否已安装
44
64
  // ==========================================================================
@@ -57,7 +77,40 @@ export async function uninstallSkill(skillId: string): Promise<void> {
57
77
  console.log(`Uninstalling ${skillId}@${skillInfo.version}...`);
58
78
 
59
79
  // ==========================================================================
60
- // 步骤 2: 删除 skill 主目录
80
+ // 步骤 2: 从平台卸载 (NEW)
81
+ // ==========================================================================
82
+
83
+ let targetAdapters: (PlatformAdapter | undefined)[] = [];
84
+
85
+ if (options?.platforms && options.platforms.length > 0) {
86
+ // 用户指定了平台
87
+ for (const platformStr of options.platforms) {
88
+ const platform = platformStr as Platform;
89
+ targetAdapters.push(getAdapterByPlatform(platform));
90
+ }
91
+ } else {
92
+ // 自动检测可用平台
93
+ targetAdapters = await detectPlatforms();
94
+ }
95
+
96
+ // 过滤掉 undefined(无效平台)
97
+ const validAdapters = targetAdapters.filter((a): a is PlatformAdapter => a !== undefined);
98
+
99
+ if (validAdapters.length > 0) {
100
+ console.log(`\nUninstalling from ${validAdapters.length} platform(s)...\n`);
101
+
102
+ for (const adapter of validAdapters) {
103
+ try {
104
+ await adapter.uninstall(skillId);
105
+ console.log(`${adapter.name.padEnd(12)} ✅ Uninstalled`);
106
+ } catch (error) {
107
+ console.log(`${adapter.name.padEnd(12)} ❌ Failed: ${error}`);
108
+ }
109
+ }
110
+ }
111
+
112
+ // ==========================================================================
113
+ // 步骤 3: 删除 skill 主目录
61
114
  // ==========================================================================
62
115
 
63
116
  // skill 主目录包含所有版本和 latest 软链接
@@ -68,7 +121,7 @@ export async function uninstallSkill(skillId: string): Promise<void> {
68
121
  await fs.remove(skillDir);
69
122
 
70
123
  // ==========================================================================
71
- // 步骤 3: 删除平台软链接
124
+ // 步骤 4: 删除平台软链接
72
125
  // ==========================================================================
73
126
 
74
127
  const platformLinksDir = getPlatformLinksDir();
@@ -85,7 +138,7 @@ export async function uninstallSkill(skillId: string): Promise<void> {
85
138
  }
86
139
 
87
140
  // ==========================================================================
88
- // 步骤 4: 更新注册表
141
+ // 步骤 5: 更新注册表
89
142
  // ==========================================================================
90
143
 
91
144
  // 从注册表中删除该 skill 的记录
@@ -47,7 +47,7 @@ export async function updateSkill(skillId?: string): Promise<void> {
47
47
 
48
48
  if (skillId) {
49
49
  // 查询 npm 获取最新版本
50
- const pkgInfo = await fetchNpmPackage(`@skillmarket/${skillId}`);
50
+ const pkgInfo = await fetchNpmPackage(`@itismyskillmarket/${skillId}`);
51
51
 
52
52
  if (pkgInfo) {
53
53
  const latestVersion = pkgInfo['dist-tags']?.latest;
@@ -81,7 +81,7 @@ export async function updateSkill(skillId?: string): Promise<void> {
81
81
  // 遍历每个已安装的 skill
82
82
  for (const skill of installed) {
83
83
  // 查询 npm 获取最新版本信息
84
- const pkgInfo = await fetchNpmPackage(`@skillmarket/${skill.id}`);
84
+ const pkgInfo = await fetchNpmPackage(`@wanxuchen/${skill.id}`);
85
85
 
86
86
  if (pkgInfo) {
87
87
  const latestVersion = pkgInfo['dist-tags']?.latest;
package/src/index.ts CHANGED
@@ -5,6 +5,24 @@
5
5
  *
6
6
  * 本文件是 SkillMarket CLI 工具的入口点。
7
7
  *
8
+ * Shebang (#!) 说明:
9
+ * - #!/usr/bin/env node 表示使用系统中的 node 解释器执行
10
+ * - 这使得脚本可以作为可执行文件直接运行
11
+ *
12
+ * 包配置 (package.json):
13
+ * {
14
+ * "bin": {
15
+ * "skm": "./dist/index.js"
16
+ * }
17
+ * }
18
+ *
19
+ * 安装后:
20
+ * - 全局安装: npm install -g skillmarket
21
+ * 会将 skm 命令链接到系统 PATH
22
+ *
23
+ * - 本地运行: npx skillmarket
24
+ * 使用 npx 直接运行而不安装
25
+ *
8
26
  * 执行流程:
9
27
  * 1. Node.js 根据 shebang 启动
10
28
  * 2. 导入 cli.ts 中的命令行解析器
@@ -22,6 +40,15 @@
22
40
  * node dist/index.js --help
23
41
  */
24
42
 
43
+ // -----------------------------------------------------------------------------
44
+ // Shebang - 在 tsup.config.ts 的 banner 中配置
45
+ // -----------------------------------------------------------------------------
46
+
47
+ /**
48
+ * 注意: shebang (#!/usr/bin/env node) 现在由 tsup.config.ts 的 banner 配置添加,
49
+ * 不再直接写在此文件中。这确保了跨平台兼容性。
50
+ */
51
+
25
52
  // -----------------------------------------------------------------------------
26
53
  // 导入 CLI 模块
27
54
  // -----------------------------------------------------------------------------
package/src/types.ts CHANGED
@@ -135,3 +135,38 @@ export interface RegistryData {
135
135
  */
136
136
  lastUpdated: string;
137
137
  }
138
+
139
+ // -----------------------------------------------------------------------------
140
+ // Platform Adapter 接口
141
+ // -----------------------------------------------------------------------------
142
+
143
+ /**
144
+ * Platform adapter interface for cross-platform skill installation
145
+ *
146
+ * @interface PlatformAdapter
147
+ */
148
+ export interface PlatformAdapter {
149
+ /** Unique platform identifier */
150
+ readonly id: string;
151
+
152
+ /** Human-readable platform name */
153
+ readonly name: string;
154
+
155
+ /** Platform's skill directory path */
156
+ readonly skillDir: string;
157
+
158
+ /** Check if this platform is available on the current system */
159
+ isAvailable(): Promise<boolean>;
160
+
161
+ /** Check if a skill is installed on this platform */
162
+ isInstalled(skillId: string): Promise<boolean>;
163
+
164
+ /** Install a skill to this platform */
165
+ install(skillId: string, sourceDir: string): Promise<void>;
166
+
167
+ /** Uninstall a skill from this platform */
168
+ uninstall(skillId: string): Promise<void>;
169
+
170
+ /** List all skills installed on this platform */
171
+ listInstalled(): Promise<string[]>;
172
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src"
9
+ }
10
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ banner: {
8
+ /**
9
+ * 添加 shebang 到编译后的输出
10
+ *
11
+ * 注意: tsup 的 banner 选项会在模块内容前添加字符串,
12
+ * 这里用 JSON 格式传递以确保正确处理
13
+ */
14
+ js: '#!/usr/bin/env node'
15
+ },
16
+ /**
17
+ * 禁用 shims 以避免潜在的兼容性问题
18
+ * shims 会自动为某些 Node.js 模块提供垫片,
19
+ * 但可能与我们的场景不兼容
20
+ */
21
+ shims: false
22
+ });
Binary file