termbeam 1.23.3 → 1.23.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.23.4] - 2026-05-01
4
+
5
+ - fix(version): mark dev builds dirty for untracked files; freeze /api/version at startup (@dorlugasigal)
6
+
3
7
  ## [1.23.3] - 2026-05-01
4
8
 
5
9
  - feat(ui): polished wordmark animation + touchbar shadow fix (@dorlugasigal)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termbeam",
3
- "version": "1.23.3",
3
+ "version": "1.23.4",
4
4
  "description": "Beam your terminal to any device — mobile-optimized web terminal with multi-session support",
5
5
  "main": "src/server/index.js",
6
6
  "bin": {
@@ -163,11 +163,12 @@ function setupRoutes(
163
163
  }
164
164
  });
165
165
 
166
- // Version API
166
+ // Version API — uses the version captured at server startup so dev/prod
167
+ // builds stay stable for the lifetime of the process. Restart the service
168
+ // to pick up a new git tag or dirty-state change.
167
169
  app.get('/api/version', (_req, res) => {
168
170
  log.debug('Version requested');
169
- const { getVersion } = require('../utils/version');
170
- res.json({ version: getVersion() });
171
+ res.json({ version: config.version });
171
172
  });
172
173
 
173
174
  // Changelog — served from repo CHANGELOG.md (bundled with the npm package).
@@ -18,9 +18,10 @@ function getVersion() {
18
18
 
19
19
  // Running from source — git tags are the version source of truth.
20
20
  // This avoids drift between package.json and tagged releases.
21
+ const repoRoot = path.join(__dirname, '..', '..');
21
22
  try {
22
23
  const gitDesc = execSync('git describe --tags --always --dirty', {
23
- cwd: path.join(__dirname, '..', '..'),
24
+ cwd: repoRoot,
24
25
  encoding: 'utf-8',
25
26
  stdio: ['pipe', 'pipe', 'pipe'],
26
27
  windowsHide: true,
@@ -31,7 +32,10 @@ function getVersion() {
31
32
  const gitVersion = tagMatch[1];
32
33
  const commits = tagMatch[2];
33
34
  const hash = tagMatch[3];
34
- const dirty = tagMatch[4];
35
+ // `git describe --dirty` only flags tracked-file modifications. Treat any
36
+ // untracked files (e.g. a fresh `hi.txt`) as dirty too so dev builds are
37
+ // always visibly distinct from the tagged release.
38
+ const dirty = tagMatch[4] || (hasUntrackedChanges(repoRoot) ? '-dirty' : '');
35
39
 
36
40
  // Exactly on a clean tag — return the tag version
37
41
  if (!commits && !dirty) {
@@ -69,4 +73,18 @@ function isInstalledGlobally() {
69
73
  return __dirname.includes('node_modules');
70
74
  }
71
75
 
76
+ function hasUntrackedChanges(cwd) {
77
+ try {
78
+ const status = execSync('git status --porcelain', {
79
+ cwd,
80
+ encoding: 'utf-8',
81
+ stdio: ['pipe', 'pipe', 'pipe'],
82
+ windowsHide: true,
83
+ });
84
+ return status.trim().length > 0;
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+
72
90
  module.exports = { getVersion };