skillhub 0.1.2 → 0.1.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.
- package/dist/index.js +78 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,27 +22,78 @@ import ora from "ora";
|
|
|
22
22
|
import { parseSkillMd } from "skillhub-core";
|
|
23
23
|
|
|
24
24
|
// src/utils/api.ts
|
|
25
|
+
import https from "https";
|
|
26
|
+
import http from "http";
|
|
25
27
|
var API_BASE_URL = process.env.SKILLHUB_API_URL || "https://skills.palebluedot.live/api";
|
|
26
28
|
var API_TIMEOUT = parseInt(process.env.SKILLHUB_API_TIMEOUT || "30000");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
function httpsRequest(url, options = {}) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const parsedUrl = new URL(url);
|
|
32
|
+
const isHttps = parsedUrl.protocol === "https:";
|
|
33
|
+
const lib = isHttps ? https : http;
|
|
34
|
+
const reqOptions = {
|
|
35
|
+
hostname: parsedUrl.hostname,
|
|
36
|
+
port: parsedUrl.port || (isHttps ? 443 : 80),
|
|
37
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
38
|
+
method: options.method || "GET",
|
|
39
|
+
headers: {
|
|
40
|
+
"User-Agent": "skillhub-cli",
|
|
41
|
+
"Accept": "application/json",
|
|
42
|
+
...options.headers
|
|
43
|
+
},
|
|
44
|
+
timeout: API_TIMEOUT
|
|
45
|
+
};
|
|
46
|
+
const req = lib.request(reqOptions, (res) => {
|
|
47
|
+
const chunks = [];
|
|
48
|
+
let resolved = false;
|
|
49
|
+
const tryResolve = () => {
|
|
50
|
+
if (resolved) return;
|
|
51
|
+
const data = Buffer.concat(chunks).toString();
|
|
52
|
+
if (data.startsWith("{") || data.startsWith("[")) {
|
|
53
|
+
try {
|
|
54
|
+
JSON.parse(data);
|
|
55
|
+
resolved = true;
|
|
56
|
+
res.destroy();
|
|
57
|
+
resolve({
|
|
58
|
+
statusCode: res.statusCode || 0,
|
|
59
|
+
data
|
|
60
|
+
});
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
res.on("data", (chunk) => {
|
|
66
|
+
chunks.push(chunk);
|
|
67
|
+
tryResolve();
|
|
68
|
+
});
|
|
69
|
+
res.on("end", () => {
|
|
70
|
+
if (!resolved) {
|
|
71
|
+
resolve({
|
|
72
|
+
statusCode: res.statusCode || 0,
|
|
73
|
+
data: Buffer.concat(chunks).toString()
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
res.setTimeout(API_TIMEOUT, () => {
|
|
78
|
+
if (!resolved) {
|
|
79
|
+
res.destroy();
|
|
80
|
+
reject(new Error(`Response timeout after ${API_TIMEOUT / 1e3}s`));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
36
83
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
84
|
+
req.on("error", (err) => {
|
|
85
|
+
if (err.code === "ERR_STREAM_DESTROYED") return;
|
|
86
|
+
reject(new Error(`Network error: ${err.message}`));
|
|
87
|
+
});
|
|
88
|
+
req.on("timeout", () => {
|
|
89
|
+
req.destroy();
|
|
90
|
+
reject(new Error(`Request timeout after ${API_TIMEOUT / 1e3}s`));
|
|
91
|
+
});
|
|
92
|
+
if (options.body) {
|
|
93
|
+
req.write(options.body);
|
|
41
94
|
}
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
clearTimeout(timeoutId);
|
|
45
|
-
}
|
|
95
|
+
req.end();
|
|
96
|
+
});
|
|
46
97
|
}
|
|
47
98
|
async function searchSkills(query, options = {}) {
|
|
48
99
|
const params = new URLSearchParams({
|
|
@@ -53,27 +104,25 @@ async function searchSkills(query, options = {}) {
|
|
|
53
104
|
if (options.platform) {
|
|
54
105
|
params.set("platform", options.platform);
|
|
55
106
|
}
|
|
56
|
-
const response = await
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
throw new Error(`API error ${response.status}: ${text || response.statusText}`);
|
|
107
|
+
const response = await httpsRequest(`${API_BASE_URL}/skills?${params}`);
|
|
108
|
+
if (response.statusCode !== 200) {
|
|
109
|
+
throw new Error(`API error ${response.statusCode}: ${response.data || "Unknown error"}`);
|
|
60
110
|
}
|
|
61
|
-
return response.
|
|
111
|
+
return JSON.parse(response.data);
|
|
62
112
|
}
|
|
63
113
|
async function getSkill(id) {
|
|
64
|
-
const response = await
|
|
65
|
-
if (response.
|
|
114
|
+
const response = await httpsRequest(`${API_BASE_URL}/skills/${encodeURIComponent(id)}`);
|
|
115
|
+
if (response.statusCode === 404) {
|
|
66
116
|
return null;
|
|
67
117
|
}
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
throw new Error(`API error ${response.status}: ${text || response.statusText}`);
|
|
118
|
+
if (response.statusCode !== 200) {
|
|
119
|
+
throw new Error(`API error ${response.statusCode}: ${response.data || "Unknown error"}`);
|
|
71
120
|
}
|
|
72
|
-
return response.
|
|
121
|
+
return JSON.parse(response.data);
|
|
73
122
|
}
|
|
74
123
|
async function trackInstall(skillId, platform, method = "cli") {
|
|
75
124
|
try {
|
|
76
|
-
await
|
|
125
|
+
await httpsRequest(`${API_BASE_URL}/skills/${encodeURIComponent(skillId)}/install`, {
|
|
77
126
|
method: "POST",
|
|
78
127
|
headers: { "Content-Type": "application/json" },
|
|
79
128
|
body: JSON.stringify({ platform, method })
|
package/package.json
CHANGED