@avcodes/skilled 0.1.0
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/bin/skilled +3 -0
- package/install.js +114 -0
- package/package.json +41 -0
package/bin/skilled
ADDED
package/install.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const https = require("https");
|
|
7
|
+
const { execSync } = require("child_process");
|
|
8
|
+
const { promisify } = require("util");
|
|
9
|
+
const { pipeline } = require("stream");
|
|
10
|
+
|
|
11
|
+
const pipelineAsync = promisify(pipeline);
|
|
12
|
+
|
|
13
|
+
const REPO = "av/skilled";
|
|
14
|
+
const BINARY = "skilled";
|
|
15
|
+
const VERSION = require("./package.json").version;
|
|
16
|
+
|
|
17
|
+
const PLATFORM_MAP = {
|
|
18
|
+
darwin: "darwin",
|
|
19
|
+
linux: "linux",
|
|
20
|
+
win32: "windows",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const ARCH_MAP = {
|
|
24
|
+
x64: "amd64",
|
|
25
|
+
arm64: "arm64",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function getPlatformArtifact() {
|
|
29
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
30
|
+
const arch = ARCH_MAP[process.arch];
|
|
31
|
+
|
|
32
|
+
if (!platform) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Unsupported platform: ${process.platform}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!arch) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Unsupported architecture: ${process.arch}. Supported: ${Object.keys(ARCH_MAP).join(", ")}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const artifact = `${BINARY}-${platform}-${arch}`;
|
|
45
|
+
const ext = platform === "windows" ? "zip" : "tar.gz";
|
|
46
|
+
return { artifact, ext, platform };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function followRedirects(url) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
https
|
|
52
|
+
.get(url, { headers: { "User-Agent": "skilled-npm" } }, (res) => {
|
|
53
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
54
|
+
followRedirects(res.headers.location).then(resolve, reject);
|
|
55
|
+
} else if (res.statusCode === 200) {
|
|
56
|
+
resolve(res);
|
|
57
|
+
} else {
|
|
58
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.on("error", reject);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function downloadAndExtract(url, destDir, platform) {
|
|
66
|
+
const res = await followRedirects(url);
|
|
67
|
+
|
|
68
|
+
if (platform === "windows") {
|
|
69
|
+
const zipPath = path.join(destDir, "download.zip");
|
|
70
|
+
const fileStream = fs.createWriteStream(zipPath);
|
|
71
|
+
await pipelineAsync(res, fileStream);
|
|
72
|
+
execSync(`tar -xf "${zipPath}" -C "${destDir}"`);
|
|
73
|
+
fs.unlinkSync(zipPath);
|
|
74
|
+
} else {
|
|
75
|
+
const tarPath = path.join(destDir, "download.tar.gz");
|
|
76
|
+
const fileStream = fs.createWriteStream(tarPath);
|
|
77
|
+
await pipelineAsync(res, fileStream);
|
|
78
|
+
execSync(`tar xzf "${tarPath}" -C "${destDir}"`);
|
|
79
|
+
fs.unlinkSync(tarPath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function main() {
|
|
84
|
+
const binDir = path.join(__dirname, "bin");
|
|
85
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
86
|
+
|
|
87
|
+
const { artifact, ext, platform } = getPlatformArtifact();
|
|
88
|
+
const tag = `v${VERSION}`;
|
|
89
|
+
const url = `https://github.com/${REPO}/releases/download/${tag}/${artifact}.${ext}`;
|
|
90
|
+
|
|
91
|
+
console.log(`Downloading ${BINARY} ${tag} for ${process.platform}-${process.arch}...`);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
await downloadAndExtract(url, binDir, platform);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error(`Failed to download ${BINARY}: ${err.message}`);
|
|
97
|
+
console.error(`URL: ${url}`);
|
|
98
|
+
console.error(
|
|
99
|
+
"You can install manually: https://github.com/av/skilled#installation"
|
|
100
|
+
);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const binaryName = platform === "windows" ? `${BINARY}.exe` : BINARY;
|
|
105
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
106
|
+
|
|
107
|
+
if (platform !== "windows") {
|
|
108
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log(`Successfully installed ${BINARY} to ${binaryPath}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@avcodes/skilled",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TUI dashboard for skill usage stats across AI coding tools",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/av/skilled.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/av/skilled",
|
|
11
|
+
"bin": {
|
|
12
|
+
"skilled": "bin/skilled"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"postinstall": "node install.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"install.js",
|
|
19
|
+
"bin/"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"skilled",
|
|
23
|
+
"tui",
|
|
24
|
+
"cli",
|
|
25
|
+
"coding-agents",
|
|
26
|
+
"skill-usage",
|
|
27
|
+
"dashboard"
|
|
28
|
+
],
|
|
29
|
+
"os": [
|
|
30
|
+
"darwin",
|
|
31
|
+
"linux",
|
|
32
|
+
"win32"
|
|
33
|
+
],
|
|
34
|
+
"cpu": [
|
|
35
|
+
"x64",
|
|
36
|
+
"arm64"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=14"
|
|
40
|
+
}
|
|
41
|
+
}
|