myskillshub 1.0.2 → 1.0.4
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/package.json +3 -2
- package/scripts/auto-bump-version.js +123 -0
- package/src/commands/publish.js +33 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myskillshub",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "CLI tool for SkillHub skill management",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "jest",
|
|
11
11
|
"lint": "eslint src/**/*.js",
|
|
12
|
-
"start": "node src/index.js"
|
|
12
|
+
"start": "node src/index.js",
|
|
13
|
+
"prepublishOnly": "node scripts/auto-bump-version.js"
|
|
13
14
|
},
|
|
14
15
|
"keywords": [
|
|
15
16
|
"cli",
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const PACKAGE_JSON_PATH = path.join(__dirname, '..', 'package.json');
|
|
9
|
+
const PACKAGE_LOCK_PATH = path.join(__dirname, '..', 'package-lock.json');
|
|
10
|
+
|
|
11
|
+
function parseSemver(version) {
|
|
12
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(String(version || '').trim());
|
|
13
|
+
if (!match) {
|
|
14
|
+
throw new Error(`Invalid semver version: ${version}`);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
major: Number(match[1]),
|
|
18
|
+
minor: Number(match[2]),
|
|
19
|
+
patch: Number(match[3]),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function compareSemver(left, right) {
|
|
24
|
+
if (left.major !== right.major) return left.major - right.major;
|
|
25
|
+
if (left.minor !== right.minor) return left.minor - right.minor;
|
|
26
|
+
return left.patch - right.patch;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function bumpPatch(version) {
|
|
30
|
+
const parsed = parseSemver(version);
|
|
31
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readJson(filePath) {
|
|
35
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function writeJson(filePath, data) {
|
|
39
|
+
fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function fetchPublishedVersion(packageName) {
|
|
43
|
+
const cacheDir = path.join(os.tmpdir(), 'myskillshub-npm-cache');
|
|
44
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
45
|
+
|
|
46
|
+
const result = spawnSync(
|
|
47
|
+
'npm',
|
|
48
|
+
['view', packageName, 'version', '--json'],
|
|
49
|
+
{
|
|
50
|
+
encoding: 'utf8',
|
|
51
|
+
env: {
|
|
52
|
+
...process.env,
|
|
53
|
+
npm_config_cache: cacheDir,
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
if (result.status === 0) {
|
|
59
|
+
const stdout = String(result.stdout || '').trim();
|
|
60
|
+
if (!stdout) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const parsed = JSON.parse(stdout);
|
|
64
|
+
return Array.isArray(parsed) ? parsed[parsed.length - 1] : String(parsed);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const stderr = String(result.stderr || '');
|
|
68
|
+
if (stderr.includes('E404') || stderr.includes('Not Found')) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
throw new Error(`Failed to query published version: ${stderr || result.stdout}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function main() {
|
|
76
|
+
const pkg = readJson(PACKAGE_JSON_PATH);
|
|
77
|
+
const packageName = pkg.name;
|
|
78
|
+
const currentVersion = pkg.version;
|
|
79
|
+
|
|
80
|
+
if (!packageName) {
|
|
81
|
+
throw new Error('package.json name is required');
|
|
82
|
+
}
|
|
83
|
+
if (!currentVersion) {
|
|
84
|
+
throw new Error('package.json version is required');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const publishedVersion = fetchPublishedVersion(packageName);
|
|
88
|
+
if (!publishedVersion) {
|
|
89
|
+
console.log(`[auto-bump] ${packageName} has no published version yet, keep ${currentVersion}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const currentParsed = parseSemver(currentVersion);
|
|
94
|
+
const publishedParsed = parseSemver(publishedVersion);
|
|
95
|
+
const shouldBump = compareSemver(currentParsed, publishedParsed) <= 0;
|
|
96
|
+
|
|
97
|
+
if (!shouldBump) {
|
|
98
|
+
console.log(`[auto-bump] local version ${currentVersion} is newer than published ${publishedVersion}, keep current`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const nextVersion = bumpPatch(publishedVersion);
|
|
103
|
+
pkg.version = nextVersion;
|
|
104
|
+
writeJson(PACKAGE_JSON_PATH, pkg);
|
|
105
|
+
|
|
106
|
+
if (fs.existsSync(PACKAGE_LOCK_PATH)) {
|
|
107
|
+
const lock = readJson(PACKAGE_LOCK_PATH);
|
|
108
|
+
lock.version = nextVersion;
|
|
109
|
+
if (lock.packages && lock.packages['']) {
|
|
110
|
+
lock.packages[''].version = nextVersion;
|
|
111
|
+
}
|
|
112
|
+
writeJson(PACKAGE_LOCK_PATH, lock);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log(`[auto-bump] bumped ${packageName} version: ${currentVersion} -> ${nextVersion}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
main();
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error(`[auto-bump] ${error.message}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
package/src/commands/publish.js
CHANGED
|
@@ -14,23 +14,24 @@ const program = new Command();
|
|
|
14
14
|
program
|
|
15
15
|
.name('publish')
|
|
16
16
|
.description('Publish a skill from local directory')
|
|
17
|
-
.argument('
|
|
17
|
+
.argument('[directory]', 'Directory containing skill to publish (default: current directory)')
|
|
18
18
|
.option('--verbose', 'Verbose output')
|
|
19
19
|
.option('-a, --api-url <url>', 'SkillHub API URL', 'http://localhost:3000')
|
|
20
20
|
.action(async (directory, options) => {
|
|
21
|
+
const targetDirectory = directory || '.';
|
|
21
22
|
const spinner = ora('Starting publish process...').start();
|
|
22
23
|
|
|
23
24
|
try {
|
|
24
25
|
// Validate directory exists
|
|
25
|
-
if (!fs.existsSync(
|
|
26
|
-
spinner.fail(chalk.red(`Directory not found: ${
|
|
26
|
+
if (!fs.existsSync(targetDirectory)) {
|
|
27
|
+
spinner.fail(chalk.red(`Directory not found: ${targetDirectory}`));
|
|
27
28
|
process.exit(1);
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
// Find skill.md file
|
|
31
|
-
const skillMdPath =
|
|
32
|
-
if (!
|
|
33
|
-
spinner.fail(chalk.red('skill.md not found in the directory'));
|
|
32
|
+
const skillMdPath = resolveSkillFilePath(targetDirectory);
|
|
33
|
+
if (!skillMdPath) {
|
|
34
|
+
spinner.fail(chalk.red('SKILL.md or skill.md not found in the directory'));
|
|
34
35
|
process.exit(1);
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -43,7 +44,7 @@ program
|
|
|
43
44
|
|
|
44
45
|
// Create ZIP package
|
|
45
46
|
spinner.text = 'Creating ZIP package...';
|
|
46
|
-
const zipPath = await createZipPackage(
|
|
47
|
+
const zipPath = await createZipPackage(targetDirectory);
|
|
47
48
|
spinner.succeed(chalk.green(`ZIP package created: ${zipPath}`));
|
|
48
49
|
|
|
49
50
|
// Upload to SkillHub API
|
|
@@ -63,6 +64,17 @@ program
|
|
|
63
64
|
}
|
|
64
65
|
});
|
|
65
66
|
|
|
67
|
+
function resolveSkillFilePath(directory) {
|
|
68
|
+
const candidates = ['SKILL.md', 'skill.md'];
|
|
69
|
+
for (const fileName of candidates) {
|
|
70
|
+
const fullPath = path.join(directory, fileName);
|
|
71
|
+
if (fs.existsSync(fullPath)) {
|
|
72
|
+
return fullPath;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
66
78
|
function parseSkillMd(content) {
|
|
67
79
|
const lines = content.split('\n');
|
|
68
80
|
const skillData = {
|
|
@@ -106,7 +118,8 @@ function parseSkillMd(content) {
|
|
|
106
118
|
|
|
107
119
|
function createZipPackage(directory) {
|
|
108
120
|
return new Promise((resolve, reject) => {
|
|
109
|
-
const
|
|
121
|
+
const baseName = path.basename(path.resolve(directory));
|
|
122
|
+
const zipPath = path.join(process.cwd(), `${baseName}-package-${Date.now()}.zip`);
|
|
110
123
|
const output = createWriteStream(zipPath);
|
|
111
124
|
const archive = archiver('zip', {
|
|
112
125
|
zlib: { level: 9 }
|
|
@@ -119,14 +132,21 @@ function createZipPackage(directory) {
|
|
|
119
132
|
output.on('error', (err) => {
|
|
120
133
|
reject(err);
|
|
121
134
|
});
|
|
135
|
+
archive.on('error', (err) => {
|
|
136
|
+
reject(err);
|
|
137
|
+
});
|
|
122
138
|
|
|
123
139
|
archive.pipe(output);
|
|
124
140
|
|
|
125
|
-
// Add all files
|
|
126
|
-
archive.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
141
|
+
// Add all files recursively, excluding typical VCS/dependency artifacts.
|
|
142
|
+
archive.glob('**/*', {
|
|
143
|
+
cwd: directory,
|
|
144
|
+
dot: true,
|
|
145
|
+
ignore: [
|
|
146
|
+
'**/node_modules/**',
|
|
147
|
+
'**/.git/**',
|
|
148
|
+
'**/.DS_Store'
|
|
149
|
+
]
|
|
130
150
|
});
|
|
131
151
|
|
|
132
152
|
archive.finalize();
|