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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myskillshub",
3
- "version": "1.0.2",
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
+ }
@@ -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('<directory>', 'Directory containing skill to publish')
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(directory)) {
26
- spinner.fail(chalk.red(`Directory not found: ${directory}`));
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 = path.join(directory, 'skill.md');
32
- if (!fs.existsSync(skillMdPath)) {
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(directory);
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 zipPath = path.join(process.cwd(), `${path.basename(directory)}-package.zip`);
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 except node_modules and .git
126
- archive.directory(directory, false, (data) => {
127
- return data.stats.isDirectory() &&
128
- !data.name.includes('node_modules') &&
129
- !data.name.includes('.git');
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();