@neat.is/core 0.10.3-dev.20260930 → 0.10.4
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-DLQNMU3R.js → chunk-2OQVIBZZ.js} +59 -22
- package/dist/chunk-2OQVIBZZ.js.map +1 -0
- package/dist/{chunk-M7CGATVC.js → chunk-EFBWQIKG.js} +12 -2
- package/dist/chunk-EFBWQIKG.js.map +1 -0
- package/dist/{chunk-5SJHA5ZH.js → chunk-LXQCL4MP.js} +2 -2
- package/dist/{chunk-LNIVRE4L.js → chunk-TUGYIRUT.js} +51 -2
- package/dist/{chunk-LNIVRE4L.js.map → chunk-TUGYIRUT.js.map} +1 -1
- package/dist/cli.cjs +104 -19
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +50 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +114 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +114 -20
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-CU73Y5WT.js → otel-grpc-B7ABHLV7.js} +3 -3
- package/dist/server.cjs +62 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +7 -4
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-DLQNMU3R.js.map +0 -1
- package/dist/chunk-M7CGATVC.js.map +0 -1
- /package/dist/{chunk-5SJHA5ZH.js.map → chunk-LXQCL4MP.js.map} +0 -0
- /package/dist/{otel-grpc-CU73Y5WT.js.map → otel-grpc-B7ABHLV7.js.map} +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -51,6 +51,10 @@ function assertBindAuthority(host, token) {
|
|
|
51
51
|
if (isLoopbackHost2(host)) return;
|
|
52
52
|
throw new BindAuthorityError(host);
|
|
53
53
|
}
|
|
54
|
+
function isBearerDelegated(req) {
|
|
55
|
+
const config = req.routeOptions?.config;
|
|
56
|
+
return config?.bearerDelegated === true;
|
|
57
|
+
}
|
|
54
58
|
function mountBearerAuth(app, opts) {
|
|
55
59
|
if (!opts.token || opts.token.length === 0) return;
|
|
56
60
|
if (opts.trustProxy) return;
|
|
@@ -66,6 +70,10 @@ function mountBearerAuth(app, opts) {
|
|
|
66
70
|
done();
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
73
|
+
if (isBearerDelegated(req)) {
|
|
74
|
+
done();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
69
77
|
if (publicRead && PUBLIC_READ_METHODS.has(req.method)) {
|
|
70
78
|
done();
|
|
71
79
|
return;
|
|
@@ -99,7 +107,7 @@ function readAuthEnv(env = process.env) {
|
|
|
99
107
|
publicRead: parseBoolEnv(env.NEAT_PUBLIC_READ)
|
|
100
108
|
};
|
|
101
109
|
}
|
|
102
|
-
var import_node_crypto, LOOPBACK_HOSTS, BindAuthorityError, PUBLIC_READ_METHODS, DEFAULT_UNAUTH_PATHS, PROJECT_SCOPED_UNAUTH_PATTERN;
|
|
110
|
+
var import_node_crypto, LOOPBACK_HOSTS, BindAuthorityError, PUBLIC_READ_METHODS, DEFAULT_UNAUTH_PATHS, PROJECT_SCOPED_UNAUTH_PATTERN, BEARER_DELEGATED;
|
|
103
111
|
var init_auth = __esm({
|
|
104
112
|
"src/auth.ts"() {
|
|
105
113
|
"use strict";
|
|
@@ -129,6 +137,7 @@ var init_auth = __esm({
|
|
|
129
137
|
PROJECT_SCOPED_UNAUTH_PATTERN = new RegExp(
|
|
130
138
|
`^/projects/[^/]+/(?:${DEFAULT_UNAUTH_PATHS.map((p) => p.slice(1)).join("|")})$`
|
|
131
139
|
);
|
|
140
|
+
BEARER_DELEGATED = { bearerDelegated: true };
|
|
132
141
|
}
|
|
133
142
|
});
|
|
134
143
|
|
|
@@ -24226,6 +24235,19 @@ function registerRoutes(scope, ctx) {
|
|
|
24226
24235
|
});
|
|
24227
24236
|
}
|
|
24228
24237
|
});
|
|
24238
|
+
scope.post("/repo-sync", async (req, reply) => {
|
|
24239
|
+
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
24240
|
+
if (!proj) return;
|
|
24241
|
+
const syncNow = ctx.repoSync?.(proj.name);
|
|
24242
|
+
if (!syncNow) {
|
|
24243
|
+
return reply.code(404).send({
|
|
24244
|
+
error: "repo-sync is not running for this project",
|
|
24245
|
+
project: proj.name,
|
|
24246
|
+
hint: "Only a hosted daemon syncs bound repos. On a local daemon, POST /graph/scan re-extracts the project path."
|
|
24247
|
+
});
|
|
24248
|
+
}
|
|
24249
|
+
return reply.code(202).send({ project: proj.name, ...syncNow() });
|
|
24250
|
+
});
|
|
24229
24251
|
scope.post("/graph/scan", async (req, reply) => {
|
|
24230
24252
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
24231
24253
|
if (!proj) return;
|
|
@@ -24473,6 +24495,39 @@ function registerRoutes(scope, ctx) {
|
|
|
24473
24495
|
}
|
|
24474
24496
|
});
|
|
24475
24497
|
}
|
|
24498
|
+
var OTLP_BODY_LIMIT = 16 * 1024 * 1024;
|
|
24499
|
+
function otlpOnRest(getReceiver) {
|
|
24500
|
+
return async function plugin(scope) {
|
|
24501
|
+
scope.removeAllContentTypeParsers();
|
|
24502
|
+
scope.addContentTypeParser(
|
|
24503
|
+
"*",
|
|
24504
|
+
{ parseAs: "buffer", bodyLimit: OTLP_BODY_LIMIT },
|
|
24505
|
+
(_req, body, done) => done(null, body)
|
|
24506
|
+
);
|
|
24507
|
+
const relay = async (req, reply) => {
|
|
24508
|
+
const receiver = getReceiver();
|
|
24509
|
+
if (!receiver) {
|
|
24510
|
+
return reply.code(503).header("retry-after", "1").send({ error: "OTLP receiver is starting" });
|
|
24511
|
+
}
|
|
24512
|
+
const headers = { ...req.headers };
|
|
24513
|
+
delete headers["content-length"];
|
|
24514
|
+
delete headers["transfer-encoding"];
|
|
24515
|
+
delete headers.connection;
|
|
24516
|
+
const res = await receiver.inject({
|
|
24517
|
+
method: "POST",
|
|
24518
|
+
url: req.url,
|
|
24519
|
+
headers,
|
|
24520
|
+
payload: req.body
|
|
24521
|
+
});
|
|
24522
|
+
const contentType = res.headers["content-type"];
|
|
24523
|
+
if (contentType !== void 0) void reply.header("content-type", contentType);
|
|
24524
|
+
return reply.code(res.statusCode).send(res.rawPayload);
|
|
24525
|
+
};
|
|
24526
|
+
const route = { config: BEARER_DELEGATED, bodyLimit: OTLP_BODY_LIMIT };
|
|
24527
|
+
scope.post("/v1/traces", route, relay);
|
|
24528
|
+
scope.post("/projects/:project/v1/traces", route, relay);
|
|
24529
|
+
};
|
|
24530
|
+
}
|
|
24476
24531
|
async function buildApi(opts) {
|
|
24477
24532
|
const app = (0, import_fastify2.default)({ logger: false, routerOptions: { maxParamLength: 1024 } });
|
|
24478
24533
|
await app.register(import_cors.default, { origin: true });
|
|
@@ -24491,6 +24546,7 @@ async function buildApi(opts) {
|
|
|
24491
24546
|
authProxy: trustProxy === true,
|
|
24492
24547
|
requiresAuth
|
|
24493
24548
|
}));
|
|
24549
|
+
if (opts.otlpReceiver) await app.register(otlpOnRest(opts.otlpReceiver));
|
|
24494
24550
|
const startedAt = opts.startedAt ?? Date.now();
|
|
24495
24551
|
const registry = buildLegacyRegistry(opts);
|
|
24496
24552
|
const legacyErrorsExplicit = !opts.projects && opts.errorsPath !== void 0;
|
|
@@ -24521,6 +24577,7 @@ async function buildApi(opts) {
|
|
|
24521
24577
|
bootstrap: opts.bootstrap,
|
|
24522
24578
|
singleProject: opts.singleProject?.name,
|
|
24523
24579
|
connectorsHome: opts.connectorsHome,
|
|
24580
|
+
repoSync: opts.repoSync,
|
|
24524
24581
|
runPoll: opts.runPoll ?? runConnectorPoll
|
|
24525
24582
|
};
|
|
24526
24583
|
app.get("/health", async () => {
|
|
@@ -30607,6 +30664,15 @@ function bindUrl(webUrl, projectId) {
|
|
|
30607
30664
|
function onboardingUrl(webUrl) {
|
|
30608
30665
|
return `${webUrl}/onboarding`;
|
|
30609
30666
|
}
|
|
30667
|
+
async function offerLocalExtraction(input, d, out, readLine) {
|
|
30668
|
+
const run = d.orchestrator;
|
|
30669
|
+
if (!run || !readLine) return false;
|
|
30670
|
+
const answer = (await readLine("Build it now? [Y/n] "))?.trim().toLowerCase();
|
|
30671
|
+
if (answer === "n" || answer === "no") return false;
|
|
30672
|
+
out("");
|
|
30673
|
+
const code = await run(d.cwd ?? process.cwd(), {});
|
|
30674
|
+
return code === 0;
|
|
30675
|
+
}
|
|
30610
30676
|
async function runPostLoginConnect(input) {
|
|
30611
30677
|
const d = input.deps;
|
|
30612
30678
|
const out = d.out ?? ((line) => console.log(line));
|
|
@@ -30616,9 +30682,27 @@ async function runPostLoginConnect(input) {
|
|
|
30616
30682
|
const readLine = d.readLine;
|
|
30617
30683
|
const repo = await detect6(cwd);
|
|
30618
30684
|
out("");
|
|
30685
|
+
const cmd = commandPrefix();
|
|
30686
|
+
const syncLine = `${cmd} sync --to ${input.project.name}`;
|
|
30619
30687
|
if (!repo) {
|
|
30620
30688
|
out("This directory has no GitHub remote, so it can't be bound to the project.");
|
|
30621
|
-
|
|
30689
|
+
const hasGraph = await (d.hasLocalGraph ?? hasLocalSnapshot)(cwd);
|
|
30690
|
+
if (!hasGraph) {
|
|
30691
|
+
out(`A graph of this directory has to be built first, then pushed to ${input.project.name}.`);
|
|
30692
|
+
const built = await offerLocalExtraction(input, d, out, readLine);
|
|
30693
|
+
out("");
|
|
30694
|
+
if (built) {
|
|
30695
|
+
out(`Now push it to ${input.project.name}:`);
|
|
30696
|
+
out(` ${syncLine}`);
|
|
30697
|
+
} else {
|
|
30698
|
+
out(`When you're ready, build it and push it to ${input.project.name}:`);
|
|
30699
|
+
out(` ${cmd}`);
|
|
30700
|
+
out(` ${syncLine}`);
|
|
30701
|
+
}
|
|
30702
|
+
out(` Manage projects and repos: ${input.webUrl}`);
|
|
30703
|
+
return;
|
|
30704
|
+
}
|
|
30705
|
+
out(` Push its graph instead: ${syncLine}`);
|
|
30622
30706
|
out(` Manage projects and repos: ${input.webUrl}`);
|
|
30623
30707
|
return;
|
|
30624
30708
|
}
|
|
@@ -30652,18 +30736,18 @@ async function runPostLoginConnect(input) {
|
|
|
30652
30736
|
out("");
|
|
30653
30737
|
if (!hasGraph) {
|
|
30654
30738
|
out("There is no local graph to push yet. Build one, then push it:");
|
|
30655
|
-
out(
|
|
30656
|
-
out(`
|
|
30739
|
+
out(` ${cmd}`);
|
|
30740
|
+
out(` ${syncLine}`);
|
|
30657
30741
|
return;
|
|
30658
30742
|
}
|
|
30659
30743
|
out("Push the local graph with:");
|
|
30660
|
-
out(`
|
|
30744
|
+
out(` ${syncLine}`);
|
|
30661
30745
|
return;
|
|
30662
30746
|
}
|
|
30663
30747
|
out("");
|
|
30664
30748
|
out("No problem \u2014 when you want this repo in the graph:");
|
|
30665
30749
|
out(` Bind it: ${bindUrl(input.webUrl, input.project.id)}`);
|
|
30666
|
-
out(` Or push it:
|
|
30750
|
+
out(` Or push it: ${syncLine}`);
|
|
30667
30751
|
}
|
|
30668
30752
|
|
|
30669
30753
|
// src/login-sso.ts
|
|
@@ -30842,7 +30926,7 @@ async function runSsoLogin(opts, deps) {
|
|
|
30842
30926
|
...deps.signal ? { signal: deps.signal } : {}
|
|
30843
30927
|
});
|
|
30844
30928
|
if (waited.kind === "aborted") {
|
|
30845
|
-
out(
|
|
30929
|
+
out(`Stopped. Run \`${commandPrefix()} login\` again once your project is up.`);
|
|
30846
30930
|
return 130;
|
|
30847
30931
|
}
|
|
30848
30932
|
if (waited.kind === "timeout") {
|
|
@@ -30910,7 +30994,7 @@ async function runSsoLogin(opts, deps) {
|
|
|
30910
30994
|
}
|
|
30911
30995
|
});
|
|
30912
30996
|
out("");
|
|
30913
|
-
out(
|
|
30997
|
+
out(`Run \`${commandPrefix()} logout\` to switch back to your local daemon.`);
|
|
30914
30998
|
}
|
|
30915
30999
|
return 0;
|
|
30916
31000
|
}
|
|
@@ -34938,23 +35022,24 @@ async function tryOrchestrator(cmd, parsed, overrides = {}) {
|
|
|
34938
35022
|
return result.exitCode;
|
|
34939
35023
|
}
|
|
34940
35024
|
async function runWelcomeFlow(parsed) {
|
|
35025
|
+
const runLocal = async (cwd, opts) => await tryOrchestrator(
|
|
35026
|
+
cwd,
|
|
35027
|
+
{
|
|
35028
|
+
...parsed,
|
|
35029
|
+
...opts?.project !== void 0 ? { project: opts.project } : {},
|
|
35030
|
+
...opts?.noInstrument !== void 0 ? { noInstrument: opts.noInstrument } : {},
|
|
35031
|
+
...opts?.yes !== void 0 ? { yes: opts.yes } : {}
|
|
35032
|
+
},
|
|
35033
|
+
{ skipBanner: opts?.headerShown === true }
|
|
35034
|
+
) ?? 0;
|
|
34941
35035
|
return runWelcome({
|
|
34942
|
-
login: (loginArgv) => runLoginCommand(loginArgv),
|
|
35036
|
+
login: (loginArgv) => runLoginCommand(loginArgv, { connect: { orchestrator: runLocal } }),
|
|
34943
35037
|
// What the person chose at the door reaches the orchestrator as the flags they
|
|
34944
35038
|
// stand for: the name as `--project`, the instrument answer as `--no-instrument`
|
|
34945
35039
|
// or as `yes` (which keeps the orchestrator's own prompt quiet, since the door
|
|
34946
35040
|
// already asked). `headerShown` isn't a flag anyone can type — it says the
|
|
34947
35041
|
// door's wordmark already opened this run, so the orchestrator's banner is skipped.
|
|
34948
|
-
orchestrator:
|
|
34949
|
-
cwd,
|
|
34950
|
-
{
|
|
34951
|
-
...parsed,
|
|
34952
|
-
...opts?.project !== void 0 ? { project: opts.project } : {},
|
|
34953
|
-
...opts?.noInstrument !== void 0 ? { noInstrument: opts.noInstrument } : {},
|
|
34954
|
-
...opts?.yes !== void 0 ? { yes: opts.yes } : {}
|
|
34955
|
-
},
|
|
34956
|
-
{ skipBanner: opts?.headerShown === true }
|
|
34957
|
-
) ?? 0,
|
|
35042
|
+
orchestrator: runLocal,
|
|
34958
35043
|
// An explicit flag is an answer; don't ask again.
|
|
34959
35044
|
instrumentFlagGiven: parsed.noInstrument || parsed.dryRun
|
|
34960
35045
|
});
|