myskillshub 1.0.6 → 1.0.8
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 +1 -1
- package/src/commands/publish.js +108 -20
package/package.json
CHANGED
package/src/commands/publish.js
CHANGED
|
@@ -12,6 +12,7 @@ const FormData = require('form-data');
|
|
|
12
12
|
const { createWriteStream } = require('fs');
|
|
13
13
|
|
|
14
14
|
const program = new Command();
|
|
15
|
+
const DEFAULT_CATEGORY_SLUG = 'dev-tools';
|
|
15
16
|
|
|
16
17
|
program
|
|
17
18
|
.name('publish')
|
|
@@ -73,7 +74,7 @@ program
|
|
|
73
74
|
console.log(chalk.cyan(`Skill URL: ${options.apiUrl}/skills/${result.slug}`));
|
|
74
75
|
|
|
75
76
|
} catch (error) {
|
|
76
|
-
spinner.fail(chalk.red(`Publish failed: ${error
|
|
77
|
+
spinner.fail(chalk.red(`Publish failed: ${formatErrorMessage(error)}`));
|
|
77
78
|
if (options.verbose) {
|
|
78
79
|
console.error(error);
|
|
79
80
|
}
|
|
@@ -229,18 +230,25 @@ async function resolveCategoryId(apiUrl, options, frontmatter) {
|
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
|
|
232
|
-
const slugCandidate = options.categorySlug
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
const slugCandidate = options.categorySlug
|
|
234
|
+
|| frontmatter.category_slug
|
|
235
|
+
|| frontmatter.category
|
|
236
|
+
|| DEFAULT_CATEGORY_SLUG;
|
|
236
237
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
try {
|
|
239
|
+
const response = await axios.get(`${apiUrl}/api/categories/${encodeURIComponent(String(slugCandidate).trim())}`);
|
|
240
|
+
const category = response.data?.data?.category;
|
|
241
|
+
if (!response.data?.success || !category?.id) {
|
|
242
|
+
throw new Error(`Failed to resolve category slug: ${slugCandidate}`);
|
|
243
|
+
}
|
|
242
244
|
|
|
243
|
-
|
|
245
|
+
return category.id;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
if (error.response?.status === 404 && slugCandidate === DEFAULT_CATEGORY_SLUG) {
|
|
248
|
+
throw new Error(`Default category "${DEFAULT_CATEGORY_SLUG}" not found. Use --category-id or --category-slug.`);
|
|
249
|
+
}
|
|
250
|
+
throw new Error(`Failed to resolve category slug: ${slugCandidate}. ${formatErrorMessage(error)}`);
|
|
251
|
+
}
|
|
244
252
|
}
|
|
245
253
|
|
|
246
254
|
async function getAuthCookie(apiUrl, options, spinner) {
|
|
@@ -260,9 +268,38 @@ async function getAuthCookie(apiUrl, options, spinner) {
|
|
|
260
268
|
}
|
|
261
269
|
}
|
|
262
270
|
|
|
263
|
-
|
|
264
|
-
|
|
271
|
+
let usedStoredCredentials = false;
|
|
272
|
+
let credentials = hasCompleteExplicitCredentials
|
|
273
|
+
? { username: resolvedUsername, password: resolvedPassword }
|
|
274
|
+
: null;
|
|
275
|
+
|
|
276
|
+
if (!credentials) {
|
|
277
|
+
const storedCredentials = getCachedCredentials(normalizedApiUrl);
|
|
278
|
+
if (storedCredentials) {
|
|
279
|
+
credentials = storedCredentials;
|
|
280
|
+
usedStoredCredentials = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!credentials) {
|
|
285
|
+
credentials = await resolveCredentials(options, spinner);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
let cookie;
|
|
289
|
+
try {
|
|
290
|
+
cookie = await loginAndGetCookie(normalizedApiUrl, credentials.username, credentials.password);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
if (usedStoredCredentials) {
|
|
293
|
+
// Stored credentials may be stale, fallback to interactive prompt once.
|
|
294
|
+
credentials = await resolveCredentials(options, spinner);
|
|
295
|
+
cookie = await loginAndGetCookie(normalizedApiUrl, credentials.username, credentials.password);
|
|
296
|
+
} else {
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
265
301
|
saveCachedCookie(normalizedApiUrl, cookie);
|
|
302
|
+
saveCachedCredentials(normalizedApiUrl, credentials.username, credentials.password);
|
|
266
303
|
return { cookie, fromCache: false };
|
|
267
304
|
}
|
|
268
305
|
|
|
@@ -304,20 +341,43 @@ function getCachedCookie(apiUrl) {
|
|
|
304
341
|
return store.sessions?.[apiUrl]?.cookie || null;
|
|
305
342
|
}
|
|
306
343
|
|
|
307
|
-
function
|
|
344
|
+
function getCachedCredentials(apiUrl) {
|
|
345
|
+
const store = readSessionStore();
|
|
346
|
+
const username = store.sessions?.[apiUrl]?.username || '';
|
|
347
|
+
const password = store.sessions?.[apiUrl]?.password || '';
|
|
348
|
+
if (!username || !password) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
return { username, password };
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function saveSessionData(apiUrl, patch) {
|
|
308
355
|
const store = readSessionStore();
|
|
309
356
|
store.sessions = store.sessions || {};
|
|
310
357
|
store.sessions[apiUrl] = {
|
|
311
|
-
|
|
312
|
-
|
|
358
|
+
...(store.sessions[apiUrl] || {}),
|
|
359
|
+
...patch,
|
|
360
|
+
updatedAt: new Date().toISOString(),
|
|
313
361
|
};
|
|
314
362
|
writeSessionStore(store);
|
|
315
363
|
}
|
|
316
364
|
|
|
365
|
+
function saveCachedCookie(apiUrl, cookie) {
|
|
366
|
+
saveSessionData(apiUrl, { cookie });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function saveCachedCredentials(apiUrl, username, password) {
|
|
370
|
+
saveSessionData(apiUrl, { username, password });
|
|
371
|
+
}
|
|
372
|
+
|
|
317
373
|
function removeCachedCookie(apiUrl) {
|
|
318
374
|
const store = readSessionStore();
|
|
319
375
|
if (store.sessions && store.sessions[apiUrl]) {
|
|
320
|
-
delete store.sessions[apiUrl];
|
|
376
|
+
delete store.sessions[apiUrl].cookie;
|
|
377
|
+
store.sessions[apiUrl].updatedAt = new Date().toISOString();
|
|
378
|
+
if (!store.sessions[apiUrl].username || !store.sessions[apiUrl].password) {
|
|
379
|
+
delete store.sessions[apiUrl];
|
|
380
|
+
}
|
|
321
381
|
writeSessionStore(store);
|
|
322
382
|
}
|
|
323
383
|
}
|
|
@@ -396,7 +456,7 @@ function promptPassword(question) {
|
|
|
396
456
|
terminal: true
|
|
397
457
|
});
|
|
398
458
|
|
|
399
|
-
rl.stdoutMuted =
|
|
459
|
+
rl.stdoutMuted = false;
|
|
400
460
|
const originalWriteToOutput = rl._writeToOutput;
|
|
401
461
|
rl._writeToOutput = function writeToOutput(stringToWrite) {
|
|
402
462
|
if (rl.stdoutMuted) {
|
|
@@ -415,6 +475,7 @@ function promptPassword(question) {
|
|
|
415
475
|
rl.close();
|
|
416
476
|
resolve(String(password || '').trim());
|
|
417
477
|
});
|
|
478
|
+
rl.stdoutMuted = true;
|
|
418
479
|
});
|
|
419
480
|
}
|
|
420
481
|
|
|
@@ -435,7 +496,7 @@ async function loginAndGetCookie(apiUrl, username, password) {
|
|
|
435
496
|
function createZipPackage(directory) {
|
|
436
497
|
return new Promise((resolve, reject) => {
|
|
437
498
|
const baseName = path.basename(path.resolve(directory));
|
|
438
|
-
const zipPath = path.join(
|
|
499
|
+
const zipPath = path.join(os.tmpdir(), `${baseName}-package-${Date.now()}.zip`);
|
|
439
500
|
const output = createWriteStream(zipPath);
|
|
440
501
|
const archive = archiver('zip', {
|
|
441
502
|
zlib: { level: 9 }
|
|
@@ -461,7 +522,10 @@ function createZipPackage(directory) {
|
|
|
461
522
|
ignore: [
|
|
462
523
|
'**/node_modules/**',
|
|
463
524
|
'**/.git/**',
|
|
464
|
-
'**/.DS_Store'
|
|
525
|
+
'**/.DS_Store',
|
|
526
|
+
'**/*-package-*.zip',
|
|
527
|
+
'**/*-package.zip',
|
|
528
|
+
'**/.-package.zip'
|
|
465
529
|
]
|
|
466
530
|
});
|
|
467
531
|
|
|
@@ -493,4 +557,28 @@ async function uploadSkill(zipPath, skillData, categoryId, apiUrl, authCookie) {
|
|
|
493
557
|
}
|
|
494
558
|
}
|
|
495
559
|
|
|
560
|
+
function formatErrorMessage(error) {
|
|
561
|
+
if (!error) {
|
|
562
|
+
return 'Unknown error';
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const status = error.response?.status;
|
|
566
|
+
const apiError = error.response?.data?.error;
|
|
567
|
+
const directMessage = error.response?.data?.message;
|
|
568
|
+
|
|
569
|
+
if (apiError?.message) {
|
|
570
|
+
return status ? `HTTP ${status}: ${apiError.message}` : apiError.message;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (directMessage) {
|
|
574
|
+
return status ? `HTTP ${status}: ${directMessage}` : directMessage;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (status) {
|
|
578
|
+
return `HTTP ${status}: ${error.message}`;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return error.message || 'Unknown error';
|
|
582
|
+
}
|
|
583
|
+
|
|
496
584
|
module.exports = program;
|