termbeam 1.17.1 → 1.17.2
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/package.json
CHANGED
package/src/server/routes.js
CHANGED
|
@@ -101,12 +101,12 @@ function setupRoutes(app, { auth, sessions, config, state, pushManager }) {
|
|
|
101
101
|
|
|
102
102
|
try {
|
|
103
103
|
const info = await checkForUpdate({ currentVersion: config.version, force });
|
|
104
|
-
const { installCmd, installArgs, ...publicInstallInfo } = detectInstallMethod();
|
|
104
|
+
const { installCmd, installArgs, cwd, ...publicInstallInfo } = detectInstallMethod();
|
|
105
105
|
state.updateInfo = { ...info, ...publicInstallInfo };
|
|
106
106
|
res.json(state.updateInfo);
|
|
107
107
|
} catch (err) {
|
|
108
108
|
log.warn(`Update check failed: ${err.message}`);
|
|
109
|
-
const { installCmd, installArgs, ...publicInstallInfo } = detectInstallMethod();
|
|
109
|
+
const { installCmd, installArgs, cwd, ...publicInstallInfo } = detectInstallMethod();
|
|
110
110
|
const fallback = {
|
|
111
111
|
current: config.version,
|
|
112
112
|
latest: null,
|
|
@@ -226,6 +226,7 @@ function setupRoutes(app, { auth, sessions, config, state, pushManager }) {
|
|
|
226
226
|
restartStrategy: installInfo.restartStrategy,
|
|
227
227
|
onProgress: broadcastProgress,
|
|
228
228
|
performRestart,
|
|
229
|
+
cwd: installInfo.cwd,
|
|
229
230
|
}).catch((err) => {
|
|
230
231
|
log.error(`Update execution error: ${err.message}`);
|
|
231
232
|
});
|
|
@@ -292,14 +292,31 @@ function detectInstallMethod() {
|
|
|
292
292
|
// Check before Docker: a git checkout running inside a container (CI/devcontainers)
|
|
293
293
|
// should be treated as source, not Docker
|
|
294
294
|
if (isRunningFromSource()) {
|
|
295
|
+
const sourceRoot = getSourceRoot();
|
|
296
|
+
const baseCmd = 'git pull && npm install && npm run build:frontend';
|
|
297
|
+
|
|
298
|
+
if (isPm2) {
|
|
299
|
+
log.debug('Install method: source (PM2)');
|
|
300
|
+
return {
|
|
301
|
+
method: 'source',
|
|
302
|
+
command: `${baseCmd} && pm2 restart termbeam`,
|
|
303
|
+
installCmd: process.platform === 'win32' ? process.env.COMSPEC || 'cmd.exe' : 'sh',
|
|
304
|
+
installArgs: process.platform === 'win32' ? ['/c', baseCmd] : ['-c', baseCmd],
|
|
305
|
+
canAutoUpdate: true,
|
|
306
|
+
restartStrategy: 'pm2',
|
|
307
|
+
cwd: sourceRoot,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
295
311
|
log.debug('Install method: source');
|
|
296
312
|
return {
|
|
297
313
|
method: 'source',
|
|
298
|
-
command:
|
|
314
|
+
command: baseCmd,
|
|
299
315
|
installCmd: null,
|
|
300
316
|
installArgs: null,
|
|
301
317
|
canAutoUpdate: false,
|
|
302
318
|
restartStrategy: 'none',
|
|
319
|
+
cwd: sourceRoot,
|
|
303
320
|
};
|
|
304
321
|
}
|
|
305
322
|
|
|
@@ -346,6 +363,26 @@ function isRunningInDocker() {
|
|
|
346
363
|
return false;
|
|
347
364
|
}
|
|
348
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Find the root of the source checkout by walking up from __dirname.
|
|
368
|
+
* Returns the absolute path to the repo root, or null if not found.
|
|
369
|
+
*/
|
|
370
|
+
function getSourceRoot() {
|
|
371
|
+
if (__dirname.includes('node_modules')) return null;
|
|
372
|
+
try {
|
|
373
|
+
let currentDir = __dirname;
|
|
374
|
+
for (let i = 0; i < 10; i++) {
|
|
375
|
+
if (fs.existsSync(path.join(currentDir, '.git'))) return currentDir;
|
|
376
|
+
const parentDir = path.dirname(currentDir);
|
|
377
|
+
if (!parentDir || parentDir === currentDir) break;
|
|
378
|
+
currentDir = parentDir;
|
|
379
|
+
}
|
|
380
|
+
} catch {
|
|
381
|
+
// ignore
|
|
382
|
+
}
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
|
|
349
386
|
/**
|
|
350
387
|
* Detect if running from a git source checkout (not installed as a package).
|
|
351
388
|
* Walks upward from __dirname looking for .git to avoid fragile fixed-depth assumptions.
|
|
@@ -387,4 +424,5 @@ module.exports = {
|
|
|
387
424
|
isRunningInDocker,
|
|
388
425
|
isRunningFromSource,
|
|
389
426
|
isRunningUnderPm2,
|
|
427
|
+
getSourceRoot,
|
|
390
428
|
};
|
|
@@ -71,6 +71,16 @@ function resetState() {
|
|
|
71
71
|
* Returns { canUpdate, reason } — if canUpdate is false, reason explains why.
|
|
72
72
|
*/
|
|
73
73
|
async function checkPermissions(method) {
|
|
74
|
+
// Source installs use git, not a package manager
|
|
75
|
+
if (method === 'source') {
|
|
76
|
+
try {
|
|
77
|
+
await execFilePromise('git', ['--version'], { timeout: VERIFY_TIMEOUT_MS });
|
|
78
|
+
} catch {
|
|
79
|
+
return { canUpdate: false, reason: 'git not found on PATH' };
|
|
80
|
+
}
|
|
81
|
+
return { canUpdate: true, reason: null };
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
const cmd = method === 'yarn' ? 'yarn' : method === 'pnpm' ? 'pnpm' : 'npm';
|
|
75
85
|
|
|
76
86
|
// Check if the package manager is available by running it directly
|
|
@@ -124,6 +134,7 @@ async function executeUpdate({
|
|
|
124
134
|
restartStrategy,
|
|
125
135
|
onProgress,
|
|
126
136
|
performRestart,
|
|
137
|
+
cwd,
|
|
127
138
|
}) {
|
|
128
139
|
if (updateState.status !== 'idle' && updateState.status !== 'failed') {
|
|
129
140
|
return { ...updateState, error: 'Update already in progress' };
|
|
@@ -169,6 +180,7 @@ async function executeUpdate({
|
|
|
169
180
|
timeout: INSTALL_TIMEOUT_MS,
|
|
170
181
|
maxBuffer: 10 * 1024 * 1024, // 10 MB — package manager installs can be verbose
|
|
171
182
|
env: { ...process.env, NO_UPDATE_NOTIFIER: '1' },
|
|
183
|
+
cwd: cwd || undefined,
|
|
172
184
|
});
|
|
173
185
|
|
|
174
186
|
const output = (stdout + '\n' + stderr).trim();
|
|
@@ -178,7 +190,7 @@ async function executeUpdate({
|
|
|
178
190
|
// Step 3: Verify
|
|
179
191
|
notify({ status: 'verifying', phase: 'Verifying update...' });
|
|
180
192
|
|
|
181
|
-
const newVersion = await verifyInstalledVersion(method);
|
|
193
|
+
const newVersion = await verifyInstalledVersion(method, cwd);
|
|
182
194
|
if (!newVersion) {
|
|
183
195
|
notify({
|
|
184
196
|
status: 'failed',
|
|
@@ -230,7 +242,22 @@ async function executeUpdate({
|
|
|
230
242
|
|
|
231
243
|
// ── Version Verification ─────────────────────────────────────────────────────
|
|
232
244
|
|
|
233
|
-
async function verifyInstalledVersion(method) {
|
|
245
|
+
async function verifyInstalledVersion(method, cwd) {
|
|
246
|
+
// Source installs: read version from the repo's package.json after git pull
|
|
247
|
+
if (method === 'source') {
|
|
248
|
+
try {
|
|
249
|
+
const pkgPath = cwd
|
|
250
|
+
? path.join(cwd, 'package.json')
|
|
251
|
+
: path.resolve(__dirname, '../../package.json');
|
|
252
|
+
const content = await fs.promises.readFile(pkgPath, 'utf8');
|
|
253
|
+
const pkg = JSON.parse(content);
|
|
254
|
+
return pkg.version || null;
|
|
255
|
+
} catch (err) {
|
|
256
|
+
log.debug(`Version verification via package.json failed: ${err.message}`);
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
|
|
234
261
|
const cmd = method === 'yarn' ? 'yarn' : method === 'pnpm' ? 'pnpm' : 'npm';
|
|
235
262
|
try {
|
|
236
263
|
// Use npm/yarn/pnpm to read the installed version
|