@oddessentials/odd-dashboard 0.3.7

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 ADDED
@@ -0,0 +1,49 @@
1
+ # npm Shim for odd-dashboard
2
+
3
+ This package provides a convenient way to install `odd-dashboard` via npm.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @oddessentials/odd-dashboard
9
+ ```
10
+
11
+ ## How it works
12
+
13
+ The npm package is a thin wrapper that:
14
+
15
+ 1. Downloads the appropriate native binary for your platform during `npm install`
16
+ 2. Verifies the binary's checksum against the signed SHA256SUMS file
17
+ 3. Provides a Node.js shim that forwards all arguments to the native binary
18
+
19
+ ## Supported Platforms
20
+
21
+ - Windows x64
22
+ - macOS x64 (Intel)
23
+ - macOS arm64 (Apple Silicon)
24
+ - Linux x64
25
+ - Linux arm64
26
+
27
+ ## Troubleshooting
28
+
29
+ ### Binary not installed
30
+
31
+ If you see "odd-dashboard binary not installed" when running the command:
32
+
33
+ 1. Check if your platform is supported
34
+ 2. Try reinstalling: `npm install -g @oddessentials/odd-dashboard`
35
+ 3. Download manually from [GitHub Releases](https://github.com/oddessentials/odd-demonstration/releases)
36
+
37
+ ### Checksum verification failed
38
+
39
+ This indicates the downloaded binary may have been tampered with. Please:
40
+
41
+ 1. Do NOT use the downloaded file
42
+ 2. Report the issue to the maintainers
43
+ 3. Download directly from GitHub Releases and verify manually
44
+
45
+ ## Alternative Installation Methods
46
+
47
+ - **Linux/macOS**: `curl -fsSL https://raw.githubusercontent.com/oddessentials/odd-demonstration/main/install.sh | sh`
48
+ - **Windows**: `iwr -useb https://raw.githubusercontent.com/oddessentials/odd-demonstration/main/install.ps1 | iex`
49
+ - **Homebrew**: `brew install oddessentials/tap/odd-dashboard`
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * odd-dashboard npm shim - CLI entry point
4
+ *
5
+ * This wrapper script spawns the native binary with all arguments forwarded.
6
+ * If the binary is not installed, it displays installation instructions
7
+ * and exits with a non-zero status code.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const { spawn } = require('child_process');
13
+
14
+ const binName = process.platform === 'win32' ? 'odd-dashboard.exe' : 'odd-dashboard';
15
+ const binPath = path.join(__dirname, binName);
16
+ const sentinelPath = path.join(__dirname, '..', '.install-failed');
17
+
18
+ // Check for installation failure sentinel
19
+ if (fs.existsSync(sentinelPath)) {
20
+ const reason = fs.readFileSync(sentinelPath, 'utf-8').trim();
21
+
22
+ console.error(`
23
+ ╔════════════════════════════════════════════════════════════════════╗
24
+ ║ odd-dashboard binary not installed ║
25
+ ╠════════════════════════════════════════════════════════════════════╣
26
+ ║ Reason: ${reason.substring(0, 54).padEnd(54)}║
27
+ ║ ║
28
+ ║ Manual installation options: ║
29
+ ║ ║
30
+ ║ Linux/macOS: ║
31
+ ║ curl -fsSL https://raw.githubusercontent.com/oddessentials/ ║
32
+ ║ odd-demonstration/main/install.sh | sh ║
33
+ ║ ║
34
+ ║ Windows PowerShell: ║
35
+ ║ iwr -useb https://raw.githubusercontent.com/oddessentials/ ║
36
+ ║ odd-demonstration/main/install.ps1 | iex ║
37
+ ║ ║
38
+ ║ Or download directly from GitHub Releases: ║
39
+ ║ https://github.com/oddessentials/odd-demonstration/releases ║
40
+ ╚════════════════════════════════════════════════════════════════════╝
41
+ `);
42
+ process.exit(1);
43
+ }
44
+
45
+ // Check if binary exists
46
+ if (!fs.existsSync(binPath)) {
47
+ console.error(`
48
+ ╔════════════════════════════════════════════════════════════════════╗
49
+ ║ odd-dashboard binary not found ║
50
+ ╠════════════════════════════════════════════════════════════════════╣
51
+ ║ Expected at: ${binPath.substring(0, 50).padEnd(50)}║
52
+ ║ ║
53
+ ║ Try reinstalling: ║
54
+ ║ npm install -g @oddessentials/odd-dashboard ║
55
+ ╚════════════════════════════════════════════════════════════════════╝
56
+ `);
57
+ process.exit(1);
58
+ }
59
+
60
+ // Forward all arguments to the binary
61
+ const args = process.argv.slice(2);
62
+ const child = spawn(binPath, args, {
63
+ stdio: 'inherit',
64
+ windowsHide: true,
65
+ });
66
+
67
+ child.on('error', (err) => {
68
+ console.error(`Failed to start odd-dashboard: ${err.message}`);
69
+ process.exit(1);
70
+ });
71
+
72
+ child.on('close', (code) => {
73
+ process.exit(code ?? 0);
74
+ });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@oddessentials/odd-dashboard",
3
+ "version": "0.3.7",
4
+ "description": "Terminal dashboard for Distributed Task Observatory",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/oddessentials/odd-demonstration.git"
8
+ },
9
+ "keywords": [
10
+ "kubernetes",
11
+ "observability",
12
+ "dashboard",
13
+ "tui",
14
+ "cli"
15
+ ],
16
+ "author": "OddEssentials",
17
+ "license": "MIT",
18
+ "homepage": "https://github.com/oddessentials/odd-demonstration#readme",
19
+ "bin": {
20
+ "odd-dashboard": "bin/odd-dashboard.js"
21
+ },
22
+ "scripts": {
23
+ "postinstall": "node scripts/install.js"
24
+ },
25
+ "engines": {
26
+ "node": ">=16"
27
+ },
28
+ "files": [
29
+ "bin/",
30
+ "scripts/"
31
+ ]
32
+ }
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * odd-dashboard postinstall script
4
+ *
5
+ * Downloads the native binary from GitHub Releases with checksum verification.
6
+ * On failure, creates a sentinel file so the CLI wrapper can provide helpful
7
+ * error messages instead of silently failing.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const https = require('https');
13
+ const crypto = require('crypto');
14
+
15
+ const PLATFORM_MAP = {
16
+ 'darwin-x64': 'odd-dashboard-macos-x64',
17
+ 'darwin-arm64': 'odd-dashboard-macos-arm64',
18
+ 'linux-x64': 'odd-dashboard-linux-x64',
19
+ 'linux-arm64': 'odd-dashboard-linux-arm64',
20
+ 'win32-x64': 'odd-dashboard-windows-x64.exe',
21
+ };
22
+
23
+ const VERSION = require('../package.json').version;
24
+ const REPO = 'oddessentials/odd-demonstration';
25
+ const BASE_URL = `https://github.com/${REPO}/releases/download/v${VERSION}`;
26
+
27
+ const binDir = path.join(__dirname, '..', 'bin');
28
+ const sentinelPath = path.join(__dirname, '..', '.install-failed');
29
+
30
+ /**
31
+ * Download a file from a URL, following redirects
32
+ */
33
+ function download(url) {
34
+ return new Promise((resolve, reject) => {
35
+ const request = (url) => {
36
+ https.get(url, (res) => {
37
+ if (res.statusCode === 301 || res.statusCode === 302) {
38
+ // Follow redirect
39
+ request(res.headers.location);
40
+ } else if (res.statusCode !== 200) {
41
+ reject(new Error(`HTTP ${res.statusCode}: ${url}`));
42
+ } else {
43
+ const chunks = [];
44
+ res.on('data', (chunk) => chunks.push(chunk));
45
+ res.on('end', () => resolve(Buffer.concat(chunks)));
46
+ res.on('error', reject);
47
+ }
48
+ }).on('error', reject);
49
+ };
50
+ request(url);
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Parse checksum file and find the expected hash for an artifact
56
+ */
57
+ function parseChecksum(content, artifact) {
58
+ const lines = content.toString().split('\n');
59
+ for (const line of lines) {
60
+ const [hash, filename] = line.trim().split(/\s+/);
61
+ if (filename === artifact) {
62
+ return hash;
63
+ }
64
+ }
65
+ throw new Error(`Artifact ${artifact} not found in SHA256SUMS`);
66
+ }
67
+
68
+ /**
69
+ * Write failure sentinel file
70
+ */
71
+ function writeSentinel(reason) {
72
+ fs.writeFileSync(sentinelPath, reason);
73
+ }
74
+
75
+ /**
76
+ * Remove failure sentinel if it exists
77
+ */
78
+ function clearSentinel() {
79
+ if (fs.existsSync(sentinelPath)) {
80
+ fs.unlinkSync(sentinelPath);
81
+ }
82
+ }
83
+
84
+ async function install() {
85
+ const platform = `${process.platform}-${process.arch}`;
86
+ const artifact = PLATFORM_MAP[platform];
87
+
88
+ if (!artifact) {
89
+ const msg = `Unsupported platform: ${platform}`;
90
+ console.log(`[odd-dashboard] ${msg}`);
91
+ console.log('[odd-dashboard] Binary not installed. Run `odd-dashboard` for manual installation options.');
92
+ writeSentinel(msg);
93
+ return; // Exit 0 to not break npm install
94
+ }
95
+
96
+ const binName = process.platform === 'win32' ? 'odd-dashboard.exe' : 'odd-dashboard';
97
+ const binPath = path.join(binDir, binName);
98
+
99
+ try {
100
+ // Ensure bin directory exists
101
+ fs.mkdirSync(binDir, { recursive: true });
102
+
103
+ console.log(`[odd-dashboard] Downloading ${artifact}...`);
104
+
105
+ // Download checksum file
106
+ const checksums = await download(`${BASE_URL}/SHA256SUMS`);
107
+ const expectedHash = parseChecksum(checksums, artifact);
108
+
109
+ // Download binary
110
+ const binary = await download(`${BASE_URL}/${artifact}`);
111
+
112
+ // Verify checksum
113
+ const actualHash = crypto.createHash('sha256').update(binary).digest('hex');
114
+ if (actualHash.toLowerCase() !== expectedHash.toLowerCase()) {
115
+ throw new Error(`Checksum mismatch! Expected: ${expectedHash}, Actual: ${actualHash}`);
116
+ }
117
+ console.log('[odd-dashboard] Checksum verified');
118
+
119
+ // Write binary
120
+ fs.writeFileSync(binPath, binary);
121
+
122
+ // Set executable permission on POSIX
123
+ if (process.platform !== 'win32') {
124
+ fs.chmodSync(binPath, 0o755);
125
+ }
126
+
127
+ console.log(`[odd-dashboard] Installed to ${binPath}`);
128
+ clearSentinel();
129
+
130
+ } catch (err) {
131
+ const msg = err.message || String(err);
132
+ console.error(`[odd-dashboard] Installation failed: ${msg}`);
133
+ console.error('[odd-dashboard] Run `odd-dashboard` for manual installation options.');
134
+ writeSentinel(msg);
135
+ // Exit 0 to not break npm install - the CLI wrapper will handle the error
136
+ }
137
+ }
138
+
139
+ install();