@neat.is/core 0.2.10 → 0.3.0
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-JMLZOKCS.js → chunk-B7UUGIXB.js} +1 -1
- package/dist/chunk-B7UUGIXB.js.map +1 -0
- package/dist/{chunk-5BQWBQJR.js → chunk-I5KODOJV.js} +2 -2
- package/dist/{chunk-W7ZYJZC7.js → chunk-NVCEZXL7.js} +48 -19
- package/dist/chunk-NVCEZXL7.js.map +1 -0
- package/dist/cli.cjs +60 -25
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +13 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +45 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -12
- package/dist/index.d.ts +4 -12
- package/dist/index.js +3 -3
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +49 -17
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-JMLZOKCS.js.map +0 -1
- package/dist/chunk-W7ZYJZC7.js.map +0 -1
- /package/dist/{chunk-5BQWBQJR.js.map → chunk-I5KODOJV.js.map} +0 -0
package/dist/neatd.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-I5KODOJV.js";
|
|
5
5
|
import {
|
|
6
6
|
listProjects,
|
|
7
7
|
registryPath
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-B7UUGIXB.js";
|
|
9
9
|
import {
|
|
10
10
|
__require
|
|
11
11
|
} from "./chunk-DGUM43GV.js";
|
package/dist/server.cjs
CHANGED
|
@@ -4126,6 +4126,10 @@ async function readRegistry() {
|
|
|
4126
4126
|
const parsed = JSON.parse(raw);
|
|
4127
4127
|
return import_types19.RegistryFileSchema.parse(parsed);
|
|
4128
4128
|
}
|
|
4129
|
+
async function getProject(name) {
|
|
4130
|
+
const reg = await readRegistry();
|
|
4131
|
+
return reg.projects.find((p) => p.name === name);
|
|
4132
|
+
}
|
|
4129
4133
|
async function listProjects() {
|
|
4130
4134
|
const reg = await readRegistry();
|
|
4131
4135
|
return reg.projects;
|
|
@@ -4242,9 +4246,15 @@ function registerRoutes(scope, ctx) {
|
|
|
4242
4246
|
scope.get("/health", async (req, reply) => {
|
|
4243
4247
|
const proj = resolveProject(registry, req, reply);
|
|
4244
4248
|
if (!proj) return;
|
|
4249
|
+
const uptimeMs = Date.now() - startedAt;
|
|
4245
4250
|
return {
|
|
4246
|
-
|
|
4251
|
+
ok: true,
|
|
4247
4252
|
project: proj.name,
|
|
4253
|
+
uptimeMs,
|
|
4254
|
+
// Legacy fields kept additively. The web shell's StatusBar reads
|
|
4255
|
+
// nodeCount / edgeCount; ADR-061's HealthResponseSchema validates
|
|
4256
|
+
// the canonical triple and lets the extras pass through.
|
|
4257
|
+
uptime: Math.floor(uptimeMs / 1e3),
|
|
4248
4258
|
nodeCount: proj.graph.order,
|
|
4249
4259
|
edgeCount: proj.graph.size,
|
|
4250
4260
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -4264,7 +4274,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4264
4274
|
if (!proj.graph.hasNode(id)) {
|
|
4265
4275
|
return reply.code(404).send({ error: "node not found", id });
|
|
4266
4276
|
}
|
|
4267
|
-
return proj.graph.getNodeAttributes(id);
|
|
4277
|
+
return { node: proj.graph.getNodeAttributes(id) };
|
|
4268
4278
|
}
|
|
4269
4279
|
);
|
|
4270
4280
|
scope.get(
|
|
@@ -4281,12 +4291,12 @@ function registerRoutes(scope, ctx) {
|
|
|
4281
4291
|
return { inbound, outbound };
|
|
4282
4292
|
}
|
|
4283
4293
|
);
|
|
4284
|
-
scope.get("/graph/
|
|
4294
|
+
scope.get("/graph/dependencies/:nodeId", async (req, reply) => {
|
|
4285
4295
|
const proj = resolveProject(registry, req, reply);
|
|
4286
4296
|
if (!proj) return;
|
|
4287
|
-
const {
|
|
4288
|
-
if (!proj.graph.hasNode(
|
|
4289
|
-
return reply.code(404).send({ error: "node not found", id });
|
|
4297
|
+
const { nodeId } = req.params;
|
|
4298
|
+
if (!proj.graph.hasNode(nodeId)) {
|
|
4299
|
+
return reply.code(404).send({ error: "node not found", id: nodeId });
|
|
4290
4300
|
}
|
|
4291
4301
|
const depth = req.query.depth ? Number(req.query.depth) : TRANSITIVE_DEPENDENCIES_DEFAULT_DEPTH;
|
|
4292
4302
|
if (!Number.isFinite(depth) || depth < 1 || depth > TRANSITIVE_DEPENDENCIES_MAX_DEPTH) {
|
|
@@ -4294,7 +4304,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4294
4304
|
error: `depth must be an integer in [1, ${TRANSITIVE_DEPENDENCIES_MAX_DEPTH}]`
|
|
4295
4305
|
});
|
|
4296
4306
|
}
|
|
4297
|
-
return getTransitiveDependencies(proj.graph,
|
|
4307
|
+
return getTransitiveDependencies(proj.graph, nodeId, depth);
|
|
4298
4308
|
});
|
|
4299
4309
|
scope.get("/graph/divergences", async (req, reply) => {
|
|
4300
4310
|
const proj = resolveProject(registry, req, reply);
|
|
@@ -4335,19 +4345,26 @@ function registerRoutes(scope, ctx) {
|
|
|
4335
4345
|
const proj = resolveProject(registry, req, reply);
|
|
4336
4346
|
if (!proj) return;
|
|
4337
4347
|
const epath = errorsPathFor(proj);
|
|
4338
|
-
if (!epath) return [];
|
|
4339
|
-
|
|
4348
|
+
if (!epath) return { count: 0, total: 0, events: [] };
|
|
4349
|
+
const events = await readErrorEvents(epath);
|
|
4350
|
+
const total = events.length;
|
|
4351
|
+
const limit = req.query.limit ? Number(req.query.limit) : 50;
|
|
4352
|
+
const safeLimit = Number.isFinite(limit) && limit > 0 ? Math.min(limit, 200) : 50;
|
|
4353
|
+
const sliced = events.slice(0, safeLimit);
|
|
4354
|
+
return { count: sliced.length, total, events: sliced };
|
|
4340
4355
|
});
|
|
4341
|
-
scope.get("/
|
|
4356
|
+
scope.get("/stale-events", async (req, reply) => {
|
|
4342
4357
|
const proj = resolveProject(registry, req, reply);
|
|
4343
4358
|
if (!proj) return;
|
|
4344
4359
|
const spath = staleEventsPathFor(proj);
|
|
4345
|
-
if (!spath) return [];
|
|
4360
|
+
if (!spath) return { count: 0, total: 0, events: [] };
|
|
4346
4361
|
const events = await readStaleEvents(spath);
|
|
4347
4362
|
const filtered = req.query.edgeType ? events.filter((e) => e.edgeType === req.query.edgeType) : events;
|
|
4348
4363
|
const ordered = [...filtered].reverse();
|
|
4364
|
+
const total = ordered.length;
|
|
4349
4365
|
const limit = req.query.limit ? Number(req.query.limit) : 50;
|
|
4350
|
-
|
|
4366
|
+
const sliced = ordered.slice(0, Number.isFinite(limit) && limit > 0 ? limit : 50);
|
|
4367
|
+
return { count: sliced.length, total, events: sliced };
|
|
4351
4368
|
});
|
|
4352
4369
|
scope.get(
|
|
4353
4370
|
"/incidents/:nodeId",
|
|
@@ -4359,14 +4376,15 @@ function registerRoutes(scope, ctx) {
|
|
|
4359
4376
|
return reply.code(404).send({ error: "node not found", id: nodeId });
|
|
4360
4377
|
}
|
|
4361
4378
|
const epath = errorsPathFor(proj);
|
|
4362
|
-
if (!epath) return [];
|
|
4379
|
+
if (!epath) return { count: 0, total: 0, events: [] };
|
|
4363
4380
|
const events = await readErrorEvents(epath);
|
|
4364
|
-
|
|
4381
|
+
const filtered = events.filter(
|
|
4365
4382
|
(e) => e.affectedNode === nodeId || e.service === nodeId.replace(/^service:/, "")
|
|
4366
4383
|
);
|
|
4384
|
+
return { count: filtered.length, total: filtered.length, events: filtered };
|
|
4367
4385
|
}
|
|
4368
4386
|
);
|
|
4369
|
-
scope.get("/
|
|
4387
|
+
scope.get("/graph/root-cause/:nodeId", async (req, reply) => {
|
|
4370
4388
|
const proj = resolveProject(registry, req, reply);
|
|
4371
4389
|
if (!proj) return;
|
|
4372
4390
|
const { nodeId } = req.params;
|
|
@@ -4386,7 +4404,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4386
4404
|
if (!result) return reply.code(404).send({ error: "no root cause found", id: nodeId });
|
|
4387
4405
|
return result;
|
|
4388
4406
|
});
|
|
4389
|
-
scope.get("/
|
|
4407
|
+
scope.get("/graph/blast-radius/:nodeId", async (req, reply) => {
|
|
4390
4408
|
const proj = resolveProject(registry, req, reply);
|
|
4391
4409
|
if (!proj) return;
|
|
4392
4410
|
const { nodeId } = req.params;
|
|
@@ -4496,7 +4514,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4496
4514
|
if (req.query.policyId) {
|
|
4497
4515
|
violations = violations.filter((v) => v.policyId === req.query.policyId);
|
|
4498
4516
|
}
|
|
4499
|
-
return violations;
|
|
4517
|
+
return { violations };
|
|
4500
4518
|
});
|
|
4501
4519
|
scope.post("/policies/check", async (req, reply) => {
|
|
4502
4520
|
const proj = resolveProject(registry, req, reply);
|
|
@@ -4575,6 +4593,20 @@ async function buildApi(opts) {
|
|
|
4575
4593
|
});
|
|
4576
4594
|
}
|
|
4577
4595
|
});
|
|
4596
|
+
app.get("/projects/:project", async (req, reply) => {
|
|
4597
|
+
try {
|
|
4598
|
+
const entry = await getProject(req.params.project);
|
|
4599
|
+
if (!entry) {
|
|
4600
|
+
return reply.code(404).send({ error: "project not found", project: req.params.project });
|
|
4601
|
+
}
|
|
4602
|
+
return { project: entry };
|
|
4603
|
+
} catch (err) {
|
|
4604
|
+
return reply.code(500).send({
|
|
4605
|
+
error: "failed to read project registry",
|
|
4606
|
+
details: err.message
|
|
4607
|
+
});
|
|
4608
|
+
}
|
|
4609
|
+
});
|
|
4578
4610
|
registerRoutes(app, routeCtx);
|
|
4579
4611
|
await app.register(
|
|
4580
4612
|
async (scope) => {
|