@neat.is/core 0.10.2 → 0.10.3
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/{chunk-CAGAHYDB.js → chunk-DLQNMU3R.js} +2 -2
- package/dist/{chunk-TXKOAART.js → chunk-LNIVRE4L.js} +6 -8
- package/dist/{chunk-TXKOAART.js.map → chunk-LNIVRE4L.js.map} +1 -1
- package/dist/cli.cjs +75 -40
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +72 -35
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +5 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +5 -7
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- /package/dist/{chunk-CAGAHYDB.js.map → chunk-DLQNMU3R.js.map} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -19403,14 +19403,12 @@ async function readLockPid(lockPath) {
|
|
|
19403
19403
|
async function classifyLockHolder(lockPath, probe = defaultLockHolderProbe) {
|
|
19404
19404
|
const lockPid = await readLockPid(lockPath);
|
|
19405
19405
|
const daemonPid = await probe.daemonPidFromFile();
|
|
19406
|
-
if (daemonPid !== void 0 && daemonPid !== process.pid && probe.isPidAlive(daemonPid) && // The lock already names the daemon, or the daemon answers on its port.
|
|
19407
|
-
// Either confirms a live daemon is in the picture (the second guards
|
|
19408
|
-
// against a stale pidfile whose PID got reused).
|
|
19409
|
-
(daemonPid === lockPid || await probe.daemonResponds())) {
|
|
19410
|
-
return { kind: "daemon", pid: daemonPid };
|
|
19411
|
-
}
|
|
19412
19406
|
if (lockPid !== void 0 && lockPid !== process.pid && probe.isPidAlive(lockPid)) {
|
|
19413
|
-
return { kind: "command", pid: lockPid };
|
|
19407
|
+
return { kind: lockPid === daemonPid ? "daemon" : "command", pid: lockPid };
|
|
19408
|
+
}
|
|
19409
|
+
if (daemonPid !== void 0 && daemonPid !== process.pid && probe.isPidAlive(daemonPid) && // Guards against a stale pidfile whose PID got reused.
|
|
19410
|
+
await probe.daemonResponds()) {
|
|
19411
|
+
return { kind: "daemon", pid: daemonPid };
|
|
19414
19412
|
}
|
|
19415
19413
|
return { kind: "stale" };
|
|
19416
19414
|
}
|
|
@@ -29364,9 +29362,15 @@ async function snapshotProjectStatus(restPort, project, body) {
|
|
|
29364
29362
|
}
|
|
29365
29363
|
return [{ name: project, status: await probeProjectHealth(restPort, project) }];
|
|
29366
29364
|
}
|
|
29367
|
-
|
|
29368
|
-
|
|
29369
|
-
|
|
29365
|
+
var STILL_WAITING_INTERVAL_MS = 1e4;
|
|
29366
|
+
function daemonProgressLine(project, event) {
|
|
29367
|
+
if (event.kind === "starting") return `starting the daemon for ${project}\u2026`;
|
|
29368
|
+
return `still waiting for ${project}'s daemon (${Math.round(event.elapsedMs / 1e3)}s)`;
|
|
29369
|
+
}
|
|
29370
|
+
async function waitForDaemonReady(restPort, project, timeoutMs, onProgress, reminderIntervalMs = STILL_WAITING_INTERVAL_MS) {
|
|
29371
|
+
const startedAt = Date.now();
|
|
29372
|
+
const deadline = startedAt + timeoutMs;
|
|
29373
|
+
let nextReminderAt = startedAt + reminderIntervalMs;
|
|
29370
29374
|
while (Date.now() < deadline) {
|
|
29371
29375
|
const body = await fetchDaemonHealth(restPort);
|
|
29372
29376
|
if (body !== null) {
|
|
@@ -29376,15 +29380,10 @@ async function waitForDaemonReady(restPort, project, timeoutMs) {
|
|
|
29376
29380
|
if (bootstrapping.length === 0) {
|
|
29377
29381
|
return { ready: true, brokenProjects: broken, stillBootstrapping: [] };
|
|
29378
29382
|
}
|
|
29379
|
-
|
|
29380
|
-
|
|
29381
|
-
|
|
29382
|
-
|
|
29383
|
-
console.log(
|
|
29384
|
-
`neat: waiting on ${bootstrapping.length} project${plural}: ${bootstrapping.join(", ")}`
|
|
29385
|
-
);
|
|
29386
|
-
lastBootstrapping = bootstrapping;
|
|
29387
|
-
}
|
|
29383
|
+
}
|
|
29384
|
+
if (Date.now() >= nextReminderAt) {
|
|
29385
|
+
onProgress?.({ kind: "waiting", elapsedMs: Date.now() - startedAt });
|
|
29386
|
+
nextReminderAt += reminderIntervalMs;
|
|
29388
29387
|
}
|
|
29389
29388
|
await new Promise((r) => setTimeout(r, PROBE_INTERVAL_MS));
|
|
29390
29389
|
}
|
|
@@ -29596,7 +29595,8 @@ async function ensureProjectDaemon(opts) {
|
|
|
29596
29595
|
projectPath: opts.projectPath,
|
|
29597
29596
|
ports: allocated
|
|
29598
29597
|
});
|
|
29599
|
-
|
|
29598
|
+
opts.onProgress?.({ kind: "starting" });
|
|
29599
|
+
const ready = await waitForDaemonReady(allocated.rest, opts.project, timeoutMs, opts.onProgress);
|
|
29600
29600
|
if (!ready.ready) {
|
|
29601
29601
|
return {
|
|
29602
29602
|
status: "timed-out",
|
|
@@ -29742,7 +29742,8 @@ async function runOrchestrator(opts) {
|
|
|
29742
29742
|
const outcome = await ensureProjectDaemon({
|
|
29743
29743
|
project: currentProjectName,
|
|
29744
29744
|
projectPath: opts.scanPath,
|
|
29745
|
-
timeoutMs
|
|
29745
|
+
timeoutMs,
|
|
29746
|
+
onProgress: (event) => console.log(`neat: ${daemonProgressLine(currentProjectName, event)}`)
|
|
29746
29747
|
});
|
|
29747
29748
|
const allocated = "ports" in outcome ? outcome.ports : null;
|
|
29748
29749
|
switch (outcome.status) {
|
|
@@ -30606,6 +30607,15 @@ function bindUrl(webUrl, projectId) {
|
|
|
30606
30607
|
function onboardingUrl(webUrl) {
|
|
30607
30608
|
return `${webUrl}/onboarding`;
|
|
30608
30609
|
}
|
|
30610
|
+
async function offerLocalExtraction(input, d, out, readLine) {
|
|
30611
|
+
const run = d.orchestrator;
|
|
30612
|
+
if (!run || !readLine) return false;
|
|
30613
|
+
const answer = (await readLine("Build it now? [Y/n] "))?.trim().toLowerCase();
|
|
30614
|
+
if (answer === "n" || answer === "no") return false;
|
|
30615
|
+
out("");
|
|
30616
|
+
const code = await run(d.cwd ?? process.cwd(), {});
|
|
30617
|
+
return code === 0;
|
|
30618
|
+
}
|
|
30609
30619
|
async function runPostLoginConnect(input) {
|
|
30610
30620
|
const d = input.deps;
|
|
30611
30621
|
const out = d.out ?? ((line) => console.log(line));
|
|
@@ -30615,9 +30625,27 @@ async function runPostLoginConnect(input) {
|
|
|
30615
30625
|
const readLine = d.readLine;
|
|
30616
30626
|
const repo = await detect6(cwd);
|
|
30617
30627
|
out("");
|
|
30628
|
+
const cmd = commandPrefix();
|
|
30629
|
+
const syncLine = `${cmd} sync --to ${input.project.name}`;
|
|
30618
30630
|
if (!repo) {
|
|
30619
30631
|
out("This directory has no GitHub remote, so it can't be bound to the project.");
|
|
30620
|
-
|
|
30632
|
+
const hasGraph = await (d.hasLocalGraph ?? hasLocalSnapshot)(cwd);
|
|
30633
|
+
if (!hasGraph) {
|
|
30634
|
+
out(`A graph of this directory has to be built first, then pushed to ${input.project.name}.`);
|
|
30635
|
+
const built = await offerLocalExtraction(input, d, out, readLine);
|
|
30636
|
+
out("");
|
|
30637
|
+
if (built) {
|
|
30638
|
+
out(`Now push it to ${input.project.name}:`);
|
|
30639
|
+
out(` ${syncLine}`);
|
|
30640
|
+
} else {
|
|
30641
|
+
out(`When you're ready, build it and push it to ${input.project.name}:`);
|
|
30642
|
+
out(` ${cmd}`);
|
|
30643
|
+
out(` ${syncLine}`);
|
|
30644
|
+
}
|
|
30645
|
+
out(` Manage projects and repos: ${input.webUrl}`);
|
|
30646
|
+
return;
|
|
30647
|
+
}
|
|
30648
|
+
out(` Push its graph instead: ${syncLine}`);
|
|
30621
30649
|
out(` Manage projects and repos: ${input.webUrl}`);
|
|
30622
30650
|
return;
|
|
30623
30651
|
}
|
|
@@ -30651,18 +30679,18 @@ async function runPostLoginConnect(input) {
|
|
|
30651
30679
|
out("");
|
|
30652
30680
|
if (!hasGraph) {
|
|
30653
30681
|
out("There is no local graph to push yet. Build one, then push it:");
|
|
30654
|
-
out(
|
|
30655
|
-
out(`
|
|
30682
|
+
out(` ${cmd}`);
|
|
30683
|
+
out(` ${syncLine}`);
|
|
30656
30684
|
return;
|
|
30657
30685
|
}
|
|
30658
30686
|
out("Push the local graph with:");
|
|
30659
|
-
out(`
|
|
30687
|
+
out(` ${syncLine}`);
|
|
30660
30688
|
return;
|
|
30661
30689
|
}
|
|
30662
30690
|
out("");
|
|
30663
30691
|
out("No problem \u2014 when you want this repo in the graph:");
|
|
30664
30692
|
out(` Bind it: ${bindUrl(input.webUrl, input.project.id)}`);
|
|
30665
|
-
out(` Or push it:
|
|
30693
|
+
out(` Or push it: ${syncLine}`);
|
|
30666
30694
|
}
|
|
30667
30695
|
|
|
30668
30696
|
// src/login-sso.ts
|
|
@@ -30841,7 +30869,7 @@ async function runSsoLogin(opts, deps) {
|
|
|
30841
30869
|
...deps.signal ? { signal: deps.signal } : {}
|
|
30842
30870
|
});
|
|
30843
30871
|
if (waited.kind === "aborted") {
|
|
30844
|
-
out(
|
|
30872
|
+
out(`Stopped. Run \`${commandPrefix()} login\` again once your project is up.`);
|
|
30845
30873
|
return 130;
|
|
30846
30874
|
}
|
|
30847
30875
|
if (waited.kind === "timeout") {
|
|
@@ -30909,7 +30937,7 @@ async function runSsoLogin(opts, deps) {
|
|
|
30909
30937
|
}
|
|
30910
30938
|
});
|
|
30911
30939
|
out("");
|
|
30912
|
-
out(
|
|
30940
|
+
out(`Run \`${commandPrefix()} logout\` to switch back to your local daemon.`);
|
|
30913
30941
|
}
|
|
30914
30942
|
return 0;
|
|
30915
30943
|
}
|
|
@@ -31811,7 +31839,13 @@ async function runUpCommand(argv, deps) {
|
|
|
31811
31839
|
err("neat up: that daemon doesn't run on this machine, so it isn't yours to start.");
|
|
31812
31840
|
return 2;
|
|
31813
31841
|
}
|
|
31814
|
-
const
|
|
31842
|
+
const project = entry2.name;
|
|
31843
|
+
const outcome = await ensure({
|
|
31844
|
+
project,
|
|
31845
|
+
projectPath: entry2.path,
|
|
31846
|
+
// `--json` prints one object and nothing else, so progress stays quiet there.
|
|
31847
|
+
...args.json ? {} : { onProgress: (event) => out(`neat up: ${daemonProgressLine(project, event)}`) }
|
|
31848
|
+
});
|
|
31815
31849
|
const log = daemonLogPath(entry2.path);
|
|
31816
31850
|
if (args.json) {
|
|
31817
31851
|
const ports = "ports" in outcome ? outcome.ports : void 0;
|
|
@@ -34931,23 +34965,24 @@ async function tryOrchestrator(cmd, parsed, overrides = {}) {
|
|
|
34931
34965
|
return result.exitCode;
|
|
34932
34966
|
}
|
|
34933
34967
|
async function runWelcomeFlow(parsed) {
|
|
34968
|
+
const runLocal = async (cwd, opts) => await tryOrchestrator(
|
|
34969
|
+
cwd,
|
|
34970
|
+
{
|
|
34971
|
+
...parsed,
|
|
34972
|
+
...opts?.project !== void 0 ? { project: opts.project } : {},
|
|
34973
|
+
...opts?.noInstrument !== void 0 ? { noInstrument: opts.noInstrument } : {},
|
|
34974
|
+
...opts?.yes !== void 0 ? { yes: opts.yes } : {}
|
|
34975
|
+
},
|
|
34976
|
+
{ skipBanner: opts?.headerShown === true }
|
|
34977
|
+
) ?? 0;
|
|
34934
34978
|
return runWelcome({
|
|
34935
|
-
login: (loginArgv) => runLoginCommand(loginArgv),
|
|
34979
|
+
login: (loginArgv) => runLoginCommand(loginArgv, { connect: { orchestrator: runLocal } }),
|
|
34936
34980
|
// What the person chose at the door reaches the orchestrator as the flags they
|
|
34937
34981
|
// stand for: the name as `--project`, the instrument answer as `--no-instrument`
|
|
34938
34982
|
// or as `yes` (which keeps the orchestrator's own prompt quiet, since the door
|
|
34939
34983
|
// already asked). `headerShown` isn't a flag anyone can type — it says the
|
|
34940
34984
|
// door's wordmark already opened this run, so the orchestrator's banner is skipped.
|
|
34941
|
-
orchestrator:
|
|
34942
|
-
cwd,
|
|
34943
|
-
{
|
|
34944
|
-
...parsed,
|
|
34945
|
-
...opts?.project !== void 0 ? { project: opts.project } : {},
|
|
34946
|
-
...opts?.noInstrument !== void 0 ? { noInstrument: opts.noInstrument } : {},
|
|
34947
|
-
...opts?.yes !== void 0 ? { yes: opts.yes } : {}
|
|
34948
|
-
},
|
|
34949
|
-
{ skipBanner: opts?.headerShown === true }
|
|
34950
|
-
) ?? 0,
|
|
34985
|
+
orchestrator: runLocal,
|
|
34951
34986
|
// An explicit flag is an answer; don't ask again.
|
|
34952
34987
|
instrumentFlagGiven: parsed.noInstrument || parsed.dryRun
|
|
34953
34988
|
});
|