zen-gitsync 2.12.8 → 2.13.1
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 +1 -1
- package/package.json +1 -1
- package/src/ui/public/assets/EditorView-BbyNq-0-.js +0 -0
- package/src/ui/public/assets/SourceMapView-CEDJofhr.js +3 -0
- package/src/ui/public/assets/WorkbenchView-DEbOy4sA.js +1 -0
- package/src/ui/public/assets/WorkbenchView-DRh-K9ZG.css +1 -0
- package/src/ui/public/assets/{_plugin-vue_export-helper-opDPZuCO.js → _plugin-vue_export-helper-CIzOKVnN.js} +3 -3
- package/src/ui/public/assets/{index-tejX3YgJ.css → index-DEEcURiV.css} +1 -1
- package/src/ui/public/assets/index-DNP2rwmI.js +66 -0
- package/src/ui/public/assets/{vendor-A4IPqbyo.js → vendor-BfQR1Ql2.js} +1 -1
- package/src/ui/public/index.html +4 -4
- package/src/ui/server/routes/npm.js +170 -1
- package/src/ui/server/routes/workbench.js +381 -75
- package/src/ui/public/assets/EditorView-DkH7PwMR.js +0 -0
- package/src/ui/public/assets/SourceMapView-BG6MIju7.js +0 -3
- package/src/ui/public/assets/WorkbenchView-CDKIBwuO.css +0 -1
- package/src/ui/public/assets/WorkbenchView-DgwZOvhW.js +0 -1
- package/src/ui/public/assets/index-DPihtJfT.js +0 -65
|
@@ -1347,4 +1347,4 @@ https://github.com/highlightjs/highlight.js/issues/2277`),i=e,r=t),n===void 0&&(
|
|
|
1347
1347
|
h${-(x.value.width-2*e.maskBorderRadius)}
|
|
1348
1348
|
a${e.maskBorderRadius},${e.maskBorderRadius} 0 0 1 -${e.maskBorderRadius},-${e.maskBorderRadius}
|
|
1349
1349
|
v${-(x.value.height-2*e.maskBorderRadius)}
|
|
1350
|
-
a${e.maskBorderRadius},${e.maskBorderRadius} 0 0 1 ${e.maskBorderRadius},-${e.maskBorderRadius}z`);Ln(t=>{if(p.value){let n=e9(p.value),r=S9t().wheelDelta(t=>Dg(t)*(e.zoomStep/10)).on(`zoom`,e.pannable?t=>{if(t.sourceEvent.type!==`mousemove`||!u.value||!d.value)return;let n=C.value*Math.max(1,o.value.zoom)*(e.inversePan?-1:1),r={x:o.value.x-t.sourceEvent.movementX*n,y:o.value.y-t.sourceEvent.movementY*n},i=[[0,0],[c.value.width,c.value.height]],a=Z9.translate(r.x,r.y).scale(o.value.zoom),l=d.value.constrain()(a,i,s.value);d.value.transform(u.value,l)}:()=>{}).on(`zoom.wheel`,e.zoomable?t=>{if(t.sourceEvent.type!==`wheel`||!u.value||!d.value)return;let n=t.sourceEvent.ctrlKey&&zg()?10:1,r=-t.sourceEvent.deltaY*(t.sourceEvent.deltaMode===1?.05:t.sourceEvent.deltaMode?1:.002)*e.zoomStep,i=o.value.zoom*2**(r*n);d.value.scaleTo(u.value,i)}:()=>{});n.call(r),t(()=>{n.on(`zoom`,null)})}},{flush:`post`});function E(e){let[n,r]=t9(e);t(`click`,{event:e,position:{x:n,y:r}})}function ee(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeClick(r),t(`nodeClick`,r)}function D(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeDoubleClick(r),t(`nodeDblclick`,r)}function O(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseEnter(r),t(`nodeMouseenter`,r)}function te(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseMove(r),t(`nodeMousemove`,r)}function ne(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseLeave(r),t(`nodeMouseleave`,r)}return(e,t)=>(M(),ii(j(cBe),{position:e.position,class:k([`vue-flow__minimap`,{pannable:e.pannable,zoomable:e.zoomable}])},{default:jn(()=>[(M(),N(`svg`,{ref_key:`el`,ref:p,width:m.value,height:h.value,viewBox:[w.value.x,w.value.y,w.value.width,w.value.height].join(` `),role:`img`,"aria-labelledby":`vue-flow__minimap-${j(i)}`,onClick:E},[e.ariaLabel?(M(),N(`title`,{key:0,id:`vue-flow__minimap-${j(i)}`},je(e.ariaLabel),9,D9t)):I(``,!0),(M(!0),N(Xr,null,Sr(j(f),t=>(M(),ii(T9t,{id:t.id,key:t.id,f:``,position:t.computedPosition,dimensions:t.dimensions,selected:t.selected,dragging:t.dragging,style:ve(t.style),class:k(y.value(t)),color:_.value(t),"border-radius":e.nodeBorderRadius,"stroke-color":v.value(t),"stroke-width":e.nodeStrokeWidth,"shape-rendering":j(g),type:t.type,hidden:t.hidden,onClick:e=>ee(e,t),onDblclick:e=>D(e,t),onMouseenter:e=>O(e,t),onMousemove:e=>te(e,t),onMouseleave:e=>ne(e,t)},null,8,[`id`,`position`,`dimensions`,`selected`,`dragging`,`style`,`class`,`color`,`border-radius`,`stroke-color`,`stroke-width`,`shape-rendering`,`type`,`hidden`,`onClick`,`onDblclick`,`onMouseenter`,`onMousemove`,`onMouseleave`]))),128)),P(`path`,{class:`vue-flow__minimap-mask`,d:T.value,fill:e.maskColor,stroke:e.maskStrokeColor,"stroke-width":e.maskStrokeWidth,"fill-rule":`evenodd`},null,8,O9t)],8,E9t))]),_:1},8,[`position`,`class`]))}});export{exe as $,
|
|
1350
|
+
a${e.maskBorderRadius},${e.maskBorderRadius} 0 0 1 ${e.maskBorderRadius},-${e.maskBorderRadius}z`);Ln(t=>{if(p.value){let n=e9(p.value),r=S9t().wheelDelta(t=>Dg(t)*(e.zoomStep/10)).on(`zoom`,e.pannable?t=>{if(t.sourceEvent.type!==`mousemove`||!u.value||!d.value)return;let n=C.value*Math.max(1,o.value.zoom)*(e.inversePan?-1:1),r={x:o.value.x-t.sourceEvent.movementX*n,y:o.value.y-t.sourceEvent.movementY*n},i=[[0,0],[c.value.width,c.value.height]],a=Z9.translate(r.x,r.y).scale(o.value.zoom),l=d.value.constrain()(a,i,s.value);d.value.transform(u.value,l)}:()=>{}).on(`zoom.wheel`,e.zoomable?t=>{if(t.sourceEvent.type!==`wheel`||!u.value||!d.value)return;let n=t.sourceEvent.ctrlKey&&zg()?10:1,r=-t.sourceEvent.deltaY*(t.sourceEvent.deltaMode===1?.05:t.sourceEvent.deltaMode?1:.002)*e.zoomStep,i=o.value.zoom*2**(r*n);d.value.scaleTo(u.value,i)}:()=>{});n.call(r),t(()=>{n.on(`zoom`,null)})}},{flush:`post`});function E(e){let[n,r]=t9(e);t(`click`,{event:e,position:{x:n,y:r}})}function ee(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeClick(r),t(`nodeClick`,r)}function D(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeDoubleClick(r),t(`nodeDblclick`,r)}function O(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseEnter(r),t(`nodeMouseenter`,r)}function te(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseMove(r),t(`nodeMousemove`,r)}function ne(e,n){let r={event:e,node:n,connectedEdges:wg([n],a.value)};l.miniMapNodeMouseLeave(r),t(`nodeMouseleave`,r)}return(e,t)=>(M(),ii(j(cBe),{position:e.position,class:k([`vue-flow__minimap`,{pannable:e.pannable,zoomable:e.zoomable}])},{default:jn(()=>[(M(),N(`svg`,{ref_key:`el`,ref:p,width:m.value,height:h.value,viewBox:[w.value.x,w.value.y,w.value.width,w.value.height].join(` `),role:`img`,"aria-labelledby":`vue-flow__minimap-${j(i)}`,onClick:E},[e.ariaLabel?(M(),N(`title`,{key:0,id:`vue-flow__minimap-${j(i)}`},je(e.ariaLabel),9,D9t)):I(``,!0),(M(!0),N(Xr,null,Sr(j(f),t=>(M(),ii(T9t,{id:t.id,key:t.id,f:``,position:t.computedPosition,dimensions:t.dimensions,selected:t.selected,dragging:t.dragging,style:ve(t.style),class:k(y.value(t)),color:_.value(t),"border-radius":e.nodeBorderRadius,"stroke-color":v.value(t),"stroke-width":e.nodeStrokeWidth,"shape-rendering":j(g),type:t.type,hidden:t.hidden,onClick:e=>ee(e,t),onDblclick:e=>D(e,t),onMouseenter:e=>O(e,t),onMousemove:e=>te(e,t),onMouseleave:e=>ne(e,t)},null,8,[`id`,`position`,`dimensions`,`selected`,`dragging`,`style`,`class`,`color`,`border-radius`,`stroke-color`,`stroke-width`,`shape-rendering`,`type`,`hidden`,`onClick`,`onDblclick`,`onMouseenter`,`onMousemove`,`onMouseleave`]))),128)),P(`path`,{class:`vue-flow__minimap-mask`,d:T.value,fill:e.maskColor,stroke:e.maskStrokeColor,"stroke-width":e.maskStrokeWidth,"fill-rule":`evenodd`},null,8,O9t)],8,E9t))]),_:1},8,[`position`,`class`]))}});export{exe as $,Rn as $n,zpe as $t,Wke as A,L as An,gpe as At,aTe as B,er as Bn,Dpe as Bt,xje as C,ra as Cn,ppe as Ct,_je as D,Xr as Dn,mpe as Dt,vje as E,ca as En,nl as Et,Nf as F,Cr as Fn,xpe as Ft,pCe as G,pr as Gn,jpe as Gt,Vwe as H,Fn as Hn,Ope as Ht,qTe as I,ui as In,Spe as It,LSe as J,Pn as Jn,Npe as Jt,YSe as K,_r as Kn,cl as Kt,JTe as L,li as Ln,Cpe as Lt,BEe as M,ii as Mn,_pe as Mt,PEe as N,I as Nn,ype as Nt,gje as O,Zee as On,il as Ot,bEe as P,N as Pn,bpe as Pt,cxe as Q,br as Qn,Ipe as Qt,MTe as R,F as Rn,wpe as Rt,Sje as S,vre as Sn,upe as St,yje as T,la as Tn,rl as Tt,Hwe as U,En as Un,kpe as Ut,iTe as V,wi as Vn,Epe as Vt,SCe as W,gr as Wn,sl as Wt,cSe as X,wr as Xn,Fpe as Xt,sSe as Y,Sr as Yn,Ppe as Yt,lSe as Z,yr as Zn,ll as Zt,sBe as _,eie as _n,fhe as _t,i7 as a,Upe as an,cn as ar,vd as at,OMe as b,kre as bn,Zc as bt,C6 as c,qpe as cn,ve as cr,md as ct,tGe as d,Xpe as dn,Age as dt,Lpe as en,jn as er,Ibe as et,VBe as f,Qpe as fn,Cge as ft,rg as g,Wre as gn,dhe as gt,sg as h,eme as hn,ou as ht,y7 as i,Hpe as in,A as ir,aye as it,tm as j,P as jn,vpe as jt,jm as k,Wn as kn,hpe as kt,aKe as l,Jpe as ln,je as lr,eve as lt,gBe as m,$pe as mn,lu as mt,j2t as n,Bpe as nn,rn as nr,iye as nt,iQt as o,Gpe as on,j as or,Eve as ot,c_ as p,ul as pn,mu as pt,HSe as q,M as qn,Mpe as qt,i6t as r,Vpe as rn,Jt as rr,oye as rt,S6 as s,Kpe as sn,k as sr,hd as st,k9t as t,Rpe as tn,Mn as tr,lye as tt,vGe as u,Ype as un,Au as ut,$g as v,tie as vn,ame as vt,bje as w,Gi as wn,tl as wt,Mm as x,Lne as xn,el as xt,o_ as y,Ai as yn,ml as yt,oTe as z,Xee as zn,Tpe as zt};
|
package/src/ui/public/index.html
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
11
11
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
12
12
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
13
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/assets/index-DNP2rwmI.js"></script>
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-CMxvf4Kt.js">
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-
|
|
16
|
-
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-BfQR1Ql2.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-CIzOKVnN.js">
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/vendor-DpYOE9sy.css">
|
|
18
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
18
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DEEcURiV.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
21
21
|
<div id="app"></div>
|
|
@@ -16,12 +16,181 @@ import express from 'express';
|
|
|
16
16
|
import fs from 'fs/promises';
|
|
17
17
|
import fsSync from 'fs';
|
|
18
18
|
import path from 'path';
|
|
19
|
-
import { exec } from 'child_process';
|
|
19
|
+
import { exec, spawn } from 'child_process';
|
|
20
|
+
import https from 'https';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = path.dirname(__filename);
|
|
20
25
|
|
|
21
26
|
export function registerNpmRoutes({
|
|
22
27
|
app,
|
|
23
28
|
getCurrentProjectPath
|
|
24
29
|
}) {
|
|
30
|
+
// 标记是否有升级任务在跑(防并发)
|
|
31
|
+
let activeUpgrade = false;
|
|
32
|
+
|
|
33
|
+
// ========== 应用自升级相关 API ==========
|
|
34
|
+
|
|
35
|
+
// 当前安装的版本(从外层 package.json 读取)
|
|
36
|
+
function getCurrentVersion() {
|
|
37
|
+
try {
|
|
38
|
+
// src/ui/server/routes/npm.js -> ../../../../package.json
|
|
39
|
+
const pkgPath = path.resolve(__dirname, '../../../..', 'package.json')
|
|
40
|
+
if (fsSync.existsSync(pkgPath)) {
|
|
41
|
+
const pkg = JSON.parse(fsSync.readFileSync(pkgPath, 'utf8'))
|
|
42
|
+
return pkg.version || '0.0.0'
|
|
43
|
+
}
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.error('读取本地 package.json 版本失败:', err)
|
|
46
|
+
}
|
|
47
|
+
return '0.0.0'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 简单的 semver 比较:a > b 返回 1, a < b 返回 -1, 相等返回 0
|
|
51
|
+
function compareSemver(a, b) {
|
|
52
|
+
const pa = a.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0)
|
|
53
|
+
const pb = b.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0)
|
|
54
|
+
for (let i = 0; i < 3; i++) {
|
|
55
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return 1
|
|
56
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return -1
|
|
57
|
+
}
|
|
58
|
+
return 0
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 缓存 npm registry latest 结果 10 分钟
|
|
62
|
+
let latestVersionCache = { value: null, at: 0 }
|
|
63
|
+
const LATEST_TTL_MS = 10 * 60 * 1000
|
|
64
|
+
|
|
65
|
+
function fetchLatestFromRegistry() {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const req = https.get(
|
|
68
|
+
'https://registry.npmjs.org/zen-gitsync/latest',
|
|
69
|
+
{ timeout: 5000, headers: { 'User-Agent': 'zen-gitsync-app' } },
|
|
70
|
+
(res) => {
|
|
71
|
+
let data = ''
|
|
72
|
+
res.on('data', chunk => { data += chunk })
|
|
73
|
+
res.on('end', () => {
|
|
74
|
+
if (res.statusCode !== 200) {
|
|
75
|
+
return reject(new Error(`registry 返回状态 ${res.statusCode}`))
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const pkg = JSON.parse(data)
|
|
79
|
+
resolve(pkg.version || null)
|
|
80
|
+
} catch (e) {
|
|
81
|
+
reject(new Error('解析 registry 响应失败'))
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
req.on('timeout', () => {
|
|
87
|
+
req.destroy(new Error('registry 请求超时'))
|
|
88
|
+
})
|
|
89
|
+
req.on('error', err => reject(err))
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function getLatestVersion() {
|
|
94
|
+
const now = Date.now()
|
|
95
|
+
if (latestVersionCache.value && now - latestVersionCache.at < LATEST_TTL_MS) {
|
|
96
|
+
return latestVersionCache.value
|
|
97
|
+
}
|
|
98
|
+
const v = await fetchLatestFromRegistry()
|
|
99
|
+
latestVersionCache = { value: v, at: now }
|
|
100
|
+
return v
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// GET /api/app-version
|
|
104
|
+
app.get('/api/app-version', async (_req, res) => {
|
|
105
|
+
const current = getCurrentVersion()
|
|
106
|
+
try {
|
|
107
|
+
const latest = await getLatestVersion()
|
|
108
|
+
const hasUpdate = !!latest && compareSemver(latest, current) > 0
|
|
109
|
+
res.json({ success: true, current, latest, hasUpdate })
|
|
110
|
+
} catch (err) {
|
|
111
|
+
// 拉取失败时仍返回当前版本,前端据此决定是否显示升级按钮
|
|
112
|
+
res.json({
|
|
113
|
+
success: false,
|
|
114
|
+
current,
|
|
115
|
+
latest: null,
|
|
116
|
+
hasUpdate: false,
|
|
117
|
+
error: err.message
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// POST /api/app-upgrade - 流式 NDJSON: { type: 'stdout'|'stderr'|'done'|'error', ... }
|
|
123
|
+
app.post('/api/app-upgrade', (req, res) => {
|
|
124
|
+
// 防并发:同一时刻只允许一个升级任务
|
|
125
|
+
if (activeUpgrade) {
|
|
126
|
+
res.status(409).json({ success: false, error: '已有升级任务在进行中' })
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
res.setHeader('Content-Type', 'application/x-ndjson; charset=utf-8')
|
|
131
|
+
res.setHeader('Cache-Control', 'no-cache')
|
|
132
|
+
res.setHeader('Connection', 'keep-alive')
|
|
133
|
+
res.flushHeaders?.()
|
|
134
|
+
|
|
135
|
+
const send = (obj) => {
|
|
136
|
+
res.write(JSON.stringify(obj) + '\n')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Windows 上 npm install -g 通常不需要管理员;*nix 需要 sudo。
|
|
140
|
+
// 用 sudo -n(非交互式)检测是否可免密,失败时让用户用 sudo 重启 GUI
|
|
141
|
+
const isWin = process.platform === 'win32'
|
|
142
|
+
const npmCmd = isWin ? 'npm.cmd' : 'npm'
|
|
143
|
+
const args = ['install', '-g', 'zen-gitsync', '--registry', 'https://registry.npmjs.org/']
|
|
144
|
+
const cmd = isWin ? npmCmd : 'sudo'
|
|
145
|
+
const finalArgs = isWin ? args : ['-n', npmCmd, ...args]
|
|
146
|
+
|
|
147
|
+
activeUpgrade = send
|
|
148
|
+
const cleanup = () => { activeUpgrade = null }
|
|
149
|
+
|
|
150
|
+
let child
|
|
151
|
+
try {
|
|
152
|
+
child = spawn(cmd, finalArgs, {
|
|
153
|
+
env: { ...process.env, FORCE_COLOR: '0' },
|
|
154
|
+
windowsHide: true,
|
|
155
|
+
// Windows 下调用 .cmd 必须 shell:true
|
|
156
|
+
shell: isWin
|
|
157
|
+
})
|
|
158
|
+
} catch (err) {
|
|
159
|
+
send({ type: 'error', message: `启动升级进程失败: ${err.message}` })
|
|
160
|
+
send({ type: 'done', code: -1 })
|
|
161
|
+
res.end()
|
|
162
|
+
cleanup()
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
send({ type: 'stdout', message: `$ ${cmd} ${finalArgs.join(' ')}\n` })
|
|
167
|
+
|
|
168
|
+
child.stdout.on('data', (buf) => send({ type: 'stdout', message: buf.toString() }))
|
|
169
|
+
child.stderr.on('data', (buf) => send({ type: 'stderr', message: buf.toString() }))
|
|
170
|
+
|
|
171
|
+
child.on('error', (err) => {
|
|
172
|
+
send({ type: 'error', message: `升级进程错误: ${err.message}` })
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
child.on('close', (code) => {
|
|
176
|
+
if (code === 0) {
|
|
177
|
+
send({ type: 'stdout', message: '\n✅ 升级完成,新版本已全局安装。\n' })
|
|
178
|
+
// 清理缓存,强制下次重新拉 latest
|
|
179
|
+
latestVersionCache = { value: null, at: 0 }
|
|
180
|
+
} else {
|
|
181
|
+
let hint = ''
|
|
182
|
+
if (!isWin) {
|
|
183
|
+
hint = '(提示:在 macOS/Linux 上全局安装需要 sudo,请用管理员权限重启 GUI 后再试)'
|
|
184
|
+
}
|
|
185
|
+
send({ type: 'error', message: `\n升级失败,退出码 ${code}${hint ? ' ' + hint : ''}\n` })
|
|
186
|
+
}
|
|
187
|
+
send({ type: 'done', code })
|
|
188
|
+
res.end()
|
|
189
|
+
cleanup()
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
|
|
25
194
|
// 读取 package.json 文件内容
|
|
26
195
|
app.post('/api/read-package-json', express.json(), async (req, res) => {
|
|
27
196
|
try {
|