@neat.is/core 0.10.4 → 0.10.5-dev.20261002
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-TUGYIRUT.js → chunk-HHAPD6JD.js} +32 -6
- package/dist/chunk-HHAPD6JD.js.map +1 -0
- package/dist/{chunk-2OQVIBZZ.js → chunk-TONL5O2E.js} +4 -4
- package/dist/chunk-TONL5O2E.js.map +1 -0
- package/dist/cli.cjs +154 -28
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +125 -25
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +33 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +33 -7
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +31 -5
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2OQVIBZZ.js.map +0 -1
- package/dist/chunk-TUGYIRUT.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
resolveNeatVersion,
|
|
9
9
|
startK8sSubstratePolling,
|
|
10
10
|
writeDaemonRecord
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-TONL5O2E.js";
|
|
12
12
|
import {
|
|
13
13
|
buildSearchIndex
|
|
14
14
|
} from "./chunk-BC53SCT7.js";
|
|
@@ -82,7 +82,7 @@ import {
|
|
|
82
82
|
startStalenessLoop,
|
|
83
83
|
upsertConnectorEntry,
|
|
84
84
|
validateConnectorEntry
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-HHAPD6JD.js";
|
|
86
86
|
import {
|
|
87
87
|
startOtelGrpcReceiver
|
|
88
88
|
} from "./chunk-LXQCL4MP.js";
|
|
@@ -5441,6 +5441,52 @@ async function waitForFirstProject(fetchImpl, cpUrl, accessToken, deps) {
|
|
|
5441
5441
|
if (deps.signal?.aborted) return { kind: "aborted" };
|
|
5442
5442
|
}
|
|
5443
5443
|
}
|
|
5444
|
+
function projectNameForRepo(repo) {
|
|
5445
|
+
const slug = repo.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
5446
|
+
return slug || "repo";
|
|
5447
|
+
}
|
|
5448
|
+
async function detailOf(res) {
|
|
5449
|
+
const body = await res.text().catch(() => "");
|
|
5450
|
+
try {
|
|
5451
|
+
const parsed = JSON.parse(body);
|
|
5452
|
+
if (parsed.error) return parsed.error;
|
|
5453
|
+
} catch {
|
|
5454
|
+
}
|
|
5455
|
+
return body.trim() || `HTTP ${res.status}`;
|
|
5456
|
+
}
|
|
5457
|
+
async function createProjectForRepo(fetchImpl, cpUrl, accessToken, name) {
|
|
5458
|
+
const headers = { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json" };
|
|
5459
|
+
let project;
|
|
5460
|
+
try {
|
|
5461
|
+
const res = await fetchImpl(`${cpUrl}/me/projects`, {
|
|
5462
|
+
method: "POST",
|
|
5463
|
+
headers,
|
|
5464
|
+
body: JSON.stringify({ name }),
|
|
5465
|
+
signal: AbortSignal.timeout(CP_TIMEOUT_MS)
|
|
5466
|
+
});
|
|
5467
|
+
if (!res.ok) return { ok: false, reason: "not-created", detail: await detailOf(res) };
|
|
5468
|
+
project = await res.json();
|
|
5469
|
+
} catch (err) {
|
|
5470
|
+
return { ok: false, reason: "not-created", detail: err instanceof Error ? err.message : String(err) };
|
|
5471
|
+
}
|
|
5472
|
+
try {
|
|
5473
|
+
const res = await fetchImpl(`${cpUrl}/me/projects/${encodeURIComponent(project.id)}/provision`, {
|
|
5474
|
+
method: "POST",
|
|
5475
|
+
headers,
|
|
5476
|
+
signal: AbortSignal.timeout(CP_TIMEOUT_MS)
|
|
5477
|
+
});
|
|
5478
|
+
if (res.status === 402) return { ok: false, reason: "needs-plan", project, detail: await detailOf(res) };
|
|
5479
|
+
if (!res.ok) return { ok: false, reason: "not-provisioned", project, detail: await detailOf(res) };
|
|
5480
|
+
} catch (err) {
|
|
5481
|
+
return {
|
|
5482
|
+
ok: false,
|
|
5483
|
+
reason: "not-provisioned",
|
|
5484
|
+
project,
|
|
5485
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
return { ok: true, project };
|
|
5489
|
+
}
|
|
5444
5490
|
function bindUrl(webUrl, projectId) {
|
|
5445
5491
|
return `${webUrl}/config/repos?project=${encodeURIComponent(projectId)}`;
|
|
5446
5492
|
}
|
|
@@ -5466,7 +5512,8 @@ async function runPostLoginConnect(input) {
|
|
|
5466
5512
|
const repo = await detect6(cwd);
|
|
5467
5513
|
out("");
|
|
5468
5514
|
const cmd = commandPrefix();
|
|
5469
|
-
const
|
|
5515
|
+
const pushCmd = input.endpoint ? `${cmd} sync --to ${input.endpoint}${input.pushToken ? ` --token ${input.pushToken}` : ""}` : null;
|
|
5516
|
+
const pushInto = (label) => pushCmd ? [` ${pushCmd}`] : [` Its daemon URL and token are on ${label} in the console: ${input.webUrl}`];
|
|
5470
5517
|
if (!repo) {
|
|
5471
5518
|
out("This directory has no GitHub remote, so it can't be bound to the project.");
|
|
5472
5519
|
const hasGraph = await (d.hasLocalGraph ?? hasLocalSnapshot)(cwd);
|
|
@@ -5476,16 +5523,17 @@ async function runPostLoginConnect(input) {
|
|
|
5476
5523
|
out("");
|
|
5477
5524
|
if (built) {
|
|
5478
5525
|
out(`Now push it to ${input.project.name}:`);
|
|
5479
|
-
out(
|
|
5526
|
+
for (const line of pushInto(input.project.name)) out(line);
|
|
5480
5527
|
} else {
|
|
5481
5528
|
out(`When you're ready, build it and push it to ${input.project.name}:`);
|
|
5482
5529
|
out(` ${cmd}`);
|
|
5483
|
-
out(
|
|
5530
|
+
for (const line of pushInto(input.project.name)) out(line);
|
|
5484
5531
|
}
|
|
5485
5532
|
out(` Manage projects and repos: ${input.webUrl}`);
|
|
5486
5533
|
return;
|
|
5487
5534
|
}
|
|
5488
|
-
out(` Push its graph
|
|
5535
|
+
out(` Push its graph to ${input.project.name}:`);
|
|
5536
|
+
for (const line of pushInto(input.project.name)) out(line);
|
|
5489
5537
|
out(` Manage projects and repos: ${input.webUrl}`);
|
|
5490
5538
|
return;
|
|
5491
5539
|
}
|
|
@@ -5498,39 +5546,87 @@ async function runPostLoginConnect(input) {
|
|
|
5498
5546
|
out(` See the graph: ${input.webUrl}`);
|
|
5499
5547
|
return;
|
|
5500
5548
|
}
|
|
5501
|
-
out(`${slug} isn't
|
|
5549
|
+
out(`${slug} isn't in ${input.project.name} \u2014 logging in connected your account, not this repo.`);
|
|
5502
5550
|
out("");
|
|
5503
|
-
const
|
|
5504
|
-
|
|
5505
|
-
out(
|
|
5506
|
-
out(`
|
|
5551
|
+
const suggested = projectNameForRepo(repo);
|
|
5552
|
+
out("Where should this repo go?");
|
|
5553
|
+
out("");
|
|
5554
|
+
out(`1) A project of its own, called ${suggested}`);
|
|
5555
|
+
out(`2) ${input.project.name} \u2014 the project this login connected to`);
|
|
5556
|
+
for (const line of sharedProjectCaveat(bound)) out(` ${line}`);
|
|
5507
5557
|
out("3) Neither, for now");
|
|
5558
|
+
out("");
|
|
5508
5559
|
const answer = readLine ? (await readLine("Choose 1, 2 or 3 (Enter skips): "))?.trim() : void 0;
|
|
5509
5560
|
if (answer === "1") {
|
|
5510
|
-
const url = bindUrl(input.webUrl, input.project.id);
|
|
5511
|
-
const opened = (d.openBrowser ?? (() => false))(url);
|
|
5512
5561
|
out("");
|
|
5513
|
-
|
|
5514
|
-
|
|
5562
|
+
const outcome = await createProjectForRepo(fetchImpl, input.cpUrl, input.accessToken, suggested);
|
|
5563
|
+
reportCreate(outcome, input.webUrl, cmd, input.project.name, out);
|
|
5515
5564
|
return;
|
|
5516
5565
|
}
|
|
5517
5566
|
if (answer === "2") {
|
|
5518
|
-
const hasGraph = await (d.hasLocalGraph ?? hasLocalSnapshot)(cwd);
|
|
5519
5567
|
out("");
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5568
|
+
out(`Two ways into ${input.project.name} \u2014 either is fine, and you can do both:`);
|
|
5569
|
+
out("");
|
|
5570
|
+
const installed = input.me?.github?.installed;
|
|
5571
|
+
out(
|
|
5572
|
+
installed === false ? " Bind it (install the GitHub App first) \u2014 hosted NEAT keeps it in sync:" : installed === true ? " Bind it \u2014 hosted NEAT clones and extracts it, and keeps it in sync:" : " Bind it through the console \u2014 hosted NEAT keeps it in sync:"
|
|
5573
|
+
);
|
|
5574
|
+
out(` ${bindUrl(input.webUrl, input.project.id)}`);
|
|
5575
|
+
out("");
|
|
5576
|
+
const hasGraph = await (d.hasLocalGraph ?? hasLocalSnapshot)(cwd);
|
|
5577
|
+
if (hasGraph) {
|
|
5578
|
+
out(" Or push the graph on this machine now \u2014 a snapshot, not a subscription:");
|
|
5579
|
+
for (const line of pushInto(input.project.name)) out(` ${line}`);
|
|
5580
|
+
} else {
|
|
5581
|
+
out(" Or build a graph here and push it \u2014 a snapshot, not a subscription:");
|
|
5582
|
+
out(` ${cmd}`);
|
|
5583
|
+
for (const line of pushInto(input.project.name)) out(` ${line}`);
|
|
5525
5584
|
}
|
|
5526
|
-
out("Push the local graph with:");
|
|
5527
|
-
out(` ${syncLine}`);
|
|
5528
5585
|
return;
|
|
5529
5586
|
}
|
|
5530
5587
|
out("");
|
|
5531
5588
|
out("No problem \u2014 when you want this repo in the graph:");
|
|
5532
|
-
out(`
|
|
5533
|
-
out(` Or
|
|
5589
|
+
out(` Its own project: ${input.webUrl}`);
|
|
5590
|
+
out(` Or into ${input.project.name}: ${bindUrl(input.webUrl, input.project.id)}`);
|
|
5591
|
+
}
|
|
5592
|
+
function sharedProjectCaveat(bound) {
|
|
5593
|
+
const hazard = "Two repos in one project can currently retire each other's files (#1294),";
|
|
5594
|
+
if (!bound) return [hazard, "so a graph there may end up short of code until that is fixed."];
|
|
5595
|
+
if (bound.length === 0) return ["Nothing else is bound there yet.", `Adding a second repo later would hit #1294 \u2014 ${hazard.toLowerCase()}`];
|
|
5596
|
+
const names = bound.map((r) => `${r.owner}/${r.name}`).join(", ");
|
|
5597
|
+
return [
|
|
5598
|
+
`${bound.length} already there: ${names}.`,
|
|
5599
|
+
hazard,
|
|
5600
|
+
"so both graphs may end up short of code until that is fixed."
|
|
5601
|
+
];
|
|
5602
|
+
}
|
|
5603
|
+
function reportCreate(outcome, webUrl, cmd, connectedTo, out) {
|
|
5604
|
+
if (outcome.ok) {
|
|
5605
|
+
out(`Created ${outcome.project.name} and started its daemon.`);
|
|
5606
|
+
out("");
|
|
5607
|
+
out(`This CLI is still pointed at ${connectedTo}. Switch it to the new project with:`);
|
|
5608
|
+
out(` ${cmd} login --project ${outcome.project.name}`);
|
|
5609
|
+
out("");
|
|
5610
|
+
out("Then bind this repo to it:");
|
|
5611
|
+
out(` ${bindUrl(webUrl, outcome.project.id)}`);
|
|
5612
|
+
return;
|
|
5613
|
+
}
|
|
5614
|
+
if (outcome.reason === "needs-plan") {
|
|
5615
|
+
out(`Created ${outcome.project.name}, but starting a daemon for it needs a plan.`);
|
|
5616
|
+
out(` Choose one: ${webUrl}/checkout`);
|
|
5617
|
+
out("");
|
|
5618
|
+
out("The project is made and keeps its name, so there's nothing to redo here afterwards.");
|
|
5619
|
+
return;
|
|
5620
|
+
}
|
|
5621
|
+
if (outcome.reason === "not-provisioned") {
|
|
5622
|
+
out(`Created ${outcome.project.name}, but its daemon didn't start: ${outcome.detail}`);
|
|
5623
|
+
out("");
|
|
5624
|
+
out("The project exists \u2014 start it from the console rather than making a second one:");
|
|
5625
|
+
out(` ${webUrl}`);
|
|
5626
|
+
return;
|
|
5627
|
+
}
|
|
5628
|
+
out(`Couldn't create the project: ${outcome.detail}`);
|
|
5629
|
+
out(`Nothing was made, so this is safe to retry, or do it in the console: ${webUrl}`);
|
|
5534
5630
|
}
|
|
5535
5631
|
|
|
5536
5632
|
// src/login-sso.ts
|
|
@@ -5767,6 +5863,10 @@ async function runSsoLogin(opts, deps) {
|
|
|
5767
5863
|
webUrl: opts.webUrl,
|
|
5768
5864
|
accessToken,
|
|
5769
5865
|
project: { id: project.id, name: project.name },
|
|
5866
|
+
// What a push actually needs: `sync --to` takes the daemon's URL, and its
|
|
5867
|
+
// token comes from the flag rather than the profile (#1302).
|
|
5868
|
+
endpoint: cred.endpoint,
|
|
5869
|
+
pushToken: cred.authToken,
|
|
5770
5870
|
me,
|
|
5771
5871
|
deps: {
|
|
5772
5872
|
fetchImpl,
|