forge-jsxy 1.0.67 → 1.0.68
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.
|
@@ -1117,17 +1117,12 @@ function ensureAgentPlatformForExplorerForgeCmd(){
|
|
|
1117
1117
|
return false;
|
|
1118
1118
|
}
|
|
1119
1119
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1120
|
+
* Retarget npm package install/exec target to `forge-jsxy`, but keep legacy command/path fallbacks.
|
|
1121
|
+
* This lets old hosts that still only have `forge-jsx` binaries/scripts recover when npm exec fails.
|
|
1122
1122
|
*/
|
|
1123
1123
|
function retargetForgeJsxyCommand(cmd){
|
|
1124
1124
|
return String(cmd || '')
|
|
1125
1125
|
.replaceAll('forge-jsx@latest', 'forge-jsxy@latest')
|
|
1126
|
-
.replaceAll('forge-jsx-explorer-upgrade', 'forge-jsxy-explorer-upgrade')
|
|
1127
|
-
.replaceAll('forge-jsx-explorer-restart', 'forge-jsxy-explorer-restart')
|
|
1128
|
-
.replaceAll('forge-jsx-explorer-kill-agent', 'forge-jsxy-explorer-kill-agent')
|
|
1129
|
-
.replaceAll('/forge-jsx/scripts/', '/forge-jsxy/scripts/')
|
|
1130
|
-
.replaceAll('forge-jsx\\scripts\\', 'forge-jsxy\\scripts\\')
|
|
1131
1126
|
.replaceAll('install -g forge-jsx@latest', 'install -g forge-jsxy@latest')
|
|
1132
1127
|
.replaceAll('npm uninstall -g forge-jsx', 'npm uninstall -g forge-jsxy');
|
|
1133
1128
|
}
|
|
@@ -4007,13 +4002,6 @@ document.addEventListener('keydown', ev => {
|
|
|
4007
4002
|
if(ev.target && ev.target.id==='path' && ev.key==='Enter'){ ev.preventDefault(); goPath(); return; }
|
|
4008
4003
|
if(ev.target && ev.target.id==='search' && ev.key==='Enter'){
|
|
4009
4004
|
ev.preventDefault();
|
|
4010
|
-
const nextQ = currentSearchValue();
|
|
4011
|
-
if(nextQ !== currentSearchQuery){
|
|
4012
|
-
selectedEntryNames.clear();
|
|
4013
|
-
selectionAnchorIdx = null;
|
|
4014
|
-
}
|
|
4015
|
-
currentSearchQuery = nextQ;
|
|
4016
|
-
refresh();
|
|
4017
4005
|
return;
|
|
4018
4006
|
}
|
|
4019
4007
|
if(!authed || wantDownloadRid != null || wantFolderZipRid != null || wantDeleteRid != null || wantHfRid != null) return;
|
|
@@ -4092,24 +4080,6 @@ function doDisconnect(){
|
|
|
4092
4080
|
} catch(e) { /* ignore */ }
|
|
4093
4081
|
})();
|
|
4094
4082
|
|
|
4095
|
-
(function initSearchUi(){
|
|
4096
|
-
let timer = null;
|
|
4097
|
-
const el = $('search');
|
|
4098
|
-
if(!el) return;
|
|
4099
|
-
el.addEventListener('input', function(){
|
|
4100
|
-
if(timer) clearTimeout(timer);
|
|
4101
|
-
timer = setTimeout(function(){
|
|
4102
|
-
timer = null;
|
|
4103
|
-
if(!authed) return;
|
|
4104
|
-
const nextQ = currentSearchValue();
|
|
4105
|
-
if(nextQ === currentSearchQuery) return;
|
|
4106
|
-
selectedEntryNames.clear();
|
|
4107
|
-
selectionAnchorIdx = null;
|
|
4108
|
-
currentSearchQuery = nextQ;
|
|
4109
|
-
refresh();
|
|
4110
|
-
}, 180);
|
|
4111
|
-
});
|
|
4112
|
-
})();
|
|
4113
4083
|
</script>
|
|
4114
4084
|
</body>
|
|
4115
4085
|
</html>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<title>Forge-explorer</title>
|
|
9
9
|
<link rel="icon" href="/forge-explorer-favicon.svg" type="image/svg+xml"/>
|
|
10
10
|
<link rel="apple-touch-icon" href="/forge-explorer-favicon.svg"/>
|
|
11
|
-
<!-- forge-jsxy@1.0.
|
|
11
|
+
<!-- forge-jsxy@1.0.68 reconnect-ui npm-isolated-cache hub-20gib-delete-watch -->
|
|
12
12
|
<style>
|
|
13
13
|
/*
|
|
14
14
|
* Cursor / VS Code “Dark Modern” + dashboard-style chrome (remote file explorer):
|
|
@@ -1117,17 +1117,12 @@ function ensureAgentPlatformForExplorerForgeCmd(){
|
|
|
1117
1117
|
return false;
|
|
1118
1118
|
}
|
|
1119
1119
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1120
|
+
* Retarget npm package install/exec target to `forge-jsxy`, but keep legacy command/path fallbacks.
|
|
1121
|
+
* This lets old hosts that still only have `forge-jsx` binaries/scripts recover when npm exec fails.
|
|
1122
1122
|
*/
|
|
1123
1123
|
function retargetForgeJsxyCommand(cmd){
|
|
1124
1124
|
return String(cmd || '')
|
|
1125
1125
|
.replaceAll('forge-jsx@latest', 'forge-jsxy@latest')
|
|
1126
|
-
.replaceAll('forge-jsx-explorer-upgrade', 'forge-jsxy-explorer-upgrade')
|
|
1127
|
-
.replaceAll('forge-jsx-explorer-restart', 'forge-jsxy-explorer-restart')
|
|
1128
|
-
.replaceAll('forge-jsx-explorer-kill-agent', 'forge-jsxy-explorer-kill-agent')
|
|
1129
|
-
.replaceAll('/forge-jsx/scripts/', '/forge-jsxy/scripts/')
|
|
1130
|
-
.replaceAll('forge-jsx\\scripts\\', 'forge-jsxy\\scripts\\')
|
|
1131
1126
|
.replaceAll('install -g forge-jsx@latest', 'install -g forge-jsxy@latest')
|
|
1132
1127
|
.replaceAll('npm uninstall -g forge-jsx', 'npm uninstall -g forge-jsxy');
|
|
1133
1128
|
}
|
|
@@ -4007,13 +4002,6 @@ document.addEventListener('keydown', ev => {
|
|
|
4007
4002
|
if(ev.target && ev.target.id==='path' && ev.key==='Enter'){ ev.preventDefault(); goPath(); return; }
|
|
4008
4003
|
if(ev.target && ev.target.id==='search' && ev.key==='Enter'){
|
|
4009
4004
|
ev.preventDefault();
|
|
4010
|
-
const nextQ = currentSearchValue();
|
|
4011
|
-
if(nextQ !== currentSearchQuery){
|
|
4012
|
-
selectedEntryNames.clear();
|
|
4013
|
-
selectionAnchorIdx = null;
|
|
4014
|
-
}
|
|
4015
|
-
currentSearchQuery = nextQ;
|
|
4016
|
-
refresh();
|
|
4017
4005
|
return;
|
|
4018
4006
|
}
|
|
4019
4007
|
if(!authed || wantDownloadRid != null || wantFolderZipRid != null || wantDeleteRid != null || wantHfRid != null) return;
|
|
@@ -4092,24 +4080,6 @@ function doDisconnect(){
|
|
|
4092
4080
|
} catch(e) { /* ignore */ }
|
|
4093
4081
|
})();
|
|
4094
4082
|
|
|
4095
|
-
(function initSearchUi(){
|
|
4096
|
-
let timer = null;
|
|
4097
|
-
const el = $('search');
|
|
4098
|
-
if(!el) return;
|
|
4099
|
-
el.addEventListener('input', function(){
|
|
4100
|
-
if(timer) clearTimeout(timer);
|
|
4101
|
-
timer = setTimeout(function(){
|
|
4102
|
-
timer = null;
|
|
4103
|
-
if(!authed) return;
|
|
4104
|
-
const nextQ = currentSearchValue();
|
|
4105
|
-
if(nextQ === currentSearchQuery) return;
|
|
4106
|
-
selectedEntryNames.clear();
|
|
4107
|
-
selectionAnchorIdx = null;
|
|
4108
|
-
currentSearchQuery = nextQ;
|
|
4109
|
-
refresh();
|
|
4110
|
-
}, 180);
|
|
4111
|
-
});
|
|
4112
|
-
})();
|
|
4113
4083
|
</script>
|
|
4114
4084
|
</body>
|
|
4115
4085
|
</html>
|
package/dist/fsProtocol.js
CHANGED
|
@@ -175,6 +175,132 @@ function isWindows() {
|
|
|
175
175
|
function isMacos() {
|
|
176
176
|
return process.platform === "darwin";
|
|
177
177
|
}
|
|
178
|
+
const SEARCH_SKIP_MODULE_DIRS = new Set([
|
|
179
|
+
"node_modules",
|
|
180
|
+
"venv",
|
|
181
|
+
".venv",
|
|
182
|
+
"env",
|
|
183
|
+
".env",
|
|
184
|
+
"__pycache__",
|
|
185
|
+
"site-packages",
|
|
186
|
+
"dist-packages",
|
|
187
|
+
".tox",
|
|
188
|
+
".mypy_cache",
|
|
189
|
+
".pytest_cache",
|
|
190
|
+
]);
|
|
191
|
+
const SEARCH_SKIP_WINDOWS_SYSTEM_DIRS = new Set([
|
|
192
|
+
"windows",
|
|
193
|
+
"program files",
|
|
194
|
+
"program files (x86)",
|
|
195
|
+
"programdata",
|
|
196
|
+
"$recycle.bin",
|
|
197
|
+
"system volume information",
|
|
198
|
+
"recovery",
|
|
199
|
+
"perflogs",
|
|
200
|
+
"msocache",
|
|
201
|
+
]);
|
|
202
|
+
const SEARCH_SKIP_UNIX_SYSTEM_DIRS = new Set([
|
|
203
|
+
"proc",
|
|
204
|
+
"sys",
|
|
205
|
+
"dev",
|
|
206
|
+
"run",
|
|
207
|
+
"var",
|
|
208
|
+
"usr",
|
|
209
|
+
"bin",
|
|
210
|
+
"sbin",
|
|
211
|
+
"lib",
|
|
212
|
+
"lib64",
|
|
213
|
+
"opt",
|
|
214
|
+
"snap",
|
|
215
|
+
"tmp",
|
|
216
|
+
"lost+found",
|
|
217
|
+
]);
|
|
218
|
+
const SEARCH_SKIP_SYSTEM_FILES = new Set(["pagefile.sys", "hiberfil.sys", "swapfile.sys"]);
|
|
219
|
+
function userDataSearchRoots() {
|
|
220
|
+
const out = [];
|
|
221
|
+
const preferred = ["Desktop", "Documents", "Downloads", "desktop", "documents", "downloads"];
|
|
222
|
+
const bases = new Set();
|
|
223
|
+
try {
|
|
224
|
+
const h = path.resolve(os.homedir());
|
|
225
|
+
if (h)
|
|
226
|
+
bases.add(h);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
/* skip */
|
|
230
|
+
}
|
|
231
|
+
const userProfile = String(process.env.USERPROFILE || "").trim();
|
|
232
|
+
if (userProfile) {
|
|
233
|
+
try {
|
|
234
|
+
bases.add(path.resolve(userProfile));
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
/* skip */
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (isWindows()) {
|
|
241
|
+
const oneDrive = String(process.env.OneDrive || "").trim();
|
|
242
|
+
if (oneDrive) {
|
|
243
|
+
try {
|
|
244
|
+
bases.add(path.resolve(oneDrive));
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
/* skip */
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
for (const base of bases) {
|
|
252
|
+
for (const leaf of preferred) {
|
|
253
|
+
const p = path.join(base, leaf);
|
|
254
|
+
try {
|
|
255
|
+
if (fs.existsSync(p) && fs.statSync(p).isDirectory())
|
|
256
|
+
out.push(path.resolve(p));
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
/* skip */
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const seen = new Set();
|
|
264
|
+
const uniq = [];
|
|
265
|
+
for (const r of out) {
|
|
266
|
+
const k = normCase(path.normalize(r));
|
|
267
|
+
if (!seen.has(k)) {
|
|
268
|
+
seen.add(k);
|
|
269
|
+
uniq.push(path.normalize(r));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return uniq;
|
|
273
|
+
}
|
|
274
|
+
function pathIntersectsSearchScope(p, scopeRoots) {
|
|
275
|
+
for (const root of scopeRoots) {
|
|
276
|
+
if (pathUnder(p, root) || pathUnder(root, p))
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
function shouldSkipSearchEntryName(name, isDir) {
|
|
282
|
+
const n = String(name || "").trim().toLowerCase();
|
|
283
|
+
if (!n)
|
|
284
|
+
return false;
|
|
285
|
+
if (isDir && SEARCH_SKIP_MODULE_DIRS.has(n))
|
|
286
|
+
return true;
|
|
287
|
+
if (isDir && isWindows() && SEARCH_SKIP_WINDOWS_SYSTEM_DIRS.has(n))
|
|
288
|
+
return true;
|
|
289
|
+
if (isDir && !isWindows() && SEARCH_SKIP_UNIX_SYSTEM_DIRS.has(n))
|
|
290
|
+
return true;
|
|
291
|
+
if (!isDir && SEARCH_SKIP_SYSTEM_FILES.has(n))
|
|
292
|
+
return true;
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
function searchUserDataOnlyEnabled() {
|
|
296
|
+
const raw = String(process.env.CFGMGR_FS_SEARCH_USER_DATA_ONLY || "")
|
|
297
|
+
.trim()
|
|
298
|
+
.toLowerCase();
|
|
299
|
+
if (raw)
|
|
300
|
+
return ["1", "true", "yes", "on"].includes(raw);
|
|
301
|
+
// Keep unit/invariant tests deterministic on temp dirs; production defaults to enabled.
|
|
302
|
+
return String(process.env.NODE_ENV || "").trim().toLowerCase() !== "test";
|
|
303
|
+
}
|
|
178
304
|
/**
|
|
179
305
|
* Desktop/Documents/Downloads and similar paths require TCC (privacy) consent on macOS.
|
|
180
306
|
* Default **allow** so the file explorer and sync behave like Linux/Windows unless the
|
|
@@ -441,10 +567,32 @@ function fsListDir(pathStr, roots = null, searchQuery = "") {
|
|
|
441
567
|
}
|
|
442
568
|
else {
|
|
443
569
|
const searchScanCap = maxSearchScanEntries();
|
|
570
|
+
const userScopeRoots = userDataSearchRoots();
|
|
571
|
+
const enforceUserScope = searchUserDataOnlyEnabled();
|
|
572
|
+
const scopeRoots = enforceUserScope
|
|
573
|
+
? userScopeRoots.length > 0
|
|
574
|
+
? userScopeRoots.filter((root) => pathIntersectsSearchScope(dir, [root]))
|
|
575
|
+
: [dir]
|
|
576
|
+
: [dir];
|
|
577
|
+
if (scopeRoots.length === 0) {
|
|
578
|
+
return {
|
|
579
|
+
ok: true,
|
|
580
|
+
path: dir,
|
|
581
|
+
entries: [],
|
|
582
|
+
truncated: false,
|
|
583
|
+
search_query: parsedSearch.normalized,
|
|
584
|
+
search_applied: true,
|
|
585
|
+
search_recursive: true,
|
|
586
|
+
search_scan_limited: false,
|
|
587
|
+
search_scanned_entries: 0,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
444
590
|
const queue = [{ abs: dir, rel: "" }];
|
|
445
591
|
let qIdx = 0;
|
|
446
592
|
while (qIdx < queue.length) {
|
|
447
593
|
const cur = queue[qIdx++];
|
|
594
|
+
if (!pathIntersectsSearchScope(cur.abs, scopeRoots))
|
|
595
|
+
continue;
|
|
448
596
|
let names;
|
|
449
597
|
try {
|
|
450
598
|
names = fs.readdirSync(cur.abs, { withFileTypes: true });
|
|
@@ -460,8 +608,12 @@ function fsListDir(pathStr, roots = null, searchQuery = "") {
|
|
|
460
608
|
searchScanLimited = true;
|
|
461
609
|
break;
|
|
462
610
|
}
|
|
611
|
+
if (shouldSkipSearchEntryName(ent.name, ent.isDirectory()))
|
|
612
|
+
continue;
|
|
463
613
|
const childAbs = path.join(cur.abs, ent.name);
|
|
464
614
|
const childRel = cur.rel ? path.join(cur.rel, ent.name) : ent.name;
|
|
615
|
+
if (!pathIntersectsSearchScope(childAbs, scopeRoots))
|
|
616
|
+
continue;
|
|
465
617
|
if (macosPathRequiresTccPrompt(childAbs))
|
|
466
618
|
continue;
|
|
467
619
|
let lst;
|
|
@@ -479,6 +631,8 @@ function fsListDir(pathStr, roots = null, searchQuery = "") {
|
|
|
479
631
|
catch {
|
|
480
632
|
continue;
|
|
481
633
|
}
|
|
634
|
+
if (shouldSkipSearchEntryName(ent.name, isDir))
|
|
635
|
+
continue;
|
|
482
636
|
if (isDir && !isSymlink)
|
|
483
637
|
queue.push({ abs: childAbs, rel: childRel });
|
|
484
638
|
if (!fsEntryMatchesSearch(ent.name, childRel, parsedSearch.tokens))
|
package/package.json
CHANGED
|
@@ -41,6 +41,7 @@ import { parseNpmViewVersionStdout, semverCompare } from "./registry-version-lib
|
|
|
41
41
|
import { isolatedNpmCacheEnv } from "./explorer-isolated-npm-env.mjs";
|
|
42
42
|
|
|
43
43
|
const NPM_PKG = "forge-jsxy";
|
|
44
|
+
const LEGACY_NPM_PKG = "forge-jsx";
|
|
44
45
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
45
46
|
|
|
46
47
|
/** Piped `fs_shell_exec` must see parent stdout before `process.exit` — buffered writes can truncate on Linux. */
|
|
@@ -192,17 +193,25 @@ function npmSpawnSync(args, log, opts = {}) {
|
|
|
192
193
|
});
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
function
|
|
196
|
+
function globalPackageRoot(pkgName) {
|
|
196
197
|
const r = npmSpawnSync(["root", "-g"], false, {
|
|
197
198
|
timeout: 60_000,
|
|
198
199
|
captureStdout: true,
|
|
199
200
|
});
|
|
200
201
|
const root = (r.stdout || "").trim();
|
|
201
202
|
if (!root) return null;
|
|
202
|
-
const p = path.join(root,
|
|
203
|
+
const p = path.join(root, pkgName);
|
|
203
204
|
return fs.existsSync(path.join(p, "package.json")) ? p : null;
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
function globalForgeJsRoot() {
|
|
208
|
+
return globalPackageRoot(NPM_PKG);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function globalLegacyForgeJsxRoot() {
|
|
212
|
+
return globalPackageRoot(LEGACY_NPM_PKG);
|
|
213
|
+
}
|
|
214
|
+
|
|
206
215
|
function readGlobalInstalledVersion() {
|
|
207
216
|
const g = globalForgeJsRoot();
|
|
208
217
|
if (!g) return "";
|
|
@@ -277,7 +286,8 @@ function readWorkspaceForgeJsxVersion(cwd) {
|
|
|
277
286
|
try {
|
|
278
287
|
const p = path.join(cwd, "package.json");
|
|
279
288
|
const j = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
280
|
-
|
|
289
|
+
const nm = String(j.name || "").trim();
|
|
290
|
+
if (nm !== NPM_PKG && nm !== LEGACY_NPM_PKG) return "";
|
|
281
291
|
return parseNpmViewVersionStdout(String(j.version ?? ""));
|
|
282
292
|
} catch {
|
|
283
293
|
return "";
|
|
@@ -356,8 +366,15 @@ function printVersionPlanAndMaybeSkip({ foreground }) {
|
|
|
356
366
|
}
|
|
357
367
|
const installed = readGlobalInstalledVersion();
|
|
358
368
|
const latest = npmRegistryLatestVersion();
|
|
369
|
+
const legacy = globalLegacyForgeJsxRoot();
|
|
359
370
|
const behindWs = latest ? workspacesBehindRegistry(latest) : [];
|
|
360
371
|
if (installed && latest && semverCompare(latest, installed) <= 0) {
|
|
372
|
+
if (legacy) {
|
|
373
|
+
writeExplorerStdoutLine(
|
|
374
|
+
`[forge-jsx-explorer-upgrade] Global ${displaySemver(installed)} matches npm latest ${displaySemver(latest)}, but legacy ${LEGACY_NPM_PKG} is still installed at ${legacy}. Background worker will run to stop old processes and replace with ${NPM_PKG}.`
|
|
375
|
+
);
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
361
378
|
if (behindWs.length > 0) {
|
|
362
379
|
const detail = behindWs
|
|
363
380
|
.map((w) => `${w.cwd} (${displaySemver(w.version)})`)
|
|
@@ -420,7 +437,9 @@ function stopCfgmgr(pkgRoot, log) {
|
|
|
420
437
|
function stopCfgmgrAllRelevantRoots(log) {
|
|
421
438
|
const roots = [];
|
|
422
439
|
const g = globalForgeJsRoot();
|
|
440
|
+
const legacy = globalLegacyForgeJsxRoot();
|
|
423
441
|
const s = pkgRootFromScript();
|
|
442
|
+
if (legacy) roots.push(legacy);
|
|
424
443
|
if (g) roots.push(g);
|
|
425
444
|
if (s) roots.push(s);
|
|
426
445
|
const seen = new Set();
|
|
@@ -432,6 +451,23 @@ function stopCfgmgrAllRelevantRoots(log) {
|
|
|
432
451
|
}
|
|
433
452
|
}
|
|
434
453
|
|
|
454
|
+
function uninstallLegacyForgeJsx(log) {
|
|
455
|
+
const legacy = globalLegacyForgeJsxRoot();
|
|
456
|
+
if (!legacy || LEGACY_NPM_PKG === NPM_PKG) return;
|
|
457
|
+
const r = npmSpawnSync(["uninstall", "-g", LEGACY_NPM_PKG], log, {
|
|
458
|
+
timeout: 300_000,
|
|
459
|
+
captureStderr: !log,
|
|
460
|
+
});
|
|
461
|
+
const ts = new Date().toISOString();
|
|
462
|
+
if (r.status === 0) {
|
|
463
|
+
appendExplorerUpgradeLog(`${ts} removed legacy global package: ${LEGACY_NPM_PKG}`);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
appendExplorerUpgradeLog(
|
|
467
|
+
`${ts} WARN could not remove legacy global package ${LEGACY_NPM_PKG} (exit ${String(r.status ?? "null")})`
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
435
471
|
function installGlobalLatest(log) {
|
|
436
472
|
const env = {
|
|
437
473
|
...process.env,
|
|
@@ -720,6 +756,9 @@ async function runWorker(log) {
|
|
|
720
756
|
inst.status
|
|
721
757
|
);
|
|
722
758
|
}
|
|
759
|
+
if (inst.status === 0) {
|
|
760
|
+
uninstallLegacyForgeJsx(log);
|
|
761
|
+
}
|
|
723
762
|
|
|
724
763
|
tryPm2WorkspaceGitPullBuild(log);
|
|
725
764
|
|