open-ready 0.2.21 → 0.2.23

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.
@@ -219,8 +219,12 @@ function resolvePortless() {
219
219
  * file, and polls the log for ready/error signals to open the browser or AI helper.
220
220
  */
221
221
  async function run() {
222
+ // Pin the log to an absolute path: the poll below runs for as long as the
223
+ // server does, and must keep reading this run's log even if the process's
224
+ // working directory changes in the meantime.
225
+ const logFile = path.resolve(logPath);
222
226
  try {
223
- await fsPromises.rm(logPath, { force: true });
227
+ await fsPromises.rm(logFile, { force: true });
224
228
  } catch {}
225
229
 
226
230
  const { portlessBin, appName } = resolvePortless();
@@ -230,7 +234,12 @@ async function run() {
230
234
  detached: true,
231
235
  });
232
236
 
233
- const logStream = fs.createWriteStream(logPath);
237
+ const logStream = fs.createWriteStream(logFile);
238
+ // A log that cannot be written (e.g. its directory was removed) must not
239
+ // crash the wrapper; the server output still reaches the terminal.
240
+ logStream.on("error", (err) => {
241
+ console.error(`[open-ready] Could not write ${logFile}: ${err.message}`);
242
+ });
234
243
  proc.stdout?.pipe(process.stdout);
235
244
  proc.stdout?.pipe(logStream);
236
245
  proc.stderr?.pipe(process.stderr);
@@ -244,8 +253,8 @@ async function run() {
244
253
 
245
254
  const poll = setInterval(async () => {
246
255
  try {
247
- const stats = fs.statSync(logPath);
248
- const currentLog = await fsPromises.readFile(logPath, "utf8");
256
+ const stats = fs.statSync(logFile);
257
+ const currentLog = await fsPromises.readFile(logFile, "utf8");
249
258
 
250
259
  // Stability check LAST - check ready first!
251
260
  const logChanged = stats.size !== lastLogSize;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-ready",
3
- "version": "0.2.21",
3
+ "version": "0.2.23",
4
4
  "description": "Smart dev server launcher: error→AI search, success→auto-open browser. Any CLI tool.",
5
5
  "type": "module",
6
6
  "bin": {
package/test/run.test.mjs CHANGED
@@ -20,6 +20,7 @@ let origArgv;
20
20
  let sigintBefore;
21
21
  let origTTY;
22
22
  let origCI;
23
+ let intervals;
23
24
 
24
25
  const printfArgs = (text) => ["printf", `'${text}'`];
25
26
 
@@ -46,6 +47,15 @@ beforeEach(() => {
46
47
  sigintBefore = process.listeners("SIGINT");
47
48
  origTTY = process.stdin.isTTY;
48
49
  origCI = process.env.CI;
50
+ // Each run() starts a poll that only stops once the server is ready or its
51
+ // log goes quiet; stop any left over so one case's poll cannot outlive it.
52
+ intervals = [];
53
+ const realSetInterval = globalThis.setInterval;
54
+ vi.spyOn(globalThis, "setInterval").mockImplementation((...args) => {
55
+ const id = realSetInterval(...args);
56
+ intervals.push(id);
57
+ return id;
58
+ });
49
59
  opener.mockReset();
50
60
  waitOn.mockReset().mockResolvedValue(undefined);
51
61
  vi.spyOn(console, "error").mockImplementation(() => {});
@@ -54,6 +64,7 @@ beforeEach(() => {
54
64
  });
55
65
 
56
66
  afterEach(() => {
67
+ for (const id of intervals) clearInterval(id);
57
68
  process.chdir(cwd);
58
69
  process.argv = origArgv;
59
70
  for (const l of process.listeners("SIGINT")) {