4runr-os 2.10.13 → 2.10.16
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/apps/gateway/dist/apps/gateway/src/db/docker-manager.js +1 -1
- package/apps/gateway/dist/apps/gateway/src/db/docker-manager.js.map +1 -1
- package/apps/gateway/dist/apps/gateway/src/db/init.js +1 -1
- package/apps/gateway/dist/apps/gateway/src/db/init.js.map +1 -1
- package/apps/gateway/package-lock.json +1 -0
- package/apps/gateway/src/db/docker-manager.ts +226 -226
- package/apps/gateway/src/db/init.ts +5 -5
- package/dist/boot-sequence.d.ts +0 -4
- package/dist/boot-sequence.d.ts.map +1 -1
- package/dist/boot-sequence.js +13 -67
- package/dist/boot-sequence.js.map +1 -1
- package/dist/deferred-npm-install-lock.d.ts +2 -4
- package/dist/deferred-npm-install-lock.d.ts.map +1 -1
- package/dist/deferred-npm-install-lock.js +4 -28
- package/dist/deferred-npm-install-lock.js.map +1 -1
- package/dist/tui-handlers.js +32 -27
- package/dist/tui-handlers.js.map +1 -1
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +14 -64
- package/dist/version-check.js.map +1 -1
- package/package.json +2 -4
- package/scripts/global-npm-guard.cjs +0 -47
package/dist/boot-sequence.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import * as fs from 'fs';
|
|
7
|
-
import * as os from 'os';
|
|
8
7
|
import * as path from 'path';
|
|
8
|
+
import { forceClearGlobalDeferredNpmLock } from './deferred-npm-install-lock.js';
|
|
9
9
|
/**
|
|
10
10
|
* Kill any stale 4r/Gateway processes that might lock files
|
|
11
11
|
*/
|
|
@@ -20,31 +20,19 @@ export function killStaleProcesses() {
|
|
|
20
20
|
}
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
// Windows:
|
|
23
|
+
// Windows: Use PowerShell Get-Process (wmic was removed in Windows 11+)
|
|
24
24
|
try {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const pid = parseInt(match[1], 10);
|
|
32
|
-
if (pid > 0 && pid !== process.pid) {
|
|
33
|
-
try {
|
|
34
|
-
process.kill(pid, 'SIGTERM');
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
// ignore
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
25
|
+
const ps = `Get-Process node -ErrorAction SilentlyContinue | Where-Object { $_.Path -like '*4runr-os*' -or $_.CommandLine -like '*gateway*' } | ForEach-Object { Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue }`;
|
|
26
|
+
execSync(`powershell -NoProfile -Command "${ps}"`, {
|
|
27
|
+
stdio: 'ignore',
|
|
28
|
+
timeout: 10000,
|
|
29
|
+
windowsHide: true,
|
|
30
|
+
});
|
|
43
31
|
}
|
|
44
32
|
catch {
|
|
45
|
-
// Fallback: just kill all node
|
|
33
|
+
// Fallback: just kill all node except current process
|
|
46
34
|
try {
|
|
47
|
-
execSync(
|
|
35
|
+
execSync(`taskkill /F /IM node.exe /FI "PID ne ${process.pid}"`, {
|
|
48
36
|
stdio: 'ignore',
|
|
49
37
|
windowsHide: true,
|
|
50
38
|
});
|
|
@@ -54,35 +42,6 @@ export function killStaleProcesses() {
|
|
|
54
42
|
}
|
|
55
43
|
}
|
|
56
44
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Wait for any in-progress npm install -g 4runr-os to complete
|
|
59
|
-
*/
|
|
60
|
-
export async function waitForInProgressUpdate(maxWaitMs = 120000) {
|
|
61
|
-
const lockPath = path.join(os.tmpdir(), '4runr-os-gnpm-in-progress.lock');
|
|
62
|
-
const start = Date.now();
|
|
63
|
-
while (Date.now() - start < maxWaitMs) {
|
|
64
|
-
if (!fs.existsSync(lockPath)) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
// Check if lock is stale (>15 min)
|
|
68
|
-
try {
|
|
69
|
-
const { mtimeMs } = fs.statSync(lockPath);
|
|
70
|
-
if (Date.now() - mtimeMs > 15 * 60 * 1000) {
|
|
71
|
-
fs.unlinkSync(lockPath);
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
// Show progress every 5s
|
|
79
|
-
if ((Date.now() - start) % 5000 < 1000) {
|
|
80
|
-
process.stderr.write('.');
|
|
81
|
-
}
|
|
82
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
83
|
-
}
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
45
|
/**
|
|
87
46
|
* Check if Prisma client is properly generated
|
|
88
47
|
*/
|
|
@@ -144,6 +103,8 @@ async function repairInstall() {
|
|
|
144
103
|
*/
|
|
145
104
|
export async function performBootSequence() {
|
|
146
105
|
const warnings = [];
|
|
106
|
+
// Clear stale npm-update lock so manual `npm install -g` never stays blocked forever
|
|
107
|
+
forceClearGlobalDeferredNpmLock();
|
|
147
108
|
// Step 1: Kill stale processes
|
|
148
109
|
try {
|
|
149
110
|
killStaleProcesses();
|
|
@@ -152,22 +113,7 @@ export async function performBootSequence() {
|
|
|
152
113
|
catch (err) {
|
|
153
114
|
warnings.push(`Could not kill stale processes: ${err instanceof Error ? err.message : String(err)}`);
|
|
154
115
|
}
|
|
155
|
-
// Step 2:
|
|
156
|
-
const lockPath = path.join(os.tmpdir(), '4runr-os-gnpm-in-progress.lock');
|
|
157
|
-
if (fs.existsSync(lockPath)) {
|
|
158
|
-
process.stderr.write('⏳ Waiting for background update to complete');
|
|
159
|
-
const ok = await waitForInProgressUpdate(60000);
|
|
160
|
-
process.stderr.write('\n');
|
|
161
|
-
if (!ok) {
|
|
162
|
-
// Force clear stale lock
|
|
163
|
-
try {
|
|
164
|
-
fs.unlinkSync(lockPath);
|
|
165
|
-
}
|
|
166
|
-
catch {
|
|
167
|
-
// ignore
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
116
|
+
// Step 2: Lock already cleared above (legacy waits removed — they blocked recovery)
|
|
171
117
|
// Step 3: Health checks
|
|
172
118
|
const prismaOk = checkPrismaClient();
|
|
173
119
|
const gatewayOk = checkGatewayBundle();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot-sequence.js","sourceRoot":"","sources":["../src/boot-sequence.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"boot-sequence.js","sourceRoot":"","sources":["../src/boot-sequence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export declare const DEFERRED_NPM_INSTALL_LOCK = "4runr-os-gnpm-in-progress.lock";
|
|
2
2
|
export declare function globalDeferredNpmLockPath(): string;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare function isGlobalDeferredNpmInstallInProgress(): boolean;
|
|
6
|
-
export declare function createGlobalDeferredNpmInstallLock(): void;
|
|
3
|
+
/** Always remove lock (called at `4r` boot). */
|
|
4
|
+
export declare function forceClearGlobalDeferredNpmLock(): void;
|
|
7
5
|
//# sourceMappingURL=deferred-npm-install-lock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferred-npm-install-lock.d.ts","sourceRoot":"","sources":["../src/deferred-npm-install-lock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deferred-npm-install-lock.d.ts","sourceRoot":"","sources":["../src/deferred-npm-install-lock.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAE1E,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,gDAAgD;AAChD,wBAAgB,+BAA+B,IAAI,IAAI,CAOtD"}
|
|
@@ -1,46 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* run concurrently with another `npm` touching the same folder — that causes EBUSY rename errors.
|
|
2
|
+
* Legacy lock file in %TEMP% — cleared at every `4r` boot so it cannot block `npm install -g`.
|
|
4
3
|
*/
|
|
5
4
|
import * as fs from 'fs';
|
|
6
5
|
import * as os from 'os';
|
|
7
6
|
import * as path from 'path';
|
|
8
7
|
export const DEFERRED_NPM_INSTALL_LOCK = '4runr-os-gnpm-in-progress.lock';
|
|
9
|
-
const STALE_MS = 12 * 60 * 1000; // 12 min — if PS dies, allow recovery
|
|
10
8
|
export function globalDeferredNpmLockPath() {
|
|
11
9
|
return path.join(os.tmpdir(), DEFERRED_NPM_INSTALL_LOCK);
|
|
12
10
|
}
|
|
13
|
-
|
|
11
|
+
/** Always remove lock (called at `4r` boot). */
|
|
12
|
+
export function forceClearGlobalDeferredNpmLock() {
|
|
14
13
|
const p = globalDeferredNpmLockPath();
|
|
15
|
-
if (!fs.existsSync(p))
|
|
16
|
-
return;
|
|
17
14
|
try {
|
|
18
|
-
|
|
19
|
-
if (Date.now() - mtimeMs > STALE_MS) {
|
|
15
|
+
if (fs.existsSync(p))
|
|
20
16
|
fs.unlinkSync(p);
|
|
21
|
-
}
|
|
22
17
|
}
|
|
23
18
|
catch {
|
|
24
19
|
/* ignore */
|
|
25
20
|
}
|
|
26
21
|
}
|
|
27
|
-
/** True if a deferred background npm is likely still running. */
|
|
28
|
-
export function isGlobalDeferredNpmInstallInProgress() {
|
|
29
|
-
const p = globalDeferredNpmLockPath();
|
|
30
|
-
if (!fs.existsSync(p))
|
|
31
|
-
return false;
|
|
32
|
-
try {
|
|
33
|
-
const { mtimeMs } = fs.statSync(p);
|
|
34
|
-
if (Date.now() - mtimeMs > STALE_MS) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export function createGlobalDeferredNpmInstallLock() {
|
|
44
|
-
fs.writeFileSync(globalDeferredNpmLockPath(), new Date().toISOString(), 'utf-8');
|
|
45
|
-
}
|
|
46
22
|
//# sourceMappingURL=deferred-npm-install-lock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferred-npm-install-lock.js","sourceRoot":"","sources":["../src/deferred-npm-install-lock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"deferred-npm-install-lock.js","sourceRoot":"","sources":["../src/deferred-npm-install-lock.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,CAAC,MAAM,yBAAyB,GAAG,gCAAgC,CAAC;AAE1E,MAAM,UAAU,yBAAyB;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,yBAAyB,CAAC,CAAC;AAC3D,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,+BAA+B;IAC7C,MAAM,CAAC,GAAG,yBAAyB,EAAE,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC"}
|
package/dist/tui-handlers.js
CHANGED
|
@@ -1568,26 +1568,28 @@ async function isGatewayHealthy(url) {
|
|
|
1568
1568
|
}
|
|
1569
1569
|
}
|
|
1570
1570
|
const TUI_LOCAL_REDIS_DEFAULT = 'redis://127.0.0.1:6379';
|
|
1571
|
-
function
|
|
1571
|
+
function tuiAutostartDockerStackDisabledByEnv() {
|
|
1572
1572
|
if (process.env['FOURRUNR_NO_AUTO_REDIS'] === '1' || process.env['FOURRUNR_NO_AUTO_REDIS'] === 'true') {
|
|
1573
1573
|
return true;
|
|
1574
1574
|
}
|
|
1575
|
+
if (process.env['FOURRUNR_NO_AUTO_DOCKER'] === '1' || process.env['FOURRUNR_NO_AUTO_DOCKER'] === 'true') {
|
|
1576
|
+
return true;
|
|
1577
|
+
}
|
|
1575
1578
|
if (process.env['FOURRUNR_SPAWN_REDIS'] === '0' || process.env['FOURRUNR_SPAWN_REDIS'] === 'false') {
|
|
1576
1579
|
return true;
|
|
1577
1580
|
}
|
|
1578
1581
|
return false;
|
|
1579
1582
|
}
|
|
1580
1583
|
/**
|
|
1581
|
-
*
|
|
1582
|
-
*
|
|
1583
|
-
* Redis is still a separate process; we only orchestrate a standard local container when Docker exists.
|
|
1584
|
+
* Start Postgres + Redis together via the same compose file the Gateway uses.
|
|
1585
|
+
* Previously we only ran a standalone Redis container, so Postgres never came up and Prisma stayed in memory mode.
|
|
1584
1586
|
*/
|
|
1585
|
-
function
|
|
1586
|
-
if (
|
|
1587
|
+
function tryTuiAutostartDockerComposeStack(bundlePath, activityLog, getCurrentTimeFn) {
|
|
1588
|
+
if (tuiAutostartDockerStackDisabledByEnv()) {
|
|
1587
1589
|
activityLog.push({
|
|
1588
1590
|
timestamp: getCurrentTimeFn(),
|
|
1589
1591
|
level: 'info',
|
|
1590
|
-
message: 'Autostart
|
|
1592
|
+
message: 'Autostart Docker stack: skipped (FOURRUNR_NO_AUTO_DOCKER / FOURRUNR_NO_AUTO_REDIS / FOURRUNR_SPAWN_REDIS=0).',
|
|
1591
1593
|
});
|
|
1592
1594
|
return undefined;
|
|
1593
1595
|
}
|
|
@@ -1595,28 +1597,32 @@ function tryTuiAutostartRedisDocker(activityLog, getCurrentTimeFn) {
|
|
|
1595
1597
|
activityLog.push({
|
|
1596
1598
|
timestamp: getCurrentTimeFn(),
|
|
1597
1599
|
level: 'info',
|
|
1598
|
-
message: 'Autostart
|
|
1600
|
+
message: 'Autostart Docker stack: skipped (REDIS_URL already set — manage Postgres yourself if needed).',
|
|
1599
1601
|
});
|
|
1600
1602
|
return undefined;
|
|
1601
1603
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1604
|
+
const composeFile = path.join(bundlePath, 'docker-compose.local.yml');
|
|
1605
|
+
if (!fs.existsSync(composeFile)) {
|
|
1606
|
+
activityLog.push({
|
|
1607
|
+
timestamp: getCurrentTimeFn(),
|
|
1608
|
+
level: 'warning',
|
|
1609
|
+
message: `Autostart Docker stack: no compose file at ${composeFile}`,
|
|
1610
|
+
});
|
|
1611
|
+
return undefined;
|
|
1612
|
+
}
|
|
1613
|
+
const dockerShell = process.platform === 'win32' ? (process.env['ComSpec'] || 'cmd.exe') : '/bin/sh';
|
|
1609
1614
|
try {
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1615
|
+
execSync(`docker compose -f "${composeFile}" up -d`, {
|
|
1616
|
+
cwd: bundlePath,
|
|
1617
|
+
stdio: 'ignore',
|
|
1618
|
+
windowsHide: true,
|
|
1619
|
+
timeout: 120000,
|
|
1620
|
+
shell: dockerShell,
|
|
1621
|
+
});
|
|
1616
1622
|
activityLog.push({
|
|
1617
1623
|
timestamp: getCurrentTimeFn(),
|
|
1618
1624
|
level: 'success',
|
|
1619
|
-
message: '
|
|
1625
|
+
message: 'Docker: Postgres + Redis started via docker-compose.local.yml (4runr-postgres :5432, 4runr-redis :6379).',
|
|
1620
1626
|
});
|
|
1621
1627
|
return TUI_LOCAL_REDIS_DEFAULT;
|
|
1622
1628
|
}
|
|
@@ -1624,7 +1630,7 @@ function tryTuiAutostartRedisDocker(activityLog, getCurrentTimeFn) {
|
|
|
1624
1630
|
activityLog.push({
|
|
1625
1631
|
timestamp: getCurrentTimeFn(),
|
|
1626
1632
|
level: 'warning',
|
|
1627
|
-
message: `Autostart
|
|
1633
|
+
message: `Autostart Docker stack failed — ${errorMessage(e)}. Gateway may fall back to memory DB without Postgres.`,
|
|
1628
1634
|
});
|
|
1629
1635
|
return undefined;
|
|
1630
1636
|
}
|
|
@@ -1682,17 +1688,16 @@ async function startLocalGatewayAndWait(bundlePath, url, activityLog, getCurrent
|
|
|
1682
1688
|
});
|
|
1683
1689
|
killRecordedLocalGateway();
|
|
1684
1690
|
await new Promise((r) => setTimeout(r, 400));
|
|
1685
|
-
const tuiRedisUrl =
|
|
1691
|
+
const tuiRedisUrl = tryTuiAutostartDockerComposeStack(bundlePath, activityLog, getCurrentTimeFn);
|
|
1686
1692
|
if (tuiRedisUrl) {
|
|
1687
|
-
|
|
1688
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
1693
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
1689
1694
|
}
|
|
1690
1695
|
const passThroughRedis = process.env['REDIS_URL'];
|
|
1691
1696
|
if (!tuiRedisUrl && !String(passThroughRedis || '').trim()) {
|
|
1692
1697
|
activityLog.push({
|
|
1693
1698
|
timestamp: getCurrentTimeFn(),
|
|
1694
1699
|
level: 'info',
|
|
1695
|
-
message: 'Autostart: GATEWAY_PERSISTENCE=auto
|
|
1700
|
+
message: 'Autostart: GATEWAY_PERSISTENCE=auto. No Docker stack started (install Docker Desktop, or set REDIS_URL). Opt out: FOURRUNR_NO_AUTO_DOCKER=1.',
|
|
1696
1701
|
});
|
|
1697
1702
|
}
|
|
1698
1703
|
const pkgJsonPath = path.join(bundlePath, 'package.json');
|