Skip to content

Commit b64af0b

Browse files
authored
feat: v1 (#1)
1 parent 3f297dc commit b64af0b

11 files changed

Lines changed: 370 additions & 48 deletions

File tree

.github/dependabot.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "monthly"
7+
open-pull-requests-limit: 10
8+
9+
- package-ecosystem: "npm"
10+
directory: "/"
11+
schedule:
12+
interval: "weekly"
13+
open-pull-requests-limit: 10

.github/workflows/ci.yml

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,75 @@
1-
name: CI
21
on:
32
push:
4-
branches: ['master']
3+
branches:
4+
- main
5+
- 'v*'
56
pull_request:
6-
branches: ['*']
7+
paths-ignore:
8+
- LICENSE
9+
- '*.md'
10+
11+
name: CI
12+
713
jobs:
8-
test:
14+
lint:
15+
permissions:
16+
contents: read
17+
name: Lint
918
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
21+
- name: Install Node.js
22+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
23+
with:
24+
node-version: v24.x
25+
cache: 'npm'
26+
cache-dependency-path: package.json
27+
28+
- name: Install dependencies
29+
run: npm install
30+
- name: Check linting
31+
run: npm run lint:ci
32+
33+
tests:
34+
permissions:
35+
contents: read
36+
name: Tests
1037
strategy:
38+
fail-fast: false
1139
matrix:
12-
node-version: [18, 17, 16, 14]
40+
os: [ubuntu-latest, macos-latest, windows-latest]
41+
node-version: [20, 22, 24]
42+
runs-on: ${{matrix.os}}
1343
steps:
14-
- uses: actions/checkout@v2
15-
- uses: actions/setup-node@v1
44+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
45+
with:
46+
persist-credentials: false
47+
48+
- name: Use Node.js ${{ matrix.node-version }}
49+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
1650
with:
1751
node-version: ${{ matrix.node-version }}
18-
- run: npm install
19-
- run: npm test
52+
cache: 'npm'
53+
cache-dependency-path: package.json
54+
55+
- name: Install Dependencies
56+
run: npm install
57+
58+
- name: Run Tests
59+
# TODO: extend to test:ci
60+
run: npm run test
61+
62+
automerge:
63+
if: >
64+
github.event_name == 'pull_request' && github.event.pull_request.user.login == 'dependabot[bot]'
65+
needs:
66+
- tests
67+
runs-on: ubuntu-latest
68+
permissions:
69+
contents: write
70+
pull-requests: write
71+
steps:
72+
- name: Merge Dependabot PR
73+
uses: fastify/github-action-merge-dependabot@e820d631adb1d8ab16c3b93e5afe713450884a4a # v3.11.1
74+
with:
75+
github-token: ${{ secrets.GITHUB_TOKEN }}

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

index.d.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/// <reference types="node" />
2+
import { SelfsignedOptions, CertificateField } from 'selfsigned';
3+
4+
type CertificateAttribute = CertificateField;
5+
6+
type HttpsPEMGenerateOpts = {
7+
attr?: CertificateAttribute[];
8+
opts?: SelfsignedOptions;
9+
};
10+
type HttpsPEMGenerateResult = {
11+
key: string;
12+
cert: string;
13+
};
14+
15+
type HttpsPEM = {
16+
key: string | null;
17+
cert: string | null;
18+
generate(config?: HttpsPEMGenerateOpts): Promise<HttpsPEMGenerateResult>;
19+
generate(
20+
config: HttpsPEMGenerateOpts | null,
21+
done: (err: Error | null, result: HttpsPEMGenerateResult) => void
22+
): void;
23+
};
24+
25+
export default HttpsPEM;
26+
export declare const key: HttpsPEM['key'];
27+
export declare const cert: HttpsPEM['cert'];
28+
export declare const generate: HttpsPEM['generate'];
29+
30+
export {
31+
SelfsignedOptions,
32+
CertificateAttribute,
33+
HttpsPEMGenerateResult,
34+
HttpsPEMGenerateOpts,
35+
};

index.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
'use strict'
22

3-
const path = require('path')
4-
const fs = require('fs')
3+
const path = require('node:path')
4+
const fs = require('node:fs')
55

6-
exports.key = fs.readFileSync(path.join(__dirname, 'key.pem'))
7-
exports.cert = fs.readFileSync(path.join(__dirname, 'cert.pem'))
6+
let selfsigned
7+
const keyPath = path.join(__dirname, 'key.pem')
8+
const certPath = path.join(__dirname, 'cert.pem')
9+
10+
// In case npm scripts are disabled, we still want to provide the key and cert
11+
exports.key = fs.existsSync(keyPath) ? fs.readFileSync(keyPath) : null
12+
exports.cert = fs.existsSync(certPath) ? fs.readFileSync(certPath) : null
13+
exports.generate = generate
14+
exports.default = exports
15+
16+
function generate ({ attr, opts } = { attr: [], opts: null }, done) {
17+
if (done == null) {
18+
const promise = new Promise((resolve, reject) => {
19+
generate({ attr, opts }, (err, pems) => {
20+
if (err) return reject(err)
21+
resolve({ key: pems.private, cert: pems.cert })
22+
})
23+
})
24+
25+
return promise
26+
}
27+
28+
if (!selfsigned) selfsigned = require('selfsigned')
29+
30+
selfsigned.generate(attr, opts, done)
31+
}

install.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
'use strict'
22

3-
const fs = require('fs')
4-
const path = require('path')
3+
const fs = require('node:fs')
4+
const path = require('node:path')
55
const selfsigned = require('selfsigned')
66

7-
const pems = selfsigned.generate()
7+
const nodeVersion = Number(process.versions.node.split('.')[0])
8+
const pems =
9+
// Due to new version of openssl, we need to use a larger key size
10+
// for node 24 and above, otherwise the default key size is sufficient
11+
nodeVersion > 22
12+
? selfsigned.generate({}, { keySize: 2048 })
13+
: selfsigned.generate()
814

915
fs.writeFileSync(path.join(__dirname, 'key.pem'), pems.private)
1016
fs.writeFileSync(path.join(__dirname, 'cert.pem'), pems.cert)

package.json

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
{
2-
"name": "https-pem",
3-
"version": "3.0.0",
4-
"description": "Self-signed PEM key and certificate ready for use in your HTTPS server",
2+
"name": "@metcoder95/https-pem",
3+
"version": "1.0.0",
4+
"description": "Self-signed PEM key and certificate ready for use in your HTTPS server (fork from https-pem)",
55
"main": "index.js",
6+
"types": "index.d.ts",
7+
"private": false,
68
"scripts": {
79
"postinstall": "node install.js",
8-
"test": "standard && node test.js"
10+
"clean": "rm -rf *.pem",
11+
"lint": "standard",
12+
"lint:ci": "standard | snazzy",
13+
"test": "node tests/index.js",
14+
"test:ts": "tsd"
915
},
1016
"repository": {
1117
"type": "git",
12-
"url": "git+https://github.com/watson/https-pem.git"
18+
"url": "git+https://github.com/metcoder95/https-pem.git"
19+
},
20+
"engines": {
21+
"node": ">=20"
1322
},
1423
"keywords": [
1524
"tls",
@@ -26,16 +35,37 @@
2635
"server"
2736
],
2837
"author": "Thomas Watson Steen <w@tson.dk> (https://twitter.com/wa7son)",
38+
"contributors": [
39+
{
40+
"name": "Carlos Fuentes",
41+
"email": "me@metcoder.dev",
42+
"url": "https://bsky.app/profile/metcoder.dev"
43+
}
44+
],
2945
"license": "MIT",
3046
"bugs": {
31-
"url": "https://github.com/watson/https-pem/issues"
47+
"url": "https://github.com/metcoder95/https-pem/issues"
3248
},
33-
"homepage": "https://github.com/watson/https-pem#readme",
49+
"homepage": "https://github.com/metcoder95/https-pem#readme",
3450
"dependencies": {
35-
"selfsigned": "^2.0.1"
51+
"selfsigned": "^3.0.1"
3652
},
3753
"devDependencies": {
38-
"standard": "^17.0.0"
54+
"@types/node": "^24.2.0",
55+
"snazzy": "^9.0.0",
56+
"standard": "^17.0.0",
57+
"tsd": "^0.33.0",
58+
"typescript": "^5.9.2",
59+
"undici": "^7.13.0"
60+
},
61+
"tsd": {
62+
"directory": "test"
63+
},
64+
"standard": {
65+
"ignore": [
66+
"*.d.ts",
67+
"*.test-d.ts"
68+
]
3969
},
4070
"coordinates": [
4171
55.7774667,

test.js

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

tests/index.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict'
2+
3+
const https = require('node:https')
4+
const { once } = require('node:events')
5+
const { test } = require('node:test')
6+
7+
const { Agent } = require('undici')
8+
9+
const client = new Agent({
10+
connect: {
11+
rejectUnauthorized: false
12+
}
13+
})
14+
15+
test('https-pem (default)', async t => {
16+
const pem = require('..')
17+
const server = https.createServer(pem, function (req, res) {
18+
res.end('foo')
19+
})
20+
21+
server.listen()
22+
await once(server, 'listening')
23+
t.after(() => server.close())
24+
25+
const response = await client.request({
26+
origin: `https://localhost:${server.address().port}`,
27+
path: '/',
28+
method: 'GET'
29+
})
30+
31+
t.plan(2)
32+
t.assert.strictEqual(response.statusCode, 200)
33+
t.assert.strictEqual(await response.body.text(), 'foo')
34+
})
35+
36+
test('https-pem (generate)', async t => {
37+
const pem = require('..')
38+
const pems = await pem.generate({
39+
attr: [{ name: 'commonName', value: 'localhost' }],
40+
opts: { keySize: 5120 }
41+
})
42+
43+
const server = https.createServer(pems, function (req, res) {
44+
res.end('foo')
45+
})
46+
47+
server.listen()
48+
await once(server, 'listening')
49+
t.after(() => server.close())
50+
51+
const response = await client.request({
52+
origin: `https://localhost:${server.address().port}`,
53+
path: '/',
54+
method: 'GET'
55+
})
56+
57+
t.plan(2)
58+
t.assert.strictEqual(response.statusCode, 200)
59+
t.assert.strictEqual(await response.body.text(), 'foo')
60+
})

tests/index.test-d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { expectAssignable } from 'tsd';
2+
3+
import {
4+
generate,
5+
key,
6+
cert,
7+
HttpsPEMGenerateResult,
8+
HttpsPEMGenerateOpts,
9+
} from '..';
10+
11+
expectAssignable<string | null>(key);
12+
expectAssignable<string | null>(cert);
13+
expectAssignable<Promise<HttpsPEMGenerateResult>>(generate({}));
14+
expectAssignable<void>(generate({}, () => {}));
15+
expectAssignable<void>(generate(null, () => {}));
16+
expectAssignable<HttpsPEMGenerateOpts>({
17+
attr: [{ name: 'hello', value: 'world' }],
18+
opts: { keySize: 1234 },
19+
});

0 commit comments

Comments
 (0)