sharelocal.dev 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/README.md +14 -0
- package/bin/sharelocal +17 -0
- package/package.json +26 -0
- package/scripts/platform.js +23 -0
- package/scripts/postinstall.js +108 -0
- package/scripts/selftest.js +26 -0
package/README.md
ADDED
package/bin/sharelocal
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawnSync } = require("node:child_process");
|
|
3
|
+
const { platformBinaryName, vendorBinaryPath } = require("../scripts/platform");
|
|
4
|
+
|
|
5
|
+
function main() {
|
|
6
|
+
const binPath = vendorBinaryPath();
|
|
7
|
+
const res = spawnSync(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
8
|
+
if (res.error) {
|
|
9
|
+
const expected = platformBinaryName();
|
|
10
|
+
console.error(`sharelocal: missing binary (${expected}). Reinstall the package.`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
process.exit(res.status ?? 1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
main();
|
|
17
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sharelocal.dev",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "sharelocal: expose localhost via https://on.sharelocal.dev",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/irava/sharelocal.dev"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"sharelocal": "bin/sharelocal"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin/",
|
|
15
|
+
"scripts/",
|
|
16
|
+
"vendor/",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"postinstall": "node ./scripts/postinstall.js",
|
|
21
|
+
"test": "node ./scripts/selftest.js"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const path = require("node:path");
|
|
2
|
+
|
|
3
|
+
function platformBinaryName(platform = process.platform, arch = process.arch) {
|
|
4
|
+
const isWindows = platform === "win32";
|
|
5
|
+
|
|
6
|
+
if (platform === "darwin" && arch === "arm64") return "sharelocal-darwin-arm64";
|
|
7
|
+
if (platform === "darwin" && arch === "x64") return "sharelocal-darwin-amd64";
|
|
8
|
+
if (platform === "linux" && arch === "arm64") return "sharelocal-linux-arm64";
|
|
9
|
+
if (platform === "linux" && arch === "x64") return "sharelocal-linux-amd64";
|
|
10
|
+
if (platform === "win32" && arch === "x64") return "sharelocal-windows-amd64.exe";
|
|
11
|
+
|
|
12
|
+
const suffix = isWindows ? ".exe" : "";
|
|
13
|
+
throw new Error(`unsupported platform: ${platform}/${arch}${suffix}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function vendorBinaryPath(platform = process.platform) {
|
|
17
|
+
const isWindows = platform === "win32";
|
|
18
|
+
const filename = isWindows ? "sharelocal.exe" : "sharelocal";
|
|
19
|
+
return path.join(__dirname, "..", "vendor", filename);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { platformBinaryName, vendorBinaryPath };
|
|
23
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const { chmodSync } = require("node:fs");
|
|
4
|
+
const crypto = require("node:crypto");
|
|
5
|
+
const { platformBinaryName, vendorBinaryPath } = require("./platform");
|
|
6
|
+
|
|
7
|
+
const REPO_OWNER = "irava";
|
|
8
|
+
const REPO_NAME = "sharelocal.dev";
|
|
9
|
+
|
|
10
|
+
function readPackageJson() {
|
|
11
|
+
const pkgPath = path.join(__dirname, "..", "package.json");
|
|
12
|
+
return JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function pkgVersion(pkg) {
|
|
16
|
+
if (process.env.npm_package_version) {
|
|
17
|
+
return process.env.npm_package_version;
|
|
18
|
+
}
|
|
19
|
+
return pkg.version;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function assetURL(version, assetName) {
|
|
23
|
+
return `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/v${version}/${assetName}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function downloadToFile(url, destPath) {
|
|
27
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const arrayBuffer = await res.arrayBuffer();
|
|
33
|
+
const buf = Buffer.from(arrayBuffer);
|
|
34
|
+
if (buf.length === 0) {
|
|
35
|
+
throw new Error("downloaded file is empty");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
39
|
+
fs.writeFileSync(destPath, buf);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function downloadText(url) {
|
|
43
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
46
|
+
}
|
|
47
|
+
return await res.text();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function sha256FileHex(filePath) {
|
|
51
|
+
const hash = crypto.createHash("sha256");
|
|
52
|
+
hash.update(fs.readFileSync(filePath));
|
|
53
|
+
return hash.digest("hex");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function expectedSha256FromSums(contents, assetName) {
|
|
57
|
+
for (const line of contents.split("\n")) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
if (!trimmed) continue;
|
|
60
|
+
const parts = trimmed.split(/\s+/);
|
|
61
|
+
if (parts.length < 2) continue;
|
|
62
|
+
const [sum, name] = parts;
|
|
63
|
+
if (name === assetName) {
|
|
64
|
+
return sum.toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const pkg = readPackageJson();
|
|
72
|
+
const version = pkgVersion(pkg);
|
|
73
|
+
const assetName = platformBinaryName();
|
|
74
|
+
const url = assetURL(version, assetName);
|
|
75
|
+
|
|
76
|
+
const outPath = vendorBinaryPath();
|
|
77
|
+
const sumsURL = assetURL(version, "sha256sums.txt");
|
|
78
|
+
|
|
79
|
+
if (process.argv.includes("--dry-run")) {
|
|
80
|
+
process.stdout.write(`${url}\n${outPath}\n${sumsURL}\n`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
await downloadToFile(url, outPath);
|
|
86
|
+
|
|
87
|
+
const sums = await downloadText(sumsURL);
|
|
88
|
+
const expected = expectedSha256FromSums(sums, assetName);
|
|
89
|
+
if (expected) {
|
|
90
|
+
const actual = sha256FileHex(outPath);
|
|
91
|
+
if (actual !== expected) {
|
|
92
|
+
throw new Error(`checksum mismatch for ${assetName}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
const message = err && err.message ? err.message : String(err);
|
|
97
|
+
process.stderr.write(`sharelocal: ${message}\n`);
|
|
98
|
+
process.stderr.write(`sharelocal: failed to download ${assetName}\n`);
|
|
99
|
+
process.stderr.write(`sharelocal: url: ${url}\n`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (process.platform !== "win32") {
|
|
104
|
+
chmodSync(outPath, 0o755);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const assert = require("node:assert");
|
|
2
|
+
const { spawnSync } = require("node:child_process");
|
|
3
|
+
const { platformBinaryName, vendorBinaryPath } = require("./platform");
|
|
4
|
+
|
|
5
|
+
function main() {
|
|
6
|
+
assert.ok(vendorBinaryPath().includes("vendor"));
|
|
7
|
+
platformBinaryName("darwin", "arm64");
|
|
8
|
+
platformBinaryName("darwin", "x64");
|
|
9
|
+
platformBinaryName("linux", "arm64");
|
|
10
|
+
platformBinaryName("linux", "x64");
|
|
11
|
+
platformBinaryName("win32", "x64");
|
|
12
|
+
|
|
13
|
+
const dryRun = spawnSync(process.execPath, [require.resolve("./postinstall"), "--dry-run"], {
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
15
|
+
encoding: "utf8"
|
|
16
|
+
});
|
|
17
|
+
assert.strictEqual(dryRun.status, 0);
|
|
18
|
+
const out = dryRun.stdout.trim().split("\n");
|
|
19
|
+
assert.ok(out[0].includes("/releases/download/v"));
|
|
20
|
+
assert.ok(out[0].endsWith(platformBinaryName()));
|
|
21
|
+
assert.ok(out[1].endsWith(vendorBinaryPath()));
|
|
22
|
+
assert.ok(out[2].endsWith("/sha256sums.txt"));
|
|
23
|
+
console.log("ok");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main();
|