Skip to content

Commit 6e88b65

Browse files
committed
npm package
1 parent 34c886c commit 6e88b65

File tree

9 files changed

+6770
-7
lines changed

9 files changed

+6770
-7
lines changed

.github/scripts/string-replace.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
4+
let cwd = process.cwd();
5+
let [, , target, from, to] = process.argv;
6+
7+
if (!path.isAbsolute(target)) {
8+
target = path.join(cwd, target);
9+
}
10+
11+
const original = fs.readFileSync(target, "utf8");
12+
const update = original.replaceAll(from, to);
13+
fs.writeFileSync(target, update, "utf8");

.github/workflows/release.yaml

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ env:
1818
JUST_VERSION: "1.36.0"
1919

2020
jobs:
21+
vars:
22+
name: "📋 Generate Variables"
23+
runs-on: ubuntu-24.04
24+
outputs:
25+
NPM_VER: ${{ steps.tag.outputs.NPM_VER }}
26+
GH_TAG: ${{ steps.tag.outputs.GH_TAG }}
27+
steps:
28+
- run: eval $(curl -sSf sh.davidalsh.com/nodejs.sh | sh)
29+
- id: tag
30+
run: |
31+
declare -i var=$(npm info http-server-rs version | cut -d "." -f 3)
32+
var=$var+1
33+
NPM_VER="0.0.$var"
34+
35+
GH_TAG="$(date -u +"v%Y.%m.%d.%H%M").${GITHUB_SHA::4}"
36+
37+
echo NPM_VER: $NPM_VER
38+
echo GH_TAG:$GH_TAG
39+
echo "NPM_VER=$NPM_VER" >> "$GITHUB_OUTPUT"
40+
echo "GH_TAG=$GH_TAG" >> "$GITHUB_OUTPUT"
41+
2142
test:
2243
name: 🧪 Test
2344
runs-on: ubuntu-24.04
@@ -106,6 +127,7 @@ jobs:
106127
name: "🔄 Publish Github Release"
107128
runs-on: ubuntu-24.04
108129
needs:
130+
- vars
109131
- test
110132
- format
111133
- lint
@@ -116,22 +138,48 @@ jobs:
116138
with: { path: artifacts }
117139
- name: Publish` Github Release
118140
env:
141+
GH_TAG: ${{needs.vars.outputs.GH_TAG}}
119142
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
120143
run: |
121144
set -e
122145
123-
TAG="$(date -u +"v%Y.%m.%d.%H%M").${GITHUB_SHA::4}"
124-
echo "Tag: ${TAG}"
146+
echo "Tag: ${GH_TAG}"
125147
126-
gh release create $TAG --draft --notes "Automatically built binaries"
127-
gh release edit $TAG --title "🚀 Latest"
148+
gh release create $GH_TAG --draft --notes "Automatically built binaries"
149+
gh release edit $GH_TAG --title "🚀 Latest"
128150
129151
cd artifacts
130152
131153
for name in *; do
132154
cd "${{ github.workspace }}/artifacts/${name}/release"
133155
tar -czvf ./${name}.tar.gz ./*
134-
gh release upload $TAG ${name}.tar.gz
156+
gh release upload $GH_TAG ${name}.tar.gz
135157
done
136158
137-
gh release edit $TAG --draft=false
159+
gh release edit $GH_TAG --draft=false
160+
161+
publish-npm-package:
162+
name: "🔄 Publish NPM Package"
163+
runs-on: ubuntu-24.04
164+
needs:
165+
- vars
166+
- test
167+
- format
168+
- lint
169+
- build
170+
steps:
171+
- uses: actions/checkout@v4
172+
- run: eval $(curl -sSf sh.davidalsh.com/nodejs.sh | sh)
173+
- env:
174+
GH_TAG: ${{needs.vars.outputs.GH_TAG}}
175+
NPM_VER: ${{needs.vars.outputs.NPM_VER}}
176+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
177+
run: |
178+
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> $HOME/.npmrc
179+
echo "GH_TAG: ${GH_TAG}"
180+
echo "NPM_VER: ${NPM_VER}"
181+
node .github/scripts/string-replace.mjs ./npm/package.json "0.0.0-local" "$NPM_VER"
182+
cp ./README.md ./npm/README.md
183+
cd npm
184+
echo "$GH_TAG" > tag
185+
npm publish --access=public

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
/target
2-
package.json
32
package-lock.json
43
/node_modules

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22.16.0

npm/http-server.exe

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
This is a placeholder file required because npm will only create
2+
a symlink to a `package.json#bin` entry if the file exists.
3+
4+
This file is replaced in a postinstall step with the actual binary
5+
downloaded from GitHub releases.
6+
7+
This file has an .exe extension for Windows compatibility because
8+
Windows requires a file extension to know a file is executable.
9+
10+
Linux and MacOS will be able to run the file as a normal binary
11+
regardless of the extension being present.

