@open-mercato/cli 0.5.1-develop.2996.ce62fd491c → 0.5.1-develop.3036.f02c281f23

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/dist/mercato.js CHANGED
@@ -248,6 +248,40 @@ function formatManagedProcessExitStatus(result) {
248
248
  function createManagedProcessExitError(result) {
249
249
  return new Error(`[server] ${result.label} exited unexpectedly with ${formatManagedProcessExitStatus(result)}.`);
250
250
  }
251
+ function formatQueueWorkerLabel(queueNames) {
252
+ if (queueNames.length === 0) return "Queue worker";
253
+ const sorted = [...queueNames].sort((a, b) => a.localeCompare(b));
254
+ const preview = sorted.length > 4 ? `${sorted.slice(0, 4).join(", ")}, +${sorted.length - 4} more` : sorted.join(", ");
255
+ return `Queue worker (${preview})`;
256
+ }
257
+ function lookupModuleCommand(allModules, moduleName, commandName) {
258
+ const mod = allModules.find((entry) => entry.id === moduleName);
259
+ if (!mod) {
260
+ return { status: "missing-module" };
261
+ }
262
+ if (!mod.cli || mod.cli.length === 0) {
263
+ return { status: "missing-cli" };
264
+ }
265
+ const command = mod.cli.find((entry) => entry.command === commandName);
266
+ if (!command) {
267
+ return { status: "missing-command" };
268
+ }
269
+ return {
270
+ status: "ok",
271
+ module: mod,
272
+ command
273
+ };
274
+ }
275
+ function describeMissingModuleCommand(result) {
276
+ switch (result.status) {
277
+ case "missing-module":
278
+ return "module not enabled";
279
+ case "missing-cli":
280
+ return "module has no CLI commands";
281
+ case "missing-command":
282
+ return "command not found";
283
+ }
284
+ }
251
285
  function ensureNextBuildIdInConfiguredDistDir(appDir) {
252
286
  const configuredDistDir = path.join(appDir, ".mercato", "next");
253
287
  const configuredBuildIdPath = path.join(configuredDistDir, "BUILD_ID");
@@ -304,36 +338,24 @@ async function handleDirectEjectCommand(args) {
304
338
  return 0;
305
339
  }
306
340
  async function runModuleCommand(allModules, moduleName, commandName, args = [], options = {}) {
307
- const mod = allModules.find((m) => m.id === moduleName);
308
- if (!mod) {
309
- if (options.optional) {
310
- if (!options.silentOptional) {
311
- console.log(`\u23ED\uFE0F Skipping "${moduleName}:${commandName}" \u2014 module not enabled`);
312
- }
313
- return false;
314
- }
315
- throw new Error(`Module not found: "${moduleName}"`);
316
- }
317
- if (!mod.cli || mod.cli.length === 0) {
341
+ const resolved = lookupModuleCommand(allModules, moduleName, commandName);
342
+ if (resolved.status !== "ok") {
318
343
  if (options.optional) {
319
344
  if (!options.silentOptional) {
320
- console.log(`\u23ED\uFE0F Skipping "${moduleName}:${commandName}" \u2014 module has no CLI commands`);
345
+ console.log(`\u23ED\uFE0F Skipping "${moduleName}:${commandName}" \u2014 ${describeMissingModuleCommand(resolved)}`);
321
346
  }
322
347
  return false;
323
348
  }
324
- throw new Error(`Module "${moduleName}" has no CLI commands`);
325
- }
326
- const cmd = mod.cli.find((c) => c.command === commandName);
327
- if (!cmd) {
328
- if (options.optional) {
329
- if (!options.silentOptional) {
330
- console.log(`\u23ED\uFE0F Skipping "${moduleName}:${commandName}" \u2014 command not found`);
331
- }
332
- return false;
349
+ switch (resolved.status) {
350
+ case "missing-module":
351
+ throw new Error(`Module not found: "${moduleName}"`);
352
+ case "missing-cli":
353
+ throw new Error(`Module "${moduleName}" has no CLI commands`);
354
+ case "missing-command":
355
+ throw new Error(`Command "${commandName}" not found in module "${moduleName}"`);
333
356
  }
334
- throw new Error(`Command "${commandName}" not found in module "${moduleName}"`);
335
357
  }
336
- await cmd.run(args);
358
+ await resolved.command.run(args);
337
359
  return true;
338
360
  }
339
361
  async function runPostGenerateStructuralCachePurge(quiet) {
@@ -1355,8 +1377,8 @@ async function run(argv = process.argv) {
1355
1377
  const autoSpawnWorkers = process.env.AUTO_SPAWN_WORKERS !== "false";
1356
1378
  const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== "false";
1357
1379
  const queueStrategy = process.env.QUEUE_STRATEGY || "local";
1358
- const runtimeEnv = buildServerProcessEnvironment(process.env);
1359
1380
  let didRetryCorruptedTurbopackCache = false;
1381
+ const schedulerCommand = lookupModuleCommand(getCliModules(), "scheduler", "start");
1360
1382
  function cleanup() {
1361
1383
  console.log("[server] Shutting down...");
1362
1384
  for (const proc of processes) {
@@ -1370,7 +1392,7 @@ async function run(argv = process.argv) {
1370
1392
  await Promise.all(
1371
1393
  processes.map(
1372
1394
  (proc) => new Promise((resolve) => {
1373
- if (proc.exitCode !== null) return resolve();
1395
+ if (proc.exitCode !== null || proc.signalCode !== null) return resolve();
1374
1396
  proc.on("exit", () => resolve());
1375
1397
  })
1376
1398
  )
@@ -1392,7 +1414,7 @@ async function run(argv = process.argv) {
1392
1414
  const startNextDev = () => new Promise((resolve) => {
1393
1415
  const nextProcess = spawn("node", [nextBin, "dev", "--turbopack"], {
1394
1416
  stdio: ["inherit", "pipe", "pipe"],
1395
- env: runtimeEnv,
1417
+ env: process.env,
1396
1418
  cwd: appDir
1397
1419
  });
1398
1420
  processes.push(nextProcess);
@@ -1437,22 +1459,26 @@ async function run(argv = process.argv) {
1437
1459
  console.log("[server] Starting workers for all queues...");
1438
1460
  const workerProcess = spawn("node", [mercatoBin, "queue", "worker", "--all"], {
1439
1461
  stdio: "inherit",
1440
- env: runtimeEnv,
1462
+ env: process.env,
1441
1463
  cwd: appDir
1442
1464
  });
1443
1465
  processes.push(workerProcess);
1444
- managedExitPromises.push(waitForManagedProcessExit(workerProcess, "Queue worker"));
1466
+ managedExitPromises.push(waitForManagedProcessExit(workerProcess, formatQueueWorkerLabel(discoveredWorkerQueues)));
1445
1467
  }
1446
1468
  }
1447
1469
  if (autoSpawnScheduler && queueStrategy === "local") {
1448
- console.log("[server] Starting scheduler polling engine...");
1449
- const schedulerProcess = spawn("node", [mercatoBin, "scheduler", "start"], {
1450
- stdio: "inherit",
1451
- env: runtimeEnv,
1452
- cwd: appDir
1453
- });
1454
- processes.push(schedulerProcess);
1455
- managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, "Scheduler polling engine"));
1470
+ if (schedulerCommand.status !== "ok") {
1471
+ console.log(`[server] Skipping scheduler auto-start \u2014 ${describeMissingModuleCommand(schedulerCommand)}`);
1472
+ } else {
1473
+ console.log("[server] Starting scheduler polling engine...");
1474
+ const schedulerProcess = spawn("node", [mercatoBin, "scheduler", "start"], {
1475
+ stdio: "inherit",
1476
+ env: process.env,
1477
+ cwd: appDir
1478
+ });
1479
+ processes.push(schedulerProcess);
1480
+ managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, "Scheduler polling engine"));
1481
+ }
1456
1482
  }
1457
1483
  const firstExit = await Promise.race(managedExitPromises);
1458
1484
  await cleanupAndWait();
@@ -1474,13 +1500,14 @@ async function run(argv = process.argv) {
1474
1500
  const autoSpawnScheduler = process.env.AUTO_SPAWN_SCHEDULER !== "false";
1475
1501
  const queueStrategy = process.env.QUEUE_STRATEGY || "local";
1476
1502
  const runtimeEnv = buildServerProcessEnvironment(process.env);
1503
+ const schedulerCommand = lookupModuleCommand(getCliModules(), "scheduler", "start");
1477
1504
  const serverStartLock = acquireServerStartLock(appDir, {
1478
1505
  port: runtimeEnv.PORT ?? process.env.PORT ?? null
1479
1506
  });
1480
1507
  function cleanup() {
1481
1508
  console.log("[server] Shutting down...");
1482
1509
  for (const proc of processes) {
1483
- if (!proc.killed) {
1510
+ if (!proc.killed && proc.exitCode === null && proc.signalCode === null) {
1484
1511
  proc.kill("SIGTERM");
1485
1512
  }
1486
1513
  }
@@ -1490,7 +1517,7 @@ async function run(argv = process.argv) {
1490
1517
  await Promise.all(
1491
1518
  processes.map(
1492
1519
  (proc) => new Promise((resolve) => {
1493
- if (proc.exitCode !== null) return resolve();
1520
+ if (proc.exitCode !== null || proc.signalCode !== null) return resolve();
1494
1521
  proc.on("exit", () => resolve());
1495
1522
  })
1496
1523
  )
@@ -1509,6 +1536,9 @@ async function run(argv = process.argv) {
1509
1536
  cwd: appDir
1510
1537
  });
1511
1538
  processes.push(nextProcess);
1539
+ const managedExitPromises = [
1540
+ waitForManagedProcessExit(nextProcess, "Next.js production server")
1541
+ ];
1512
1542
  if (autoSpawnWorkers) {
1513
1543
  const discoveredWorkerQueues = [...new Set(getRegisteredCliWorkers().map((worker) => worker.queue))];
1514
1544
  if (discoveredWorkerQueues.length === 0) {
@@ -1521,25 +1551,28 @@ async function run(argv = process.argv) {
1521
1551
  cwd: appDir
1522
1552
  });
1523
1553
  processes.push(workerProcess);
1554
+ managedExitPromises.push(waitForManagedProcessExit(workerProcess, formatQueueWorkerLabel(discoveredWorkerQueues)));
1524
1555
  }
1525
1556
  }
1526
1557
  if (autoSpawnScheduler && queueStrategy === "local") {
1527
- console.log("[server] Starting scheduler polling engine...");
1528
- const schedulerProcess = spawn("node", [mercatoBin, "scheduler", "start"], {
1529
- stdio: "inherit",
1530
- env: runtimeEnv,
1531
- cwd: appDir
1532
- });
1533
- processes.push(schedulerProcess);
1558
+ if (schedulerCommand.status !== "ok") {
1559
+ console.log(`[server] Skipping scheduler auto-start \u2014 ${describeMissingModuleCommand(schedulerCommand)}`);
1560
+ } else {
1561
+ console.log("[server] Starting scheduler polling engine...");
1562
+ const schedulerProcess = spawn("node", [mercatoBin, "scheduler", "start"], {
1563
+ stdio: "inherit",
1564
+ env: runtimeEnv,
1565
+ cwd: appDir
1566
+ });
1567
+ processes.push(schedulerProcess);
1568
+ managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, "Scheduler polling engine"));
1569
+ }
1534
1570
  }
1535
- await Promise.race(
1536
- processes.map(
1537
- (proc) => new Promise((resolve) => {
1538
- proc.on("exit", () => resolve());
1539
- })
1540
- )
1541
- );
1571
+ const firstExit = await Promise.race(managedExitPromises);
1542
1572
  await cleanupAndWait();
1573
+ if (!isExpectedManagedExitSignal(firstExit.signal)) {
1574
+ throw createManagedProcessExitError(firstExit);
1575
+ }
1543
1576
  } finally {
1544
1577
  serverStartLock.release();
1545
1578
  }