@open-mercato/cli 0.6.3-develop.3876.1.d40fe4ec2d → 0.6.3-develop.3894.1.352abf4240
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/.turbo/turbo-build.log +1 -1
- package/dist/lib/in-process-generate-watcher-mode.js +13 -0
- package/dist/lib/in-process-generate-watcher-mode.js.map +7 -0
- package/dist/lib/in-process-generate-watcher.js +112 -0
- package/dist/lib/in-process-generate-watcher.js.map +7 -0
- package/dist/lib/testing/integration.js +5 -1
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +99 -75
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +9 -0
- package/src/lib/__tests__/in-process-generate-watcher-mode.test.ts +20 -0
- package/src/lib/__tests__/in-process-generate-watcher.test.ts +191 -0
- package/src/lib/in-process-generate-watcher-mode.ts +21 -0
- package/src/lib/in-process-generate-watcher.ts +175 -0
- package/src/lib/testing/integration.ts +5 -1
- package/src/mercato.ts +126 -81
package/dist/mercato.js
CHANGED
|
@@ -16,6 +16,12 @@ import {
|
|
|
16
16
|
resolveLazySchedulerRestart
|
|
17
17
|
} from "./lib/auto-spawn-scheduler.js";
|
|
18
18
|
import { startLazySchedulerSupervisor } from "./lib/scheduler-supervisor.js";
|
|
19
|
+
import {
|
|
20
|
+
startInProcessGenerateWatcher
|
|
21
|
+
} from "./lib/in-process-generate-watcher.js";
|
|
22
|
+
import {
|
|
23
|
+
resolveGenerateWatcherMode
|
|
24
|
+
} from "./lib/in-process-generate-watcher-mode.js";
|
|
19
25
|
import { parseModuleInstallArgs } from "./lib/module-install-args.js";
|
|
20
26
|
import { resolveNextBuildIdCandidate } from "./lib/next-build-id.js";
|
|
21
27
|
import { acquireServerStartLock } from "./lib/server-start-lock.js";
|
|
@@ -414,6 +420,45 @@ async function runPostGenerateStructuralCachePurge(quiet) {
|
|
|
414
420
|
}
|
|
415
421
|
}
|
|
416
422
|
}
|
|
423
|
+
async function runGeneratorSuite(quiet) {
|
|
424
|
+
const { createResolver } = await import("./lib/resolver.js");
|
|
425
|
+
const {
|
|
426
|
+
generateEntityIds,
|
|
427
|
+
generateModuleRegistry,
|
|
428
|
+
generateModuleRegistryApp,
|
|
429
|
+
generateModuleRegistryCli,
|
|
430
|
+
generateModuleEntities,
|
|
431
|
+
generateModuleDi,
|
|
432
|
+
generateModulePackageSources,
|
|
433
|
+
generateOpenApi
|
|
434
|
+
} = await import("./lib/generators/index.js");
|
|
435
|
+
const resolver = createResolver();
|
|
436
|
+
await generateEntityIds({ resolver, quiet });
|
|
437
|
+
await generateModuleRegistry({ resolver, quiet });
|
|
438
|
+
await generateModuleRegistryApp({ resolver, quiet });
|
|
439
|
+
await generateModuleRegistryCli({ resolver, quiet });
|
|
440
|
+
await generateModuleEntities({ resolver, quiet });
|
|
441
|
+
await generateModuleDi({ resolver, quiet });
|
|
442
|
+
await generateModulePackageSources({ resolver, quiet });
|
|
443
|
+
await generateOpenApi({ resolver, quiet });
|
|
444
|
+
}
|
|
445
|
+
function createGenerateWatchChecksumFn() {
|
|
446
|
+
return async () => {
|
|
447
|
+
const { createResolver } = await import("./lib/resolver.js");
|
|
448
|
+
const { calculateStructureChecksum } = await import("./lib/utils.js");
|
|
449
|
+
const resolver = createResolver();
|
|
450
|
+
const tracked = /* @__PURE__ */ new Set([
|
|
451
|
+
path.join(resolver.getAppDir(), "src", "modules.ts"),
|
|
452
|
+
path.join(resolver.getAppDir(), "src", "modules")
|
|
453
|
+
]);
|
|
454
|
+
for (const entry of resolver.loadEnabledModules()) {
|
|
455
|
+
const roots = resolver.getModulePaths(entry);
|
|
456
|
+
tracked.add(roots.appBase);
|
|
457
|
+
tracked.add(roots.pkgBase);
|
|
458
|
+
}
|
|
459
|
+
return calculateStructureChecksum(Array.from(tracked));
|
|
460
|
+
};
|
|
461
|
+
}
|
|
417
462
|
async function buildAllModules() {
|
|
418
463
|
const modules = getCliModules();
|
|
419
464
|
let appCli = [];
|
|
@@ -1204,28 +1249,6 @@ async function run(argv = process.argv) {
|
|
|
1204
1249
|
}
|
|
1205
1250
|
]
|
|
1206
1251
|
});
|
|
1207
|
-
const runGeneratorSuite = async (quiet) => {
|
|
1208
|
-
const { createResolver } = await import("./lib/resolver.js");
|
|
1209
|
-
const {
|
|
1210
|
-
generateEntityIds,
|
|
1211
|
-
generateModuleRegistry,
|
|
1212
|
-
generateModuleRegistryApp,
|
|
1213
|
-
generateModuleRegistryCli,
|
|
1214
|
-
generateModuleEntities,
|
|
1215
|
-
generateModuleDi,
|
|
1216
|
-
generateModulePackageSources,
|
|
1217
|
-
generateOpenApi
|
|
1218
|
-
} = await import("./lib/generators/index.js");
|
|
1219
|
-
const resolver = createResolver();
|
|
1220
|
-
await generateEntityIds({ resolver, quiet });
|
|
1221
|
-
await generateModuleRegistry({ resolver, quiet });
|
|
1222
|
-
await generateModuleRegistryApp({ resolver, quiet });
|
|
1223
|
-
await generateModuleRegistryCli({ resolver, quiet });
|
|
1224
|
-
await generateModuleEntities({ resolver, quiet });
|
|
1225
|
-
await generateModuleDi({ resolver, quiet });
|
|
1226
|
-
await generateModulePackageSources({ resolver, quiet });
|
|
1227
|
-
await generateOpenApi({ resolver, quiet });
|
|
1228
|
-
};
|
|
1229
1252
|
all.push({
|
|
1230
1253
|
id: "generate",
|
|
1231
1254
|
cli: [
|
|
@@ -1242,70 +1265,40 @@ async function run(argv = process.argv) {
|
|
|
1242
1265
|
{
|
|
1243
1266
|
command: "watch",
|
|
1244
1267
|
run: async (args) => {
|
|
1245
|
-
const { createResolver } = await import("./lib/resolver.js");
|
|
1246
|
-
const { calculateStructureChecksum } = await import("./lib/utils.js");
|
|
1247
1268
|
const quiet = args.includes("--quiet") || args.includes("-q");
|
|
1248
1269
|
const skipInitial = args.includes("--skip-initial");
|
|
1249
1270
|
const intervalArg = args.find((arg) => arg.startsWith("--interval="));
|
|
1250
1271
|
const parsedInterval = intervalArg ? Number.parseInt(intervalArg.split("=")[1] ?? "", 10) : NaN;
|
|
1251
1272
|
const intervalMs = Number.isFinite(parsedInterval) && parsedInterval >= 250 ? parsedInterval : 1e3;
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
path.join(resolver.getAppDir(), "src", "modules.ts"),
|
|
1259
|
-
path.join(resolver.getAppDir(), "src", "modules")
|
|
1260
|
-
]);
|
|
1261
|
-
for (const entry of resolver.loadEnabledModules()) {
|
|
1262
|
-
const roots = resolver.getModulePaths(entry);
|
|
1263
|
-
tracked.add(roots.appBase);
|
|
1264
|
-
tracked.add(roots.pkgBase);
|
|
1265
|
-
}
|
|
1266
|
-
return Array.from(tracked);
|
|
1267
|
-
};
|
|
1268
|
-
const runWatchGeneration = async (reason) => {
|
|
1269
|
-
if (running) {
|
|
1270
|
-
pending = true;
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
running = true;
|
|
1274
|
-
try {
|
|
1275
|
-
if (!quiet) {
|
|
1276
|
-
console.log(`[generate:watch] Regenerating (${reason})...`);
|
|
1277
|
-
}
|
|
1273
|
+
const watcher = startInProcessGenerateWatcher({
|
|
1274
|
+
pollMs: intervalMs,
|
|
1275
|
+
skipInitial,
|
|
1276
|
+
quiet,
|
|
1277
|
+
computeStructureChecksum: createGenerateWatchChecksumFn(),
|
|
1278
|
+
runGenerators: async () => {
|
|
1278
1279
|
await runGeneratorSuite(true);
|
|
1279
1280
|
await runPostGenerateStructuralCachePurge(true);
|
|
1280
|
-
if (!quiet) {
|
|
1281
|
-
console.log("[generate:watch] Generators completed.");
|
|
1282
|
-
}
|
|
1283
|
-
} catch (error) {
|
|
1284
|
-
console.error("[generate:watch] Generation failed:", error instanceof Error ? error.message : error);
|
|
1285
|
-
} finally {
|
|
1286
|
-
running = false;
|
|
1287
|
-
if (pending) {
|
|
1288
|
-
pending = false;
|
|
1289
|
-
await runWatchGeneration("queued change");
|
|
1290
|
-
}
|
|
1291
1281
|
}
|
|
1282
|
+
});
|
|
1283
|
+
const shutdownSignals = ["SIGINT", "SIGTERM"];
|
|
1284
|
+
let shuttingDown = false;
|
|
1285
|
+
const handleSignal = () => {
|
|
1286
|
+
if (shuttingDown) return;
|
|
1287
|
+
shuttingDown = true;
|
|
1288
|
+
void watcher.close();
|
|
1292
1289
|
};
|
|
1293
|
-
|
|
1294
|
-
|
|
1290
|
+
for (const signal of shutdownSignals) {
|
|
1291
|
+
process.once(signal, handleSignal);
|
|
1295
1292
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1293
|
+
const keepAlive = setInterval(() => {
|
|
1294
|
+
}, 1 << 30);
|
|
1295
|
+
try {
|
|
1296
|
+
await watcher.done;
|
|
1297
|
+
} finally {
|
|
1298
|
+
clearInterval(keepAlive);
|
|
1299
|
+
for (const signal of shutdownSignals) {
|
|
1300
|
+
process.removeListener(signal, handleSignal);
|
|
1300
1301
|
}
|
|
1301
|
-
console.log(`[generate:watch] Watching structural module files every ${intervalMs}ms`);
|
|
1302
|
-
}
|
|
1303
|
-
while (true) {
|
|
1304
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
1305
|
-
const nextChecksum = calculateStructureChecksum(getTrackedPaths());
|
|
1306
|
-
if (nextChecksum === previousChecksum) continue;
|
|
1307
|
-
previousChecksum = nextChecksum;
|
|
1308
|
-
await runWatchGeneration("structure change");
|
|
1309
1302
|
}
|
|
1310
1303
|
}
|
|
1311
1304
|
},
|
|
@@ -1400,6 +1393,8 @@ async function run(argv = process.argv) {
|
|
|
1400
1393
|
let envChangePromiseResolve = null;
|
|
1401
1394
|
let activeLazySupervisor = null;
|
|
1402
1395
|
let activeLazySchedulerSupervisor = null;
|
|
1396
|
+
let activeGenerateWatcher = null;
|
|
1397
|
+
const generateWatcherMode = resolveGenerateWatcherMode(process.env);
|
|
1403
1398
|
const envReloader = createDevEnvReloader(appDir, process.env, initialProcessEnvironmentEntries);
|
|
1404
1399
|
function cleanup() {
|
|
1405
1400
|
console.log("[server] Shutting down...");
|
|
@@ -1414,6 +1409,9 @@ async function run(argv = process.argv) {
|
|
|
1414
1409
|
if (activeLazySchedulerSupervisor) {
|
|
1415
1410
|
void activeLazySchedulerSupervisor.close().catch(() => void 0);
|
|
1416
1411
|
}
|
|
1412
|
+
if (activeGenerateWatcher) {
|
|
1413
|
+
void activeGenerateWatcher.close().catch(() => void 0);
|
|
1414
|
+
}
|
|
1417
1415
|
}
|
|
1418
1416
|
async function cleanupAndWait() {
|
|
1419
1417
|
cleanup();
|
|
@@ -1439,6 +1437,13 @@ async function run(argv = process.argv) {
|
|
|
1439
1437
|
}
|
|
1440
1438
|
activeLazySchedulerSupervisor = null;
|
|
1441
1439
|
}
|
|
1440
|
+
if (activeGenerateWatcher) {
|
|
1441
|
+
try {
|
|
1442
|
+
await activeGenerateWatcher.close();
|
|
1443
|
+
} catch {
|
|
1444
|
+
}
|
|
1445
|
+
activeGenerateWatcher = null;
|
|
1446
|
+
}
|
|
1442
1447
|
const lockFile = path.join(appDir, ".mercato", "next", "dev", "lock");
|
|
1443
1448
|
try {
|
|
1444
1449
|
fs.unlinkSync(lockFile);
|
|
@@ -1569,6 +1574,25 @@ async function run(argv = process.argv) {
|
|
|
1569
1574
|
managedExitPromises.push(waitForManagedProcessExit(schedulerProcess, "Scheduler polling engine"));
|
|
1570
1575
|
}
|
|
1571
1576
|
}
|
|
1577
|
+
if (generateWatcherMode === "in-process") {
|
|
1578
|
+
console.log("[server] In-process generate watcher enabled \u2014 structural changes will regenerate without a sidecar process.");
|
|
1579
|
+
activeGenerateWatcher = startInProcessGenerateWatcher({
|
|
1580
|
+
// `--skip-initial` equivalent: `yarn dev` always runs an
|
|
1581
|
+
// initial `mercato generate` before reaching the server
|
|
1582
|
+
// command, so the watcher must not re-run generators at
|
|
1583
|
+
// boot time. Otherwise dev startup pays a generator pass
|
|
1584
|
+
// twice in a row.
|
|
1585
|
+
skipInitial: true,
|
|
1586
|
+
quiet: false,
|
|
1587
|
+
computeStructureChecksum: createGenerateWatchChecksumFn(),
|
|
1588
|
+
runGenerators: async () => {
|
|
1589
|
+
await runGeneratorSuite(true);
|
|
1590
|
+
await runPostGenerateStructuralCachePurge(true);
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
} else {
|
|
1594
|
+
console.log("[server] Legacy out-of-process generate watcher selected via OM_DEV_GENERATE_WATCH_MODE=legacy \u2014 expect the dev orchestrator to spawn `mercato generate watch --skip-initial`.");
|
|
1595
|
+
}
|
|
1572
1596
|
const firstExit = await Promise.race(managedExitPromises);
|
|
1573
1597
|
await cleanupAndWait();
|
|
1574
1598
|
envChangePromiseResolve = null;
|