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.
@@ -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: kill node.exe processes running from global 4runr-os or Gateway paths
23
+ // Windows: Use PowerShell Get-Process (wmic was removed in Windows 11+)
24
24
  try {
25
- const output = execSync('wmic process where "name=\'node.exe\'" get ProcessId,CommandLine /format:csv', { encoding: 'utf-8', windowsHide: true });
26
- const lines = output.split(/\r?\n/);
27
- for (const line of lines) {
28
- if (line.includes('4runr-os') || line.includes('gateway')) {
29
- const match = line.match(/,(\d+)$/);
30
- if (match) {
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.exe (aggressive but effective)
33
+ // Fallback: just kill all node except current process
46
34
  try {
47
- execSync('taskkill /F /IM node.exe /FI "PID ne ' + process.pid + '"', {
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: Wait for in-progress updates
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,EAAS,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAS7B;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,kDAAkD;QAClD,IAAI,CAAC;YACH,QAAQ,CAAC,qCAAqC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,OAAO;IACT,CAAC;IAED,iFAAiF;IACjF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CACrB,8EAA8E,EAC9E,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CACzC,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBACpC,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACnC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC;wBACnC,IAAI,CAAC;4BACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;wBAC/B,CAAC;wBAAC,MAAM,CAAC;4BACP,SAAS;wBACX,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,IAAI,CAAC;YACH,QAAQ,CAAC,uCAAuC,GAAG,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE;gBACpE,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,YAAoB,MAAM;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gCAAgC,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;gBAC1C,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;YACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB;IACxB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,UAAU,EACV,UAAU,EACV,MAAM,EACN,SAAS,EACT,cAAc,EACd,SAAS,EACT,QAAQ,CACT,CAAC;QACF,OAAO,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QAC7F,OAAO,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa;IAC1B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAExE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAEvD,+CAA+C;QAC/C,QAAQ,CAAC,wBAAwB,EAAE;YACjC,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,QAAQ,CAAC,qBAAqB,EAAE;YAC9B,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjG,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,+BAA+B;IAC/B,IAAI,CAAC;QACH,kBAAkB,EAAE,CAAC;QACrB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,mCAAmC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;IAED,uCAAuC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gCAAgC,CAAC,CAAC;IAC1E,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACpE,MAAM,EAAE,GAAG,MAAM,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3B,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,yBAAyB;YACzB,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IAEvC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAElD,iBAAiB;QACjB,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,oFAAoF;gBAC3F,QAAQ;aACT,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC5E,CAAC"}
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
- export declare function tryClearStaleGlobalDeferredNpmLock(): void;
4
- /** True if a deferred background npm is likely still running. */
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":"AAQA,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAI1E,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAWzD;AAED,iEAAiE;AACjE,wBAAgB,oCAAoC,IAAI,OAAO,CAY9D;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAEzD"}
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
- * Single global `npm install -g 4runr-os` (Windows: deferred from 4r after exit) must not
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
- export function tryClearStaleGlobalDeferredNpmLock() {
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
- const { mtimeMs } = fs.statSync(p);
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;;;GAGG;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,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,sCAAsC;AAEvE,MAAM,UAAU,yBAAyB;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,yBAAyB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,kCAAkC;IAChD,MAAM,CAAC,GAAG,yBAAyB,EAAE,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;YACpC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,oCAAoC;IAClD,MAAM,CAAC,GAAG,yBAAyB,EAAE,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kCAAkC;IAChD,EAAE,CAAC,aAAa,CAAC,yBAAyB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;AACnF,CAAC"}
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"}
@@ -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 tuiAutostartRedisDisabledByEnv() {
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
- * On TUI-spawned Gateway, start local Redis by default (Docker: container `4runr-redis` on 6379).
1582
- * Skips if REDIS_URL is already set (you manage Redis yourself) or FOURRUNR_NO_AUTO_REDIS=1.
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 tryTuiAutostartRedisDocker(activityLog, getCurrentTimeFn) {
1586
- if (tuiAutostartRedisDisabledByEnv()) {
1587
+ function tryTuiAutostartDockerComposeStack(bundlePath, activityLog, getCurrentTimeFn) {
1588
+ if (tuiAutostartDockerStackDisabledByEnv()) {
1587
1589
  activityLog.push({
1588
1590
  timestamp: getCurrentTimeFn(),
1589
1591
  level: 'info',
1590
- message: 'Autostart Redis: skipped (FOURRUNR_NO_AUTO_REDIS or FOURRUNR_SPAWN_REDIS=0).',
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 Redis: skipped (REDIS_URL already set in environment).',
1600
+ message: 'Autostart Docker stack: skipped (REDIS_URL already set manage Postgres yourself if needed).',
1599
1601
  });
1600
1602
  return undefined;
1601
1603
  }
1602
- // shell as string: some @types/child_process only allow `string` (not `true`) for shell.
1603
- const dockerShell = process.platform === 'win32' ? (process.env.ComSpec || 'cmd.exe') : '/bin/sh';
1604
- const dockerExecOpts = {
1605
- stdio: 'ignore',
1606
- windowsHide: true,
1607
- shell: dockerShell,
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
- try {
1611
- execSync('docker start 4runr-redis', dockerExecOpts);
1612
- }
1613
- catch {
1614
- execSync('docker run -d --name 4runr-redis -p 6379:6379 redis:7-alpine', dockerExecOpts);
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: 'Redis: started via Docker (4runr-redis → 127.0.0.1:6379). Gateway will use REDIS_URL.',
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 Redis: Docker not available or failed — ${errorMessage(e)}. Install Docker or set REDIS_URL manually.`,
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 = tryTuiAutostartRedisDocker(activityLog, getCurrentTimeFn);
1691
+ const tuiRedisUrl = tryTuiAutostartDockerComposeStack(bundlePath, activityLog, getCurrentTimeFn);
1686
1692
  if (tuiRedisUrl) {
1687
- // Brief pause so the container is accepting connections before the Gateway process connects
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 (Docker DB if available, memory fallback). Redis not running (install Docker for auto-Redis, or set REDIS_URL). Opt out: FOURRUNR_NO_AUTO_REDIS=1.',
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');