certops 1.0.16 → 1.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/dist/commands/service/install.js +7 -1
- package/dist/version.js +13 -12
- package/package.json +6 -3
- package/scripts/postinstall.cjs +72 -0
- package/scripts/preuninstall.cjs +15 -0
|
@@ -7,7 +7,13 @@ import { domainHookPath, GLOBAL_HOOK } from '../../hooks.js';
|
|
|
7
7
|
import { BRAND } from '../../brand.js';
|
|
8
8
|
const UNIT_PATH = `/etc/systemd/system/${BRAND.serviceUnit}.service`;
|
|
9
9
|
const API_KEY_ENV = `${BRAND.envPrefix}_API_KEY`;
|
|
10
|
+
function resolveBinPath() {
|
|
11
|
+
// process.argv[1] is the actual path of the running certops script
|
|
12
|
+
return process.argv[1] ?? `/usr/local/bin/${BRAND.binName}`;
|
|
13
|
+
}
|
|
10
14
|
function buildUnitContent(apiKey) {
|
|
15
|
+
const binPath = resolveBinPath();
|
|
16
|
+
const nodePath = process.execPath;
|
|
11
17
|
return `\
|
|
12
18
|
[Unit]
|
|
13
19
|
Description=${BRAND.displayName} Certificate Monitor
|
|
@@ -17,7 +23,7 @@ Wants=network-online.target
|
|
|
17
23
|
[Service]
|
|
18
24
|
Type=simple
|
|
19
25
|
Environment=${API_KEY_ENV}=${apiKey}
|
|
20
|
-
ExecStart
|
|
26
|
+
ExecStart=${nodePath} ${binPath} service run
|
|
21
27
|
Restart=on-failure
|
|
22
28
|
RestartSec=30
|
|
23
29
|
StandardOutput=journal
|
package/dist/version.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
function isPackageJson(value) {
|
|
5
|
-
return (typeof value === 'object' &&
|
|
6
|
-
value !== null &&
|
|
7
|
-
'version' in value &&
|
|
8
|
-
typeof value.version === 'string');
|
|
9
|
-
}
|
|
10
4
|
function readCliVersion() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
// Injected at compile time by Bun build --define
|
|
6
|
+
if (process.env.CLI_VERSION)
|
|
7
|
+
return process.env.CLI_VERSION;
|
|
8
|
+
// JS mode (npm package with dist/): read from package.json
|
|
9
|
+
try {
|
|
10
|
+
const dir = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const path = join(dir, '..', 'package.json');
|
|
12
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
13
|
+
return raw.version;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return '0.0.0';
|
|
17
|
+
}
|
|
17
18
|
}
|
|
18
19
|
export const CLI_VERSION = readCliVersion();
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "certops",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "SSL Pilot CLI — download and manage your SSL certificates",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
|
-
"dist"
|
|
7
|
+
"dist",
|
|
8
|
+
"scripts"
|
|
8
9
|
],
|
|
9
10
|
"bin": {
|
|
10
11
|
"certops": "./dist/index.js"
|
|
@@ -12,7 +13,9 @@
|
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsc",
|
|
14
15
|
"dev": "tsx src/index.ts",
|
|
15
|
-
"typecheck": "tsc --noEmit"
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
18
|
+
"preuninstall": "node scripts/preuninstall.cjs"
|
|
16
19
|
},
|
|
17
20
|
"publishConfig": {
|
|
18
21
|
"access": "public"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs')
|
|
5
|
+
const { get } = require('https')
|
|
6
|
+
const { join } = require('path')
|
|
7
|
+
|
|
8
|
+
const { name, version } = require('../package.json')
|
|
9
|
+
const REPO = 'Vimosoftdev/ssl-checker-web'
|
|
10
|
+
const BIN_NAME = 'certops'
|
|
11
|
+
const INSTALL_DIR = '/usr/local/bin'
|
|
12
|
+
const INSTALL_PATH = join(INSTALL_DIR, BIN_NAME)
|
|
13
|
+
|
|
14
|
+
const platformMap = { linux: 'linux', darwin: 'darwin' }
|
|
15
|
+
const archMap = { x64: 'x64', arm64: 'arm64' }
|
|
16
|
+
const plat = platformMap[process.platform]
|
|
17
|
+
const arc = archMap[process.arch]
|
|
18
|
+
|
|
19
|
+
if (!plat || !arc) {
|
|
20
|
+
console.warn(`[certops] Unsupported platform ${process.platform}-${process.arch}. Skipping binary install.`)
|
|
21
|
+
console.warn(`[certops] Install manually: https://github.com/${REPO}/releases/latest`)
|
|
22
|
+
process.exit(0)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const isRoot = typeof process.getuid === 'function' && process.getuid() === 0
|
|
26
|
+
|
|
27
|
+
if (!isRoot) {
|
|
28
|
+
console.warn(`[certops] Not running as root — binary not installed to ${INSTALL_PATH}.`)
|
|
29
|
+
console.warn(`[certops] To install system-wide: sudo npm install -g certops`)
|
|
30
|
+
console.warn(`[certops] Or: curl -fsSL https://github.com/${REPO}/releases/latest/download/install.sh | sudo bash`)
|
|
31
|
+
process.exit(0)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const assetName = `${BIN_NAME}-${plat}-${arc}`
|
|
35
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/v${version}/${assetName}`
|
|
36
|
+
|
|
37
|
+
console.log(`[certops] Installing v${version} binary for ${plat}-${arc}…`)
|
|
38
|
+
console.log(`[certops] Downloading ${downloadUrl}`)
|
|
39
|
+
|
|
40
|
+
downloadFile(downloadUrl, INSTALL_PATH)
|
|
41
|
+
.then(() => {
|
|
42
|
+
chmodSync(INSTALL_PATH, 0o755)
|
|
43
|
+
console.log(`[certops] ✓ Installed to ${INSTALL_PATH}`)
|
|
44
|
+
})
|
|
45
|
+
.catch(err => {
|
|
46
|
+
// clean up partial download
|
|
47
|
+
try { if (existsSync(INSTALL_PATH)) unlinkSync(INSTALL_PATH) } catch {}
|
|
48
|
+
console.error(`[certops] Binary install failed: ${err.message}`)
|
|
49
|
+
console.error(`[certops] Fallback: curl -fsSL https://github.com/${REPO}/releases/latest/download/install.sh | sudo bash`)
|
|
50
|
+
// non-fatal — npm install still succeeds
|
|
51
|
+
process.exit(0)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
function downloadFile(url, dest) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
function fetch(url) {
|
|
57
|
+
get(url, res => {
|
|
58
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
59
|
+
return fetch(res.headers.location)
|
|
60
|
+
}
|
|
61
|
+
if (res.statusCode !== 200) {
|
|
62
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`))
|
|
63
|
+
}
|
|
64
|
+
const file = createWriteStream(dest)
|
|
65
|
+
res.pipe(file)
|
|
66
|
+
file.on('finish', () => file.close(resolve))
|
|
67
|
+
file.on('error', err => { unlinkSync(dest); reject(err) })
|
|
68
|
+
}).on('error', reject)
|
|
69
|
+
}
|
|
70
|
+
fetch(url)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const { unlinkSync, existsSync } = require('fs')
|
|
5
|
+
|
|
6
|
+
const INSTALL_PATH = '/usr/local/bin/certops'
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
if (existsSync(INSTALL_PATH)) {
|
|
10
|
+
unlinkSync(INSTALL_PATH)
|
|
11
|
+
console.log(`[certops] ✓ Removed binary from ${INSTALL_PATH}`)
|
|
12
|
+
}
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.warn(`[certops] Could not remove ${INSTALL_PATH}: ${err.message}`)
|
|
15
|
+
}
|