Skip to content

Commit 540a645

Browse files
committed
Fix asset resolution and caffeinate crash for dist runtime
- cli.ts: walk up from import.meta.dirname to find package.json (works from both source and dist/) - build.ts: walk up to find styles/base.css for PROJECT_ROOT - src/serve.ts: walk up to find src/pwa/icons/, catch async caffeinate spawn errors on Linux
1 parent 4156f17 commit 540a645

3 files changed

Lines changed: 49 additions & 13 deletions

File tree

‎build.ts‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
import { readFileSync, unlinkSync, writeFileSync } from 'node:fs'
2-
import { resolve } from 'node:path'
1+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
2+
import { dirname, resolve } from 'node:path'
33
import * as esbuild from 'esbuild'
44
import { generatePwaHtml } from './src/pwa/meta-tags'
55
import type { WebmuxConfig } from './src/types'
66
import { readStdin, sleep, spawnProcess } from './src/util/node-compat'
77

8-
const PROJECT_ROOT = import.meta.dirname
8+
// Walk up from module location to find project root (where styles/ lives)
9+
function findProjectRoot(): string {
10+
let dir = import.meta.dirname
11+
for (let i = 0; i < 5; i++) {
12+
if (existsSync(resolve(dir, 'styles/base.css'))) return dir
13+
dir = dirname(dir)
14+
}
15+
return import.meta.dirname
16+
}
17+
18+
const PROJECT_ROOT = findProjectRoot()
919

1020
/** Bundle the overlay JS + CSS into strings */
1121
export async function bundleOverlay(config: WebmuxConfig): Promise<{ js: string; css: string }> {

‎cli.ts‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#!/usr/bin/env node
2-
import { existsSync, writeFileSync } from 'node:fs'
3-
import { createRequire } from 'node:module'
2+
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
43
import { homedir } from 'node:os'
5-
import { join, resolve } from 'node:path'
4+
import { dirname, join, resolve } from 'node:path'
65
import { build, injectFromStdin } from './build'
76
import { parseCliArgs } from './src/cli/args'
87
import { defaultConfig, defineConfig, mergeConfig } from './src/config'
@@ -15,11 +14,22 @@ import { serve } from './src/serve'
1514
import type { WebmuxConfig, WebmuxConfigOverrides } from './src/types'
1615
import { readStdin } from './src/util/node-compat'
1716

18-
const require = createRequire(import.meta.url)
19-
// oxlint-disable-next-line typescript/consistent-type-assertions -- createRequire returns unknown, safe narrowing
20-
const pkg = require('./package.json') as { version: string }
17+
// Walk up from module location to find package.json — works from both source and dist/
18+
function loadPackageVersion(): string {
19+
let dir = import.meta.dirname
20+
for (let i = 0; i < 5; i++) {
21+
try {
22+
const content = readFileSync(resolve(dir, 'package.json'), 'utf-8')
23+
// oxlint-disable-next-line typescript/consistent-type-assertions -- JSON.parse returns unknown
24+
return (JSON.parse(content) as { version: string }).version
25+
} catch {
26+
dir = dirname(dir)
27+
}
28+
}
29+
return '0.0.0'
30+
}
2131

22-
const VERSION: string = pkg.version
32+
const VERSION: string = loadPackageVersion()
2333

2434
function usage(): void {
2535
console.log(`webmux v${VERSION} — mobile-friendly terminal overlay for ttyd + tmux

‎src/serve.ts‎

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { readFileSync } from 'node:fs'
2-
import { resolve } from 'node:path'
1+
import { existsSync, readFileSync } from 'node:fs'
2+
import { dirname, resolve } from 'node:path'
33
import { serve as honoServe } from '@hono/node-server'
44
import { createNodeWebSocket } from '@hono/node-ws'
55
import { Hono } from 'hono'
@@ -14,7 +14,19 @@ import type { SpawnedProcess } from './util/node-compat'
1414

1515
const DEFAULT_PORT = 7681
1616
const DEFAULT_COMMAND = ['tmux', 'new-session', '-A', '-s', 'main']
17-
const ICONS_DIR = resolve(import.meta.dirname, 'pwa/icons')
17+
// Walk up from module location to find package root, then resolve icons
18+
function findIconsDir(): string {
19+
let dir = import.meta.dirname
20+
for (let i = 0; i < 5; i++) {
21+
const candidate = resolve(dir, 'src/pwa/icons')
22+
if (existsSync(candidate)) return candidate
23+
dir = dirname(dir)
24+
}
25+
// Fallback for source layout (running from src/)
26+
return resolve(import.meta.dirname, 'pwa/icons')
27+
}
28+
29+
const ICONS_DIR = findIconsDir()
1830

1931
interface WsData {
2032
backend: WebSocket | null
@@ -83,6 +95,10 @@ function spawnCaffeinate(pid: number): SpawnedProcess | null {
8395
stdout: 'ignore',
8496
stderr: 'ignore',
8597
})
98+
// Catch async spawn errors (e.g. caffeinate not found on Linux)
99+
proc.exited.catch(() => {
100+
console.warn('webmux: --no-sleep requires caffeinate (macOS only), ignoring')
101+
})
86102
console.log(`webmux: sleep prevention active (caffeinate -s -w ${pid})`)
87103
return proc
88104
} catch {

0 commit comments

Comments
 (0)