Skip to content

Commit c580766

Browse files
authored
feat!: modernize to TypeScript, plain Node http, and pnpm (Node 24+) (#119)
## Breaking changes - **Node.js 24 or newer is required** (tested on Node 24 and 26; release runs on 26) - **License changed from AGPL-3.0 to MIT** - **`express` app replaced with a minimal router**: the module no longer returns an express app. `createServer()` now takes named options (`domain`, `certPath`, `reinstall`) and exposes `get`, `listen`, `redirect`, `serve` - **Dual ESM/CJS build**: published package ships `dist/` (ESM + CJS + types) instead of raw source - **Production mode removed**: HTTP/2 (`spdy`), compression, minify, and the packaged-binary update checker are gone — this is a development tool - **pnpm** replaces npm for development and CI ## What changed - **Migrated the whole project to TypeScript** (`strict`, type-aware linting) - **Replaced `express` and `cors` with plain `node:http` handlers**: static serving (ETag, Last-Modified, range requests, 404 fallback, directory redirect, MIME types via `mrmime`), request routing, and CORS headers now live in small dedicated modules; dependencies reduced to `mrmime` and `zod` - **Validated CLI configuration**: flags via `parseArgs` (`-p`, `-H`, `--cert-path`, `--reinstall`) layered over environment variables, parsed with `zod` - **Security hardening** (resolves all open CodeQL alerts): - `execFile` instead of shell string concatenation for mkcert invocations - path traversal protection and sanitized directory redirects in the static handler - rejection of protocol-relative and absolute-form request targets - tests trust the mkcert root CA instead of disabling certificate validation - **mkcert upgraded to v1.4.4**; download is skipped when the binary already exists, and the download stream is closed cleanly - **Toolchain**: `oxlint` + `oxfmt` + `knip` replace ESLint; native `node:test` runner with tests split by source module; internalized `appdata-path` - **CI**: test matrix on Node 24/26 across Ubuntu/macOS, explicit workflow permissions, SHA-pinned actions, concurrency cancellation, lint step in CI; Coveralls and stale-bot message config updated - **New `CONTRIBUTING.md`** with the local gate commands ## Verification - All CI checks green (CodeQL, tests on 24/26 × Ubuntu/macOS) - Locally: `pnpm run lint` and `pnpm test` (33/33) pass on Node 24
1 parent dd59376 commit c580766

42 files changed

Lines changed: 3199 additions & 5595 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.eslintrc.json‎

Lines changed: 0 additions & 22 deletions
This file was deleted.

‎.github/workflows/release.yml‎

Lines changed: 23 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -23,83 +23,38 @@ jobs:
2323
runs-on: ubuntu-latest
2424
steps:
2525
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26+
- uses: pnpm/action-setup@d9184bf108216479bc5a137cc391f4d7b14c870b # v6.1.0
27+
with:
28+
version: 12.3.4
2629
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
2730
with:
28-
node-version: 24
31+
node-version: 26
2932
registry-url: https://registry.npmjs.org/
30-
package-manager-cache: false
33+
cache: pnpm
3134

32-
- name: Setup git
35+
- name: Bump and push version
3336
if: inputs.upgrade != 'existing'
3437
run: |-
3538
git config --global user.name "github-actions[bot]"
3639
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
40+
pnpm version ${{ inputs.upgrade }} -m "chore: release %s"
41+
git push --follow-tags
3742
38-
- name: Bump version
39-
if: inputs.upgrade != 'existing'
40-
run: npm version ${{ inputs.upgrade }}
41-
42-
- name: Push version
43-
if: inputs.upgrade != 'existing'
44-
run: |-
45-
git push
46-
git push --tags
47-
48-
- run: npm publish
43+
- run: pnpm publish
4944

50-
- name: Prepare build
51-
run: npm i -g pkg
52-
53-
- name: Build
54-
run: pkg --out-path build .
55-
56-
- name: Get version and package name
57-
id: get_info
45+
- name: Build and create release
46+
env:
47+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5848
run: |-
59-
version=$(node -p "require('./package.json').version")
60-
echo $version
61-
echo "::set-output name=version::$version"
6249
name=$(node -p "require('./package.json').name")
63-
echo $name
64-
echo "::set-output name=name::$name"
65-
66-
- name: Create Release
67-
id: create_release
68-
uses: actions/create-release@v1
69-
env:
70-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71-
with:
72-
tag_name: v${{ steps.get_info.outputs.version }}
73-
release_name: Release v${{ steps.get_info.outputs.version }}
74-
draft: false
75-
prerelease: false
76-
77-
- name: Upload Linux Binary
78-
uses: actions/upload-release-asset@v1
79-
env:
80-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
81-
with:
82-
upload_url: ${{ steps.create_release.outputs.upload_url }}
83-
asset_path: ./build/${{ steps.get_info.outputs.name }}-linux
84-
asset_name: ${{ steps.get_info.outputs.name }}-linux
85-
asset_content_type: application/x-executable
86-
87-
- name: Upload MacOS Binary
88-
uses: actions/upload-release-asset@v1
89-
env:
90-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
91-
with:
92-
upload_url: ${{ steps.create_release.outputs.upload_url }}
93-
asset_path: ./build/${{ steps.get_info.outputs.name }}-macos
94-
asset_name: ${{ steps.get_info.outputs.name }}-macos
95-
asset_content_type: application/x-mach-binary
96-
97-
- name: Upload Windows Binary
98-
uses: actions/upload-release-asset@v1
99-
env:
100-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
101-
with:
102-
upload_url: ${{ steps.create_release.outputs.upload_url }}
103-
asset_path: ./build/${{ steps.get_info.outputs.name }}-win.exe
104-
asset_name: ${{ steps.get_info.outputs.name }}-win.exe
105-
asset_content_type: application/x-dosexec
50+
version=$(node -p "require('./package.json').version")
51+
pnpm add --global pkg
52+
pnpm build
53+
pkg --out-path build dist/index.js
54+
55+
gh release create "v$version" \
56+
--title "Release v$version" \
57+
--notes "Release v$version" \
58+
"./build/$name-linux" \
59+
"./build/$name-macos" \
60+
"./build/$name-win.exe"

‎.github/workflows/stale.yml‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
name: "Stale"
22
on:
33
schedule:
4-
- cron: "0 0 * * *"
4+
- cron: "0 0 * * *"
5+
6+
permissions:
7+
contents: write
8+
issues: write
9+
pull-requests: write
510

611
jobs:
712
stale:
813
runs-on: ubuntu-latest
914
steps:
10-
- uses: actions/stale@v3
11-
with:
12-
repo-token: ${{ secrets.GITHUB_TOKEN }}
13-
stale-issue-message: "Marked as stale for no activity in the past 60 days. In 7 days it will be closed unless new activity."
14-
stale-pr-message: "Marked as stale for no activity in the past 60 days. In 7 days it will be closed unless new activity."
15-
exempt-issue-labels: "no-stale"
16-
exempt-pr-labels: "no-stale"
15+
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
16+
with:
17+
delete-branch: true

‎.github/workflows/test.yml‎

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,37 @@
11
name: Test
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
branches: [master, main]
6+
pull_request:
7+
8+
concurrency:
9+
group: test-${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
permissions:
13+
contents: read
414

515
jobs:
616
test:
717
name: Test
818
runs-on: ${{ matrix.os }}
919

1020
strategy:
21+
fail-fast: false
1122
matrix:
1223
os: [ubuntu-latest, macOS-latest]
13-
node: [18, 20]
24+
node: [24, 26]
1425

1526
steps:
1627
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17-
- name: Use Node.js ${{matrix.node}}
18-
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
28+
- uses: pnpm/action-setup@d9184bf108216479bc5a137cc391f4d7b14c870b # v6.1.0
1929
with:
20-
node-version: ${{ matrix.node }}
21-
- name: npm install and test
22-
run: |
23-
npm install
24-
npm test
25-
env:
26-
CI: true
27-
28-
coverage:
29-
name: Coverage (Coveralls)
30-
needs: test
31-
runs-on: ubuntu-latest
32-
steps:
33-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30+
version: 12.3.4
3431
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
3532
with:
36-
node-version: 20
37-
- run: |
38-
npm install
39-
npm test
40-
env:
41-
CI: true
42-
- name: Coveralls
43-
if: success()
44-
uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2.3.8
45-
with:
46-
github-token: ${{secrets.GITHUB_TOKEN}}
33+
node-version: ${{ matrix.node }}
34+
cache: pnpm
35+
- run: pnpm install --frozen-lockfile
36+
- run: pnpm run lint
37+
- run: pnpm test

‎.gitignore‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# MacOS
22
.DS_STORE
33

4-
# Node, npm & CI
4+
# Node
55
node_modules
6-
coverage
7-
.nyc_output
6+
build
7+
dist
8+
*.tsbuildinfo
89

9-
# Build
10-
build
10+
# Test-generated certificate directories
11+
test/custom-folder/
12+
test/custom\ folder/

‎.oxfmtrc.json‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "./node_modules/oxfmt/configuration_schema.json",
3+
"arrowParens": "avoid",
4+
"semi": false,
5+
"sortImports": true,
6+
"ignorePatterns": ["dist/**", "node_modules/**", "pnpm-lock.yaml"]
7+
}

‎CONTRIBUTING.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Contributing
2+
3+
Thanks for reading this document!
4+
5+
Contributions are welcome, but I have little time to invest in this project. I ask you to test the change extensively to make my review as easier and possible, and I apologize in advance if it will take me some time to review it.
6+
7+
## Helpful commands
8+
9+
```sh
10+
# install dependencies
11+
pnpm install
12+
13+
# type checking and style fixes
14+
pnpm lint
15+
16+
# run tests
17+
pnpm test
18+
```

0 commit comments

Comments
 (0)