centralu 0.1.0-beta.3 → 0.1.0-beta.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/bin/centralu.mjs +41 -1
- package/bin/semver.mjs +19 -0
- package/package.json +4 -4
package/bin/centralu.mjs
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* instead of being rediscovered in every function.
|
|
17
17
|
*/
|
|
18
18
|
import { execFileSync, spawn } from 'node:child_process'
|
|
19
|
-
import { isNewer } from './semver.mjs'
|
|
19
|
+
import { copyDiffers, isNewer } from './semver.mjs'
|
|
20
20
|
import { chmodSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
|
|
21
21
|
import { createRequire } from 'node:module'
|
|
22
22
|
import { homedir } from 'node:os'
|
|
@@ -238,6 +238,8 @@ async function update() {
|
|
|
238
238
|
const latest = res.version
|
|
239
239
|
if (!isNewer(latest, pkg.version)) {
|
|
240
240
|
console.log(`이미 최신입니다 (${pkg.version}).`)
|
|
241
|
+
// 패키지가 최신이어도 사본은 아닐 수 있다 — `npm i -g`로 올린 사람이 정확히 그 상태다
|
|
242
|
+
notifyIfCopyStale()
|
|
241
243
|
return
|
|
242
244
|
}
|
|
243
245
|
console.log(`${pkg.version} → ${latest} 로 올립니다.`)
|
|
@@ -253,6 +255,43 @@ async function update() {
|
|
|
253
255
|
console.log('끝났습니다. 앱이 떠 있다면 다시 시작해 주세요.')
|
|
254
256
|
}
|
|
255
257
|
|
|
258
|
+
/**
|
|
259
|
+
* /Applications에 넣어둔 사본의 버전. 견줄 것이 없으면 null.
|
|
260
|
+
*
|
|
261
|
+
* `defaults`를 쓰는 이유는 Info.plist가 XML이라는 보장이 없어서다 — 오늘 Tauri가 XML로
|
|
262
|
+
* 쓰고 있을 뿐이고, 바이너리 plist로 바뀌면 정규식으로 읽던 쪽이 조용히 못 읽게 된다.
|
|
263
|
+
* `defaults`는 맥에 항상 있고 둘 다 읽는다.
|
|
264
|
+
*/
|
|
265
|
+
function installedCopyVersion() {
|
|
266
|
+
if (process.platform !== 'darwin' || !existsSync(INSTALLED)) return null
|
|
267
|
+
try {
|
|
268
|
+
const out = execFileSync('/usr/bin/defaults', ['read', join(INSTALLED, 'Contents/Info.plist'), 'CFBundleShortVersionString'], {
|
|
269
|
+
encoding: 'utf8',
|
|
270
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
271
|
+
})
|
|
272
|
+
return out.trim()
|
|
273
|
+
} catch {
|
|
274
|
+
// 못 읽는 것은 말할 거리가 아니다 — 앱은 이미 떴고, 여기서 할 수 있는 말이 없다
|
|
275
|
+
return null
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 패키지와 /Applications 사본이 어긋났으면 한 줄.
|
|
281
|
+
*
|
|
282
|
+
* `npm i -g centralu`는 패키지만 바꾼다. 그래서 런처는 새것인데 Spotlight에서 열리는 앱은
|
|
283
|
+
* 옛것인 상태가 조용히 만들어진다 — 실제로 그렇게 됐고(beta.1이 /Applications에 남아 있는
|
|
284
|
+
* 채로 패키지만 beta.3), 화면 어디에도 그 사실이 없었다.
|
|
285
|
+
*
|
|
286
|
+
* **말하되 대신 하지 않는다.** 앱 안의 업데이트 줄과 같은 규칙이다. 묻지도 않고 남의
|
|
287
|
+
* /Applications를 덮는 일은 이 패키지가 `install`을 따로 둔 이유 그 자체다.
|
|
288
|
+
*/
|
|
289
|
+
function notifyIfCopyStale() {
|
|
290
|
+
const version = installedCopyVersion()
|
|
291
|
+
if (!copyDiffers(pkg.version, version)) return
|
|
292
|
+
console.log(`\n/Applications 사본은 ${version}입니다 (이 패키지는 ${pkg.version}).\n centralu install`)
|
|
293
|
+
}
|
|
294
|
+
|
|
256
295
|
/** 앱을 띄운 뒤에만 알린다 — 업데이트 확인 때문에 실행이 늦어지면 안 된다 */
|
|
257
296
|
async function notifyIfOutdated() {
|
|
258
297
|
// 여기서는 실패를 **전부 삼킨다.** 앱을 띄우러 온 사람에게 레지스트리 사정을 말할 이유가 없다
|
|
@@ -294,5 +333,6 @@ switch (cmd) {
|
|
|
294
333
|
break
|
|
295
334
|
default:
|
|
296
335
|
run(cmd ? [cmd, ...rest] : [])
|
|
336
|
+
notifyIfCopyStale()
|
|
297
337
|
await notifyIfOutdated()
|
|
298
338
|
}
|
package/bin/semver.mjs
CHANGED
|
@@ -49,6 +49,25 @@ export function isNewer(a, b) {
|
|
|
49
49
|
return false
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Whether the copy in /Applications is a different app than the one this package carries.
|
|
54
|
+
*
|
|
55
|
+
* `npm i -g centralu` replaces the package and nothing else. That is deliberate — this
|
|
56
|
+
* project does not write into someone's /Applications unless asked (`centralu install`) —
|
|
57
|
+
* but the cost is that the two drift apart in silence, and the copy is the one people
|
|
58
|
+
* actually click. So the launcher says so. It still does not act.
|
|
59
|
+
*
|
|
60
|
+
* Not `isNewer`. Drift in either direction is worth a line: a copy *newer* than the package
|
|
61
|
+
* means an update went backwards, which is more surprising, not less.
|
|
62
|
+
*
|
|
63
|
+
* Lives beside `isNewer` because it ships and is tested for the same reason — a launcher
|
|
64
|
+
* already on someone's machine cannot be corrected later. 0.1.0-beta.1 is still out there
|
|
65
|
+
* answering "이미 최신입니다" and always will be.
|
|
66
|
+
*/
|
|
67
|
+
export function copyDiffers(pkgVersion, copyVersion) {
|
|
68
|
+
return typeof copyVersion === 'string' && copyVersion !== '' && copyVersion !== pkgVersion
|
|
69
|
+
}
|
|
70
|
+
|
|
52
71
|
function split(v) {
|
|
53
72
|
const dash = v.indexOf('-')
|
|
54
73
|
const core = (dash === -1 ? v : v.slice(0, dash)).split('.').map(Number)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "centralu",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.4",
|
|
4
4
|
"description": "Run, watch and steer several Claude Code and Codex CLI sessions from one window",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ijun17",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"linux"
|
|
36
36
|
],
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"centralu-darwin-arm64": "0.1.0-beta.
|
|
39
|
-
"centralu-linux-arm64": "0.1.0-beta.
|
|
40
|
-
"centralu-linux-x64": "0.1.0-beta.
|
|
38
|
+
"centralu-darwin-arm64": "0.1.0-beta.4",
|
|
39
|
+
"centralu-linux-arm64": "0.1.0-beta.4",
|
|
40
|
+
"centralu-linux-x64": "0.1.0-beta.4"
|
|
41
41
|
}
|
|
42
42
|
}
|