@adonis0123/commit 1.0.3 → 1.0.5
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.
- package/README.md +2 -1
- package/install-skill.js +102 -26
- package/package.json +1 -1
- package/uninstall-skill.js +83 -10
package/README.md
CHANGED
|
@@ -61,7 +61,8 @@ npm install -g @adonis0123/commit
|
|
|
61
61
|
- [@adonis0123/skill-development](https://www.npmjs.com/package/@adonis0123/skill-development) - 技能开发指南
|
|
62
62
|
- [@adonis0123/staged-changes-review](https://www.npmjs.com/package/@adonis0123/staged-changes-review) - 代码审查
|
|
63
63
|
- [@adonis0123/create-skill](https://www.npmjs.com/package/@adonis0123/create-skill) - 创建新技能包
|
|
64
|
-
|
|
64
|
+
- [@adonis0123/code-doc-generator](https://www.npmjs.com/package/@adonis0123/code-doc-generator) - 代码文档生成
|
|
65
|
+
- [@adonis0123/css-tailwind-styling](https://www.npmjs.com/package/@adonis0123/css-tailwind-styling) - CSS 和 Tailwind 样式规范
|
|
65
66
|
## License
|
|
66
67
|
|
|
67
68
|
MIT
|
package/install-skill.js
CHANGED
|
@@ -23,9 +23,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
));
|
|
24
24
|
|
|
25
25
|
// shared/src/install-skill.ts
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
var
|
|
26
|
+
var import_fs3 = __toESM(require("fs"));
|
|
27
|
+
var import_path3 = __toESM(require("path"));
|
|
28
|
+
var import_os3 = __toESM(require("os"));
|
|
29
29
|
var import_child_process = require("child_process");
|
|
30
30
|
|
|
31
31
|
// shared/src/utils.ts
|
|
@@ -116,6 +116,69 @@ function readSkillConfig(dir) {
|
|
|
116
116
|
return JSON.parse(import_fs.default.readFileSync(configPath, "utf-8"));
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// shared/src/claude-settings.ts
|
|
120
|
+
var import_fs2 = __toESM(require("fs"));
|
|
121
|
+
var import_path2 = __toESM(require("path"));
|
|
122
|
+
var import_os2 = __toESM(require("os"));
|
|
123
|
+
function getClaudeSettingsPath() {
|
|
124
|
+
return import_path2.default.join(import_os2.default.homedir(), ".claude", "settings.json");
|
|
125
|
+
}
|
|
126
|
+
function readClaudeSettings() {
|
|
127
|
+
const settingsPath = getClaudeSettingsPath();
|
|
128
|
+
if (!import_fs2.default.existsSync(settingsPath)) {
|
|
129
|
+
return {};
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
const content = import_fs2.default.readFileSync(settingsPath, "utf-8");
|
|
133
|
+
return JSON.parse(content);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.warn(" \u26A0 Warning: Could not parse settings.json, treating as empty");
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function writeClaudeSettings(settings) {
|
|
140
|
+
const settingsPath = getClaudeSettingsPath();
|
|
141
|
+
const settingsDir = import_path2.default.dirname(settingsPath);
|
|
142
|
+
if (!import_fs2.default.existsSync(settingsDir)) {
|
|
143
|
+
import_fs2.default.mkdirSync(settingsDir, { recursive: true });
|
|
144
|
+
}
|
|
145
|
+
import_fs2.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
146
|
+
}
|
|
147
|
+
function hookMatcherExists(existingHooks, newMatcher) {
|
|
148
|
+
return existingHooks.some((hook) => hook.matcher === newMatcher.matcher);
|
|
149
|
+
}
|
|
150
|
+
function addClaudeHooks(hooksConfig, skillName) {
|
|
151
|
+
const settings = readClaudeSettings();
|
|
152
|
+
let modified = false;
|
|
153
|
+
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
154
|
+
settings.hooks = {};
|
|
155
|
+
}
|
|
156
|
+
const hooks = settings.hooks;
|
|
157
|
+
for (const [hookType, hookMatchers] of Object.entries(hooksConfig)) {
|
|
158
|
+
if (!hookMatchers || !Array.isArray(hookMatchers)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (!hooks[hookType] || !Array.isArray(hooks[hookType])) {
|
|
162
|
+
hooks[hookType] = [];
|
|
163
|
+
}
|
|
164
|
+
const existingHooks = hooks[hookType];
|
|
165
|
+
for (const matcher of hookMatchers) {
|
|
166
|
+
if (!hookMatcherExists(existingHooks, matcher)) {
|
|
167
|
+
existingHooks.push(matcher);
|
|
168
|
+
modified = true;
|
|
169
|
+
console.log(` \u2713 Added ${hookType} hook for ${skillName}`);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(` \u2139 ${hookType} hook already exists, skipping`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
hooks[hookType] = existingHooks;
|
|
175
|
+
}
|
|
176
|
+
if (modified) {
|
|
177
|
+
writeClaudeSettings(settings);
|
|
178
|
+
}
|
|
179
|
+
return modified;
|
|
180
|
+
}
|
|
181
|
+
|
|
119
182
|
// shared/src/install-skill.ts
|
|
120
183
|
function fetchFromRemote(tempDir, remoteSource) {
|
|
121
184
|
try {
|
|
@@ -124,7 +187,7 @@ function fetchFromRemote(tempDir, remoteSource) {
|
|
|
124
187
|
stdio: "pipe",
|
|
125
188
|
timeout: 6e4
|
|
126
189
|
});
|
|
127
|
-
if (
|
|
190
|
+
if (import_fs3.default.existsSync(import_path3.default.join(tempDir, "SKILL.md"))) {
|
|
128
191
|
console.log(" \u2713 Fetched latest version from remote");
|
|
129
192
|
return true;
|
|
130
193
|
}
|
|
@@ -146,14 +209,14 @@ function getSourceDir(config, packageDir) {
|
|
|
146
209
|
isRemote: false
|
|
147
210
|
};
|
|
148
211
|
}
|
|
149
|
-
const tempDir =
|
|
212
|
+
const tempDir = import_path3.default.join(import_os3.default.tmpdir(), `skill-fetch-${Date.now()}`);
|
|
150
213
|
const remoteSuccess = fetchFromRemote(tempDir, config.remoteSource);
|
|
151
214
|
if (remoteSuccess) {
|
|
152
215
|
return {
|
|
153
216
|
sourceDir: tempDir,
|
|
154
217
|
cleanup: () => {
|
|
155
218
|
try {
|
|
156
|
-
|
|
219
|
+
import_fs3.default.rmSync(tempDir, { recursive: true, force: true });
|
|
157
220
|
} catch {
|
|
158
221
|
}
|
|
159
222
|
},
|
|
@@ -161,7 +224,7 @@ function getSourceDir(config, packageDir) {
|
|
|
161
224
|
};
|
|
162
225
|
}
|
|
163
226
|
try {
|
|
164
|
-
|
|
227
|
+
import_fs3.default.rmSync(tempDir, { recursive: true, force: true });
|
|
165
228
|
} catch {
|
|
166
229
|
}
|
|
167
230
|
return {
|
|
@@ -172,11 +235,11 @@ function getSourceDir(config, packageDir) {
|
|
|
172
235
|
};
|
|
173
236
|
}
|
|
174
237
|
function updateManifest(skillsDir, config, targetName, isRemote) {
|
|
175
|
-
const manifestPath =
|
|
238
|
+
const manifestPath = import_path3.default.join(skillsDir, ".skills-manifest.json");
|
|
176
239
|
let manifest = { skills: {} };
|
|
177
|
-
if (
|
|
240
|
+
if (import_fs3.default.existsSync(manifestPath)) {
|
|
178
241
|
try {
|
|
179
|
-
manifest = JSON.parse(
|
|
242
|
+
manifest = JSON.parse(import_fs3.default.readFileSync(manifestPath, "utf-8"));
|
|
180
243
|
} catch {
|
|
181
244
|
console.warn(" Warning: Could not parse existing manifest, creating new one");
|
|
182
245
|
manifest = { skills: {} };
|
|
@@ -187,55 +250,68 @@ function updateManifest(skillsDir, config, targetName, isRemote) {
|
|
|
187
250
|
version: config.version,
|
|
188
251
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
189
252
|
package: config.package || config.name,
|
|
190
|
-
path:
|
|
253
|
+
path: import_path3.default.join(skillsDir, skillName),
|
|
191
254
|
target: targetName,
|
|
192
255
|
...config.remoteSource && { source: config.remoteSource }
|
|
193
256
|
};
|
|
194
|
-
|
|
257
|
+
import_fs3.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
195
258
|
}
|
|
196
259
|
function installToTarget(target, config, sourceDir, isRemote) {
|
|
197
|
-
var _a;
|
|
260
|
+
var _a, _b;
|
|
198
261
|
console.log(`
|
|
199
262
|
\u{1F4E6} Installing to ${target.name}...`);
|
|
200
263
|
const isGlobal = isGlobalInstall();
|
|
201
264
|
const location = detectInstallLocation(target.paths, isGlobal);
|
|
202
265
|
const skillName = extractSkillName(config.name);
|
|
203
|
-
const targetDir =
|
|
204
|
-
const altTargetDir =
|
|
266
|
+
const targetDir = import_path3.default.join(location.base, skillName);
|
|
267
|
+
const altTargetDir = import_path3.default.join(location.base, config.name);
|
|
205
268
|
console.log(` Type: ${location.type}${isGlobal ? " (global)" : " (project)"}`);
|
|
206
269
|
console.log(` Directory: ${targetDir}`);
|
|
207
|
-
if (
|
|
270
|
+
if (import_fs3.default.existsSync(altTargetDir) && altTargetDir !== targetDir) {
|
|
208
271
|
console.log(" \u{1F9F9} Cleaning up alternative path format...");
|
|
209
272
|
removeDir(altTargetDir);
|
|
210
273
|
console.log(` \u2713 Removed directory: ${config.name}`);
|
|
211
274
|
}
|
|
212
275
|
ensureDir(targetDir);
|
|
213
|
-
const skillMdSource =
|
|
214
|
-
if (!
|
|
276
|
+
const skillMdSource = import_path3.default.join(sourceDir, "SKILL.md");
|
|
277
|
+
if (!import_fs3.default.existsSync(skillMdSource)) {
|
|
215
278
|
throw new Error("SKILL.md is required but not found");
|
|
216
279
|
}
|
|
217
|
-
|
|
280
|
+
import_fs3.default.copyFileSync(skillMdSource, import_path3.default.join(targetDir, "SKILL.md"));
|
|
218
281
|
console.log(" \u2713 Copied SKILL.md");
|
|
219
282
|
const filesToCopy = config.files || {};
|
|
220
283
|
for (const [source, dest] of Object.entries(filesToCopy)) {
|
|
221
|
-
const sourcePath =
|
|
222
|
-
if (!
|
|
284
|
+
const sourcePath = import_path3.default.join(sourceDir, source);
|
|
285
|
+
if (!import_fs3.default.existsSync(sourcePath)) {
|
|
223
286
|
console.warn(` \u26A0 Warning: ${source} not found, skipping`);
|
|
224
287
|
continue;
|
|
225
288
|
}
|
|
226
|
-
const destPath =
|
|
227
|
-
if (
|
|
289
|
+
const destPath = import_path3.default.join(targetDir, dest);
|
|
290
|
+
if (import_fs3.default.statSync(sourcePath).isDirectory()) {
|
|
228
291
|
copyDir(sourcePath, destPath);
|
|
229
292
|
console.log(` \u2713 Copied directory: ${source}`);
|
|
230
293
|
} else {
|
|
231
|
-
const destDir =
|
|
294
|
+
const destDir = import_path3.default.dirname(destPath);
|
|
232
295
|
ensureDir(destDir);
|
|
233
|
-
|
|
296
|
+
import_fs3.default.copyFileSync(sourcePath, destPath);
|
|
234
297
|
console.log(` \u2713 Copied file: ${source}`);
|
|
235
298
|
}
|
|
236
299
|
}
|
|
237
300
|
updateManifest(location.base, config, target.name, isRemote);
|
|
238
|
-
if ((_a = config.
|
|
301
|
+
if (target.name === "claude-code" && ((_a = config.claudeSettings) == null ? void 0 : _a.hooks)) {
|
|
302
|
+
console.log(" \u{1F527} \u914D\u7F6E Claude Code \u94A9\u5B50...");
|
|
303
|
+
try {
|
|
304
|
+
const skillName2 = extractSkillName(config.name);
|
|
305
|
+
const modified = addClaudeHooks(config.claudeSettings.hooks, skillName2);
|
|
306
|
+
if (modified) {
|
|
307
|
+
console.log(" \u2705 \u94A9\u5B50\u5DF2\u914D\u7F6E\u5230 ~/.claude/settings.json");
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
311
|
+
console.warn(` \u26A0 \u8B66\u544A: \u65E0\u6CD5\u914D\u7F6E\u94A9\u5B50: ${message}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if ((_b = config.hooks) == null ? void 0 : _b.postinstall) {
|
|
239
315
|
console.log(" \u{1F527} Running postinstall hook...");
|
|
240
316
|
try {
|
|
241
317
|
(0, import_child_process.execSync)(config.hooks.postinstall, {
|
package/package.json
CHANGED
package/uninstall-skill.js
CHANGED
|
@@ -23,8 +23,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
));
|
|
24
24
|
|
|
25
25
|
// shared/src/uninstall-skill.ts
|
|
26
|
-
var
|
|
27
|
-
var
|
|
26
|
+
var import_fs3 = __toESM(require("fs"));
|
|
27
|
+
var import_path3 = __toESM(require("path"));
|
|
28
28
|
|
|
29
29
|
// shared/src/utils.ts
|
|
30
30
|
var import_fs = __toESM(require("fs"));
|
|
@@ -96,17 +96,77 @@ function readSkillConfig(dir) {
|
|
|
96
96
|
return JSON.parse(import_fs.default.readFileSync(configPath, "utf-8"));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// shared/src/claude-settings.ts
|
|
100
|
+
var import_fs2 = __toESM(require("fs"));
|
|
101
|
+
var import_path2 = __toESM(require("path"));
|
|
102
|
+
var import_os2 = __toESM(require("os"));
|
|
103
|
+
function getClaudeSettingsPath() {
|
|
104
|
+
return import_path2.default.join(import_os2.default.homedir(), ".claude", "settings.json");
|
|
105
|
+
}
|
|
106
|
+
function readClaudeSettings() {
|
|
107
|
+
const settingsPath = getClaudeSettingsPath();
|
|
108
|
+
if (!import_fs2.default.existsSync(settingsPath)) {
|
|
109
|
+
return {};
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const content = import_fs2.default.readFileSync(settingsPath, "utf-8");
|
|
113
|
+
return JSON.parse(content);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.warn(" \u26A0 Warning: Could not parse settings.json, treating as empty");
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function writeClaudeSettings(settings) {
|
|
120
|
+
const settingsPath = getClaudeSettingsPath();
|
|
121
|
+
const settingsDir = import_path2.default.dirname(settingsPath);
|
|
122
|
+
if (!import_fs2.default.existsSync(settingsDir)) {
|
|
123
|
+
import_fs2.default.mkdirSync(settingsDir, { recursive: true });
|
|
124
|
+
}
|
|
125
|
+
import_fs2.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
126
|
+
}
|
|
127
|
+
function removeClaudeHooks(hooksConfig, skillName) {
|
|
128
|
+
const settings = readClaudeSettings();
|
|
129
|
+
let modified = false;
|
|
130
|
+
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
const hooks = settings.hooks;
|
|
134
|
+
for (const [hookType, hookMatchers] of Object.entries(hooksConfig)) {
|
|
135
|
+
if (!hookMatchers || !Array.isArray(hookMatchers)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (!hooks[hookType] || !Array.isArray(hooks[hookType])) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const existingHooks = hooks[hookType];
|
|
142
|
+
const initialLength = existingHooks.length;
|
|
143
|
+
const matchersToRemove = hookMatchers.map((m) => m.matcher);
|
|
144
|
+
const filteredHooks = existingHooks.filter(
|
|
145
|
+
(hook) => !matchersToRemove.includes(hook.matcher)
|
|
146
|
+
);
|
|
147
|
+
if (filteredHooks.length < initialLength) {
|
|
148
|
+
hooks[hookType] = filteredHooks;
|
|
149
|
+
modified = true;
|
|
150
|
+
console.log(` \u2713 Removed ${hookType} hook for ${skillName}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (modified) {
|
|
154
|
+
writeClaudeSettings(settings);
|
|
155
|
+
}
|
|
156
|
+
return modified;
|
|
157
|
+
}
|
|
158
|
+
|
|
99
159
|
// shared/src/uninstall-skill.ts
|
|
100
160
|
function updateManifest(skillsDir, config) {
|
|
101
|
-
const manifestPath =
|
|
102
|
-
if (!
|
|
161
|
+
const manifestPath = import_path3.default.join(skillsDir, ".skills-manifest.json");
|
|
162
|
+
if (!import_fs3.default.existsSync(manifestPath)) {
|
|
103
163
|
return;
|
|
104
164
|
}
|
|
105
165
|
try {
|
|
106
|
-
const manifest = JSON.parse(
|
|
166
|
+
const manifest = JSON.parse(import_fs3.default.readFileSync(manifestPath, "utf-8"));
|
|
107
167
|
if (manifest.skills && manifest.skills[config.name]) {
|
|
108
168
|
delete manifest.skills[config.name];
|
|
109
|
-
|
|
169
|
+
import_fs3.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
110
170
|
console.log(" \u2713 Updated manifest");
|
|
111
171
|
}
|
|
112
172
|
} catch (error) {
|
|
@@ -115,25 +175,38 @@ function updateManifest(skillsDir, config) {
|
|
|
115
175
|
}
|
|
116
176
|
}
|
|
117
177
|
function uninstallFromTarget(target, config) {
|
|
178
|
+
var _a;
|
|
118
179
|
console.log(`
|
|
119
180
|
\u{1F5D1}\uFE0F Uninstalling from ${target.name}...`);
|
|
120
181
|
const isGlobal = isGlobalInstall();
|
|
121
182
|
const location = detectInstallLocation(target.paths, isGlobal);
|
|
122
183
|
const skillName = extractSkillName(config.name);
|
|
123
|
-
const skillNameTargetDir =
|
|
124
|
-
const fullPackageNameTargetDir =
|
|
184
|
+
const skillNameTargetDir = import_path3.default.join(location.base, skillName);
|
|
185
|
+
const fullPackageNameTargetDir = import_path3.default.join(location.base, config.name);
|
|
125
186
|
let removed = false;
|
|
126
|
-
if (
|
|
187
|
+
if (import_fs3.default.existsSync(skillNameTargetDir)) {
|
|
127
188
|
removeDir(skillNameTargetDir);
|
|
128
189
|
console.log(` \u2713 Removed skill directory: ${skillName}`);
|
|
129
190
|
removed = true;
|
|
130
191
|
}
|
|
131
|
-
if (
|
|
192
|
+
if (import_fs3.default.existsSync(fullPackageNameTargetDir) && fullPackageNameTargetDir !== skillNameTargetDir) {
|
|
132
193
|
removeDir(fullPackageNameTargetDir);
|
|
133
194
|
console.log(` \u2713 Removed skill directory: ${config.name}`);
|
|
134
195
|
removed = true;
|
|
135
196
|
}
|
|
136
197
|
updateManifest(location.base, config);
|
|
198
|
+
if (target.name === "claude-code" && removed && ((_a = config.claudeSettings) == null ? void 0 : _a.hooks)) {
|
|
199
|
+
try {
|
|
200
|
+
console.log(" \u{1F527} \u79FB\u9664 Claude Code \u94A9\u5B50...");
|
|
201
|
+
const skillName2 = extractSkillName(config.name);
|
|
202
|
+
const modified = removeClaudeHooks(config.claudeSettings.hooks, skillName2);
|
|
203
|
+
if (modified) {
|
|
204
|
+
console.log(" \u2705 \u94A9\u5B50\u5DF2\u4ECE ~/.claude/settings.json \u79FB\u9664");
|
|
205
|
+
}
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.warn(" \u26A0 \u8B66\u544A: \u65E0\u6CD5\u79FB\u9664\u94A9\u5B50\uFF08\u53EF\u5B89\u5168\u5FFD\u7565\uFF09");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
137
210
|
if (removed) {
|
|
138
211
|
console.log(` \u2705 Uninstalled from ${target.name}`);
|
|
139
212
|
return true;
|