npm/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "http-server-rs",
3+
"version": "0.0.0-local",
4+
"bin": {
5+
"http-server-rs": "./http-server.exe"
6+
},
7+
"scripts": {
8+
"postinstall": "node ./postinstall.mjs"
9+
}
10+
}

npm/postinstall.mjs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import * as process from "node:process";
2+
import * as fs from "node:fs";
3+
import * as path from "node:path";
4+
import * as url from "node:url";
5+
import * as stream from "node:stream";
6+
import * as tar from "./tar.cjs";
7+
8+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
9+
const __bin = path.join(__dirname, "http-server.exe");
10+
const __bin_unix = path.join(__dirname, "http-server");
11+
12+
const HTTP_SERVER_RS_BIN_PATH = process.env.HTTP_SERVER_RS_BIN_PATH;
13+
const HTTP_SERVER_RS_SKIP_DOWNLOAD = process.env.HTTP_SERVER_RS_SKIP_DOWNLOAD;
14+
const HTTP_SERVER_RS_FORCE_TAG = process.env.HTTP_SERVER_RS_FORCE_TAG;
15+
16+
const os = {
17+
darwin: "macos",
18+
linux: "linux",
19+
win32: "windows",
20+
}[process.platform];
21+
22+
const arch = {
23+
arm64: "arm64",
24+
x64: "amd64",
25+
}[process.arch];
26+
27+
void (async function main() {
28+
if (HTTP_SERVER_RS_SKIP_DOWNLOAD === "true") {
29+
// Do nothing
30+
} else if (
31+
HTTP_SERVER_RS_BIN_PATH &&
32+
fs.existsSync(HTTP_SERVER_RS_BIN_PATH)
33+
) {
34+
await fs.promises.rm(__bin, { recursive: true, force: true });
35+
await fs.promises.symlink(__bin, HTTP_SERVER_RS_BIN_PATH);
36+
} else {
37+
await downloadBin();
38+
}
39+
})();
40+
41+
async function downloadBin() {
42+
if (!arch || !os) {
43+
throw new Error(
44+
"Unable to determine what Atlaspack Version Manager binary to download"
45+
);
46+
}
47+
48+
let tag = HTTP_SERVER_RS_FORCE_TAG || "latest";
49+
if (fs.existsSync(path.join(__dirname, "tag"))) {
50+
tag = (
51+
await fs.promises.readFile(path.join(__dirname, "tag"), "utf8")
52+
).trim();
53+
}
54+
55+
let url = `https://github.com/alshdavid/http-server-rs/releases/latest/download/http-server-${os}-${arch}.tar.gz`;
56+
if (tag !== "latest") {
57+
url = `https://github.com/alshdavid/http-server-rs/releases/download/${tag}/http-server-${os}-${arch}.tar.gz`;
58+
}
59+
60+
const response = await globalThis.fetch(url);
61+
if (!response.ok) {
62+
throw new Error("Unable to fetch http-server-rs binary");
63+
}
64+
65+
const body = await response.bytes();
66+
const file = new stream.Duplex();
67+
68+
file.push(body);
69+
file.push(null);
70+
71+
if (fs.existsSync(__bin)) {
72+
fs.rmSync(__bin, { recursive: true, force: true });
73+
}
74+
75+
let writable = tar.x({
76+
C: __dirname,
77+
chmod: true,
78+
});
79+
80+
file.pipe(writable);
81+
await new Promise((res) => writable.on("close", res));
82+
83+
await fs.promises.rm(__bin, { recursive: true, force: true });
84+
if (fs.existsSync(__bin_unix)) {
85+
await fs.promises.rename(__bin_unix, __bin);
86+
}
87+
await fs.promises.chmod(__bin, "755");
88+
}

npm/tag

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
latest

0 commit comments

Comments
 (0)